OS2.jugend: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
SLC (Diskussion | Beiträge) K (TYPO) |
SLC (Diskussion | Beiträge) (Update OS2.jugendV4, Version 0.41) |
||
| Zeile 7: | Zeile 7: | ||
|- bgcolor="#FFCC00" | |- bgcolor="#FFCC00" | ||
| '''Version''' | | '''Version''' | ||
| ''' | | '''0.41''' | ||
|- bgcolor="#FFCC00" | |- bgcolor="#FFCC00" | ||
| '''Autor''' | | '''Autor''' | ||
| Zeile 29: | Zeile 29: | ||
|- bgcolor="#FFCC00" | |- bgcolor="#FFCC00" | ||
| '''Funktionalität''' | | '''Funktionalität''' | ||
| '''Trennstriche zwischen den Jahrgängen'''<br> '''Aktueller Skill, Opti und MW'''<br> '''Prognose von Opti und MW für Ende Jahrgang 18'''<br> '''Optionen und Menu'''<br> '''Neue Marktwertformel'''<br> '''Automatische Ermittlung des ZATs''' | | '''Trennstriche zwischen den Jahrgängen'''<br> '''Aktueller Skill, Opti und MW'''<br> '''Prognose von Opti und MW für Ende Jahrgang 18'''<br> '''Optionen und Menu'''<br> '''Neue Marktwertformel'''<br> '''Automatische Ermittlung des ZATs'''<br> '''Hidden-Optionen und Datenspeicher'''<br> '''Geburtstage und dezimales Alter''' | ||
|- bgcolor="#FFCC00" | |- bgcolor="#FFCC00" | ||
| '''Letzte Änderung''' | | '''Letzte Änderung''' | ||
| Zeile 38: | Zeile 38: | ||
// @name OS2.jugendV4 | // @name OS2.jugendV4 | ||
// @namespace http://os.ongapo.com/ | // @namespace http://os.ongapo.com/ | ||
// @version 0. | // @version 0.41 | ||
// @copyright 2013+ | // @copyright 2013+ | ||
// @author Andreas Eckes (Strindheim BK) | // @author Andreas Eckes (Strindheim BK) | ||
| Zeile 76: | Zeile 76: | ||
'SW' : "switch", | 'SW' : "switch", | ||
'TF' : "true/false", | 'TF' : "true/false", | ||
'SD' : "simple data", | |||
'SI' : "simple option" | 'SI' : "simple option" | ||
}; | }; | ||
| Zeile 81: | Zeile 82: | ||
// Moegliche Optionen (hier die Standardwerte editieren oder ueber das Benutzermenu setzen): | // Moegliche Optionen (hier die Standardwerte editieren oder ueber das Benutzermenu setzen): | ||
const __OPTCONFIG = { | const __OPTCONFIG = { | ||
'zeigeGeb' : { // Spaltenauswahl fuer Geburtstage (true = anzeigen, false = nicht anzeigen) | |||
'Name' : "showBirthday", | |||
'Type' : __OPTTYPES.SW, | |||
'Default' : false, | |||
'Action' : switchShowBirthday, | |||
'Label' : "Geb. ein", | |||
'Hotkey' : 'G', | |||
'AltLabel' : "Geb. aus", | |||
'AltHotkey' : 'G' | |||
}, | |||
'zeigeAlter' : { // Spaltenauswahl fuer dezimales Alter (true = anzeigen, false = nicht anzeigen) | |||
'Name' : "showAge", | |||
'Type' : __OPTTYPES.SW, | |||
'Default' : true, | |||
'Action' : switchShowAge, | |||
'Label' : "Alter ein", | |||
'Hotkey' : 'A', | |||
'AltLabel' : "Alter aus", | |||
'AltHotkey' : 'A' | |||
}, | |||
'zeigePosition' : { // Position anzeigen | 'zeigePosition' : { // Position anzeigen | ||
'Name' : "showPos", | 'Name' : "showPos", | ||
| Zeile 204: | Zeile 225: | ||
'Label' : "ZAT: $", | 'Label' : "ZAT: $", | ||
'Hotkey' : 'Z' | 'Hotkey' : 'Z' | ||
}, | |||
'birthdays' : { // Datenspeicher fuer Geburtstage der Jugendspieler | |||
'Name' : "birthdays", | |||
'Type' : __OPTTYPES.SD, | |||
'Default' : [], | |||
'Action' : undefined, | |||
'Hidden' : true, | |||
'Serial' : true | |||
}, | |||
'team' : { // Datenspeicher fuer Daten des Erst- bzw. Zweitteams | |||
'Name' : "team", | |||
'Type' : __OPTTYPES.SD, | |||
'Default' : { 'Team' : undefined, 'Liga' : undefined, 'Land' : undefined }, | |||
'Action' : undefined, | |||
'Hidden' : true, | |||
'Serial' : true | |||
}, | }, | ||
'reset' : { // Optionen auf die "Werkseinstellungen" zuruecksetzen | 'reset' : { // Optionen auf die "Werkseinstellungen" zuruecksetzen | ||
| Zeile 240: | Zeile 277: | ||
__CONFIG.AltAction = __CONFIG.Action; | __CONFIG.AltAction = __CONFIG.Action; | ||
} | } | ||
break; | |||
case __OPTTYPES.SD : value = __CONFIG.Default; | |||
__CONFIG.Serial = true; | |||
break; | break; | ||
case __OPTTYPES.SI : value = undefined; | case __OPTTYPES.SI : value = undefined; | ||
break; | break; | ||
default : break; | |||
} | |||
if (__CONFIG.Serial) { | |||
__CONFIG.Hidden = true; | |||
} | } | ||
optSet[opt] = { | optSet[opt] = { | ||
| Zeile 258: | Zeile 302: | ||
// reload: Seite mit neuem Wert neu laden | // reload: Seite mit neuem Wert neu laden | ||
// return Gesetzter Wert | // return Gesetzter Wert | ||
function setOption(name, value, reload = true) { | function setOption(name, value, reload = true, serial = false) { | ||
if (serial) { | |||
serialize(name, value); | |||
} else { | |||
GM_setValue(name, value); | |||
} | |||
GM_setValue(name, value); | GM_setValue(name, value); | ||
| Zeile 274: | Zeile 323: | ||
// reload: Seite mit neuem Wert neu laden | // reload: Seite mit neuem Wert neu laden | ||
// return Gesetzter Wert | // return Gesetzter Wert | ||
function setNextOption(arr, name, value, reload = true) { | function setNextOption(arr, name, value, reload = true, serial = false) { | ||
const __POS = arr.indexOf(value) + 1; | const __POS = arr.indexOf(value) + 1; | ||
return setOption(name, arr[(__POS < arr.length) ? __POS : 0], reload); | return setOption(name, arr[(__POS < arr.length) ? __POS : 0], reload, serial); | ||
} | } | ||
| Zeile 286: | Zeile 335: | ||
// reload: Seite mit neuem Wert neu laden | // reload: Seite mit neuem Wert neu laden | ||
function setOpt(opt, value, reload = false) { | function setOpt(opt, value, reload = false) { | ||
opt.Value = setOption(opt.Config.Name, value, reload); | opt.Value = setOption(opt.Config.Name, value, reload, opt.Config.Serial); | ||
} | } | ||
| Zeile 297: | Zeile 346: | ||
switch (__CONFIG.Type) { | switch (__CONFIG.Type) { | ||
case __OPTTYPES.MC : opt.Value = setNextOption(__CONFIG.Choice, __CONFIG.Name, opt.Value, reload); | case __OPTTYPES.MC : opt.Value = setNextOption(__CONFIG.Choice, __CONFIG.Name, opt.Value, reload, __CONFIG.Serial); | ||
break; | break; | ||
case __OPTTYPES.SW : opt.Value = setOption(__CONFIG.Name, ! opt.Value, reload); | case __OPTTYPES.SW : opt.Value = setOption(__CONFIG.Name, ! opt.Value, reload, __CONFIG.Serial); | ||
break; | break; | ||
case __OPTTYPES.TF : opt.Value = setOption(__CONFIG.Name, (value !== undefined) ? value : ! opt.Value, reload); | case __OPTTYPES.TF : opt.Value = setOption(__CONFIG.Name, (value !== undefined) ? value : ! opt.Value, reload, __CONFIG.Serial); | ||
break; | |||
case __OPTTYPES.SD : opt.Value = setOption(__CONFIG.Name, (value !== undefined) ? value : opt.Value, reload, __CONFIG.Serial); | |||
break; | break; | ||
case __OPTTYPES.SI : break; | case __OPTTYPES.SI : break; | ||
default : break; | |||
} | } | ||
} | } | ||
| Zeile 330: | Zeile 382: | ||
// opt: Derzeitiger Wert der Option | // opt: Derzeitiger Wert der Option | ||
// arr: Array-Liste mit den moeglichen Optionen | // arr: Array-Liste mit den moeglichen Optionen | ||
// menu: Text zum Setzen im Menu | // menu: Text zum Setzen im Menu ($ wird durch gesetzten Wert ersetzt) | ||
// fun: Funktion zum Setzen des naechsten Wertes | // fun: Funktion zum Setzen des naechsten Wertes | ||
// key: Hotkey zum Setzen des naechsten Wertes im Menu | // key: Hotkey zum Setzen des naechsten Wertes im Menu | ||
function registerNextMenuOption(opt, arr, menu, fun, key) { | function registerNextMenuOption(opt, arr, menu, fun, key) { | ||
let options = "OPTION " + | const __MENU = menu.replace('$', opt); | ||
let options = "OPTION " + __MENU; | |||
for (let value of arr) { | for (let value of arr) { | ||
| Zeile 344: | Zeile 397: | ||
} | } | ||
console.log(options); | console.log(options); | ||
GM_registerMenuCommand(menu, fun, key); | GM_registerMenuCommand(__MENU, fun, key); | ||
} | |||
// Zeigt den Eintrag im Menu einer Option, falls nicht hidden | |||
// opt: Derzeitiger Wert der Option | |||
// menu: Text zum Setzen im Menu ($ wird durch gesetzten Wert ersetzt) | |||
// fun: Funktion zum Setzen des naechsten Wertes | |||
// key: Hotkey zum Setzen des naechsten Wertes im Menu | |||
// hidden: Angabe, ob Menupunkt nicht sichtbar sein soll (default: sichtbar) | |||
// serial: Serialization fuer komplexe Daten | |||
function registerDataOption(opt, menu, fun, key, hidden = false, serial = true) { | |||
const __VALUE = ((serial && (opt !== undefined)) ? uneval(opt) : opt); | |||
const __MENU = ((menu !== undefined) ? menu.replace('$', __VALUE) : ""); | |||
const __OPTIONS = (hidden ? "HIDDEN " : "") + "OPTION " + __MENU + | |||
((__VALUE !== undefined) ? " / *" + __VALUE + '*' : ""); | |||
console.log(__OPTIONS); | |||
if (! hidden) { | |||
GM_registerMenuCommand(__MENU, fun, key); | |||
} | |||
} | } | ||
| Zeile 352: | Zeile 424: | ||
const __CONFIG = opt.Config; | const __CONFIG = opt.Config; | ||
switch (__CONFIG.Type) { | if (! __CONFIG.Hidden) { | ||
switch (__CONFIG.Type) { | |||
case __OPTTYPES.MC : registerNextMenuOption(opt.Value, __CONFIG.Choice, | |||
__CONFIG.Label, __CONFIG.Action, __CONFIG.Hotkey); | |||
break; | |||
case __OPTTYPES.SW : registerMenuOption(opt.Value, __CONFIG.Label, __CONFIG.Action, __CONFIG.Hotkey, | |||
__CONFIG.AltLabel, __CONFIG.Action, __CONFIG.AltHotkey); | |||
break; | |||
case __OPTTYPES.TF : registerMenuOption(opt.Value, __CONFIG.Label, __CONFIG.Action, __CONFIG.Hotkey, | |||
__CONFIG.AltLabel, __CONFIG.AltAction, __CONFIG.AltHotkey); | |||
break; | |||
case __OPTTYPES.SD : registerDataOption(opt.Value, __CONFIG.Label, __CONFIG.Action, __CONFIG.Hotkey, | |||
__CONFIG.Hidden, __CONFIG.Serial); | |||
break; | |||
case __OPTTYPES.SI : registerDataOption(opt.Value, __CONFIG.Label, __CONFIG.Action, __CONFIG.Hotkey, | |||
__CONFIG.Hidden, __CONFIG.Serial); | |||
break; | |||
default : break; | |||
} | |||
} else { | |||
// Nur Anzeige im Log... | |||
registerDataOption(opt.Value, __CONFIG.Name, __CONFIG.Action, __CONFIG.Hotkey, __CONFIG.Hidden, __CONFIG.Serial); | |||
} | } | ||
} | } | ||
| Zeile 383: | Zeile 465: | ||
const __OPT = optSet[opt]; | const __OPT = optSet[opt]; | ||
__OPT.Value = GM_getValue(__OPT.Config.Name, __OPT.Value); | if (__OPT.Config.Serial) { | ||
__OPT.Value = deserialize(__OPT.Config.Name, __OPT.Value); | |||
} else { | |||
__OPT.Value = GM_getValue(__OPT.Config.Name, __OPT.Value); | |||
} | |||
} | } | ||
} | } | ||
| Zeile 404: | Zeile 490: | ||
window.location.reload(); | window.location.reload(); | ||
} | } | ||
// Teamparameter fuer getrennte Speicherung der Optionen fuer Erst- und Zweitteam... | |||
const __MYTEAM = { 'Team' : undefined, 'Liga' : undefined, 'Land' : undefined }; | |||
// Behandelt die Optionen und laedt das Benutzermenu | // Behandelt die Optionen und laedt das Benutzermenu | ||
| Zeile 409: | Zeile 498: | ||
// optSet: Platz für die gesetzten Optionen | // optSet: Platz für die gesetzten Optionen | ||
// optParams: Eventuell notwendige Parameter zur Initialisierung | // optParams: Eventuell notwendige Parameter zur Initialisierung | ||
// ' | // 'teamParams': Getrennte "ligaSize"-Option wird genutzt, hier: __MYTEAM mit 'Land' des Erst- bzw. Zweitteams | ||
// 'menuAnchor': Startpunkt fuer das Optionsmenu auf der Seite | // 'menuAnchor': Startpunkt fuer das Optionsmenu auf der Seite | ||
// return Gefuelltes Objekt mit den gesetzten Optionen | // return Gefuelltes Objekt mit den gesetzten Optionen | ||
function buildOptions(optConfig, optSet = undefined, optParams = { | function buildOptions(optConfig, optSet = undefined, optParams = { 'hideMenu' : false }) { | ||
const __TEAMPARAMS = optParams.teamParams; // Ermittelte Parameter | |||
let saveTeam = false; | |||
optSet = initOptions(optConfig, optSet); | optSet = initOptions(optConfig, optSet); | ||
if (__TEAMPARAMS !== undefined) { | |||
__MYTEAM.Team = __TEAMPARAMS.Team; | |||
__MYTEAM.Liga = __TEAMPARAMS.Liga; | |||
__MYTEAM.Land = __TEAMPARAMS.Land; | |||
console.log("Ermittelt: " + uneval(__MYTEAM)); | |||
saveTeam = true; | |||
} else { | |||
const __TEAM = deserialize(optSet.team.Config.Name); // Gespeicherte Parameter | |||
if ((__TEAM !== undefined) && (__TEAM.Land !== undefined)) { | |||
__MYTEAM.Team = __TEAM.Team; | |||
__MYTEAM.Liga = __TEAM.Liga; | |||
__MYTEAM.Land = __TEAM.Land; | |||
console.log("Gespeichert: " + uneval(__MYTEAM)); | |||
} else { | |||
console.log("Unbekannt: " + uneval(__MYTEAM)); | |||
} | |||
} | |||
if (__MYTEAM.Land !== undefined) { | |||
// Prefix fuer die Option "birthdays" | |||
optSet.birthdays.Config.Name = __MYTEAM.Land + optSet.birthdays.Config.Name; | |||
} | |||
loadOptions(optSet); | loadOptions(optSet); | ||
if (optParams. | if (saveTeam) { | ||
// ... und abspeichern... | |||
setOpt(optSet.team, __MYTEAM, false); | |||
} | |||
if (! optParams.hideMenu) { | |||
buildMenu(optSet); | buildMenu(optSet); | ||
} | } | ||
| Zeile 427: | Zeile 545: | ||
// ==================== Abschnitt mit Reaktionen auf Optionen ==================== | // ==================== Abschnitt mit Reaktionen auf Optionen ==================== | ||
// Wechselt die Anzeige des Geburtstags zwischen an und aus | |||
function switchShowBirthday() { | |||
setNextOpt(__OPTSET.zeigeGeb); | |||
} | |||
// Wechselt die Anzeige des dezimalen Alters zwischen an und aus | |||
function switchShowAge() { | |||
setNextOpt(__OPTSET.zeigeAlter); | |||
} | |||
// Wechselt die Anzeige der Position zwischen an und aus | // Wechselt die Anzeige der Position zwischen an und aus | ||
| Zeile 491: | Zeile 619: | ||
function setNextZAT() { | function setNextZAT() { | ||
setNextOpt(__OPTSET.aktuellerZat); | setNextOpt(__OPTSET.aktuellerZat); | ||
} | |||
// ==================== Abschnitt fuer diverse Utilities ==================== | |||
// Speichert einen beliebiegen Wert bzw. Code unter einem Namen ab | |||
// name: GM_serValue-Name, unter dem die Daten gespeichert werden | |||
// value: Beliebiger Wert oder Code (Vorsicht! Mit Augenmass benutzen!) | |||
function serialize(name, value) { | |||
GM_setValue(name, uneval(value)); | |||
} | |||
// Holt einen beliebiegen Wert bzw. Code unter einem Namen zurueck | |||
// name: GM_serValue-Name, unter dem die Daten gespeichert werden | |||
// defValue: Default-Wert fuer den Fall, dass nichts gespeichert ist | |||
function deserialize(name, defValue = "({})") { | |||
/* jshint evil: true */ | |||
return eval(GM_getValue(name, defValue)); | |||
} | } | ||
| Zeile 497: | Zeile 642: | ||
// ==================== Abschnitt genereller Code zur Anzeige der Jugend ==================== | // ==================== Abschnitt genereller Code zur Anzeige der Jugend ==================== | ||
// | // Zeitpunktangaben | ||
const __TIME = { | |||
'cre' : 0, // Jugendspieler angelegt (mit 12 Jahren) | |||
'beg' : 1, // Jugendspieler darf trainieren (wird 13 Jahre alt) | |||
'now' : 2, // Aktueller ZAT | |||
'end' : 3 // Jugendspieler wird Ende 18 gezogen (Geb. - 1 bzw. ZAT 71 für '?') | |||
}; | |||
// Funktionen *************************************************************************** | // Funktionen *************************************************************************** | ||
// Erschafft die Spieler-Objekte und fuellt sie mit Werten | // Erschafft die Spieler-Objekte und fuellt sie mit Werten | ||
function init(playerRows, optSet, colIdx, offsetUpper = 1, offsetLower = 0) { | |||
function init() { | const __SAISON = optSet.saison.Value; | ||
const __CURRZAT = optSet.aktuellerZat.Value; | |||
const __BIRTHDAYS = ((optSet.birthdays.Value !== undefined) ? optSet.birthdays.Value : []); | |||
const __PLAYERS = []; | |||
for (let i = offsetUpper, j = 0; i < playerRows.length - offsetLower; i++, j++) { | |||
const __CELLS = playerRows[i].cells; | |||
const __AGE = getAgeFromHTML(__CELLS, colIdx.Age); | |||
const __SKILLS = getSkillsFromHTML(__CELLS, colIdx); | |||
const __ISGOALIE = isGoalieFromHTML(__CELLS, colIdx.Age); | |||
const __NEWPLAYER = new PlayerRecord(__AGE, __SKILLS, __ISGOALIE); | |||
__NEWPLAYER.initPlayer(__SAISON, __CURRZAT, __BIRTHDAYS[j]); | |||
__PLAYERS[j] = __NEWPLAYER; | |||
} | |||
return __PLAYERS; | |||
} | } | ||
// Trennt die Jahrgaenge mit Linien | // Trennt die Gruppen (z.B. Jahrgaenge) mit Linien | ||
function separateGroups(rows, borderString, colIdxSort = 0, offsetUpper = 1, offsetLower = 0, offsetLeft = -1, offsetRight = 0) { | |||
function | if (offsetLeft < 0) { | ||
// | offsetLeft = colIdxSort; // ab Sortierspalte | ||
} | |||
for (let i = offsetUpper; i < rows.length - offsetLower - 1; i++) { | |||
if (rows[i].cells[colIdxSort].textContent != rows[i + 1].cells[colIdxSort].textContent) { | |||
for (let j = offsetLeft; j < rows[i].cells.length - offsetRight; j++) { | |||
rows[i].cells[j].style.borderBottom = borderString; | |||
} | |||
} | |||
} | |||
} | } | ||
// Klasse ColumnManager ***************************************************************** | // Klasse ColumnManager ***************************************************************** | ||
function ColumnManager() { | function ColumnManager(optSet) { | ||
this.geb = optSet.zeigeGeb.Value; | |||
this.alter = optSet.zeigeAlter.Value; | |||
this.skill = optSet.zeigeSkill.Value; | |||
this.pos = optSet.zeigePosition.Value; | |||
this.opti = ((optSet.anzahlOpti.Value >= 1) && (optSet.anzahlOpti.Value <= 6)); | |||
this.mw = ((optSet.anzahlMW.Value >= 1) && (optSet.anzahlMW.Value <= 6)); | |||
this.anzOpti = optSet.anzahlOpti.Value; | |||
this.anzMw = optSet.anzahlMW.Value; | |||
this.skillE = optSet.zeigeSkillEnde.Value; | |||
this.optiE = ((optSet.anzahlOptiEnde.Value >= 1) && (optSet.anzahlOptiEnde.Value <= 6)); | |||
this.mwE = ((optSet.anzahlMWEnde.Value >= 1) && (optSet.anzahlMWEnde.Value <= 6)); | |||
this.anzOptiE = optSet.anzahlOptiEnde.Value; | |||
this.anzMwE = optSet.anzahlMWEnde.Value; | |||
this.kennzE = optSet.kennzeichenEnde.Value; | |||
this.toString = function() { | |||
let result = "Skillschnitt\t\t" + this.skill + "\n"; | |||
result += "Beste Position\t" + this.pos + "\n"; | |||
result += "Optis\t\t\t" + this.opti + " (" + this.anzOpti + ")\n"; | |||
result += "Marktwerte\t\t" + this.mw + " (" + this.anzMw + ")\n"; | |||
result += "Skillschnitt Ende\t" + this.skillE + "\n"; | |||
result += "Optis Ende\t\t" + this.optiE + " (" + this.anzOptiE + ")\n"; | |||
result += "Marktwerte Ende\t" + this.mwE + " (" + this.anzMwE + ")\n"; | |||
return result; | |||
}; | |||
this.addCell = function(tableRow) { | |||
tableRow.insertCell(-1); | |||
return tableRow.cells.length - 1; | |||
}; | |||
this.addAndFillCell = function(tableRow, value, color, digits = 2) { | |||
if (isFinite(value) && (value !== true) && (value !== false)) { | |||
// Zahl einfuegen | |||
if (value < 1000) { | |||
// Mit Nachkommastellen darstellen | |||
tableRow.cells[this.addCell(tableRow)].textContent = parseFloat(value).toFixed(digits); | |||
} else { | |||
// Mit Tausenderpunkten darstellen | |||
tableRow.cells[this.addCell(tableRow)].textContent = getNumberString(value.toString()); | |||
} | |||
} else { | |||
// String einfuegen | |||
tableRow.cells[this.addCell(tableRow)].textContent = value; | |||
} | |||
tableRow.cells[tableRow.cells.length - 1].style.color = color; | |||
}; | |||
this.addTitles = function(headers, titleColor = "#FFFFFF") { | |||
// Spaltentitel zentrieren | |||
headers.align = "center"; | |||
// Titel fuer die aktuellen Werte | |||
if (this.geb) { | |||
this.addAndFillCell(headers, "Geb.", titleColor); | |||
} | |||
if (this.alter) { | |||
this.addAndFillCell(headers, "Alter", titleColor); | |||
} | |||
if (this.skill) { | |||
this.addAndFillCell(headers, "Skill", titleColor); | |||
} | |||
if (this.pos) { | |||
this.addAndFillCell(headers, "Pos", titleColor); | |||
} | |||
if (this.opti) { | |||
for (let i = 1; i <= this.anzOpti; i++) { | |||
this.addAndFillCell(headers, "Opti " + i, titleColor); | |||
if (this.mw && (this.anzMw >= i)) { | |||
this.addAndFillCell(headers, "MW " + i, titleColor); | |||
} | |||
} | |||
if (this.mw) { | |||
for (let i = this.anzOpti + 1; i <= this.anzMw; i++) { | |||
// Mehr MW- als Opti-Spalten | |||
this.addAndFillCell(headers, "MW " + i, titleColor); | |||
} | |||
} | |||
} else if (this.mw) { | |||
// Keine Opti-, dafuer MW-Spalten | |||
for (let i = 1; i <= this.anzMw; i++) { | |||
this.addAndFillCell(headers, "MW " + i, titleColor); | |||
} | |||
} | |||
// Titel fuer die Werte mit Ende 18 | |||
if (this.skillE) { | |||
this.addAndFillCell(headers, "Skill" + this.kennzE, titleColor); | |||
} | |||
if (this.optiE) { | |||
for (let i = 1; i <= this.anzOptiE; i++) { | |||
this.addAndFillCell(headers, "Opti " + i + this.kennzE, titleColor); | |||
if (this.mwE && (this.anzMwE >= i)) { | |||
this.addAndFillCell(headers, "MW " + i + this.kennzE, titleColor); | |||
} | |||
} | |||
if (this.mwE) { | |||
for (let i = this.anzOptiE + 1; i <= this.anzMwE; i++) { | |||
this.addAndFillCell(headers, "MW " + i + this.kennzE, titleColor); | |||
} | |||
} | |||
} else if (this.mwE) { | |||
for (let i = 1; i <= this.anzMwE; i++) { | |||
this.addAndFillCell(headers, "MW " + i + this.kennzE, titleColor); | |||
} | |||
} | |||
}; // Ende addTitles() | |||
this.addValues = function(player, playerRow, color = "#FFFFFF") { | |||
const __COLOR = (player.isGoalie ? getColor("TOR") : color); | |||
const __POS1COLOR = (player.isGoalie ? getColor("TOR") : getColor(player.getPos(1))); | |||
// Aktuelle Werte | |||
if (this.geb) { | |||
this.addAndFillCell(playerRow, (player.zatGeb < 0) ? '?' : player.zatGeb, __COLOR, 0); | |||
} | |||
if (this.alter) { | |||
this.addAndFillCell(playerRow, player.getAge(), __COLOR, 2); | |||
} | |||
if (this.skill) { | |||
this.addAndFillCell(playerRow, player.getSkill(), __COLOR, 2); | |||
} | |||
if (this.pos) { | |||
this.addAndFillCell(playerRow, player.getPos(1), __POS1COLOR); | |||
} | |||
if (this.opti) { | |||
for (let i = 1; i <= this.anzOpti; i++) { | |||
if (player.isGoalie) { | |||
if (i == 1) { | |||
// TOR-Opti anzeigen | |||
this.addAndFillCell(playerRow, player.getOpti("TOR"), getColor("TOR"), 2); | |||
} else { | |||
// TOR, aber nicht bester Opti -> nur Zelle hinzufuegen | |||
this.addCell(playerRow); | |||
} | |||
} else { | |||
// Feld-Opti anzeigen | |||
this.addAndFillCell(playerRow, player.getOpti(player.getPos(i)), getColor(player.getPos(i)), 2); | |||
} | |||
if (this.mw && (this.anzMw >= i)) { | |||
if (player.isGoalie) { | |||
if (i == 1) { | |||
// TOR-MW anzeigen | |||
this.addAndFillCell(playerRow, player.getMarketValue("TOR"), getColor("TOR"), 0); | |||
} else { | |||
// TOR, aber nicht bester MW -> nur Zelle hinzufuegen | |||
this.addCell(playerRow); | |||
} | |||
} else { | |||
// Feld-MW anzeigen | |||
this.addAndFillCell(playerRow, player.getMarketValue(player.getPos(i)), getColor(player.getPos(i)), 0); | |||
} | |||
} | |||
} | |||
// Verbleibende MW anzeigen | |||
if (this.mw) { | |||
for (let i = this.anzOpti + 1; i <= this.anzMw; i++) { | |||
if (player.isGoalie) { | |||
if (i == 1) { | |||
// TOR-MW anzeigen | |||
this.addAndFillCell(playerRow, player.getMarketValue("TOR"), getColor("TOR"), 0); | |||
} else { | |||
// TOR, aber nicht bester MW -> nur Zelle hinzufuegen | |||
this.addCell(playerRow); | |||
} | |||
} else { | |||
// Feld-MW anzeigen | |||
this.addAndFillCell(playerRow, player.getMarketValue(player.getPos(i)), getColor(player.getPos(i)), 0); | |||
} | |||
} | |||
} | |||
} else if (this.mw) { | |||
// Opti soll nicht angezeigt werden, dafuer aber MW | |||
for (let i = 1; i <= this.anzMw; i++) { | |||
if (player.isGoalie) { | |||
if (i == 1) { | |||
// TOR-MW anzeigen | |||
this.addAndFillCell(playerRow, player.getMarketValue("TOR"), getColor("TOR"), 0); | |||
} else { | |||
// TOR, aber nicht bester MW -> nur Zelle hinzufuegen | |||
this.addCell(playerRow); | |||
} | |||
} else { | |||
// Feld-MW anzeigen | |||
this.addAndFillCell(playerRow, player.getMarketValue(player.getPos(i)), getColor(player.getPos(i)), 0); | |||
} | |||
} | |||
} | |||
// Werte mit Ende 18 | |||
if (this.skillE) { | |||
this.addAndFillCell(playerRow, player.getSkill(__TIME.end), __COLOR, 2); | |||
} | |||
if (this.optiE) { | |||
for (let i = 1; i <= this.anzOptiE; i++) { | |||
if (player.isGoalie) { | |||
if (i == 1) { | |||
// TOR-Opti anzeigen | |||
this.addAndFillCell(playerRow, player.getOpti("TOR", __TIME.end), getColor("TOR"), 2); | |||
} else { | |||
// TOR, aber nicht bester Opti -> nur Zelle hinzufuegen | |||
this.addCell(playerRow); | |||
} | |||
} else { | |||
// Feld-Opti anzeigen | |||
this.addAndFillCell(playerRow, player.getOpti(player.getPos(i), __TIME.end), getColor(player.getPos(i)), 2); | |||
} | |||
if (this.mwE && (this.anzMwE >= i)) { | |||
if (player.isGoalie) { | |||
if (i == 1) { | |||
// TOR-MW anzeigen | |||
this.addAndFillCell(playerRow, player.getMarketValue("TOR", __TIME.end), getColor("TOR"), 0); | |||
} else { | |||
// TOR, aber nicht bester MW -> nur Zelle hinzufuegen | |||
this.addCell(playerRow); | |||
} | |||
} else { | |||
// Feld-MW anzeigen | |||
this.addAndFillCell(playerRow, player.getMarketValue(player.getPos(i), __TIME.end), getColor(player.getPos(i)), 0); | |||
} | |||
} | |||
} | |||
// Verbleibende MW anzeigen | |||
if (this.mwE) { | |||
for (let i = this.anzOptiE + 1; i <= this.anzMwE; i++) { | |||
if (player.isGoalie) { | |||
if (i == 1) { | |||
// TOR-MW anzeigen | |||
this.addAndFillCell(playerRow, player.getMarketValue("TOR", __TIME.end), getColor("TOR"), 0); | |||
} else { | |||
// TOR, aber nicht bester MW -> nur Zelle hinzufuegen | |||
this.addCell(playerRow); | |||
} | |||
} else { | |||
// Feld-MW anzeigen | |||
this.addAndFillCell(playerRow, player.getMarketValue(player.getPos(i), __TIME.end), getColor(player.getPos(i)), 0); | |||
} | |||
} | |||
} | |||
} else if (this.mwE) { | |||
// Opti soll nicht angezeigt werden, dafuer aber MW | |||
for (let i = 1; i <= this.anzMwE; i++) { | |||
if (player.isGoalie) { | |||
if (i == 1) { | |||
// TOR-MW anzeigen | |||
this.addAndFillCell(playerRow, player.getMarketValue("TOR", __TIME.end), getColor("TOR"), 0); | |||
} else { | |||
// TOR, aber nicht bester MW -> nur Zelle hinzufuegen | |||
this.addCell(playerRow); | |||
} | |||
} else { | |||
// Feld-MW anzeigen | |||
this.addAndFillCell(playerRow, player.getMarketValue(player.getPos(i), __TIME.end), getColor(player.getPos(i)), 0); | |||
} | |||
} | |||
} | |||
}; // Ende addValues(player, playerRow) | |||
} | } | ||
| Zeile 783: | Zeile 954: | ||
function PlayerRecord(age, skills, isGoalie) { | function PlayerRecord(age, skills, isGoalie) { | ||
// Zu benutzende Marktwertformel | |||
const __MWFORMEL = { | |||
'alt' : 0, // Marktwertformel bis Saison 9 inklusive | |||
'S10' : 1 // Marktwertformel MW5 ab Saison 10 | |||
}; | |||
this.mwFormel = __MWFORMEL.S10; // Neue Formel, genauer in initPlayer() | |||
this.age = age; | |||
this.skills = skills; | |||
this.isGoalie = isGoalie; | |||
// in this.initPlayer() definiert: | |||
// this.zatGeb: ZAT, an dem der Spieler Geburtstag hat, -1 fuer "noch nicht zugewiesen", also "?" | |||
// this.zatAge: Bisherige erfolgte Trainings-ZATs | |||
// this.positions[][]: Positionstext und Opti; TOR-Index ist 5 | |||
// this.skillsEnd[]: Berechnet aus this.skills, this.age und aktuellerZat | |||
this.toString = function() { | |||
let result = "Alter\t\t" + this.age + "\n\n"; | |||
result += "Aktuelle Werte\n"; | |||
result += "Skillschnitt\t" + this.getSkill().toFixed(2) + "\n"; | |||
result += "Optis und Marktwerte"; | |||
for (let pos of this.positions) { | |||
result += "\n\t" + pos + " \t"; | |||
result += this.getOpti(pos).toFixed(2) + "\t"; | |||
result += getNumberString(this.getMarketValue(pos).toString()); | |||
} | |||
result += "\n\nWerte mit Ende 18\n"; | |||
result += "Skillschnitt\t" + this.getSkill(__TIME.end).toFixed(2) + "\n"; | |||
result += "Optis und Marktwerte"; | |||
for (let pos of this.positions) { | |||
result += "\n\t" + this.getPos()[i] + " \t"; | |||
result += this.getOpti(pos, __TIME.end).toFixed(2) + "\t"; | |||
result += getNumberString(this.getMarketValue(pos, __TIME.end).toString()); | |||
} | |||
return result; | |||
}; // Ende this.toString() | |||
// Berechnet die Opti-Werte, sortiert das Positionsfeld und berechnet die Einzelskills mit Ende 18 | |||
this.initPlayer = function(saison, currZAT, gebZAT) { | |||
this.zatGeb = gebZAT; | |||
this.zatAge = this.getZatAge(currZAT); | |||
this.mwFormel = (saison < 10) ? __MWFORMEL.alt : __MWFORMEL.S10; | |||
this.positions = []; | |||
// ABW | |||
this.positions[0] = []; | |||
this.positions[0][0] = "ABW"; | |||
this.positions[0][1] = this.getOpti("ABW"); | |||
// DMI | |||
this.positions[1] = []; | |||
this.positions[1][0] = "DMI"; | |||
this.positions[1][1] = this.getOpti("DMI"); | |||
// MIT | |||
this.positions[2] = []; | |||
this.positions[2][0] = "MIT"; | |||
this.positions[2][1] = this.getOpti("MIT"); | |||
// OMI | |||
this.positions[3] = []; | |||
this.positions[3][0] = "OMI"; | |||
this.positions[3][1] = this.getOpti("OMI"); | |||
// STU | |||
this.positions[4] = []; | |||
this.positions[4][0] = "STU"; | |||
this.positions[4][1] = this.getOpti("STU"); | |||
// TOR | |||
this.positions[5] = []; | |||
this.positions[5][0] = "TOR"; | |||
this.positions[5][1] = this.getOpti("TOR"); | |||
// Sortieren | |||
sortPositionArray(this.positions); | |||
// Einzelskills mit Ende 18 berechnen | |||
this.skillsEnd = []; | |||
const __ZATMAX = (18 - 12) * 72 - 1; | |||
const __ZATSOFAR = this.zatAge; | |||
const __ZATTILLEND = __ZATMAX - __ZATSOFAR; | |||
for (let i in this.skills) { | |||
const __SKILL = this.skills[i]; | |||
if (isTrainableSkill(i)) { | |||
// Auf ganze Zahl runden und parseInt, da das sonst irgendwie als String interpretiert wird | |||
this.skillsEnd[i] = parseInt((__SKILL * (1 + __ZATTILLEND / __ZATSOFAR)).toFixed(0), 10); | |||
} else { | |||
this.skillsEnd[i] = __SKILL; | |||
} | |||
} | |||
}; // Ende this.iniPlayer() | |||
this.getZatAge = function(currZAT) { | |||
if (this.age < 13) { | |||
return 0; // noch nicht trainiert | |||
} else { | |||
let ZATs = (this.age - ((currZAT < this.zatGeb) ? 12 : 13)) * 72; // Basiszeit fuer die Jahre seit Jahrgang 13 | |||
if (this.zatGeb < 0) { | |||
return ZATs + currZAT; // Zaehlung begann Anfang der Saison (und der Geburtstag wird erst nach dem Ziehen bestimmt) | |||
} else { | |||
return ZATs + currZAT - this.zatGeb; // Verschiebung relativ zum Geburtstag (von -zatGeb, ..., 0, ..., 71 - zatGeb) | |||
} | |||
} | |||
}; | |||
this.getAge = function(when = __TIME.now) { | |||
if (this.mwFormel === __MWFORMEL.alt) { | |||
return (when === __TIME.end) ? 18 : this.age; | |||
} else { // Geburtstage ab Saison 10... | |||
return (when === __TIME.end) ? 18.00 : (13.00 + this.zatAge / 72); | |||
} | |||
}; | |||
this.getPos = function(idx) { | |||
const __IDXOFFSET = 1; | |||
return this.positions[idx - __IDXOFFSET][0]; | |||
}; | |||
this.getSkill = function(when = __TIME.now) { | |||
const __SKILLS = (when === __TIME.end) ? this.skillsEnd : this.skills; | |||
let result = 0; | |||
for (let skill of __SKILLS) { | |||
result += skill; | |||
} | |||
return result / __SKILLS.length; | |||
}; | |||
this.getOpti = function(pos, when = __TIME.now) { | |||
const __SKILLS = (when === __TIME.end) ? this.skillsEnd : this.skills; | |||
const __IDXPRISKILLS = getIdxPriSkills(pos); | |||
const __IDXSECSKILLS = getIdxSecSkills(pos); | |||
let sumPriSkills = 0; | |||
let sumSecSkills = 0; | |||
for (let idx of __IDXPRISKILLS) { | |||
sumPriSkills += __SKILLS[idx]; | |||
} | |||
for (let idx of __IDXSECSKILLS) { | |||
sumSecSkills += __SKILLS[idx]; | |||
} | |||
return (5 * sumPriSkills + sumSecSkills) / 27; | |||
}; | |||
this.getMarketValue = function(pos, when = __TIME.now) { | |||
const __AGE = this.getAge(when); | |||
if (this.mwFormel === __MWFORMEL.alt) { | |||
return Math.round(Math.pow((1 + this.getSkill(when)/100) * (1 + this.getOpti(pos, when)/100)* (2 - __AGE/100), 10) * 2); // Alte Formel bis Saison 9 | |||
} else { // MW-Formel ab Saison 10... | |||
const __MW5TF = 1.00; // Zwischen 0.97 und 1.03 | |||
return Math.round(Math.pow(1 + this.getSkill(when)/100, 5.65) * Math.pow(1 + this.getOpti(pos, when)/100, 8.1) * Math.pow(1 + (100 - __AGE)/49, 10) * __MW5TF); | |||
} | |||
}; | |||
} | } | ||
| Zeile 901: | Zeile 1.122: | ||
// Liest das Alter aus | // Liest das Alter aus | ||
// | function getAgeFromHTML(cells, colIdxAge) { | ||
function | return parseInt(cells[colIdxAge].textContent, 10); | ||
} | |||
// Liest das Geburtsdatum aus | |||
function getGebFromHTML(cells, colIdxGeb) { | |||
const __TEXT = ((cells[colIdxGeb] === undefined) ? '?' : cells[colIdxGeb].textContent); | |||
return parseInt((__TEXT === '?') ? -1 : __TEXT, 10); | |||
} | } | ||
// Liest die Einzelskills aus | // Liest die Einzelskills aus | ||
function getSkillsFromHTML(cells, colIdx) { | |||
function getSkillsFromHTML( | const __RESULT = []; | ||
for (let i = colIdx.Einz; i < colIdx.Zus; i++) { | |||
__RESULT[i - colIdx.Einz] = parseInt(cells[i].textContent, 10); | |||
} | |||
return __RESULT; | |||
} | } | ||
// Liest aus, ob der Spieler Torwart oder Feldspieler ist | // Liest aus, ob der Spieler Torwart oder Feldspieler ist | ||
function isGoalieFromHTML(cells, colIdxClass) { | |||
function isGoalieFromHTML( | return (cells[colIdxClass].className == "TOR"); | ||
} | } | ||
| Zeile 929: | Zeile 1.152: | ||
// Sortiert das Positionsfeld per BubbleSort | // Sortiert das Positionsfeld per BubbleSort | ||
function sortPositionArray(array) { | function sortPositionArray(array) { | ||
const __TEMP = []; | |||
let transposed = true; | |||
// TOR soll immer die letzte Position im Feld sein, deshalb - 1 | |||
let length = array.length - 1; | |||
while (transposed && (length > 1)) { | |||
transposed = false; | |||
for (let i = 0; i < length - 1; i++) { | |||
// Vergleich Opti-Werte: | |||
if (array[i][1] < array[i + 1][1]) { | |||
// vertauschen | |||
__TEMP[0] = array[i][0]; | |||
__TEMP[1] = array[i][1]; | |||
array[i][0] = array[i + 1][0]; | |||
array[i][1] = array[i + 1][1]; | |||
array[i + 1][0] = __TEMP[0]; | |||
array[i + 1][1] = __TEMP[1]; | |||
transposed = true; | |||
} | |||
} | |||
length--; | |||
} | |||
} | } | ||
// Fuegt in die uebergebene Zahl Tausender-Trennpunkte ein | // Fuegt in die uebergebene Zahl Tausender-Trennpunkte ein | ||
// Wandelt einen etwaig vorhandenen Dezimalpunkt in ein Komma um | // Wandelt einen etwaig vorhandenen Dezimalpunkt in ein Komma um | ||
function getNumberString(numberString) { | function getNumberString(numberString) { | ||
if (numberString.lastIndexOf(".") != -1) { | |||
// Zahl enthaelt Dezimalpunkt | |||
const __VORKOMMA = numberString.substring(0, numberString.lastIndexOf(".")); | |||
const __NACHKOMMA = numberString.substring(numberString.lastIndexOf(".") + 1, numberString.length); | |||
return getNumberString(__VORKOMMA) + "," + __NACHKOMMA; | |||
} else { | |||
// Kein Dezimalpunkt, fuege Tausender-Trennpunkte ein: | |||
// String umdrehen, nach jedem dritten Zeichen Punkt einfuegen, dann wieder umdrehen: | |||
const __TEMP = reverseString(numberString); | |||
let result = ""; | |||
for (let i = 0; i < __TEMP.length; i++) { | |||
if ((i > 0) && (i % 3 === 0)) { | |||
result += "."; | |||
} | |||
result += __TEMP.substr(i, 1); | |||
} | |||
return reverseString(result); | |||
} | |||
} | } | ||
// Dreht den uebergebenen String um | // Dreht den uebergebenen String um | ||
function reverseString(string) { | function reverseString(string) { | ||
let result = ""; | |||
for (let i = string.length - 1; i >= 0; i--) { | |||
result += string.substr(i, 1); | |||
} | |||
return result; | |||
} | } | ||
// Schaut nach, ob der uebergebene Index zu einem trainierbaren Skill gehoert | // Schaut nach, ob der uebergebene Index zu einem trainierbaren Skill gehoert | ||
// Die Indizes gehen von 0 (SCH) bis 16 (EIN) | // Die Indizes gehen von 0 (SCH) bis 16 (EIN) | ||
function isTrainableSkill(idx) { | function isTrainableSkill(idx) { | ||
const __TRAINABLESKILLS = [0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 15]; | |||
let result = false; | |||
for (let idxTrainable of __TRAINABLESKILLS) { | |||
if (idx == idxTrainable) { | |||
result = true; | |||
break; | |||
} | |||
} | |||
return result; | |||
} | } | ||
// Gibt die Indizes der Primaerskills zurueck | // Gibt die Indizes der Primaerskills zurueck | ||
function getIdxPriSkills(pos) { | function getIdxPriSkills(pos) { | ||
switch (pos) { | |||
case "TOR" : return new Array(2, 3, 4, 5); | |||
case "ABW" : return new Array(2, 3, 4, 15); | |||
case "DMI" : return new Array(1, 4, 9, 11); | |||
case "MIT" : return new Array(1, 3, 9, 11); | |||
case "OMI" : return new Array(1, 5, 9, 11); | |||
case "STU" : return new Array(0, 2, 3, 5); | |||
default : return []; | |||
} | |||
} | } | ||
// Gibt die Indizes der Sekundaerskills zurueck | // Gibt die Indizes der Sekundaerskills zurueck | ||
function getIdxSecSkills(pos) { | function getIdxSecSkills(pos) { | ||
switch (pos) { | |||
case "TOR" : return new Array(0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); | |||
case "ABW" : return new Array(0, 1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16); | |||
case "DMI" : return new Array(0, 2, 3, 5, 6, 7, 8, 10, 12, 13, 14, 15, 16); | |||
case "MIT" : return new Array(0, 2, 4, 5, 6, 7, 8, 10, 12, 13, 14, 15, 16); | |||
case "OMI" : return new Array(0, 2, 3, 4, 6, 7, 8, 10, 12, 13, 14, 15, 16); | |||
case "STU" : return new Array(1, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); | |||
default : return []; | |||
} | |||
} | } | ||
// Gibt die zur Position gehoerige Farbe zurueck | // Gibt die zur Position gehoerige Farbe zurueck | ||
function getColor(pos) { | function getColor(pos) { | ||
switch (pos) { | |||
case "TOR" : return "#FFFF00"; | |||
case "ABW" : return "#00FF00"; | |||
case "DMI" : return "#3366FF"; | |||
case "MIT" : return "#66FFFF"; | |||
case "OMI" : return "#FF66FF"; | |||
case "STU" : return "#FF0000"; | |||
case "LEI" : return "#FFFFFF"; | |||
default : return ""; | |||
} | |||
} | } | ||
| Zeile 1.049: | Zeile 1.277: | ||
// url: Adresse der Seite | // url: Adresse der Seite | ||
function getPageIdFromURL(url) { | function getPageIdFromURL(url) { | ||
// Variablen zur Identifikation der Seite | |||
const __INDEXS = url.lastIndexOf("page="); | |||
const __HAUPT = url.match(/haupt\.php/); // Ansicht "Haupt" (Managerbuero) | |||
const __JU = url.match(/ju\.php/); // Ansicht "Jugendteam" | |||
let page = -1; // Seitenindex (Rueckgabewert) | |||
// Wert von page (Seitenindex) ermitteln... | |||
// Annahme: Entscheidend ist jeweils das letzte Vorkommnis von "page=" und ggf. von '&' | |||
if (__HAUPT) { | |||
page = 0; | |||
} else if (__JU) { | |||
if (__INDEXS < 0) { | |||
page = 1; | |||
} else if (url.indexOf('&', __INDEXS) < 0) { | |||
// Wert von page setzt sich aus allen Zeichen hinter "page=" zusammen | |||
page = parseInt(url.substring(__INDEXS + 5, url.length), 10); | |||
} else { | |||
// Wert von page setzt sich aus allen Zeichen zwischen "page=" und '&' zusammen | |||
page = parseInt(url.substring(__INDEXS + 5, url.indexOf('&', __INDEXS)), 10); | |||
} | |||
} | |||
return page; | |||
} | |||
// Ermittelt, wie das eigene Team heisst und aus welchem Land bzw. Liga es kommt (zur Unterscheidung von Erst- und Zweitteam) | |||
// cell: Tabellenzelle mit den Parametern zum Team "<b>Willkommen im Managerbüro von TEAM</b><br>LIGA LAND<a href=..." | |||
// return Im Beispiel { 'Team' : "TEAM", 'Liga' : "LIGA", 'Land' : "LAND" }, | |||
// z.B. { 'Team' : "Choromonets Odessa", 'Liga' : "1. Liga", 'Land' : "Ukraine" } | |||
function getTeamParamsFromCell(cell) { | |||
const __SEARCHSTART = " von "; | |||
const __SEARCHMIDDLE = "</b><br>"; | |||
const __SEARCHLIGA = ". Liga "; | |||
const __SEARCHEND = "<a href="; | |||
let teamParams = cell.innerHTML.substring(cell.innerHTML.indexOf(__SEARCHSTART) + __SEARCHSTART.length, cell.innerHTML.indexOf(__SEARCHEND)); | |||
let land = teamParams.substring(teamParams.indexOf(__SEARCHLIGA) + __SEARCHLIGA.length); | |||
if (land.charAt(1) == ' ') { // Land z.B. hinter "2. Liga A " statt "1. Liga " | |||
land = land.substr(2); | |||
} | |||
const __TEAM = teamParams.substring(0, teamParams.indexOf(__SEARCHMIDDLE)); | |||
const __LIGA = teamParams.substring(teamParams.indexOf(__SEARCHMIDDLE) + __SEARCHMIDDLE.length, | |||
teamParams.length - land.length - 1); | |||
const __RET = { | |||
'Team' : __TEAM, | |||
'Liga' : __LIGA, | |||
'Land' : land | |||
}; | |||
return __RET; | |||
} | } | ||
| Zeile 1.099: | Zeile 1.355: | ||
function procHaupt() { | function procHaupt() { | ||
const __TTAGS = document.getElementsByTagName("table"); | const __TTAGS = document.getElementsByTagName("table"); | ||
const __TEAMPARAMS = getTeamParamsFromCell(__TTAGS[1].rows[0].cells[1]); // Link mit Team, Liga, Land... | |||
buildOptions(__OPTCONFIG, __OPTSET, { | |||
'teamParams' : __TEAMPARAMS, | |||
'hideMenu' : true | |||
}); | |||
const __NEXTZAT = getZATNrFromCell(__TTAGS[0].rows[2].cells[0]); // "Der naechste ZAT ist ZAT xx und ..." | const __NEXTZAT = getZATNrFromCell(__TTAGS[0].rows[2].cells[0]); // "Der naechste ZAT ist ZAT xx und ..." | ||
| Zeile 1.114: | Zeile 1.374: | ||
// Verarbeitet Ansicht "Teamuebersicht" | // Verarbeitet Ansicht "Teamuebersicht" | ||
function procTeamuebersicht() { | function procTeamuebersicht() { | ||
const __ROWOFFSETUPPER = 1; // Header-Zeile | |||
const __ROWOFFSETLOWER = 1; // Ziehen-Button | |||
const __COLUMNINDEX = { | |||
'Age' : 0, | |||
'Geb' : 1, | |||
'Flg' : 2, | |||
'Land' : 3, | |||
'U' : 4, | |||
'Skill' : 5, | |||
'Tal' : 6, | |||
'Akt' : 7, | |||
'Auf' : 8, | |||
'Zus' : 9 | |||
}; | |||
buildOptions(__OPTCONFIG, __OPTSET); | |||
const __TTAGS = document.getElementsByTagName("table"); | |||
const __TABLE = __TTAGS[1]; | |||
const __ROWS = __TABLE.rows; | |||
const __BIRTHDAYS = []; | |||
for (let i = __ROWOFFSETUPPER; i < __ROWS.length - __ROWOFFSETLOWER; i++) { | |||
__BIRTHDAYS[i - __ROWOFFSETUPPER] = getGebFromHTML(__ROWS[i].cells, __COLUMNINDEX.Geb); | |||
} | |||
setOpt(__OPTSET.birthdays, __BIRTHDAYS, false); | |||
// Format der Trennlinie zwischen den Monaten... | |||
const __BORDERSTRING = __OPTSET.sepStyle.Value + ' ' + __OPTSET.sepColor.Value + ' ' + __OPTSET.sepWidth.Value; | |||
separateGroups(__ROWS, __BORDERSTRING, __COLUMNINDEX.Age, __ROWOFFSETUPPER, __ROWOFFSETLOWER, -1, 0); | |||
} | } | ||
// Verarbeitet Ansicht "Spielereinzelwerte" | // Verarbeitet Ansicht "Spielereinzelwerte" | ||
function procSpielereinzelwerte() { | function procSpielereinzelwerte() { | ||
const __ROWOFFSETUPPER = 1; // Header-Zeile | |||
const __ROWOFFSETLOWER = 0; | |||
const __COLUMNINDEX = { | |||
'Flg' : 0, | |||
'Land' : 1, | |||
'U' : 2, | |||
'Age' : 3, | |||
'Einz' : 4, // ab hier die Einzelskills | |||
'SCH' : 4, | |||
'ABS' : 4, // TOR | |||
'BAK' : 5, | |||
'STS' : 5, // TOR | |||
'KOB' : 6, | |||
'FAN' : 6, // TOR | |||
'ZWK' : 7, | |||
'STB' : 7, // TOR | |||
'DEC' : 8, | |||
'SPL' : 8, // TOR | |||
'GES' : 9, | |||
'REF' : 9, // TOR | |||
'FUQ' : 10, | |||
'ERF' : 11, | |||
'AGG' : 12, | |||
'PAS' : 13, | |||
'AUS' : 14, | |||
'UEB' : 15, | |||
'WID' : 16, | |||
'SEL' : 17, | |||
'DIS' : 18, | |||
'ZUV' : 19, | |||
'EIN' : 20, | |||
'Zus' : 21 // Zusaetze hinter den Einzelskills | |||
}; | |||
const __TTAGS = document.getElementsByTagName("table"); | |||
const __TABLE = __TTAGS[1]; | |||
const __ROWS = __TABLE.rows; | |||
const __HEADERS = __ROWS[0]; | |||
buildOptions(__OPTCONFIG, __OPTSET); | |||
const __TITLECOLOR = getColor("LEI"); // "#FFFFFF" | |||
const __COLMAN = new ColumnManager(__OPTSET); | |||
__COLMAN.addTitles(__HEADERS, __TITLECOLOR); | |||
const __PLAYERS = init(__ROWS, __OPTSET, __COLUMNINDEX, __ROWOFFSETUPPER, __ROWOFFSETLOWER); | |||
for (let i = 0; i < __PLAYERS.length; i++) { | |||
__COLMAN.addValues(__PLAYERS[i], __ROWS[i + __ROWOFFSETUPPER], __TITLECOLOR); | |||
} | |||
// Format der Trennlinie zwischen den Monaten... | |||
const __BORDERSTRING = __OPTSET.sepStyle.Value + ' ' + __OPTSET.sepColor.Value + ' ' + __OPTSET.sepWidth.Value; | |||
separateGroups(__ROWS, __BORDERSTRING, __COLUMNINDEX.Age, __ROWOFFSETUPPER, __ROWOFFSETLOWER, -1, 0); | |||
} | } | ||
| Zeile 1.143: | Zeile 1.477: | ||
// Verzweige in unterschiedliche Verarbeitungen je nach Wert von page: | // Verzweige in unterschiedliche Verarbeitungen je nach Wert von page: | ||
switch (getPageIdFromURL(window.location.href)) { | switch (getPageIdFromURL(window.location.href)) { | ||
case 0: procHaupt(); break; | |||
case 1: procTeamuebersicht(); break; | |||
case 2: procSpielereinzelwerte(); break; | |||
default: break; | |||
} | } | ||
Version vom 12. September 2016, 15:34 Uhr
| OS2.jugendV4 | |||||||
| Dateiname | os2.jugendV4.user.js | ||||||
| Version | 0.41 | ||||||
| Autor | Andreas Eckes, Strindheim BK Sven Loges (SLC), Choromonets Odessa | ||||||
| Beschreibung | Jugendteam-Script fuer Online Soccer 2.0 | ||||||
| Webseiten |
| ||||||
| Funktionalität | Trennstriche zwischen den Jahrgängen Aktueller Skill, Opti und MW Prognose von Opti und MW für Ende Jahrgang 18 Optionen und Menu Neue Marktwertformel Automatische Ermittlung des ZATs Hidden-Optionen und Datenspeicher Geburtstage und dezimales Alter | ||||||
| Letzte Änderung | 12.09.2016 | ||||||
// ==UserScript==
// @name OS2.jugendV4
// @namespace http://os.ongapo.com/
// @version 0.41
// @copyright 2013+
// @author Andreas Eckes (Strindheim BK)
// @author Sven Loges (SLC)
// @description Jugendteam-Script fuer Online Soccer 2.0
// @include http://os.ongapo.com/haupt.php
// @include http://os.ongapo.com/haupt.php?changetosecond=*
// @include http://os.ongapo.com/ju.php
// @include http://os.ongapo.com/ju.php?page=*
// @include http://www.os.ongapo.com/haupt.php
// @include http://www.os.ongapo.com/haupt.php?changetosecond=*
// @include http://www.os.ongapo.com/ju.php
// @include http://www.os.ongapo.com/ju.php?page=*
// @include http://online-soccer.eu/haupt.php
// @include http://online-soccer.eu/haupt.php?changetosecond=*
// @include http://online-soccer.eu/ju.php
// @include http://online-soccer.eu/ju.php?page=*
// @include http://www.online-soccer.eu/haupt.php
// @include http://www.online-soccer.eu/haupt.php?changetosecond=*
// @include http://www.online-soccer.eu/ju.php
// @include http://www.online-soccer.eu/ju.php?page=*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @grant GM_registerMenuCommand
// ==/UserScript==
// ECMAScript 6: Erlaubt 'const', 'let', ...
/* jshint esnext: true */
/* jshint moz: true */
// ==================== Konfigurations-Abschnitt fuer Optionen ====================
// Options-Typen
const __OPTTYPES = {
'MC' : "multiple choice",
'SW' : "switch",
'TF' : "true/false",
'SD' : "simple data",
'SI' : "simple option"
};
// Moegliche Optionen (hier die Standardwerte editieren oder ueber das Benutzermenu setzen):
const __OPTCONFIG = {
'zeigeGeb' : { // Spaltenauswahl fuer Geburtstage (true = anzeigen, false = nicht anzeigen)
'Name' : "showBirthday",
'Type' : __OPTTYPES.SW,
'Default' : false,
'Action' : switchShowBirthday,
'Label' : "Geb. ein",
'Hotkey' : 'G',
'AltLabel' : "Geb. aus",
'AltHotkey' : 'G'
},
'zeigeAlter' : { // Spaltenauswahl fuer dezimales Alter (true = anzeigen, false = nicht anzeigen)
'Name' : "showAge",
'Type' : __OPTTYPES.SW,
'Default' : true,
'Action' : switchShowAge,
'Label' : "Alter ein",
'Hotkey' : 'A',
'AltLabel' : "Alter aus",
'AltHotkey' : 'A'
},
'zeigePosition' : { // Position anzeigen
'Name' : "showPos",
'Type' : __OPTTYPES.SW,
'Default' : false,
'Action' : switchShowPos,
'Label' : "Position ein",
'Hotkey' : 'P',
'AltLabel' : "Position aus",
'AltHotkey' : 'P'
},
'zeigeSkill' : { // Spaltenauswahl fuer die aktuellen Werte (true = anzeigen, false = nicht anzeigen)
'Name' : "showSkill",
'Type' : __OPTTYPES.SW,
'Default' : true,
'Action' : switchShowSkill,
'Label' : "Skill ein",
'Hotkey' : 'S',
'AltLabel' : "Skill aus",
'AltHotkey' : 'S'
},
'anzahlOpti' : { // Gibt die Anzahl der Opti-Spalten an / 1: nur bester Opti, 2: die beiden besten, ..., 6: Alle inklusive TOR
// Bei Torhuetern wird immer nur der TOR-Opti angezeigt / Werte < 1 oder > 6 schalten die Anzeige aus
'Name' : "anzOpti",
'Type' : __OPTTYPES.MC,
'Choice' : [ 1, 2, 3, 4, 5, 6, 0 ],
'Action' : setNextAnzOpti,
'Label' : "Opti: beste $",
'Hotkey' : 'O'
},
'anzahlMW' : { // Gibt die Anzahl der MW-Spalten an / 1: nur hoechsten MW, 2: die beiden hoechsten, ..., 6: Alle inklusive TOR
// Bei Torhuetern wird immer nur der TOR-MW angezeigt / Werte < 1 oder > 6 schalten die Anzeige aus
'Name' : "anzMW",
'Type' : __OPTTYPES.MC,
'Choice' : [ 1, 2, 3, 4, 5, 6, 0 ],
'Action' : setNextAnzMW,
'Label' : "MW: beste $",
'Hotkey' : 'M'
},
'zeigeSkillEnde' : { // Spaltenauswahl fuer die Werte mit Ende 18 (true = anzeigen, false = nicht anzeigen)
'Name' : "showSkillEnde",
'Type' : __OPTTYPES.SW,
'Default' : true,
'Action' : switchShowSkillEnde,
'Label' : "Skill Ende ein",
'Hotkey' : 'i',
'AltLabel' : "Skill Ende aus",
'AltHotkey' : 'i'
},
'anzahlOptiEnde' : { // Spaltenauswahl fuer die Werte mit Ende 18:
// Gibt die Anzahl der Opti-Spalten an / 1: nur bester Opti, 2: die beiden besten, ..., 6: Alle inklusive TOR
// Bei Torhuetern wird immer nur der TOR-Opti angezeigt / Werte < 1 oder > 6 schalten die Anzeige aus
'Name' : "anzOptiEnde",
'Type' : __OPTTYPES.MC,
'Choice' : [ 1, 2, 3, 4, 5, 6, 0 ],
'Action' : setNextAnzOptiEnde,
'Label' : "Opti Ende: beste $",
'Hotkey' : 't'
},
'anzahlMWEnde' : { // Spaltenauswahl fuer die Werte mit Ende 18:
// Gibt die Anzahl der MW-Spalten an / 1: nur hoechsten MW, 2: die beiden hoechsten, ..., 6: Alle inklusive TOR
// Bei Torhuetern wird immer nur der TOR-MW angezeigt / Werte < 1 oder > 6 schalten die Anzeige aus
'Name' : "anzMWEnde",
'Type' : __OPTTYPES.MC,
'Choice' : [ 1, 2, 3, 4, 5, 6, 0 ],
'Action' : setNextAnzMWEnde,
'Label' : "MW Ende: beste $",
'Hotkey' : 'W'
},
'kennzeichenEnde' : { // Markierung fuer Ende 18
'Name' : "charEnde",
'Type' : __OPTTYPES.MC,
'Choice' : [ " \u03A9", " 18" ],
'Action' : setNextCharEnde,
'Label' : "Ende: $",
'Hotkey' : 'E'
},
'sepStyle' : { // Stil der Trennlinie
'Name' : "sepStyle",
'Type' : __OPTTYPES.MC,
'Choice' : [ "solid", "hidden", "dotted", "dashed", "double", "groove", "ridge",
"inset", "outset", "none" ],
'Action' : setNextSepStyle,
'Label' : "Stil: $",
'Hotkey' : 'l'
},
'sepColor' : { // Farbe der Trennlinie
'Name' : "sepColor",
'Type' : __OPTTYPES.MC,
'Choice' : [ "white", "yellow", "black", "blue", "cyan", "gold", "grey", "green",
"lime", "magenta", "maroon", "navy", "olive", "orange", "purple",
"red", "teal", "transparent" ],
'Action' : setNextSepColor,
'Label' : "Farbe: $",
'Hotkey' : 'F'
},
'sepWidth' : { // Dicke der Trennlinie
'Name' : "sepWidth",
'Type' : __OPTTYPES.MC,
'Choice' : [ "thin", "medium", "thick" ],
'Action' : setNextSepWidth,
'Label' : "Dicke: $",
'Hotkey' : 'D'
},
'saison' : { // Laufende Saison
'Name' : "saison",
'Type' : __OPTTYPES.MC,
'Choice' : [ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ],
'Action' : setNextSaison,
'Label' : "Saison: $",
'Hotkey' : 'a'
},
'aktuellerZat' : { // Laufender ZAT
'Name' : "currZAT",
'Type' : __OPTTYPES.MC,
'Choice' : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
70, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71 ],
'Action' : setNextZAT,
'Label' : "ZAT: $",
'Hotkey' : 'Z'
},
'birthdays' : { // Datenspeicher fuer Geburtstage der Jugendspieler
'Name' : "birthdays",
'Type' : __OPTTYPES.SD,
'Default' : [],
'Action' : undefined,
'Hidden' : true,
'Serial' : true
},
'team' : { // Datenspeicher fuer Daten des Erst- bzw. Zweitteams
'Name' : "team",
'Type' : __OPTTYPES.SD,
'Default' : { 'Team' : undefined, 'Liga' : undefined, 'Land' : undefined },
'Action' : undefined,
'Hidden' : true,
'Serial' : true
},
'reset' : { // Optionen auf die "Werkseinstellungen" zuruecksetzen
'Name' : "reset",
'Type' : __OPTTYPES.SI,
'Action' : resetOptions,
'Label' : "Standard-Optionen",
'Hotkey' : 'r',
'AltLabel' : ""
}
};
// ==================== Invarianter Abschnitt fuer Optionen ====================
// Initialisiert die gesetzten Optionen
// optConfig: Konfiguration der Optionen
// optSet: Platz für die gesetzten Optionen
// return Gefuelltes Objekt mit den gesetzten Optionen
function initOptions(optConfig, optSet = undefined) {
var value;
if (optSet === undefined) {
optSet = { };
}
for (let opt in optConfig) {
const __CONFIG = optConfig[opt];
switch (__CONFIG.Type) {
case __OPTTYPES.MC : value = __CONFIG.Choice[0];
break;
case __OPTTYPES.SW : value = __CONFIG.Default;
break;
case __OPTTYPES.TF : value = __CONFIG.Default;
if (__CONFIG.AltAction === undefined) {
__CONFIG.AltAction = __CONFIG.Action;
}
break;
case __OPTTYPES.SD : value = __CONFIG.Default;
__CONFIG.Serial = true;
break;
case __OPTTYPES.SI : value = undefined;
break;
default : break;
}
if (__CONFIG.Serial) {
__CONFIG.Hidden = true;
}
optSet[opt] = {
'Config' : __CONFIG,
'Value' : value
};
}
return optSet;
}
// Setzt eine Option dauerhaft und laedt die Seite neu
// name: Name der Option als Speicherort
// value: Zu setzender Wert
// reload: Seite mit neuem Wert neu laden
// return Gesetzter Wert
function setOption(name, value, reload = true, serial = false) {
if (serial) {
serialize(name, value);
} else {
GM_setValue(name, value);
}
GM_setValue(name, value);
if (reload) {
window.location.reload();
}
return value;
}
// Setzt den naechsten Wert aus einer Array-Liste als Option
// arr: Array-Liste mit den moeglichen Optionen
// name: Name der Option als Speicherort
// value: Zu setzender Wert
// reload: Seite mit neuem Wert neu laden
// return Gesetzter Wert
function setNextOption(arr, name, value, reload = true, serial = false) {
const __POS = arr.indexOf(value) + 1;
return setOption(name, arr[(__POS < arr.length) ? __POS : 0], reload, serial);
}
// Setzt eine Option auf einen vorgegebenen Wert
// Fuer kontrollierte Auswahl des Values siehe setNextOpt()
// opt: Config und vorheriger Value der Option
// value: (Bei allen Typen) zu setzender Wert
// reload: Seite mit neuem Wert neu laden
function setOpt(opt, value, reload = false) {
opt.Value = setOption(opt.Config.Name, value, reload, opt.Config.Serial);
}
// Setzt die naechste moegliche Option
// opt: Config und Value der Option
// value: Bei __OPTTYPES.TF zu setzender Wert
// reload: Seite mit neuem Wert neu laden
function setNextOpt(opt, value = undefined, reload = true) {
const __CONFIG = opt.Config;
switch (__CONFIG.Type) {
case __OPTTYPES.MC : opt.Value = setNextOption(__CONFIG.Choice, __CONFIG.Name, opt.Value, reload, __CONFIG.Serial);
break;
case __OPTTYPES.SW : opt.Value = setOption(__CONFIG.Name, ! opt.Value, reload, __CONFIG.Serial);
break;
case __OPTTYPES.TF : opt.Value = setOption(__CONFIG.Name, (value !== undefined) ? value : ! opt.Value, reload, __CONFIG.Serial);
break;
case __OPTTYPES.SD : opt.Value = setOption(__CONFIG.Name, (value !== undefined) ? value : opt.Value, reload, __CONFIG.Serial);
break;
case __OPTTYPES.SI : break;
default : break;
}
}
// Zeigt den Eintrag im Menu einer Option
// opt: Derzeitiger Wert der Option
// menuOn: Text zum Setzen im Menu
// funOn: Funktion zum Setzen
// keyOn: Hotkey zum Setzen im Menu
// menuOff: Text zum Ausschalten im Menu
// funOff: Funktion zum Ausschalten
// keyOff: Hotkey zum Ausschalten im Menu
function registerMenuOption(opt, menuOn, funOn, keyOn, menuOff, funOff, keyOff) {
const __ON = (opt ? '*' : "");
const __OFF = (opt ? "" : '*');
console.log("OPTION " + __ON + menuOn + __ON + " / " + __OFF + menuOff + __OFF);
if (opt) {
GM_registerMenuCommand(menuOff, funOff, keyOff);
} else {
GM_registerMenuCommand(menuOn, funOn, keyOn);
}
}
// Zeigt den Eintrag im Menu einer Option mit Wahl des naechsten Wertes
// opt: Derzeitiger Wert der Option
// arr: Array-Liste mit den moeglichen Optionen
// menu: Text zum Setzen im Menu ($ wird durch gesetzten Wert ersetzt)
// fun: Funktion zum Setzen des naechsten Wertes
// key: Hotkey zum Setzen des naechsten Wertes im Menu
function registerNextMenuOption(opt, arr, menu, fun, key) {
const __MENU = menu.replace('$', opt);
let options = "OPTION " + __MENU;
for (let value of arr) {
if (value === opt) {
options += " / *" + value + '*';
} else {
options += " / " + value;
}
}
console.log(options);
GM_registerMenuCommand(__MENU, fun, key);
}
// Zeigt den Eintrag im Menu einer Option, falls nicht hidden
// opt: Derzeitiger Wert der Option
// menu: Text zum Setzen im Menu ($ wird durch gesetzten Wert ersetzt)
// fun: Funktion zum Setzen des naechsten Wertes
// key: Hotkey zum Setzen des naechsten Wertes im Menu
// hidden: Angabe, ob Menupunkt nicht sichtbar sein soll (default: sichtbar)
// serial: Serialization fuer komplexe Daten
function registerDataOption(opt, menu, fun, key, hidden = false, serial = true) {
const __VALUE = ((serial && (opt !== undefined)) ? uneval(opt) : opt);
const __MENU = ((menu !== undefined) ? menu.replace('$', __VALUE) : "");
const __OPTIONS = (hidden ? "HIDDEN " : "") + "OPTION " + __MENU +
((__VALUE !== undefined) ? " / *" + __VALUE + '*' : "");
console.log(__OPTIONS);
if (! hidden) {
GM_registerMenuCommand(__MENU, fun, key);
}
}
// Zeigt den Eintrag im Menu einer Option
// opt: Config und Value der Option
function registerOption(opt) {
const __CONFIG = opt.Config;
if (! __CONFIG.Hidden) {
switch (__CONFIG.Type) {
case __OPTTYPES.MC : registerNextMenuOption(opt.Value, __CONFIG.Choice,
__CONFIG.Label, __CONFIG.Action, __CONFIG.Hotkey);
break;
case __OPTTYPES.SW : registerMenuOption(opt.Value, __CONFIG.Label, __CONFIG.Action, __CONFIG.Hotkey,
__CONFIG.AltLabel, __CONFIG.Action, __CONFIG.AltHotkey);
break;
case __OPTTYPES.TF : registerMenuOption(opt.Value, __CONFIG.Label, __CONFIG.Action, __CONFIG.Hotkey,
__CONFIG.AltLabel, __CONFIG.AltAction, __CONFIG.AltHotkey);
break;
case __OPTTYPES.SD : registerDataOption(opt.Value, __CONFIG.Label, __CONFIG.Action, __CONFIG.Hotkey,
__CONFIG.Hidden, __CONFIG.Serial);
break;
case __OPTTYPES.SI : registerDataOption(opt.Value, __CONFIG.Label, __CONFIG.Action, __CONFIG.Hotkey,
__CONFIG.Hidden, __CONFIG.Serial);
break;
default : break;
}
} else {
// Nur Anzeige im Log...
registerDataOption(opt.Value, __CONFIG.Name, __CONFIG.Action, __CONFIG.Hotkey, __CONFIG.Hidden, __CONFIG.Serial);
}
}
// Baut das Benutzermenu auf
// optSet: Gesetzte Optionen
function buildMenu(optSet) {
console.log("buildMenu()");
for (let opt in optSet) {
registerOption(optSet[opt]);
}
}
// Laedt die permament (ueber Menu) gesetzten Optionen
// optSet: Gesetzte Optionen
function loadOptions(optSet) {
for (let opt in optSet) {
const __OPT = optSet[opt];
if (__OPT.Config.Serial) {
__OPT.Value = deserialize(__OPT.Config.Name, __OPT.Value);
} else {
__OPT.Value = GM_getValue(__OPT.Config.Name, __OPT.Value);
}
}
}
// ==================== Spezialisierter Abschnitt fuer Optionen ====================
// Gesetzte Optionen (wird von initOptions() angelegt und von loadOptions() gefuellt):
const __OPTSET = { };
// Setzt die Optionen auf die "Werkseinstellungen" des Skripts
function resetOptions() {
const __CURRZAT = __OPTSET.aktuellerZat.Value; // Aktuellen ZAT beibehalten (sichern)
for (let opt in __OPTSET) {
GM_deleteValue(__OPTSET[opt].Config.Name);
}
setOpt(__OPTSET.aktuellerZat, __CURRZAT, false); // Aktuellen ZAT wiederherstellen
window.location.reload();
}
// Teamparameter fuer getrennte Speicherung der Optionen fuer Erst- und Zweitteam...
const __MYTEAM = { 'Team' : undefined, 'Liga' : undefined, 'Land' : undefined };
// Behandelt die Optionen und laedt das Benutzermenu
// optConfig: Konfiguration der Optionen
// optSet: Platz für die gesetzten Optionen
// optParams: Eventuell notwendige Parameter zur Initialisierung
// 'teamParams': Getrennte "ligaSize"-Option wird genutzt, hier: __MYTEAM mit 'Land' des Erst- bzw. Zweitteams
// 'menuAnchor': Startpunkt fuer das Optionsmenu auf der Seite
// return Gefuelltes Objekt mit den gesetzten Optionen
function buildOptions(optConfig, optSet = undefined, optParams = { 'hideMenu' : false }) {
const __TEAMPARAMS = optParams.teamParams; // Ermittelte Parameter
let saveTeam = false;
optSet = initOptions(optConfig, optSet);
if (__TEAMPARAMS !== undefined) {
__MYTEAM.Team = __TEAMPARAMS.Team;
__MYTEAM.Liga = __TEAMPARAMS.Liga;
__MYTEAM.Land = __TEAMPARAMS.Land;
console.log("Ermittelt: " + uneval(__MYTEAM));
saveTeam = true;
} else {
const __TEAM = deserialize(optSet.team.Config.Name); // Gespeicherte Parameter
if ((__TEAM !== undefined) && (__TEAM.Land !== undefined)) {
__MYTEAM.Team = __TEAM.Team;
__MYTEAM.Liga = __TEAM.Liga;
__MYTEAM.Land = __TEAM.Land;
console.log("Gespeichert: " + uneval(__MYTEAM));
} else {
console.log("Unbekannt: " + uneval(__MYTEAM));
}
}
if (__MYTEAM.Land !== undefined) {
// Prefix fuer die Option "birthdays"
optSet.birthdays.Config.Name = __MYTEAM.Land + optSet.birthdays.Config.Name;
}
loadOptions(optSet);
if (saveTeam) {
// ... und abspeichern...
setOpt(optSet.team, __MYTEAM, false);
}
if (! optParams.hideMenu) {
buildMenu(optSet);
}
return optSet;
}
// ==================== Abschnitt mit Reaktionen auf Optionen ====================
// Wechselt die Anzeige des Geburtstags zwischen an und aus
function switchShowBirthday() {
setNextOpt(__OPTSET.zeigeGeb);
}
// Wechselt die Anzeige des dezimalen Alters zwischen an und aus
function switchShowAge() {
setNextOpt(__OPTSET.zeigeAlter);
}
// Wechselt die Anzeige der Position zwischen an und aus
function switchShowPos() {
setNextOpt(__OPTSET.zeigePosition);
}
// Wechselt die Anzeige des Skills zwischen an und aus
function switchShowSkill() {
setNextOpt(__OPTSET.zeigeSkill);
}
// Setzt die naechste moegliche Anzahl Opti-Spalten als Option
function setNextAnzOpti() {
setNextOpt(__OPTSET.anzahlOpti);
}
// Setzt die naechste moegliche Anzahl MW-Spalten als Option
function setNextAnzMW() {
setNextOpt(__OPTSET.anzahlMW);
}
// Wechselt die Anzeige des Skills Ende 18 zwischen an und aus
function switchShowSkillEnde() {
setNextOpt(__OPTSET.zeigeSkillEnde);
}
// Setzt die naechste moegliche Anzahl Opti-Spalten Ende 18 als Option
function setNextAnzOptiEnde() {
setNextOpt(__OPTSET.anzahlOptiEnde);
}
// Setzt die naechste moegliche Anzahl MW-Spalten Ende 18 als Option
function setNextAnzMWEnde() {
setNextOpt(__OPTSET.anzahlMWEnde);
}
// Setzt das naechste moegliche Kennzeichen fuer Ende 18 als Option
function setNextCharEnde() {
setNextOpt(__OPTSET.kennzeichenEnde);
}
// Setzt den naechsten Stil der Trennlinie als Option
function setNextSepStyle() {
setNextOpt(__OPTSET.sepStyle);
}
// Setzt die naechste Farbe der Trennlinie als Option
function setNextSepColor() {
setNextOpt(__OPTSET.sepColor);
}
// Setzt die naechste Dicke der Trennlinie als Option
function setNextSepWidth() {
setNextOpt(__OPTSET.sepWidth);
}
// Setzt die naechste moegliche Saison als Option
function setNextSaison() {
setNextOpt(__OPTSET.saison);
}
// Setzt den naechsten ZAT als Option
function setNextZAT() {
setNextOpt(__OPTSET.aktuellerZat);
}
// ==================== Abschnitt fuer diverse Utilities ====================
// Speichert einen beliebiegen Wert bzw. Code unter einem Namen ab
// name: GM_serValue-Name, unter dem die Daten gespeichert werden
// value: Beliebiger Wert oder Code (Vorsicht! Mit Augenmass benutzen!)
function serialize(name, value) {
GM_setValue(name, uneval(value));
}
// Holt einen beliebiegen Wert bzw. Code unter einem Namen zurueck
// name: GM_serValue-Name, unter dem die Daten gespeichert werden
// defValue: Default-Wert fuer den Fall, dass nichts gespeichert ist
function deserialize(name, defValue = "({})") {
/* jshint evil: true */
return eval(GM_getValue(name, defValue));
}
// ==================== Ende Abschnitt fuer Optionen ====================
// ==================== Abschnitt genereller Code zur Anzeige der Jugend ====================
// Zeitpunktangaben
const __TIME = {
'cre' : 0, // Jugendspieler angelegt (mit 12 Jahren)
'beg' : 1, // Jugendspieler darf trainieren (wird 13 Jahre alt)
'now' : 2, // Aktueller ZAT
'end' : 3 // Jugendspieler wird Ende 18 gezogen (Geb. - 1 bzw. ZAT 71 für '?')
};
// Funktionen ***************************************************************************
// Erschafft die Spieler-Objekte und fuellt sie mit Werten
function init(playerRows, optSet, colIdx, offsetUpper = 1, offsetLower = 0) {
const __SAISON = optSet.saison.Value;
const __CURRZAT = optSet.aktuellerZat.Value;
const __BIRTHDAYS = ((optSet.birthdays.Value !== undefined) ? optSet.birthdays.Value : []);
const __PLAYERS = [];
for (let i = offsetUpper, j = 0; i < playerRows.length - offsetLower; i++, j++) {
const __CELLS = playerRows[i].cells;
const __AGE = getAgeFromHTML(__CELLS, colIdx.Age);
const __SKILLS = getSkillsFromHTML(__CELLS, colIdx);
const __ISGOALIE = isGoalieFromHTML(__CELLS, colIdx.Age);
const __NEWPLAYER = new PlayerRecord(__AGE, __SKILLS, __ISGOALIE);
__NEWPLAYER.initPlayer(__SAISON, __CURRZAT, __BIRTHDAYS[j]);
__PLAYERS[j] = __NEWPLAYER;
}
return __PLAYERS;
}
// Trennt die Gruppen (z.B. Jahrgaenge) mit Linien
function separateGroups(rows, borderString, colIdxSort = 0, offsetUpper = 1, offsetLower = 0, offsetLeft = -1, offsetRight = 0) {
if (offsetLeft < 0) {
offsetLeft = colIdxSort; // ab Sortierspalte
}
for (let i = offsetUpper; i < rows.length - offsetLower - 1; i++) {
if (rows[i].cells[colIdxSort].textContent != rows[i + 1].cells[colIdxSort].textContent) {
for (let j = offsetLeft; j < rows[i].cells.length - offsetRight; j++) {
rows[i].cells[j].style.borderBottom = borderString;
}
}
}
}
// Klasse ColumnManager *****************************************************************
function ColumnManager(optSet) {
this.geb = optSet.zeigeGeb.Value;
this.alter = optSet.zeigeAlter.Value;
this.skill = optSet.zeigeSkill.Value;
this.pos = optSet.zeigePosition.Value;
this.opti = ((optSet.anzahlOpti.Value >= 1) && (optSet.anzahlOpti.Value <= 6));
this.mw = ((optSet.anzahlMW.Value >= 1) && (optSet.anzahlMW.Value <= 6));
this.anzOpti = optSet.anzahlOpti.Value;
this.anzMw = optSet.anzahlMW.Value;
this.skillE = optSet.zeigeSkillEnde.Value;
this.optiE = ((optSet.anzahlOptiEnde.Value >= 1) && (optSet.anzahlOptiEnde.Value <= 6));
this.mwE = ((optSet.anzahlMWEnde.Value >= 1) && (optSet.anzahlMWEnde.Value <= 6));
this.anzOptiE = optSet.anzahlOptiEnde.Value;
this.anzMwE = optSet.anzahlMWEnde.Value;
this.kennzE = optSet.kennzeichenEnde.Value;
this.toString = function() {
let result = "Skillschnitt\t\t" + this.skill + "\n";
result += "Beste Position\t" + this.pos + "\n";
result += "Optis\t\t\t" + this.opti + " (" + this.anzOpti + ")\n";
result += "Marktwerte\t\t" + this.mw + " (" + this.anzMw + ")\n";
result += "Skillschnitt Ende\t" + this.skillE + "\n";
result += "Optis Ende\t\t" + this.optiE + " (" + this.anzOptiE + ")\n";
result += "Marktwerte Ende\t" + this.mwE + " (" + this.anzMwE + ")\n";
return result;
};
this.addCell = function(tableRow) {
tableRow.insertCell(-1);
return tableRow.cells.length - 1;
};
this.addAndFillCell = function(tableRow, value, color, digits = 2) {
if (isFinite(value) && (value !== true) && (value !== false)) {
// Zahl einfuegen
if (value < 1000) {
// Mit Nachkommastellen darstellen
tableRow.cells[this.addCell(tableRow)].textContent = parseFloat(value).toFixed(digits);
} else {
// Mit Tausenderpunkten darstellen
tableRow.cells[this.addCell(tableRow)].textContent = getNumberString(value.toString());
}
} else {
// String einfuegen
tableRow.cells[this.addCell(tableRow)].textContent = value;
}
tableRow.cells[tableRow.cells.length - 1].style.color = color;
};
this.addTitles = function(headers, titleColor = "#FFFFFF") {
// Spaltentitel zentrieren
headers.align = "center";
// Titel fuer die aktuellen Werte
if (this.geb) {
this.addAndFillCell(headers, "Geb.", titleColor);
}
if (this.alter) {
this.addAndFillCell(headers, "Alter", titleColor);
}
if (this.skill) {
this.addAndFillCell(headers, "Skill", titleColor);
}
if (this.pos) {
this.addAndFillCell(headers, "Pos", titleColor);
}
if (this.opti) {
for (let i = 1; i <= this.anzOpti; i++) {
this.addAndFillCell(headers, "Opti " + i, titleColor);
if (this.mw && (this.anzMw >= i)) {
this.addAndFillCell(headers, "MW " + i, titleColor);
}
}
if (this.mw) {
for (let i = this.anzOpti + 1; i <= this.anzMw; i++) {
// Mehr MW- als Opti-Spalten
this.addAndFillCell(headers, "MW " + i, titleColor);
}
}
} else if (this.mw) {
// Keine Opti-, dafuer MW-Spalten
for (let i = 1; i <= this.anzMw; i++) {
this.addAndFillCell(headers, "MW " + i, titleColor);
}
}
// Titel fuer die Werte mit Ende 18
if (this.skillE) {
this.addAndFillCell(headers, "Skill" + this.kennzE, titleColor);
}
if (this.optiE) {
for (let i = 1; i <= this.anzOptiE; i++) {
this.addAndFillCell(headers, "Opti " + i + this.kennzE, titleColor);
if (this.mwE && (this.anzMwE >= i)) {
this.addAndFillCell(headers, "MW " + i + this.kennzE, titleColor);
}
}
if (this.mwE) {
for (let i = this.anzOptiE + 1; i <= this.anzMwE; i++) {
this.addAndFillCell(headers, "MW " + i + this.kennzE, titleColor);
}
}
} else if (this.mwE) {
for (let i = 1; i <= this.anzMwE; i++) {
this.addAndFillCell(headers, "MW " + i + this.kennzE, titleColor);
}
}
}; // Ende addTitles()
this.addValues = function(player, playerRow, color = "#FFFFFF") {
const __COLOR = (player.isGoalie ? getColor("TOR") : color);
const __POS1COLOR = (player.isGoalie ? getColor("TOR") : getColor(player.getPos(1)));
// Aktuelle Werte
if (this.geb) {
this.addAndFillCell(playerRow, (player.zatGeb < 0) ? '?' : player.zatGeb, __COLOR, 0);
}
if (this.alter) {
this.addAndFillCell(playerRow, player.getAge(), __COLOR, 2);
}
if (this.skill) {
this.addAndFillCell(playerRow, player.getSkill(), __COLOR, 2);
}
if (this.pos) {
this.addAndFillCell(playerRow, player.getPos(1), __POS1COLOR);
}
if (this.opti) {
for (let i = 1; i <= this.anzOpti; i++) {
if (player.isGoalie) {
if (i == 1) {
// TOR-Opti anzeigen
this.addAndFillCell(playerRow, player.getOpti("TOR"), getColor("TOR"), 2);
} else {
// TOR, aber nicht bester Opti -> nur Zelle hinzufuegen
this.addCell(playerRow);
}
} else {
// Feld-Opti anzeigen
this.addAndFillCell(playerRow, player.getOpti(player.getPos(i)), getColor(player.getPos(i)), 2);
}
if (this.mw && (this.anzMw >= i)) {
if (player.isGoalie) {
if (i == 1) {
// TOR-MW anzeigen
this.addAndFillCell(playerRow, player.getMarketValue("TOR"), getColor("TOR"), 0);
} else {
// TOR, aber nicht bester MW -> nur Zelle hinzufuegen
this.addCell(playerRow);
}
} else {
// Feld-MW anzeigen
this.addAndFillCell(playerRow, player.getMarketValue(player.getPos(i)), getColor(player.getPos(i)), 0);
}
}
}
// Verbleibende MW anzeigen
if (this.mw) {
for (let i = this.anzOpti + 1; i <= this.anzMw; i++) {
if (player.isGoalie) {
if (i == 1) {
// TOR-MW anzeigen
this.addAndFillCell(playerRow, player.getMarketValue("TOR"), getColor("TOR"), 0);
} else {
// TOR, aber nicht bester MW -> nur Zelle hinzufuegen
this.addCell(playerRow);
}
} else {
// Feld-MW anzeigen
this.addAndFillCell(playerRow, player.getMarketValue(player.getPos(i)), getColor(player.getPos(i)), 0);
}
}
}
} else if (this.mw) {
// Opti soll nicht angezeigt werden, dafuer aber MW
for (let i = 1; i <= this.anzMw; i++) {
if (player.isGoalie) {
if (i == 1) {
// TOR-MW anzeigen
this.addAndFillCell(playerRow, player.getMarketValue("TOR"), getColor("TOR"), 0);
} else {
// TOR, aber nicht bester MW -> nur Zelle hinzufuegen
this.addCell(playerRow);
}
} else {
// Feld-MW anzeigen
this.addAndFillCell(playerRow, player.getMarketValue(player.getPos(i)), getColor(player.getPos(i)), 0);
}
}
}
// Werte mit Ende 18
if (this.skillE) {
this.addAndFillCell(playerRow, player.getSkill(__TIME.end), __COLOR, 2);
}
if (this.optiE) {
for (let i = 1; i <= this.anzOptiE; i++) {
if (player.isGoalie) {
if (i == 1) {
// TOR-Opti anzeigen
this.addAndFillCell(playerRow, player.getOpti("TOR", __TIME.end), getColor("TOR"), 2);
} else {
// TOR, aber nicht bester Opti -> nur Zelle hinzufuegen
this.addCell(playerRow);
}
} else {
// Feld-Opti anzeigen
this.addAndFillCell(playerRow, player.getOpti(player.getPos(i), __TIME.end), getColor(player.getPos(i)), 2);
}
if (this.mwE && (this.anzMwE >= i)) {
if (player.isGoalie) {
if (i == 1) {
// TOR-MW anzeigen
this.addAndFillCell(playerRow, player.getMarketValue("TOR", __TIME.end), getColor("TOR"), 0);
} else {
// TOR, aber nicht bester MW -> nur Zelle hinzufuegen
this.addCell(playerRow);
}
} else {
// Feld-MW anzeigen
this.addAndFillCell(playerRow, player.getMarketValue(player.getPos(i), __TIME.end), getColor(player.getPos(i)), 0);
}
}
}
// Verbleibende MW anzeigen
if (this.mwE) {
for (let i = this.anzOptiE + 1; i <= this.anzMwE; i++) {
if (player.isGoalie) {
if (i == 1) {
// TOR-MW anzeigen
this.addAndFillCell(playerRow, player.getMarketValue("TOR", __TIME.end), getColor("TOR"), 0);
} else {
// TOR, aber nicht bester MW -> nur Zelle hinzufuegen
this.addCell(playerRow);
}
} else {
// Feld-MW anzeigen
this.addAndFillCell(playerRow, player.getMarketValue(player.getPos(i), __TIME.end), getColor(player.getPos(i)), 0);
}
}
}
} else if (this.mwE) {
// Opti soll nicht angezeigt werden, dafuer aber MW
for (let i = 1; i <= this.anzMwE; i++) {
if (player.isGoalie) {
if (i == 1) {
// TOR-MW anzeigen
this.addAndFillCell(playerRow, player.getMarketValue("TOR", __TIME.end), getColor("TOR"), 0);
} else {
// TOR, aber nicht bester MW -> nur Zelle hinzufuegen
this.addCell(playerRow);
}
} else {
// Feld-MW anzeigen
this.addAndFillCell(playerRow, player.getMarketValue(player.getPos(i), __TIME.end), getColor(player.getPos(i)), 0);
}
}
}
}; // Ende addValues(player, playerRow)
}
// Klasse PlayerRecord ******************************************************************
function PlayerRecord(age, skills, isGoalie) {
// Zu benutzende Marktwertformel
const __MWFORMEL = {
'alt' : 0, // Marktwertformel bis Saison 9 inklusive
'S10' : 1 // Marktwertformel MW5 ab Saison 10
};
this.mwFormel = __MWFORMEL.S10; // Neue Formel, genauer in initPlayer()
this.age = age;
this.skills = skills;
this.isGoalie = isGoalie;
// in this.initPlayer() definiert:
// this.zatGeb: ZAT, an dem der Spieler Geburtstag hat, -1 fuer "noch nicht zugewiesen", also "?"
// this.zatAge: Bisherige erfolgte Trainings-ZATs
// this.positions[][]: Positionstext und Opti; TOR-Index ist 5
// this.skillsEnd[]: Berechnet aus this.skills, this.age und aktuellerZat
this.toString = function() {
let result = "Alter\t\t" + this.age + "\n\n";
result += "Aktuelle Werte\n";
result += "Skillschnitt\t" + this.getSkill().toFixed(2) + "\n";
result += "Optis und Marktwerte";
for (let pos of this.positions) {
result += "\n\t" + pos + " \t";
result += this.getOpti(pos).toFixed(2) + "\t";
result += getNumberString(this.getMarketValue(pos).toString());
}
result += "\n\nWerte mit Ende 18\n";
result += "Skillschnitt\t" + this.getSkill(__TIME.end).toFixed(2) + "\n";
result += "Optis und Marktwerte";
for (let pos of this.positions) {
result += "\n\t" + this.getPos()[i] + " \t";
result += this.getOpti(pos, __TIME.end).toFixed(2) + "\t";
result += getNumberString(this.getMarketValue(pos, __TIME.end).toString());
}
return result;
}; // Ende this.toString()
// Berechnet die Opti-Werte, sortiert das Positionsfeld und berechnet die Einzelskills mit Ende 18
this.initPlayer = function(saison, currZAT, gebZAT) {
this.zatGeb = gebZAT;
this.zatAge = this.getZatAge(currZAT);
this.mwFormel = (saison < 10) ? __MWFORMEL.alt : __MWFORMEL.S10;
this.positions = [];
// ABW
this.positions[0] = [];
this.positions[0][0] = "ABW";
this.positions[0][1] = this.getOpti("ABW");
// DMI
this.positions[1] = [];
this.positions[1][0] = "DMI";
this.positions[1][1] = this.getOpti("DMI");
// MIT
this.positions[2] = [];
this.positions[2][0] = "MIT";
this.positions[2][1] = this.getOpti("MIT");
// OMI
this.positions[3] = [];
this.positions[3][0] = "OMI";
this.positions[3][1] = this.getOpti("OMI");
// STU
this.positions[4] = [];
this.positions[4][0] = "STU";
this.positions[4][1] = this.getOpti("STU");
// TOR
this.positions[5] = [];
this.positions[5][0] = "TOR";
this.positions[5][1] = this.getOpti("TOR");
// Sortieren
sortPositionArray(this.positions);
// Einzelskills mit Ende 18 berechnen
this.skillsEnd = [];
const __ZATMAX = (18 - 12) * 72 - 1;
const __ZATSOFAR = this.zatAge;
const __ZATTILLEND = __ZATMAX - __ZATSOFAR;
for (let i in this.skills) {
const __SKILL = this.skills[i];
if (isTrainableSkill(i)) {
// Auf ganze Zahl runden und parseInt, da das sonst irgendwie als String interpretiert wird
this.skillsEnd[i] = parseInt((__SKILL * (1 + __ZATTILLEND / __ZATSOFAR)).toFixed(0), 10);
} else {
this.skillsEnd[i] = __SKILL;
}
}
}; // Ende this.iniPlayer()
this.getZatAge = function(currZAT) {
if (this.age < 13) {
return 0; // noch nicht trainiert
} else {
let ZATs = (this.age - ((currZAT < this.zatGeb) ? 12 : 13)) * 72; // Basiszeit fuer die Jahre seit Jahrgang 13
if (this.zatGeb < 0) {
return ZATs + currZAT; // Zaehlung begann Anfang der Saison (und der Geburtstag wird erst nach dem Ziehen bestimmt)
} else {
return ZATs + currZAT - this.zatGeb; // Verschiebung relativ zum Geburtstag (von -zatGeb, ..., 0, ..., 71 - zatGeb)
}
}
};
this.getAge = function(when = __TIME.now) {
if (this.mwFormel === __MWFORMEL.alt) {
return (when === __TIME.end) ? 18 : this.age;
} else { // Geburtstage ab Saison 10...
return (when === __TIME.end) ? 18.00 : (13.00 + this.zatAge / 72);
}
};
this.getPos = function(idx) {
const __IDXOFFSET = 1;
return this.positions[idx - __IDXOFFSET][0];
};
this.getSkill = function(when = __TIME.now) {
const __SKILLS = (when === __TIME.end) ? this.skillsEnd : this.skills;
let result = 0;
for (let skill of __SKILLS) {
result += skill;
}
return result / __SKILLS.length;
};
this.getOpti = function(pos, when = __TIME.now) {
const __SKILLS = (when === __TIME.end) ? this.skillsEnd : this.skills;
const __IDXPRISKILLS = getIdxPriSkills(pos);
const __IDXSECSKILLS = getIdxSecSkills(pos);
let sumPriSkills = 0;
let sumSecSkills = 0;
for (let idx of __IDXPRISKILLS) {
sumPriSkills += __SKILLS[idx];
}
for (let idx of __IDXSECSKILLS) {
sumSecSkills += __SKILLS[idx];
}
return (5 * sumPriSkills + sumSecSkills) / 27;
};
this.getMarketValue = function(pos, when = __TIME.now) {
const __AGE = this.getAge(when);
if (this.mwFormel === __MWFORMEL.alt) {
return Math.round(Math.pow((1 + this.getSkill(when)/100) * (1 + this.getOpti(pos, when)/100)* (2 - __AGE/100), 10) * 2); // Alte Formel bis Saison 9
} else { // MW-Formel ab Saison 10...
const __MW5TF = 1.00; // Zwischen 0.97 und 1.03
return Math.round(Math.pow(1 + this.getSkill(when)/100, 5.65) * Math.pow(1 + this.getOpti(pos, when)/100, 8.1) * Math.pow(1 + (100 - __AGE)/49, 10) * __MW5TF);
}
};
}
// Funktionen fuer die HTML-Seite *******************************************************
// Liest das Alter aus
function getAgeFromHTML(cells, colIdxAge) {
return parseInt(cells[colIdxAge].textContent, 10);
}
// Liest das Geburtsdatum aus
function getGebFromHTML(cells, colIdxGeb) {
const __TEXT = ((cells[colIdxGeb] === undefined) ? '?' : cells[colIdxGeb].textContent);
return parseInt((__TEXT === '?') ? -1 : __TEXT, 10);
}
// Liest die Einzelskills aus
function getSkillsFromHTML(cells, colIdx) {
const __RESULT = [];
for (let i = colIdx.Einz; i < colIdx.Zus; i++) {
__RESULT[i - colIdx.Einz] = parseInt(cells[i].textContent, 10);
}
return __RESULT;
}
// Liest aus, ob der Spieler Torwart oder Feldspieler ist
function isGoalieFromHTML(cells, colIdxClass) {
return (cells[colIdxClass].className == "TOR");
}
// Hilfsfunktionen **********************************************************************
// Sortiert das Positionsfeld per BubbleSort
function sortPositionArray(array) {
const __TEMP = [];
let transposed = true;
// TOR soll immer die letzte Position im Feld sein, deshalb - 1
let length = array.length - 1;
while (transposed && (length > 1)) {
transposed = false;
for (let i = 0; i < length - 1; i++) {
// Vergleich Opti-Werte:
if (array[i][1] < array[i + 1][1]) {
// vertauschen
__TEMP[0] = array[i][0];
__TEMP[1] = array[i][1];
array[i][0] = array[i + 1][0];
array[i][1] = array[i + 1][1];
array[i + 1][0] = __TEMP[0];
array[i + 1][1] = __TEMP[1];
transposed = true;
}
}
length--;
}
}
// Fuegt in die uebergebene Zahl Tausender-Trennpunkte ein
// Wandelt einen etwaig vorhandenen Dezimalpunkt in ein Komma um
function getNumberString(numberString) {
if (numberString.lastIndexOf(".") != -1) {
// Zahl enthaelt Dezimalpunkt
const __VORKOMMA = numberString.substring(0, numberString.lastIndexOf("."));
const __NACHKOMMA = numberString.substring(numberString.lastIndexOf(".") + 1, numberString.length);
return getNumberString(__VORKOMMA) + "," + __NACHKOMMA;
} else {
// Kein Dezimalpunkt, fuege Tausender-Trennpunkte ein:
// String umdrehen, nach jedem dritten Zeichen Punkt einfuegen, dann wieder umdrehen:
const __TEMP = reverseString(numberString);
let result = "";
for (let i = 0; i < __TEMP.length; i++) {
if ((i > 0) && (i % 3 === 0)) {
result += ".";
}
result += __TEMP.substr(i, 1);
}
return reverseString(result);
}
}
// Dreht den uebergebenen String um
function reverseString(string) {
let result = "";
for (let i = string.length - 1; i >= 0; i--) {
result += string.substr(i, 1);
}
return result;
}
// Schaut nach, ob der uebergebene Index zu einem trainierbaren Skill gehoert
// Die Indizes gehen von 0 (SCH) bis 16 (EIN)
function isTrainableSkill(idx) {
const __TRAINABLESKILLS = [0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 15];
let result = false;
for (let idxTrainable of __TRAINABLESKILLS) {
if (idx == idxTrainable) {
result = true;
break;
}
}
return result;
}
// Gibt die Indizes der Primaerskills zurueck
function getIdxPriSkills(pos) {
switch (pos) {
case "TOR" : return new Array(2, 3, 4, 5);
case "ABW" : return new Array(2, 3, 4, 15);
case "DMI" : return new Array(1, 4, 9, 11);
case "MIT" : return new Array(1, 3, 9, 11);
case "OMI" : return new Array(1, 5, 9, 11);
case "STU" : return new Array(0, 2, 3, 5);
default : return [];
}
}
// Gibt die Indizes der Sekundaerskills zurueck
function getIdxSecSkills(pos) {
switch (pos) {
case "TOR" : return new Array(0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
case "ABW" : return new Array(0, 1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16);
case "DMI" : return new Array(0, 2, 3, 5, 6, 7, 8, 10, 12, 13, 14, 15, 16);
case "MIT" : return new Array(0, 2, 4, 5, 6, 7, 8, 10, 12, 13, 14, 15, 16);
case "OMI" : return new Array(0, 2, 3, 4, 6, 7, 8, 10, 12, 13, 14, 15, 16);
case "STU" : return new Array(1, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
default : return [];
}
}
// Gibt die zur Position gehoerige Farbe zurueck
function getColor(pos) {
switch (pos) {
case "TOR" : return "#FFFF00";
case "ABW" : return "#00FF00";
case "DMI" : return "#3366FF";
case "MIT" : return "#66FFFF";
case "OMI" : return "#FF66FF";
case "STU" : return "#FF0000";
case "LEI" : return "#FFFFFF";
default : return "";
}
}
// ==================== Ende Abschnitt genereller Code zur Anzeige der Jugend ====================
// ==================== Abschnitt fuer sonstige Parameter ====================
// Verarbeitet die URL der Seite und ermittelt die Nummer der gewuenschten Unterseite
// url: Adresse der Seite
function getPageIdFromURL(url) {
// Variablen zur Identifikation der Seite
const __INDEXS = url.lastIndexOf("page=");
const __HAUPT = url.match(/haupt\.php/); // Ansicht "Haupt" (Managerbuero)
const __JU = url.match(/ju\.php/); // Ansicht "Jugendteam"
let page = -1; // Seitenindex (Rueckgabewert)
// Wert von page (Seitenindex) ermitteln...
// Annahme: Entscheidend ist jeweils das letzte Vorkommnis von "page=" und ggf. von '&'
if (__HAUPT) {
page = 0;
} else if (__JU) {
if (__INDEXS < 0) {
page = 1;
} else if (url.indexOf('&', __INDEXS) < 0) {
// Wert von page setzt sich aus allen Zeichen hinter "page=" zusammen
page = parseInt(url.substring(__INDEXS + 5, url.length), 10);
} else {
// Wert von page setzt sich aus allen Zeichen zwischen "page=" und '&' zusammen
page = parseInt(url.substring(__INDEXS + 5, url.indexOf('&', __INDEXS)), 10);
}
}
return page;
}
// Ermittelt, wie das eigene Team heisst und aus welchem Land bzw. Liga es kommt (zur Unterscheidung von Erst- und Zweitteam)
// cell: Tabellenzelle mit den Parametern zum Team "<b>Willkommen im Managerbüro von TEAM</b><br>LIGA LAND<a href=..."
// return Im Beispiel { 'Team' : "TEAM", 'Liga' : "LIGA", 'Land' : "LAND" },
// z.B. { 'Team' : "Choromonets Odessa", 'Liga' : "1. Liga", 'Land' : "Ukraine" }
function getTeamParamsFromCell(cell) {
const __SEARCHSTART = " von ";
const __SEARCHMIDDLE = "</b><br>";
const __SEARCHLIGA = ". Liga ";
const __SEARCHEND = "<a href=";
let teamParams = cell.innerHTML.substring(cell.innerHTML.indexOf(__SEARCHSTART) + __SEARCHSTART.length, cell.innerHTML.indexOf(__SEARCHEND));
let land = teamParams.substring(teamParams.indexOf(__SEARCHLIGA) + __SEARCHLIGA.length);
if (land.charAt(1) == ' ') { // Land z.B. hinter "2. Liga A " statt "1. Liga "
land = land.substr(2);
}
const __TEAM = teamParams.substring(0, teamParams.indexOf(__SEARCHMIDDLE));
const __LIGA = teamParams.substring(teamParams.indexOf(__SEARCHMIDDLE) + __SEARCHMIDDLE.length,
teamParams.length - land.length - 1);
const __RET = {
'Team' : __TEAM,
'Liga' : __LIGA,
'Land' : land
};
return __RET;
}
// Gibt die laufende Nummer des ZATs im Text einer Zelle zurueck
// cell: Tabellenzelle mit der ZAT-Nummer im Text
// return ZAT-Nummer im Text
function getZATNrFromCell(cell) {
const __TEXT = cell.textContent.split(' ');
let ZATNr = 0;
for (let i = 1; (ZATNr === 0) && (i < __TEXT.length); i++) {
if (__TEXT[i - 1] === "ZAT") {
if (__TEXT[i] !== "ist") {
ZATNr = parseInt(__TEXT[i], 10);
}
}
}
return ZATNr;
}
// ==================== Ende Abschnitt fuer sonstige Parameter ====================
// ==================== Hauptprogramm ====================
// Verarbeitet Ansicht "Haupt" (Managerbuero) zur Ermittlung des aktuellen ZATs
function procHaupt() {
const __TTAGS = document.getElementsByTagName("table");
const __TEAMPARAMS = getTeamParamsFromCell(__TTAGS[1].rows[0].cells[1]); // Link mit Team, Liga, Land...
buildOptions(__OPTCONFIG, __OPTSET, {
'teamParams' : __TEAMPARAMS,
'hideMenu' : true
});
const __NEXTZAT = getZATNrFromCell(__TTAGS[0].rows[2].cells[0]); // "Der naechste ZAT ist ZAT xx und ..."
const __CURRZAT = __NEXTZAT - 1;
if (__CURRZAT >= 0) {
console.log("Aktueller ZAT: " + __CURRZAT);
setOpt(__OPTSET.aktuellerZat, __CURRZAT, false);
}
}
// Verarbeitet Ansicht "Teamuebersicht"
function procTeamuebersicht() {
const __ROWOFFSETUPPER = 1; // Header-Zeile
const __ROWOFFSETLOWER = 1; // Ziehen-Button
const __COLUMNINDEX = {
'Age' : 0,
'Geb' : 1,
'Flg' : 2,
'Land' : 3,
'U' : 4,
'Skill' : 5,
'Tal' : 6,
'Akt' : 7,
'Auf' : 8,
'Zus' : 9
};
buildOptions(__OPTCONFIG, __OPTSET);
const __TTAGS = document.getElementsByTagName("table");
const __TABLE = __TTAGS[1];
const __ROWS = __TABLE.rows;
const __BIRTHDAYS = [];
for (let i = __ROWOFFSETUPPER; i < __ROWS.length - __ROWOFFSETLOWER; i++) {
__BIRTHDAYS[i - __ROWOFFSETUPPER] = getGebFromHTML(__ROWS[i].cells, __COLUMNINDEX.Geb);
}
setOpt(__OPTSET.birthdays, __BIRTHDAYS, false);
// Format der Trennlinie zwischen den Monaten...
const __BORDERSTRING = __OPTSET.sepStyle.Value + ' ' + __OPTSET.sepColor.Value + ' ' + __OPTSET.sepWidth.Value;
separateGroups(__ROWS, __BORDERSTRING, __COLUMNINDEX.Age, __ROWOFFSETUPPER, __ROWOFFSETLOWER, -1, 0);
}
// Verarbeitet Ansicht "Spielereinzelwerte"
function procSpielereinzelwerte() {
const __ROWOFFSETUPPER = 1; // Header-Zeile
const __ROWOFFSETLOWER = 0;
const __COLUMNINDEX = {
'Flg' : 0,
'Land' : 1,
'U' : 2,
'Age' : 3,
'Einz' : 4, // ab hier die Einzelskills
'SCH' : 4,
'ABS' : 4, // TOR
'BAK' : 5,
'STS' : 5, // TOR
'KOB' : 6,
'FAN' : 6, // TOR
'ZWK' : 7,
'STB' : 7, // TOR
'DEC' : 8,
'SPL' : 8, // TOR
'GES' : 9,
'REF' : 9, // TOR
'FUQ' : 10,
'ERF' : 11,
'AGG' : 12,
'PAS' : 13,
'AUS' : 14,
'UEB' : 15,
'WID' : 16,
'SEL' : 17,
'DIS' : 18,
'ZUV' : 19,
'EIN' : 20,
'Zus' : 21 // Zusaetze hinter den Einzelskills
};
const __TTAGS = document.getElementsByTagName("table");
const __TABLE = __TTAGS[1];
const __ROWS = __TABLE.rows;
const __HEADERS = __ROWS[0];
buildOptions(__OPTCONFIG, __OPTSET);
const __TITLECOLOR = getColor("LEI"); // "#FFFFFF"
const __COLMAN = new ColumnManager(__OPTSET);
__COLMAN.addTitles(__HEADERS, __TITLECOLOR);
const __PLAYERS = init(__ROWS, __OPTSET, __COLUMNINDEX, __ROWOFFSETUPPER, __ROWOFFSETLOWER);
for (let i = 0; i < __PLAYERS.length; i++) {
__COLMAN.addValues(__PLAYERS[i], __ROWS[i + __ROWOFFSETUPPER], __TITLECOLOR);
}
// Format der Trennlinie zwischen den Monaten...
const __BORDERSTRING = __OPTSET.sepStyle.Value + ' ' + __OPTSET.sepColor.Value + ' ' + __OPTSET.sepWidth.Value;
separateGroups(__ROWS, __BORDERSTRING, __COLUMNINDEX.Age, __ROWOFFSETUPPER, __ROWOFFSETLOWER, -1, 0);
}
// URL-Legende:
// page=0: Managerbuero
// page=1: Teamuebersicht
// page=2: Spielereinzelwerte
// Verzweige in unterschiedliche Verarbeitungen je nach Wert von page:
switch (getPageIdFromURL(window.location.href)) {
case 0: procHaupt(); break;
case 1: procTeamuebersicht(); break;
case 2: procSpielereinzelwerte(); break;
default: break;
}
console.log("SCRIPT END");
// *** EOF ***