Bearbeiten von „OS2.jugend“
Zur Navigation springen
Zur Suche springen
Die Bearbeitung kann rückgängig gemacht werden. Bitte prüfe den Vergleich unten, um sicherzustellen, dass du dies tun möchtest, und veröffentliche dann unten deine Änderungen, um die Bearbeitung rückgängig zu machen.
Aktuelle Version | Dein Text | ||
Zeile 1: | Zeile 1: | ||
[[Kategorie:Greasemonkey]] | [[Kategorie:Greasemonkey]] | ||
{| style="background-color:white; font-size:11px; float: right; margin:3px 3px 3px 10px; border:1px solid #999; border-color: #9C1818; border-collapse:collapse;" width=500 cellpadding=3 cellspacing=0 | {| style="background-color:white; font-size:11px; float: right; margin:3px 3px 3px 10px; border:1px solid #999; border-color: #9C1818; border-collapse:collapse;" width=500 cellpadding=3 cellspacing=0 | ||
| colspan="2" style="padding:0.3em; background-color:#9C1818; font-size: 18px; color:#FFFFFF" align=center| '''OS2.jugend''' | | colspan="2" style="padding:0.3em; background-color:#9C1818; font-size: 18px; color:#FFFFFF" align=center| '''OS2.jugend''' | ||
Zeile 8: | Zeile 7: | ||
|- bgcolor="#FFCC00" | |- bgcolor="#FFCC00" | ||
| '''Version''' | | '''Version''' | ||
| '''0. | | '''0.48''' | ||
|- bgcolor="#FFCC00" | |- bgcolor="#FFCC00" | ||
| '''Autor''' | | '''Autor''' | ||
Zeile 27: | Zeile 26: | ||
| '''ju.php?page=2''' | | '''ju.php?page=2''' | ||
| '''Jugendteam-Spielereinzelwerte''' | | '''Jugendteam-Spielereinzelwerte''' | ||
|} | |} | ||
|- 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'''<br> '''Hidden-Optionen und Datenspeicher'''<br> '''Geburtstage und dezimales Alter'''<br> '''Erweiterte Optionen auch auf der Seite'''<br> '''Zusatzspalten Talent/Quote/Aufw./Geb./Alter'''<br> '''Zusatzspalten Quote/Alter/Pos in der Übersicht''' | | '''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'''<br> '''Erweiterte Optionen auch auf der Seite'''<br> '''Zusatzspalten Talent/Quote/Aufw./Geb./Alter'''<br> '''Zusatzspalten Quote/Alter/Pos in der Übersicht''' | ||
|- bgcolor="#FFCC00" | |- bgcolor="#FFCC00" | ||
| '''Letzte Änderung''' | | '''Letzte Änderung''' | ||
| '''{{REVISIONDAY}}.{{REVISIONMONTH}}.{{REVISIONYEAR}}''' | | '''{{REVISIONDAY}}.{{REVISIONMONTH}}.{{REVISIONYEAR}}''' | ||
|} | |} | ||
<pre> | <pre> | ||
// ==UserScript== | // ==UserScript== | ||
// @name OS2.jugend | // @name OS2.jugend | ||
// @namespace http://os.ongapo.com/ | // @namespace http://os.ongapo.com/ | ||
// @version 0. | // @version 0.48 | ||
// @copyright 2013+ | // @copyright 2013+ | ||
// @author | // @author Andreas Eckes (Strindheim BK) | ||
// @author Sven Loges (SLC) | |||
// @description Jugendteam-Script fuer Online Soccer 2.0 | // @description Jugendteam-Script fuer Online Soccer 2.0 | ||
// @include / | // @include http*://os.ongapo.com/haupt.php | ||
// @include | // @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_getValue | ||
// @grant GM_setValue | // @grant GM_setValue | ||
Zeile 67: | Zeile 66: | ||
// ==/UserScript== | // ==/UserScript== | ||
// ECMAScript 6: | // ECMAScript 6: Erlaubt 'const', 'let', ... | ||
/* jshint esnext: true */ | /* jshint esnext: true */ | ||
/* jshint moz: true */ | /* jshint moz: true */ | ||
// ==================== Konfigurations-Abschnitt fuer Optionen ==================== | // ==================== Konfigurations-Abschnitt fuer Optionen ==================== | ||
// Options-Typen | // Options-Typen | ||
Zeile 93: | Zeile 90: | ||
const __OPTMEM = { | const __OPTMEM = { | ||
'normal' : { | 'normal' : { | ||
'Name' : "Session", | |||
'Value' : sessionStorage, | |||
'Display' : "sessionStorage", | |||
'Prefix' : 'run' | |||
}, | |||
'unbegrenzt' : { | |||
'Name' : "Browser", | 'Name' : "Browser", | ||
'Value' : localStorage, | 'Value' : localStorage, | ||
'Display' : "localStorage", | 'Display' : "localStorage", | ||
'Prefix' : 'run' | 'Prefix' : 'run' | ||
}, | }, | ||
Zeile 114: | Zeile 111: | ||
// 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 = { | ||
' | 'zeigeTal' : { // Spaltenauswahl fuer Talente (true = anzeigen, false = nicht anzeigen) | ||
'Name' : " | 'Name' : "showTclasses", | ||
'Type' : __OPTTYPES.SW, | 'Type' : __OPTTYPES.SW, | ||
'Default' : | 'Default' : true, | ||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "Talent ein", | ||
'Hotkey' : ' | 'Hotkey' : 'T', | ||
'AltLabel' : " | 'AltLabel' : "Talent aus", | ||
'AltHotkey' : ' | 'AltHotkey' : 'T', | ||
'FormLabel' : " | 'FormLabel' : "Talent" | ||
}, | }, | ||
' | 'zeigeQuote' : { // Spaltenauswahl fuer Aufwertungsschnitt (true = anzeigen, false = nicht anzeigen) | ||
'Name' : " | 'Name' : "showRatio", | ||
'Type' : __OPTTYPES.SW, | 'Type' : __OPTTYPES.SW, | ||
'Default' : true, | 'Default' : true, | ||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "Quote ein", | ||
'Hotkey' : ' | 'Hotkey' : 'T', | ||
'AltLabel' : " | 'AltLabel' : "Quote aus", | ||
'AltHotkey' : ' | 'AltHotkey' : 'T', | ||
'FormLabel' : " | 'FormLabel' : "Quote" | ||
}, | }, | ||
' | 'zeigeAufw' : { // Spaltenauswahl fuer Aufwertungen (true = anzeigen, false = nicht anzeigen) | ||
'Name' : " | 'Name' : "showProgresses", | ||
'Type' : __OPTTYPES.SW, | 'Type' : __OPTTYPES.SW, | ||
'Default' : | 'Default' : false, | ||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "Aufw. ein", | ||
'Hotkey' : ' | 'Hotkey' : 'W', | ||
'AltLabel' : " | 'AltLabel' : "Aufw. aus", | ||
'AltHotkey' : ' | 'AltHotkey' : 'W', | ||
'FormLabel' : " | 'FormLabel' : "Aufwertung" | ||
}, | }, | ||
' | 'zeigeGeb' : { // Spaltenauswahl fuer Geburtstage (true = anzeigen, false = nicht anzeigen) | ||
'Name' : " | 'Name' : "showBirthday", | ||
'Type' : __OPTTYPES.SW, | 'Type' : __OPTTYPES.SW, | ||
'Default' : | 'Default' : false, | ||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "Geb. ein", | ||
'Hotkey' : ' | 'Hotkey' : 'G', | ||
'AltLabel' : " | 'AltLabel' : "Geb. aus", | ||
'AltHotkey' : ' | 'AltHotkey' : 'G', | ||
'FormLabel' : " | 'FormLabel' : "Geburtstag" | ||
}, | }, | ||
' | 'zeigeAlter' : { // Spaltenauswahl fuer dezimales Alter (true = anzeigen, false = nicht anzeigen) | ||
'Name' : " | 'Name' : "showAge", | ||
'Type' : __OPTTYPES.SW, | 'Type' : __OPTTYPES.SW, | ||
'Default' : true, | 'Default' : true, | ||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "Alter ein", | ||
'Hotkey' : ' | 'Hotkey' : 'A', | ||
'AltLabel' : " | 'AltLabel' : "Alter aus", | ||
'AltHotkey' : ' | 'AltHotkey' : 'A', | ||
'FormLabel' : " | 'FormLabel' : "Alter" | ||
}, | }, | ||
' | 'zeigeSkill' : { // Spaltenauswahl fuer die aktuellen Werte (true = anzeigen, false = nicht anzeigen) | ||
'Name' : " | 'Name' : "showSkill", | ||
'Type' : __OPTTYPES.SW, | 'Type' : __OPTTYPES.SW, | ||
'Default' : true, | 'Default' : true, | ||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "Skill ein", | ||
'Hotkey' : ' | 'Hotkey' : 'S', | ||
'AltLabel' : " | 'AltLabel' : "Skill aus", | ||
'AltHotkey' : ' | 'AltHotkey' : 'S', | ||
'FormLabel' : " | 'FormLabel' : "Skill" | ||
}, | }, | ||
' | 'zeigePosition' : { // Position anzeigen | ||
'Name' : " | 'Name' : "showPos", | ||
'Type' : __OPTTYPES.SW, | 'Type' : __OPTTYPES.SW, | ||
'Default' : false, | 'Default' : false, | ||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "Position ein", | ||
'Hotkey' : ' | 'Hotkey' : 'P', | ||
'AltLabel' : " | 'AltLabel' : "Position aus", | ||
'AltHotkey' : ' | 'AltHotkey' : 'P', | ||
'FormLabel' : " | 'FormLabel' : "Position" | ||
}, | }, | ||
' | 'anzahlOpti' : { // Gibt die Anzahl der Opti-Spalten an / 1: nur bester Opti, 2: die beiden besten, ..., 6: Alle inklusive TOR | ||
'Name' : " | // Bei Torhuetern wird immer nur der TOR-Opti angezeigt / Werte < 1 oder > 6 schalten die Anzeige aus | ||
'Type' : __OPTTYPES. | 'Name' : "anzOpti", | ||
'Default' : | 'Type' : __OPTTYPES.MC, | ||
'ValType' : "Number", | |||
'Choice' : [ 0, 1, 2, 3, 4, 5, 6 ], | |||
'Default' : 1, | |||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "Opti: beste $", | ||
'Hotkey' : ' | 'Hotkey' : 'O', | ||
' | 'FormLabel' : "Opti:|beste $" | ||
}, | }, | ||
' | 'anzahlMW' : { // Gibt die Anzahl der MW-Spalten an / 1: nur hoechsten MW, 2: die beiden hoechsten, ..., 6: Alle inklusive TOR | ||
'Name' : " | // Bei Torhuetern wird immer nur der TOR-MW angezeigt / Werte < 1 oder > 6 schalten die Anzeige aus | ||
'Type' : __OPTTYPES. | 'Name' : "anzMW", | ||
'Default' : | 'Type' : __OPTTYPES.MC, | ||
'ValType' : "Number", | |||
'Choice' : [ 0, 1, 2, 3, 4, 5, 6 ], | |||
'Default' : 1, | |||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "MW: beste $", | ||
'Hotkey' : ' | 'Hotkey' : 'M', | ||
' | 'FormLabel' : "MW:|beste $" | ||
}, | }, | ||
' | 'zeigeSkillEnde' : { // Spaltenauswahl fuer die Werte mit Ende 18 (true = anzeigen, false = nicht anzeigen) | ||
'Name' : " | 'Name' : "showSkillEnde", | ||
'Type' : __OPTTYPES.SW, | 'Type' : __OPTTYPES.SW, | ||
'Default' : true, | 'Default' : true, | ||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "Skill Ende ein", | ||
'Hotkey' : ' | 'Hotkey' : 'i', | ||
'AltLabel' : " | 'AltLabel' : "Skill Ende aus", | ||
'AltHotkey' : ' | 'AltHotkey' : 'i', | ||
'FormLabel' : " | 'FormLabel' : "Skill \u03A9" | ||
}, | }, | ||
' | 'anzahlOptiEnde' : { // Spaltenauswahl fuer die Werte mit Ende 18: | ||
'Name' : " | // Gibt die Anzahl der Opti-Spalten an / 1: nur bester Opti, 2: die beiden besten, ..., 6: Alle inklusive TOR | ||
'Type' : __OPTTYPES. | // Bei Torhuetern wird immer nur der TOR-Opti angezeigt / Werte < 1 oder > 6 schalten die Anzeige aus | ||
' | 'Name' : "anzOptiEnde", | ||
' | 'Type' : __OPTTYPES.MC, | ||
' | 'ValType' : "Number", | ||
' | 'Choice' : [ 0, 1, 2, 3, 4, 5, 6 ], | ||
' | 'Default' : 1, | ||
' | 'Action' : __OPTACTION.NXT, | ||
'FormLabel' : " | 'Label' : "Opti Ende: beste $", | ||
'Hotkey' : 't', | |||
'FormLabel' : "Opti \u03A9:|beste $" | |||
}, | }, | ||
' | 'anzahlMWEnde' : { // Spaltenauswahl fuer die Werte mit Ende 18: | ||
'Name' : " | // Gibt die Anzahl der MW-Spalten an / 1: nur hoechsten MW, 2: die beiden hoechsten, ..., 6: Alle inklusive TOR | ||
'Type' : __OPTTYPES. | // Bei Torhuetern wird immer nur der TOR-MW angezeigt / Werte < 1 oder > 6 schalten die Anzeige aus | ||
' | 'Name' : "anzMWEnde", | ||
'Default' : | 'Type' : __OPTTYPES.MC, | ||
'ValType' : "Number", | |||
'Choice' : [ 0, 1, 2, 3, 4, 5, 6 ], | |||
'Default' : 1, | |||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "MW Ende: beste $", | ||
'Hotkey' : ' | 'Hotkey' : 'W', | ||
' | 'FormLabel' : "MW \u03A9:|beste $" | ||
}, | }, | ||
' | 'kennzeichenEnde' : { // Markierung fuer Ende 18 | ||
'Name' : " | 'Name' : "charEnde", | ||
'Type' : __OPTTYPES. | 'Type' : __OPTTYPES.MC, | ||
' | 'ValType' : "String", | ||
'Choice' : [ " \u03A9", " 18" ], | |||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "Ende: $", | ||
'Hotkey' : ' | 'Hotkey' : 'E', | ||
' | 'FormLabel' : "Ende 18:|$" | ||
}, | }, | ||
' | 'sepStyle' : { // Stil der Trennlinie | ||
'Name' : " | 'Name' : "sepStyle", | ||
'Type' : __OPTTYPES. | 'Type' : __OPTTYPES.MC, | ||
' | 'ValType' : "String", | ||
'Choice' : [ "solid", "hidden", "dotted", "dashed", "double", "groove", "ridge", | |||
"inset", "outset", "none" ], | |||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "Stil: $", | ||
'Hotkey' : ' | 'Hotkey' : 'l', | ||
' | 'FormLabel' : "Stil:|$" | ||
}, | }, | ||
' | 'sepColor' : { // Farbe der Trennlinie | ||
'Name' : " | 'Name' : "sepColor", | ||
'Type' : __OPTTYPES. | 'Type' : __OPTTYPES.MC, | ||
' | 'ValType' : "String", | ||
'Choice' : [ "white", "yellow", "black", "blue", "cyan", "gold", "grey", "green", | |||
"lime", "magenta", "maroon", "navy", "olive", "orange", "purple", | |||
"red", "teal", "transparent" ], | |||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "Farbe: $", | ||
'Hotkey' : ' | 'Hotkey' : 'F', | ||
' | 'FormLabel' : "Farbe:|$" | ||
}, | }, | ||
' | 'sepWidth' : { // Dicke der Trennlinie | ||
'Name' : " | 'Name' : "sepWidth", | ||
'Type' : __OPTTYPES. | 'Type' : __OPTTYPES.MC, | ||
' | 'ValType' : "String", | ||
'Choice' : [ "thin", "medium", "thick" ], | |||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "Dicke: $", | ||
'Hotkey' : ' | 'Hotkey' : 'D', | ||
' | 'FormLabel' : "Dicke:|$" | ||
}, | }, | ||
' | 'saison' : { // Laufende Saison | ||
'Name' : " | 'Name' : "saison", | ||
'Type' : __OPTTYPES. | 'Type' : __OPTTYPES.MC, | ||
'Default' : | 'ValType' : "Number", | ||
'Choice' : [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ], | |||
'Default' : 10, | |||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "Saison: $", | ||
'Hotkey' : ' | 'Hotkey' : 'a', | ||
' | 'FormLabel' : "Saison:|$" | ||
}, | }, | ||
' | 'aktuellerZat' : { // Laufender ZAT | ||
'Name' : " | 'Name' : "currZAT", | ||
'Type' : __OPTTYPES. | 'Type' : __OPTTYPES.MC, | ||
' | 'ValType' : "Number", | ||
'Permanent' : true, | |||
'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, | |||
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71 ], | |||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "ZAT: $", | ||
'Hotkey' : 'Z', | 'Hotkey' : 'Z', | ||
' | 'FormLabel' : "ZAT:|$" | ||
}, | }, | ||
' | 'datenZat' : { // Stand der Daten zum Team und ZAT | ||
'Name' : " | 'Name' : "dataZAT", | ||
'Type' : __OPTTYPES. | 'Type' : __OPTTYPES.SD, | ||
'Default' : | 'ValType' : "Number", | ||
'Action' : __OPTACTION. | 'Hidden' : true, | ||
' | 'Serial' : true, | ||
' | 'AutoReset' : true, | ||
' | 'Permanent' : true, | ||
' | 'Default' : undefined, | ||
' | 'Action' : __OPTACTION.SET, | ||
'Submit' : undefined, | |||
'Cols' : 1, | |||
'Rows' : 1, | |||
'Replace' : null, | |||
'Space' : 0, | |||
'Label' : "Daten-ZAT:" | |||
}, | }, | ||
' | 'birthdays' : { // Datenspeicher fuer Geburtstage der Jugendspieler | ||
'Name' : " | 'Name' : "birthdays", | ||
'Type' : __OPTTYPES. | 'Type' : __OPTTYPES.SD, | ||
' | 'Hidden' : false, | ||
' | 'Serial' : true, | ||
' | 'AutoReset' : true, | ||
' | 'Permanent' : true, | ||
' | 'Default' : [], | ||
' | 'Submit' : undefined, | ||
' | 'Cols' : 36, | ||
'Rows' : 2, | |||
'Replace' : null, | |||
'Space' : 0, | |||
'Label' : "Geburtstage:" | |||
}, | }, | ||
' | 'tClasses' : { // Datenspeicher fuer Talente der Jugendspieler (-1=wenig, 0=normal, +1=hoch) | ||
'Name' : " | 'Name' : "tClasses", | ||
'Type' : __OPTTYPES. | 'Type' : __OPTTYPES.SD, | ||
' | 'Hidden' : false, | ||
' | 'Serial' : true, | ||
' | 'AutoReset' : true, | ||
' | 'Permanent' : true, | ||
' | 'Default' : [], | ||
' | 'Submit' : undefined, | ||
' | 'Cols' : 36, | ||
'Rows' : 2, | |||
'Replace' : null, | |||
'Space' : 0, | |||
'Label' : "Talente:" | |||
}, | }, | ||
' | 'progresses' : { // Datenspeicher fuer Aufwertungen der Jugendspieler (als Strings) | ||
'Name' : " | 'Name' : "progresses", | ||
'Type' : __OPTTYPES. | 'Type' : __OPTTYPES.SD, | ||
' | 'Hidden' : false, | ||
' | 'Serial' : true, | ||
' | 'AutoReset' : true, | ||
' | 'Permanent' : true, | ||
' | 'Default' : [], | ||
' | 'Submit' : undefined, | ||
' | 'Cols' : 36, | ||
'Rows' : 7, | |||
'Replace' : null, | |||
'Space' : 0, | |||
'Label' : "Aufwertungen:" | |||
}, | }, | ||
' | 'zatAges' : { // Datenspeicher fuer (gebrochene) Alter der Jugendspieler | ||
'Name' : " | 'Name' : "zatAges", | ||
'Type' : __OPTTYPES. | 'Type' : __OPTTYPES.SD, | ||
' | 'Hidden' : false, | ||
' | 'Serial' : true, | ||
' | 'AutoReset' : true, | ||
' | 'Permanent' : true, | ||
' | 'Default' : [], | ||
' | 'Submit' : undefined, | ||
' | 'Cols' : 36, | ||
'Rows' : 2, | |||
'Replace' : null, | |||
'Space' : 0, | |||
'Label' : "ZAT-Alter:" | |||
}, | }, | ||
' | 'trainiert' : { // Datenspeicher fuer Trainingsquoten der Jugendspieler | ||
'Name' : " | 'Name' : "numProgresses", | ||
'Type' : __OPTTYPES. | 'Type' : __OPTTYPES.SD, | ||
' | 'Hidden' : false, | ||
' | 'Serial' : true, | ||
' | 'AutoReset' : true, | ||
' | 'Permanent' : true, | ||
' | 'Default' : [], | ||
' | 'Submit' : undefined, | ||
' | 'Cols' : 36, | ||
'Rows' : 2, | |||
'Replace' : null, | |||
'Space' : 0, | |||
'Label' : "Trainiert:" | |||
}, | }, | ||
' | 'positions' : { // Datenspeicher fuer optimale Positionen der Jugendspieler | ||
'Name' : " | 'Name' : "positions", | ||
'Type' : __OPTTYPES. | 'Type' : __OPTTYPES.SD, | ||
' | 'Hidden' : false, | ||
' | 'Serial' : true, | ||
' | 'AutoReset' : true, | ||
' | 'Permanent' : true, | ||
' | 'Default' : [], | ||
' | 'Submit' : undefined, | ||
' | 'Cols' : 36, | ||
'Rows' : 3, | |||
'Replace' : null, | |||
'Space' : 0, | |||
'Label' : "Positionen:" | |||
}, | }, | ||
' | 'team' : { // Datenspeicher fuer Daten des Erst- bzw. Zweitteams | ||
'Name' : " | 'Name' : "team", | ||
'Type' : __OPTTYPES. | 'Type' : __OPTTYPES.SD, | ||
' | 'Hidden' : false, | ||
' | 'Serial' : true, | ||
' | 'Permanent' : true, | ||
' | 'Default' : { 'Team' : undefined, 'Liga' : undefined, 'Land' : undefined, 'LdNr' : 0, 'LgNr' : 0 }, | ||
' | 'Submit' : undefined, | ||
' | 'Cols' : 36, | ||
' | 'Rows' : 6, | ||
'Replace' : null, | |||
'Space' : 1, | |||
'Label' : "Verein:" | |||
}, | }, | ||
' | 'reset' : { // Optionen auf die "Werkseinstellungen" zuruecksetzen | ||
'Name' : "reset", | |||
'Name' : " | 'Type' : __OPTTYPES.SI, | ||
'Action' : __OPTACTION.RST, | |||
'Label' : "Standard-Optionen", | |||
'Hotkey' : 'r', | |||
'FormLabel' : "" | |||
}, | |||
'storage' : { // Browserspeicher fuer die Klicks auf Optionen | |||
'Name' : "storage", | |||
'Type' : __OPTTYPES.MC, | 'Type' : __OPTTYPES.MC, | ||
'ValType' : | 'ValType' : "String", | ||
'Choice' : Object.keys(__OPTMEM), | |||
'Choice' : | |||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "Speicher: $", | ||
'Hotkey' : ' | 'Hotkey' : 'c', | ||
'FormLabel' : " | 'FormLabel' : "Speicher:|$" | ||
}, | }, | ||
' | 'oldStorage' : { // Vorheriger Browserspeicher fuer die Klicks auf Optionen | ||
'Name' : "oldStorage", | |||
'Name' : " | 'Type' : __OPTTYPES.SD, | ||
'Type' : __OPTTYPES. | 'AutoReset' : true, | ||
'Hidden' : true | |||
' | |||
' | |||
}, | }, | ||
' | 'showForm' : { // Optionen auf der Webseite (true = anzeigen, false = nicht anzeigen) | ||
'Name' : "showForm", | |||
'Name' : " | |||
'Type' : __OPTTYPES.SW, | 'Type' : __OPTTYPES.SW, | ||
'FormType' : __OPTTYPES.SI, | |||
'Permanent' : true, | |||
'Default' : false, | 'Default' : false, | ||
'Action' : __OPTACTION.NXT, | 'Action' : __OPTACTION.NXT, | ||
'Label' : " | 'Label' : "Optionen anzeigen", | ||
'Hotkey' : ' | 'Hotkey' : 'O', | ||
'AltLabel' : " | 'AltLabel' : "Optionen verbergen", | ||
'AltHotkey' : ' | 'AltHotkey' : 'O', | ||
'FormLabel' : " | 'FormLabel' : "" | ||
} | } | ||
}; | |||
// ==================== Invarianter Abschnitt fuer Optionen ==================== | |||
// ==================== Abschnitt fuer diverse Utilities ==================== | |||
// Gibt einen Wert zurueck. Ist dieser nicht definiert oder null, wird ein Alternativwert geliefert | |||
// value: Ein Wert. Ist dieser nicht undefined oder null, wird er zurueckgeliefert (oder retValue) | |||
// defValue: Default-Wert fuer den Fall, dass nichts gesetzt ist | |||
// retValue: Falls definiert, Rueckgabe-Wert fuer den Fall, dass value nicht undefined oder null ist | |||
// return Der Wert. Sind weder value noch defValue definiert, dann undefined | |||
function getValue(value, defValue = undefined, retValue = undefined) { | |||
return ((value === undefined) || (value === null)) ? defValue : (retValue === undefined) ? value : retValue; | |||
} | |||
// Gibt einen Wert zurueck. Ist dieser nicht definiert, wird ein Alternativwert geliefert | |||
// value: Ein Wert. Ist dieser definiet und in den Grenzen, wird er zurueckgeliefert | |||
// minValue: Untere Grenze fuer den Wert, falls angegeben | |||
// minValue: Obere Grenze fuer den Wert, falls angegeben | |||
// defValue: Default-Wert fuer den Fall, dass nichts gesetzt ist oder der Wert ausserhalb liegt | |||
// return Der Wert. Sind weder value (in den Grenzen) noch defValue definiert, dann undefined | |||
function getValueIn(value, minValue = undefined, maxValue = undefined, defValue = undefined) { | |||
const __VALUE = getValue(value, defValue); | |||
if ((minValue !== undefined) && (__VALUE < minValue)) { | |||
return defValue; | |||
} | |||
if ((maxValue !== undefined) && (__VALUE > maxValue)) { | |||
return defValue; | |||
} | |||
return __VALUE; | |||
} | |||
// Ermittelt den naechsten Wert aus einer Array-Liste | |||
// arr: Array-Liste mit den moeglichen Werte | |||
// value: Vorher gesetzter Wert | |||
// return Naechster Wert in der Array-Liste | |||
function getNextValue(arr, value) { | |||
const __POS = arr.indexOf(value) + 1; | |||
return arr[getValueIn(__POS, 0, arr.length - 1, 0)]; | |||
} | |||
// Gibt ein Produkt zurueck. Ist einer der Multiplikanten nicht definiert, wird ein Alternativwert geliefert | |||
// valueA: Ein Multipliksnt. Ist dieser undefined, wird als Produkt defValue zurueckgeliefert | |||
// valueB: Ein Multipliksnt. Ist dieser undefined, wird als Produkt defValue zurueckgeliefert | |||
// digits: Anzahl der Stellen nach dem Komma fuer das Produkt (Default: 0) | |||
// defValue: Default-Wert fuer den Fall, dass ein Multiplikant nicht gesetzt ist (Default: NaN) | |||
// return Das Produkt auf digits Stellen genau. Ist dieses nicht definiert, dann defValue | |||
function getMulValue(valueA, valueB, digits = 0, defValue = NaN) { | |||
let product = defValue; | |||
if ((valueA !== undefined) && (valueB !== undefined)) { | |||
product = parseFloat(valueA) * parseFloat(valueB); | |||
} | |||
return parseFloat(product.toFixed(digits)); | |||
} | |||
// Speichert einen beliebiegen (strukturierten) Wert unter einem Namen ab | |||
// name: GM_setValue-Name, unter dem die Daten gespeichert werden | |||
// value: Beliebiger (strukturierter) Wert | |||
// return String-Darstellung des Wertes | |||
function serialize(name, value) { | |||
const __STREAM = (value !== undefined) ? JSON.stringify(value) : value; | |||
console.log(name + " >> " + __STREAM); | |||
GM_setValue(name, __STREAM); | |||
return __STREAM; | |||
} | |||
// Holt einen beliebiegen (strukturierter) Wert unter einem Namen zurueck | |||
// name: GM_setValue-Name, unter dem die Daten gespeichert werden | |||
// defValue: Default-Wert fuer den Fall, dass nichts gespeichert ist | |||
// return Objekt, das unter dem Namen gespeichert war | |||
function deserialize(name, defValue = undefined) { | |||
const __STREAM = GM_getValue(name, defValue); | |||
console.log(name + " << " + __STREAM); | |||
if ((__STREAM !== undefined) && (__STREAM.length !== 0)) { | |||
try { | |||
return JSON.parse(__STREAM); | |||
} catch (ex) { | |||
console.error(name + ": " + ex.message); | |||
} | |||
} | |||
return undefined; | |||
} | |||
// 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 Gespeicherter Wert fuer setOptValue() | |||
function setStored(name, value, reload = true, serial = false) { | |||
if (serial) { | |||
serialize(name, value); | |||
} else { | |||
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: Vorher gesetzter Wert | |||
// reload: Seite mit neuem Wert neu laden | |||
// return Gespeicherter Wert fuer setOptValue() | |||
function setNextStored(arr, name, value, reload = true, serial = false) { | |||
return setStored(name, getNextValue(arr, value), reload, serial); | |||
} | |||
// Fuehrt die in einem Storage gespeicherte Operation aus | |||
// optSet: Set mit den Optionen | |||
// memory: __OPTMEM.normal = bis Browserende gespeichert (sessionStorage), __OPTMEM.unbegrenzt = unbegrenzt gespeichert (localStorage), __OPTMEM.inaktiv | |||
function runStored(optSet, memory = undefined) { | |||
const __STORAGE = getMemory(memory); | |||
const __MEMORY = __STORAGE.Value; | |||
const __RUNPREFIX = __STORAGE.Prefix; | |||
if (__MEMORY !== undefined) { | |||
const __GETITEM = function(item) { | |||
return __MEMORY.getItem(__RUNPREFIX + item); | |||
}; | |||
const __DELITEM = function(item) { | |||
return __MEMORY.removeItem(__RUNPREFIX + item); | |||
}; | |||
const __CMD = ((__MEMORY !== undefined) ? __GETITEM('cmd') : undefined); | |||
if (__CMD !== undefined) { | |||
const __KEY = __GETITEM('key'); | |||
let value = __GETITEM('val'); | |||
try { | |||
value = JSON.parse(value); | |||
} catch (ex) { | |||
console.error("runStored(): " + __CMD + " '" + __KEY + "' hat illegalen Wert '" + value + "'"); | |||
// ... meist kann man den String selber aber speichern, daher kein "return"... | |||
} | |||
const __VAL = value; | |||
switch (__OPTACTION[__CMD]) { | |||
case __OPTACTION.SET : console.log("SET '" + __KEY + "' " + __VAL); | |||
setStored(__KEY, __VAL, false, false); | |||
break; | |||
case __OPTACTION.NXT : console.log("SETNEXT '" + __KEY + "' " + __VAL); | |||
//setNextStored(__CONFIG.Choice, __KEY, __VAL, false, false); | |||
setStored(__KEY, __VAL, false, false); | |||
break; | |||
case __OPTACTION.RST : console.log("RESET"); | |||
resetOptions(optSet, false); | |||
break; | |||
default : break; | |||
} | |||
} | |||
__DELITEM('cmd'); | |||
__DELITEM('key'); | |||
__DELITEM('val'); | |||
} | |||
} | |||
// Gibt eine Option sicher zurueck | |||
// opt: Config und Value der Option, ggfs. undefined | |||
// defOpt: Rueckgabewert, falls undefined | |||
// return Daten zur Option (oder defOpt) | |||
function getOpt(opt, defOpt = { }) { | |||
return getValue(opt, defOpt); | |||
} | |||
// Gibt eine Option sicher zurueck (Version mit Key) | |||
// optSet: Platz fuer die gesetzten Optionen (und Config) | |||
// item: Key der Option | |||
// defOpt: Rueckgabewert, falls nicht zu finden | |||
// return Daten zur Option (oder defOpt) | |||
function getOptByName(optSet, item, defOpt = { }) { | |||
if ((optSet !== undefined) && (item !== undefined)) { | |||
return getOpt(optSet[item], defOpt); | |||
} else { | |||
return defOpt; | |||
} | |||
} | |||
// Gibt die Konfigurationsdaten einer Option zurueck | |||
// opt: Config und Value der Option | |||
// defConfig: Rueckgabewert, falls Config nicht zu finden | |||
// return Konfigurationsdaten der Option | |||
function getOptConfig(opt, defConfig = { }) { | |||
return getValue(getOpt(opt).Config, defConfig); | |||
} | |||
// Setzt den Namen einer Option | |||
// opt: Config und Value der Option | |||
// name: Zu setzender Name der Option | |||
// reload: Seite mit neuem Wert neu laden | |||
// return Gesetzter Name der Option | |||
function setOptName(opt, name) { | |||
const __NAME = getOptName(opt); | |||
console.log("RENAME " + __NAME + " => " + name); | |||
return (getOptConfig(opt).Name = name); | |||
} | |||
// Gibt den Namen einer Option zurueck | |||
// opt: Config und Value der Option | |||
// return Name der Option | |||
function getOptName(opt) { | |||
return getOptConfig(opt).Name; | |||
} | |||
// Setzt den Wert einer Option | |||
// opt: Config und Value der Option | |||
// name: Zu setzender Wert der Option | |||
// return Gesetzter Wert | |||
function setOptValue(opt, value) { | |||
return (opt !== undefined) ? (opt.Value = value) : undefined; | |||
} | |||
// Gibt den Wert einer Option zurueck | |||
// opt: Config und Value der Option | |||
// defValue: Default-Wert fuer den Fall, dass nichts gesetzt ist | |||
// return Gesetzter Wert | |||
function getOptValue(opt, defValue = undefined) { | |||
return getValue((opt !== undefined) ? opt.Value : undefined, defValue); | |||
} | |||
// ==================== Ende Abschnitt fuer diverse Utilities ==================== | |||
// ==================== Abschnitt fuer Speicher und die Scriptdatenbank ==================== | |||
// Namen des Default-, Dauer- und Null-Memories... | |||
const __MEMNORMAL = 'normal'; | |||
const __MEMINFINITE = 'unbegrenzt'; | |||
const __MEMINAKTIVE = 'inaktiv'; | |||
// Definition des Default-, Dauer- und Null-Memories... | |||
const __OPTMEMNORMAL = __OPTMEM[__MEMNORMAL]; | |||
const __OPTMEMINFINITE = __OPTMEM[__MEMINFINITE]; | |||
const __OPTMEMINAKTIVE = __OPTMEM[__MEMINAKTIVE]; | |||
// Medium fuer die Datenbank (Speicher) | |||
let myOptMem = __OPTMEMNORMAL; | |||
// Speicher fuer die DB-Daten | |||
const __DBMEM = __OPTMEMNORMAL.Value; | |||
// Infos ueber dieses Script-Modul | |||
const __DBMOD = { }; | |||
// Inhaltsverzeichnis der DB-Daten (indiziert durch die Script-Namen) | |||
const __DBTOC = { }; | |||
// Daten zu den Modulen (indiziert durch die Script-Namen) | |||
const __DBDATA = { }; | |||
// ==================== Abschnitt fuer Speicher ==================== | |||
// Ermittelt fuer die uebergebene Speicher-Konfiguration einen Speicher | |||
// memory: __OPTMEM.normal = bis Browserende gespeichert (sessionStorage), __OPTMEM.unbegrenzt = unbegrenzt gespeichert (localStorage), __OPTMEM.inaktiv | |||
// return memory, falls okay, sonst einen Defaultwert | |||
function getMemory(memory = undefined) { | |||
return getValue(memory, getValue(myOptMem, __OPTMEMNORMAL)); | |||
} | |||
// Kompatibilitaetsfunktion: Testet, ob der uebergebene Speicher genutzt werden kann | |||
// memory: __OPTMEM.normal = bis Browserende gespeichert (sessionStorage), __OPTMEM.unbegrenzt = unbegrenzt gespeichert (localStorage), __OPTMEM.inaktiv | |||
function canUseMemory(memory = undefined) { | |||
const __STORAGE = getMemory(memory); | |||
const __MEMORY = __STORAGE.Value; | |||
let ret = false; | |||
if (__MEMORY !== undefined) { | |||
const __TESTPREFIX = 'canUseStorageTest'; | |||
const __TESTDATA = Math.random().toString(); | |||
const __TESTITEM = __TESTPREFIX + __TESTDATA; | |||
__MEMORY.setItem(__TESTITEM, __TESTDATA); | |||
ret = (__MEMORY.getItem(__TESTITEM) === __TESTDATA); | |||
__MEMORY.removeItem(__TESTITEM); | |||
} | |||
console.log("canUseStorage(" + __STORAGE.Name + ") = " + ret); | |||
return ret; | |||
} | |||
// Restauriert den vorherigen Speicher (der in einer Option definiert ist) | |||
// opt: Option zur Wahl des Speichers | |||
// return Gesuchter Speicher oder Null-Speicher ('inaktiv') | |||
function restoreMemoryByOpt(opt) { | |||
// Memory Storage fuer vorherige Speicherung... | |||
const __STORAGE = loadOption(getOpt(opt), true); | |||
return __OPTMEM[getValue(__STORAGE, __MEMNORMAL)]; | |||
} | |||
// Initialisiert den Speicher (der in einer Option definiert ist) und merkt sich diesen ggfs. | |||
// opt: Option zur Wahl des Speichers | |||
// saveOpt: Option zur Speicherung der Wahl des Speichers (fuer restoreMemoryByOpt) | |||
// return Gesuchter Speicher oder Null-Speicher ('inaktiv'), falls speichern nicht moeglich ist | |||
function startMemoryByOpt(opt, saveOpt = undefined) { | |||
// Memory Storage fuer naechste Speicherung... | |||
let storage = getOptValue(opt, __MEMNORMAL); | |||
let optMem = __OPTMEM[storage]; | |||
if (! canUseMemory(optMem)) { | |||
if (storage !== __MEMINAKTIVE) { | |||
storage = __MEMINAKTIVE; | |||
optMem = __OPTMEM[storage]; | |||
} | |||
} | |||
if (saveOpt !== undefined) { | |||
setOpt(saveOpt, storage, false); | |||
} | |||
return optMem; | |||
} | |||
// ==================== Ende Abschnitt fuer Speicher ==================== | |||
// ==================== Abschnitt fuer die Scriptdatenbank ==================== | |||
// Initialisiert die Scriptdatenbank, die einen Datenaustausch zwischen den Scripten ermoeglicht | |||
// optSet: Gesetzte Optionen (und Config) | |||
function initScriptDB(optSet) { | |||
const __INFO = GM_info; | |||
const __META = __INFO.script; | |||
//console.log(__INFO); | |||
__DBTOC.versions = getValue(JSON.parse(__DBMEM.getItem('__DBTOC.versions')), { }); | |||
// Infos zu diesem Script... | |||
__DBMOD.name = __META.name; | |||
__DBMOD.version = __META.version; | |||
console.log(__DBMOD); | |||
// Zunaechst den alten Eintrag entfernen... | |||
__DBTOC.versions[__DBMOD.name] = undefined; | |||
// ... und die Daten der Fremdscripte laden... | |||
for (let module in __DBTOC.versions) { | |||
__DBDATA[module] = getValue(JSON.parse(__DBMEM.getItem('__DBDATA.' + module)), { }); | |||
} | |||
} | |||
// Setzt die Daten dieses Scriptes in der Scriptdatenbank, die einen Datenaustausch zwischen den Scripten ermoeglicht | |||
// optSet: Gesetzte Optionen (und Config) | |||
function updateScriptDB(optSet) { | |||
// Eintrag ins Inhaltsverzeichnis... | |||
__DBTOC.versions[__DBMOD.name] = __DBMOD.version; | |||
// | // Permanente Speicherung der Eintraege... | ||
__DBMEM.setItem('__DBTOC.versions', JSON.stringify(__DBTOC.versions)); | |||
__DBMEM.setItem('__DBDATA.' + __DBMOD.name, JSON.stringify(optSet)); | |||
// | // Jetzt die inzwischen gefuellten Daten *dieses* Scripts ergaenzen... | ||
__DBDATA[__DBMOD.name] = getValue(optSet, { }); | |||
console.log(__DBDATA); | |||
} | } | ||
// | // ==================== Ende Abschnitt fuer die Scriptdatenbank ==================== | ||
// ==================== Ende Abschnitt fuer Speicher und die Scriptdatenbank ==================== | |||
// | // ==================== Abschnitt fuer das Benutzermenu ==================== | ||
// | // 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 | ||
function | // 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); | |||
if ( | |||
} else { | |||
} | } | ||
} | } | ||
// | // 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) | ||
function | // 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; | |||
if ( | for (let value of arr) { | ||
if (value === opt) { | |||
options += " / *" + value + '*'; | |||
} else { | } 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)) ? JSON.stringify(opt) : opt); | |||
const __MENU = getValue(menu, "").replace('$', __VALUE); | |||
const __OPTIONS = (hidden ? "HIDDEN " : "") + "OPTION " + __MENU + | |||
getValue(__VALUE, "", " = " + __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 = getOptConfig(opt); | |||
if (! __CONFIG.HiddenMenu) { | |||
switch (__CONFIG.Type) { | |||
case __OPTTYPES.MC : registerNextMenuOption(getOptValue(opt), __CONFIG.Choice, | |||
__CONFIG.Label, opt.Action, __CONFIG.Hotkey); | |||
break; | |||
case __OPTTYPES.SW : registerMenuOption(getOptValue(opt), __CONFIG.Label, opt.Action, __CONFIG.Hotkey, | |||
__CONFIG.AltLabel, opt.Action, __CONFIG.AltHotkey); | |||
break; | |||
case __OPTTYPES.TF : registerMenuOption(getOptValue(opt), __CONFIG.Label, opt.Action, __CONFIG.Hotkey, | |||
__CONFIG.AltLabel, opt.AltAction, __CONFIG.AltHotkey); | |||
break; | |||
case __OPTTYPES.SD : registerDataOption(getOptValue(opt), __CONFIG.Label, opt.Action, __CONFIG.Hotkey, | |||
__CONFIG.HiddenMenu, __CONFIG.Serial); | |||
break; | |||
case __OPTTYPES.SI : registerDataOption(getOptValue(opt), __CONFIG.Label, opt.Action, __CONFIG.Hotkey, | |||
__CONFIG.HiddenMenu, __CONFIG.Serial); | |||
break; | |||
default : break; | |||
} | } | ||
} else { | |||
// Nur Anzeige im Log... | |||
registerDataOption(getOptValue(opt), getOptName(opt), opt.Action, __CONFIG.Hotkey, __CONFIG.HiddenMenu, __CONFIG.Serial); | |||
} | } | ||
} | } | ||
// ==================== Ende Abschnitt fuer das Benutzermenu ==================== | |||
// Initialisiert die gesetzten Option | |||
// config: Konfiguration der Option | |||
// return Initialwert der gesetzten Option | |||
function initOptValue(config) { | |||
let value = config.Default; // Standard | |||
switch (config.Type) { | |||
case __OPTTYPES.MC : if ((value === undefined) && (config.Choice !== undefined)) { | |||
value = config.Choice[0]; | |||
} | |||
break; | |||
case __OPTTYPES.SW : break; | |||
case __OPTTYPES.TF : break; | |||
case __OPTTYPES.SD : config.Serial = true; | |||
break; | |||
case __OPTTYPES.SI : break; | |||
default : break; | |||
} | |||
if (config.Serial || config.Hidden) { | |||
config.HiddenMenu = true; | |||
} | |||
return value; | |||
} | |||
// Initialisiert die Menue-Funktion einer Option | |||
// optAction: Typ der Funktion | |||
// item: Key der Option | |||
// optSet: Platz fuer die gesetzten Optionen (und Config) | |||
// return Funktion fuer die Option | |||
function initOptAction(optAction, item = undefined, optSet = undefined) { | |||
var fun; | |||
if (optAction !== undefined) { | |||
const __CONFIG = getOptConfig(getOptByName(optSet, item)); | |||
const __RELOAD = ((__CONFIG !== undefined) ? __CONFIG.ActionReload : false); | |||
switch (optAction) { | |||
case __OPTACTION.SET : fun = function() { | |||
return setOptByName(optSet, item, optSet.SetValue, __RELOAD); | |||
}; | |||
break; | |||
case __OPTACTION.NXT : fun = function() { | |||
return setNextOptByName(optSet, item, optSet.SetValue, __RELOAD); | |||
}; | |||
break; | |||
case __OPTACTION.RST : fun = function() { | |||
return resetOptions(optSet, __RELOAD); | |||
}; | |||
break; | |||
default : break; | |||
} | } | ||
} | } | ||
return fun; | |||
} | } | ||
// Initialisiert die gesetzten Optionen | |||
// optConfig: Konfiguration der Optionen | |||
// optSet: Platz fuer 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]; | |||
const __ALTACTION = getValue(__CONFIG.AltAction, __CONFIG.Action); | |||
optSet[opt] = { | |||
'Config' : __CONFIG, | |||
'Value' : initOptValue(__CONFIG), | |||
'SetValue' : undefined, | |||
'Action' : initOptAction(__CONFIG.Action, opt, optSet), | |||
'AltAction' : initOptAction(__ALTACTION, opt, optSet) | |||
}; | |||
} | |||
} | } | ||
return optSet; | |||
} | } | ||
// Initialisiert die gesetzten Optionen und den Speicher und laedt die Optionen zum Start | |||
// optConfig: Konfiguration der Optionen | |||
// optSet: Platz fuer die gesetzten Optionen | |||
// return Gefuelltes Objekt mit den gesetzten Optionen | |||
function startOptions(optConfig, optSet = undefined) { | |||
optSet = initOptions(optConfig, optSet); | |||
// | // Memory Storage fuer vorherige Speicherung... | ||
myOptMem = restoreMemoryByOpt(optSet.oldStorage); | |||
runStored(optSet); | |||
loadOptions(optSet); | |||
// | // Memory Storage fuer naechste Speicherung... | ||
myOptMem = startMemoryByOpt(optSet.storage, optSet.oldStorage); | |||
initScriptDB(optSet); | |||
return optSet; | |||
} | } | ||
// Installiert die Visualisierung und Steuerung der Optionen | |||
// optSet: Platz fuer die gesetzten Optionen | |||
// optParams: Eventuell notwendige Parameter zur Initialisierung | |||
// 'hideMenu': Optionen werden zwar geladen und genutzt, tauchen aber nicht im Benutzermenu auf | |||
// 'menuAnchor': Startpunkt fuer das Optionsmenu auf der Seite | |||
// 'showForm': Checkliste der auf der Seite sichtbaren Optionen (true fuer sichtbar) | |||
// 'hideForm': Checkliste der auf der Seite unsichtbaren Optionen (true fuer unsichtbar) | |||
// 'formWidth': Anzahl der Elemente pro Zeile | |||
// 'formBreak': Elementnummer des ersten Zeilenumbruchs | |||
function showOptions(optSet = undefined, optParams = { 'hideMenu' : false }) { | |||
updateScriptDB(optSet); | |||
if (! optParams.hideMenu) { | |||
buildMenu(optSet); | |||
} | |||
if ((optParams.menuAnchor !== undefined) && (myOptMem !== __OPTMEMINAKTIVE)) { | |||
buildForm(optParams.menuAnchor, optSet, optParams); | |||
} | |||
} | |||
// 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 | |||
// return Gesetzter Wert | |||
function setOpt(opt, value, reload = false) { | |||
return setOptValue(opt, setStored(getOptName(opt), value, reload, getOptConfig(opt).Serial)); | |||
} | |||
// Ermittelt die naechste moegliche Option | |||
// opt: Config und Value der Option | |||
// value: Ggfs. zu setzender Wert | |||
// return Zu setzender Wert | |||
function getNextOpt(opt, value = undefined) { | |||
const __CONFIG = getOptConfig(opt); | |||
const __VALUE = getOptValue(opt, value); | |||
// | |||
// | |||
// | |||
// | |||
function | |||
const | |||
switch (__CONFIG.Type) { | |||
case __OPTTYPES.MC : return getValue(value, getNextValue(__CONFIG.Choice, __VALUE)); | |||
case __OPTTYPES.SW : return getValue(value, ! __VALUE); | |||
case __OPTTYPES.TF : return getValue(value, ! __VALUE); | |||
case __OPTTYPES.SD : return getValue(value, __VALUE); | |||
case __OPTTYPES.SI : break; | |||
default : break; | |||
} | |||
return __VALUE; | |||
} | } | ||
// Setzt die naechste moegliche Option | |||
// opt: Config und Value der Option | |||
// value: Default fuer ggfs. zu setzenden Wert | |||
// reload: Seite mit neuem Wert neu laden | |||
// return Gesetzter Wert | |||
function setNextOpt(opt, value = undefined, reload = true) { | |||
const __CONFIG = getOptConfig(opt); | |||
return setOpt(opt, getNextOpt(opt, value), reload); | |||
} | |||
// Setzt eine Option auf einen vorgegebenen Wert (Version mit Key) | |||
// Fuer kontrollierte Auswahl des Values siehe setNextOptByName() | |||
// optSet: Platz fuer die gesetzten Optionen (und Config) | |||
// item: Key der Option | |||
// value: (Bei allen Typen) Zu setzender Wert | |||
// reload: Seite mit neuem Wert neu laden | |||
// return Gesetzter Wert | |||
function setOptByName(optSet, item, value, reload = false) { | |||
const __OPT = getOptByName(optSet, item); | |||
return setOpt(__OPT, value, reload); | |||
} | |||
// Ermittelt die naechste moegliche Option (Version mit Key) | |||
// opt: Config und Value der Option | |||
// optSet: Platz fuer die gesetzten Optionen (und Config) | |||
// item: Key der Option | |||
// value: Ggfs. zu setzender Wert | |||
// return Zu setzender Wert | |||
function getNextOptByName(optSet, item, value = undefined) { | |||
const __OPT = getOptByName(optSet, item); | |||
return getNextOpt(__OPT, value); | |||
} | |||
// Setzt die naechste moegliche Option (Version mit Key) | |||
// opt: Config und Value der Option | |||
// optSet: Platz fuer die gesetzten Optionen (und Config) | |||
// item: Key der Option | |||
// value: Ggfs. zu setzender Wert | |||
// reload: Seite mit neuem Wert neu laden | |||
// return Gesetzter Wert | |||
function setNextOptByName(optSet, item, value = undefined, reload = true) { | |||
const __OPT = getOptByName(optSet, item); | |||
return setNextOpt(__OPT, value, reload); | |||
} | |||
// Baut das Benutzermenu auf | |||
// optSet: Gesetzte Optionen | |||
function buildMenu(optSet) { | |||
console.log("buildMenu()"); | |||
for (let opt in optSet) { | |||
registerOption(optSet[opt]); | |||
} | |||
} | |||
// Laedt eine (ueber Menu) gesetzte Option | |||
// opt: Zu ladende Option | |||
// force: Laedt auch Optionen mit 'AutoReset'-Attribut | |||
// return Gesetzter Wert der gelandenen Option | |||
function loadOption(opt, force = false) { | |||
const __CONFIG = getOptConfig(opt); | |||
if (! force && __CONFIG.AutoReset) { | |||
return setOptValue(opt, initOptValue(__CONFIG)); | |||
} else if (__CONFIG.Serial) { | |||
return setOptValue(opt, deserialize(getOptName(opt), getOptValue(opt))); | |||
} else { | |||
return setOptValue(opt, GM_getValue(getOptName(opt), getOptValue(opt))); | |||
} | |||
} | |||
// Laedt die (ueber Menu) gesetzten Optionen | |||
// optSet: Set mit den Optionen | |||
// force: Laedt auch Optionen mit 'AutoReset'-Attribut | |||
// return Set mit den geladenen Optionen | |||
function loadOptions(optSet, force = false) { | |||
for (let opt in optSet) { | |||
loadOption(optSet[opt], force); | |||
} | |||
return optSet; | |||
} | |||
// Entfernt eine (ueber Menu) gesetzte Option (falls nicht 'Permanent') | |||
// opt: Gesetzte Option | |||
// force: Entfernt auch Optionen mit 'Permanent'-Attribut | |||
// reset: Setzt bei Erfolg auf Initialwert der Option | |||
function deleteOption(opt, force = false, reset = true) { | |||
const __CONFIG = getOptConfig(opt); | |||
if (force || ! __CONFIG.Permanent) { | |||
const __NAME = getOptName(opt); | |||
console.log("DELETE " + __NAME); | |||
GM_deleteValue(__NAME); | |||
if (reset) { | |||
setOptValue(opt, initOptValue(__CONFIG)); | |||
} | |||
} | |||
} | |||
// Entfernt die (ueber Menu) gesetzten Optionen (falls nicht 'Permanent') | |||
// optSet: Gesetzte Optionen | |||
// optSelect: Liste von ausgewaehlten Optionen, true = entfernen, false = nicht entfernen | |||
// force: Entfernt auch Optionen mit 'Permanent'-Attribut | |||
// reset: Setzt bei Erfolg auf Initialwert der Option | |||
function deleteOptions(optSet, optSelect = undefined, force = false, reset = true) { | |||
const __DELETEALL = (optSelect === undefined) || (optSelect === true); | |||
const __OPTSELECT = getValue(optSelect, { }); | |||
for (let opt in optSet) { | |||
if (getValue(__OPTSELECT[opt], __DELETEALL)) { | |||
deleteOption(optSet[opt], force, reset); | |||
} | |||
} | |||
} | |||
// === | // Benennt eine Option um und laedt sie ggfs. nach | ||
// opt: Gesetzte Option | |||
// name: Neu zu setzender Name (Speicheradresse) | |||
// reload: Wert nachladen statt beizubehalten | |||
// force: Laedt auch Optionen mit 'AutoReset'-Attribut | |||
// return Umbenannte Option | |||
function renameOption(opt, name, reload = false, force = false) { | |||
const __NAME = getOptName(opt); | |||
if (__NAME !== name) { | |||
deleteOption(opt, true, ! reload); | |||
setOptName(opt, name); | |||
if (reload) { | |||
loadOption(opt, force); | |||
} | |||
} | |||
return opt; | |||
} | |||
// | // Ermittelt einen neuen Namen mit einem Prefix. Parameter fuer renameOptions() | ||
// name: Gesetzter Name (Speicheradresse) | |||
// | // prefix: Prefix, das vorangestellt werden soll | ||
// return Neu zu setzender Name (Speicheradresse) | |||
function prefixName(name, prefix) { | |||
return (prefix + name); | |||
} | } | ||
// Ermittelt einen neuen Namen mit einem Postfix. Parameter fuer renameOptions() | |||
// name: Gesetzter Name (Speicheradresse) | |||
// postfix: Postfix, das angehaengt werden soll | |||
// return Neu zu setzender Name (Speicheradresse) | |||
function postfixName(name, postfix) { | |||
return (name + postfix); | |||
// | |||
// | |||
// | |||
// return | |||
function | |||
return ( | |||
} | } | ||
// | // Benennt selektierte Optionen nach einem Schema um und laedt sie ggfs. nach | ||
// | // optSet: Gesetzte Optionen | ||
// | // optSelect: Liste von ausgewaehlten Optionen, true = nachladen, false = nicht nachladen | ||
// | // 'reload': Option nachladen? | ||
// | // 'force': Option auch mit 'AutoReset'-Attribut nachladen? | ||
// return | // renameParam: Wird an renameFun uebergeen | ||
function | // renameFun: function(name, param) zur Ermittlung des neuen Namens | ||
// name: Neu zu setzender Name (Speicheradresse) | |||
// reload: Wert nachladen statt beizubehalten | |||
if ( | // force: Laedt auch Optionen mit 'AutoReset'-Attribut | ||
// return Umbenannte Option | |||
function renameOptions(optSet, optSelect, renameParam = undefined, renameFun = prefixName) { | |||
if (renameFun === undefined) { | |||
console.error("RENAME: Illegale Funktion!"); | |||
} | } | ||
for (let opt in optSelect) { | |||
const __OPTPARAMS = optSelect[opt]; | |||
const __OPT = optSet[opt]; | |||
if (__OPT === undefined) { | |||
} | console.error("RENAME: Option '" + opt + "' nicht gefunden!"); | ||
} else { | |||
const __NAME = getOptName(__OPT); | |||
// | const __NEWNAME = renameFun(__NAME, renameParam); | ||
// Laedt die unter dem neuen Namen gespeicherten Daten nach? | |||
// | const __RELOAD = ((typeof __OPTPARAMS === 'boolean') ? __OPTPARAMS : __OPTPARAMS.reload); | ||
// Laedt auch Optionen mit 'AutoReset'-Attribut? | |||
const __FORCE = ((typeof __OPTPARAMS === 'boolean') ? true : __OPTPARAMS.force); | |||
renameOption(__OPT, __NEWNAME, __FORCE); | |||
if (__RELOAD) { | |||
// ... und nachladen... | |||
loadOption(__OPT, __FORCE); | |||
} | |||
} | |||
} | |||
} | } | ||
// | // Setzt die Optionen in optSet auf die "Werkseinstellungen" des Skripts | ||
// | // optSet: Gesetzte Optionen | ||
// | // reload: Seite mit "Werkseinstellungen" neu laden | ||
function resetOptions(optSet, reload = true) { | |||
// | // Alle (nicht 'Permanent') gesetzten Optionen entfernen... | ||
deleteOptions(optSet, true, false, ! reload); | |||
if ( | if (reload) { | ||
// ... und Seite neu laden (mit "Werkseinstellungen")... | |||
window.location.reload(); | |||
} | } | ||
} | } | ||
// | // ==================== Spezialisierter Abschnitt fuer Optionen ==================== | ||
// | // Gesetzte Optionen (wird von initOptions() angelegt und von loadOptions() gefuellt): | ||
const __OPTSET = { }; | |||
// | // Teamparameter fuer getrennte Speicherung der Optionen fuer Erst- und Zweitteam... | ||
const __MYTEAM = { 'Team' : undefined, 'Liga' : undefined, 'Land' : undefined, 'LdNr' : 0, 'LgNr' : 0 }; | |||
// | // Optionen mit Daten, die ZAT- und Team-bezogen gemerkt werden... | ||
const __DATAOPTS = { | |||
'datenZat' : true, | |||
'birthdays' : true, | |||
'tClasses' : true, | |||
'progresses' : true, | |||
'zatAges' : true, | |||
'trainiert' : true, | |||
'positions' : true | |||
}; | |||
// Behandelt die Optionen und laedt das Benutzermenu | |||
// optConfig: Konfiguration der Optionen | |||
// optSet: Platz fuer die gesetzten Optionen | |||
// optParams: Eventuell notwendige Parameter zur Initialisierung | |||
// 'hideMenu': Optionen werden zwar geladen und genutzt, tauchen aber nicht im Benutzermenu auf | |||
// 'teamParams': Getrennte "ligaSize"-Option wird genutzt, hier: __MYTEAM mit 'LdNr'/'LgNr' des Erst- bzw. Zweitteams | |||
// 'menuAnchor': Startpunkt fuer das Optionsmenu auf der Seite | |||
// 'showForm': Checkliste der auf der Seite sichtbaren Optionen (true fuer sichtbar) | |||
// 'hideForm': Checkliste der auf der Seite unsichtbaren Optionen (true fuer unsichtbar) | |||
// 'formWidth': Anzahl der Elemente pro Zeile | |||
// 'formBreak': Elementnummer des ersten Zeilenumbruchs | |||
// return Gefuelltes Objekt mit den gesetzten Optionen | |||
function buildOptions(optConfig, optSet = undefined, optParams = { 'hideMenu' : false }) { | |||
const __TEAMPARAMS = optParams.teamParams; // Ermittelte Parameter | |||
optSet = startOptions(optConfig, optSet); | |||
if (__TEAMPARAMS !== undefined) { | |||
const | __MYTEAM.Team = __TEAMPARAMS.Team; | ||
__MYTEAM.Liga = __TEAMPARAMS.Liga; | |||
__MYTEAM.Land = __TEAMPARAMS.Land; | |||
__MYTEAM.LdNr = __TEAMPARAMS.LdNr; | |||
__MYTEAM.LgNr = __TEAMPARAMS.LgNr; | |||
console.log("Ermittelt: " + JSON.stringify(__MYTEAM)); | |||
// ... und abspeichern... | |||
setOpt(optSet.team, __MYTEAM, false); | |||
} else { | |||
const __TEAM = getOptValue(optSet.team); // Gespeicherte Parameter | |||
if ((__TEAM !== undefined) && (__TEAM.Land !== undefined)) { | |||
__MYTEAM.Team = __TEAM.Team; | |||
__MYTEAM.Liga = __TEAM.Liga; | |||
__MYTEAM.Land = __TEAM.Land; | |||
__MYTEAM.LdNr = __TEAM.LdNr; | |||
__MYTEAM.LgNr = __TEAM.LgNr; | |||
console.log("Gespeichert: " + JSON.stringify(__MYTEAM)); | |||
} else { | |||
console.error("Unbekannt: " + JSON.stringify(__TEAM)); | |||
} | } | ||
} | } | ||
if (__MYTEAM.LdNr !== undefined) { | |||
// Prefix fuer die Optionen 'datenZat', 'birthdays', 'tClasses', 'progresses', | |||
// 'zatAges', 'trainiert' und 'positions' zur gesonderten Behandlung... | |||
const __PREFIX = __MYTEAM.LdNr.toString() + __MYTEAM.LgNr.toString(); | |||
// | // Team-bezogene Daten umbenennen... | ||
renameOptions(optSet, __DATAOPTS, __PREFIX, prefixName); | |||
} | |||
showOptions(optSet, optParams); | |||
return | return optSet; | ||
} | } | ||
// | // ==================== Abschnitt fuer diverse Utilities ==================== | ||
// Legt Input-Felder in einem Form-Konstrukt an, falls noetig | |||
// form: <form>...</form> | |||
// props: Map von name:value-Paaren | |||
// type: Typ der Input-Felder (Default: unsichtbare Daten) | |||
// return Ergaenztes Form-Konstrukt | |||
function addInputField(form, props, type = "hidden") { | |||
for (let fieldName in props) { | |||
let field = form[fieldName]; | |||
if (! field) { | |||
field = document.createElement("input"); | |||
field.type = type; | |||
field.name = fieldName; | |||
form.appendChild(field); | |||
} | } | ||
field.value = props[fieldName]; | |||
} | } | ||
return | return form; | ||
} | } | ||
// | // Legt unsichtbare Input-Daten in einem Form-Konstrukt an, falls noetig | ||
// | // form: <form>...</form> | ||
/ | // props: Map von name:value-Paaren | ||
// | // return Ergaenztes Form-Konstrukt | ||
function addHiddenField(form, props) { | |||
// return | return addInputField(form, props, "hidden"); | ||
function | |||
} | } | ||
// | // Hilfsfunktion fuer alle Browser: Fuegt fuer ein Event eine Reaktion ein | ||
// | // obj: Betroffenes Objekt, z.B. ein Eingabeelement | ||
// | // type: Name des Events, z.B. "click" | ||
// | // callback: Funktion als Reaktion | ||
// return | // capture: Event fuer Parent zuerst (true) oder Child (false als Default) | ||
function | // return false bei Misserfolg | ||
function addEvent(obj, type, callback, capture = false) { | |||
if (obj.addEventListener) { | |||
return obj.addEventListener(type, callback, capture); | |||
} else if (obj.attachEvent) { | |||
} | return obj.attachEvent("on" + type, callback); | ||
} else { | |||
console.log("Could not add " + type + " event:"); | |||
console.log(callback); | |||
return false; | |||
return | |||
} | } | ||
} | |||
// Hilfsfunktion fuer alle Browser: Entfernt eine Reaktion fuer ein Event | |||
// obj: Betroffenes Objekt, z.B. ein Eingabeelement | |||
// type: Name des Events, z.B. "click" | |||
// callback: Funktion als Reaktion | |||
// capture: Event fuer Parent zuerst (true) oder Child (false als Default) | |||
// return false bei Misserfolg | |||
function removeEvent(obj, type, callback, capture = false) { | |||
if (obj.removeEventListener) { | |||
return obj.removeEventListener(type, callback, capture); | |||
} else if (obj.detachEvent) { | |||
return obj.detachEvent("on" + type, callback); | |||
} else { | |||
console.log("Could not remove " + type + " event:"); | |||
console.log(callback); | |||
return false; | |||
return | |||
} | } | ||
} | } | ||
// | // Hilfsfunktion fuer alle Browser: Fuegt fuer ein Event eine Reaktion ein | ||
// | // id: ID des betroffenen Eingabeelements | ||
// | // type: Name des Events, z.B. "click" | ||
function | // callback: Funktion als Reaktion | ||
// capture: Event fuer Parent zuerst (true) oder Child (false als Default) | |||
// return false bei Misserfolg | |||
function addDocEvent(id, type, callback, capture = false) { | |||
const __OBJ = document.getElementById(id); | |||
return addEvent(__OBJ, type, callback, capture); | |||
return | |||
} | } | ||
// Hilfsfunktion fuer | // Hilfsfunktion fuer alle Browser: Entfernt eine Reaktion fuer ein Event | ||
// | // id: ID des betroffenen Eingabeelements | ||
// | // type: Name des Events, z.B. "click" | ||
// | // callback: Funktion als Reaktion | ||
function | // capture: Event fuer Parent zuerst (true) oder Child (false als Default) | ||
const | // return false bei Misserfolg | ||
function removeDocEvent(id, type, callback, capture = false) { | |||
const __OBJ = document.getElementById(id); | |||
return | return removeEvent(__OBJ, type, callback, capture); | ||
} | |||
// Hilfsfunktion fuer die Ueberpruefung, ob ein Item sichtbar sein soll | |||
// item: Name des betroffenen Items | |||
// showList: Checkliste der sichtbaren Items (true fuer sichtbar) | |||
// hideList: Checkliste der unsichtbaren Items (true fuer unsichtbar) | |||
// return Angabe, ob das Item sichtbar sein soll | |||
function checkVisible(item, showList, hideList = undefined) { | |||
let show = true; | |||
if (showList !== undefined) { | |||
show = (showList[item] === true); // gesetzt und true | |||
} | |||
if (hideList !== undefined) { | |||
if (hideList[item] === true) { // gesetzt und true | |||
// | show = false; // NICHT anzeigen | ||
} | |||
} | } | ||
return | return show; | ||
} | } | ||
// | // Hilfsfunktion fuer die Ermittlung eines Elements der Seite | ||
// name: Name des Elements (siehe "name=") | |||
// | // index: Laufende Nummer des Elements (0-based), Default: 0 | ||
// return | // doc: Dokument (document) | ||
function | // return Gesuchtes Element mit der lfd. Nummer index oder undefined (falls nicht gefunden) | ||
function getElement(name, index = 0, doc = document) { | |||
const __TAGS = document.getElementsByName(name); | |||
const __TABLE = (__TAGS === undefined) ? undefined : __TAGS[index]; | |||
return __TABLE; | |||
return | |||
} | } | ||
// | // Hilfsfunktion fuer die Ermittlung eines Elements der Seite (Default: Tabelle) | ||
// index: Laufende Nummer des Elements (0-based) | |||
// tag: Tag des Elements ("table") | |||
// doc: Dokument (document) | |||
// return Gesuchtes Element oder undefined (falls nicht gefunden) | |||
function getTable(index, tag = "table", doc = document) { | |||
const __TAGS = document.getElementsByTagName(tag); | |||
const __TABLE = (__TAGS === undefined) ? undefined : __TAGS[index]; | |||
return __TABLE; | |||
} | |||
// Hilfsfunktion fuer die Ermittlung der Zeilen einer Tabelle | |||
// index: Laufende Nummer des Elements (0-based) | |||
// doc: Dokument (document) | |||
// return Gesuchte Zeilen oder undefined (falls nicht gefunden) | |||
function getRows(index, doc = document) { | |||
const __TABLE = getTable(index, "table", doc); | |||
const __ROWS = (__TABLE === undefined) ? undefined : __TABLE.rows; | |||
return __ROWS; | |||
return | |||
} | } | ||
// | // ==================== Abschnitt fuer Optionen auf der Seite ==================== | ||
return | // Liefert den Funktionsaufruf zur Option als String | ||
// opt: Auszufuehrende Option | |||
// isAlt: Angabe, ob AltAction statt Action gemeint ist | |||
// value: Ggfs. zu setzender Wert | |||
const | // serial: Serialization fuer String-Werte (Select, Textarea) | ||
// memory: __OPTMEM.normal = bis Browserende gespeichert (sessionStorage), __OPTMEM.unbegrenzt = unbegrenzt gespeichert (localStorage), __OPTMEM.inaktiv | |||
// return String mit dem (reinen) Funktionsaufruf | |||
function getFormAction(opt, isAlt = false, value = undefined, serial = undefined, memory = undefined) { | |||
const __STORAGE = getMemory(memory); | |||
const __MEMORY = __STORAGE.Value; | |||
const __MEMSTR = __STORAGE.Display; | |||
const __RUNPREFIX = __STORAGE.Prefix; | |||
if (__MEMORY !== undefined) { | |||
const __RELOAD = "window.location.reload()"; | |||
const __SETITEM = function(item, val, quotes = true) { | |||
return (__MEMSTR + ".setItem('" + __RUNPREFIX + item + "', " + (quotes ? "'" + val + "'" : val) + "),"); | |||
}; | |||
const __SETITEMS = function(cmd, key = undefined, val = undefined) { | |||
return ('(' + __SETITEM('cmd', cmd) + ((key === undefined) ? "" : | |||
__SETITEM('key', key) + __SETITEM('val', val, false)) + __RELOAD + ')'); | |||
}; | |||
const __CONFIG = getOptConfig(opt); | |||
const __SERIAL = getValue(serial, getValue(__CONFIG.Serial, false)); | |||
const __THISVAL = ((__CONFIG.ValType === "String") ? "'\\x22' + this.value + '\\x22'" : "this.value"); | |||
const __TVALUE = getValue(__CONFIG.ValType, __THISVAL, "new " + __CONFIG.ValType + '(' + __THISVAL + ')'); | |||
const __VALSTR = ((value !== undefined) ? JSON.stringify(value) : __SERIAL ? "JSON.stringify(" + __TVALUE + ')' : __TVALUE); | |||
const __ACTION = (isAlt ? getValue(__CONFIG.AltAction, __CONFIG.Action) : __CONFIG.Action); | |||
if (__ACTION !== undefined) { | |||
switch (__ACTION) { | |||
case __OPTACTION.SET : //return "doActionSet('" + getOptName(opt) + "', " + getNextOpt(opt, __VALSTR) + ')'; | |||
return __SETITEMS('SET', getOptName(opt), __VALSTR); | |||
case __OPTACTION.NXT : //return "doActionNxt('" + getOptName(opt) + "', " + getNextOpt(opt, __VALSTR) + ')'; | |||
return __SETITEMS('NXT', getOptName(opt), __VALSTR); | |||
case __OPTACTION.RST : //return "doActionRst()"; | |||
return __SETITEMS('RST'); | |||
default : break; | |||
} | } | ||
} | } | ||
} | |||
return undefined; | |||
} | } | ||
// | // Liefert die Funktionsaufruf zur Option als String | ||
// | // opt: Auszufuehrende Option | ||
// return | // isAlt: Angabe, ob AltAction statt Action gemeint ist | ||
function | // value: Ggfs. zu setzender Wert | ||
// type: Event-Typ fuer <input>, z.B. "click" fuer "onclick=" | |||
// serial: Serialization fuer String-Werte (Select, Textarea) | |||
// memory: __OPTMEM.normal = bis Browserende gespeichert (sessionStorage), __OPTMEM.unbegrenzt = unbegrenzt gespeichert (localStorage), __OPTMEM.inaktiv | |||
// return String mit dem (reinen) Funktionsaufruf | |||
function getFormActionEvent(opt, isAlt = false, value = undefined, type = "click", serial = undefined, memory = undefined) { | |||
const __ACTION = getFormAction(opt, isAlt, value, serial, memory); | |||
return getValue(__ACTION, "", ' on' + type + '="' + __ACTION + '"'); | |||
} | } | ||
// | // Zeigt eine Option auf der Seite als Auswahlbox an | ||
// | // opt: Anzuzeigende Option | ||
// | // return String mit dem HTML-Code | ||
function getOptionSelect(opt) { | |||
const __CONFIG = getOptConfig(opt); | |||
const __NAME = getOptName(opt); | |||
const __VALUE = getOptValue(opt); | |||
const __ACTION = getFormActionEvent(opt, false, undefined, "change", undefined); | |||
const __FORMLABEL = getValue(__CONFIG.FormLabel, __CONFIG.Label); | |||
const __LABEL = '<label for="' + __NAME + '">' + __FORMLABEL + '</label>'; | |||
let element = '<select name="' + __NAME + '" id="' + __NAME + '"' + __ACTION + '>'; | |||
for (let value of __CONFIG.Choice) { | |||
element += '\n<option value="' + value + '"' + | |||
((value === __VALUE) ? ' SELECTED' : "") + | |||
'>' + value + '</option>'; | |||
} | |||
element += '\n</select>'; | |||
return __LABEL.replace('$', element); | |||
} | } | ||
// | // Zeigt eine Option auf der Seite als Radiobutton an | ||
// opt: Anzuzeigende Option | |||
// | // return String mit dem HTML-Code | ||
// return | function getOptionRadio(opt) { | ||
function | const __CONFIG = getOptConfig(opt); | ||
const __NAME = getOptName(opt); | |||
const __VALUE = getOptValue(opt, false); | |||
const __ACTION = getFormActionEvent(opt, false, true, "click", false); | |||
const __ALTACTION = getFormActionEvent(opt, true, false, "click", false); | |||
const __ELEMENTON = '<input type="radio" name="' + __NAME + | |||
'" id="' + __NAME + 'ON" value="1"' + | |||
(__VALUE ? ' CHECKED' : __ACTION) + | |||
' /><label for="' + __NAME + 'ON">' + | |||
__CONFIG.Label + '</label>'; | |||
const __ELEMENTOFF = '<input type="radio" name="' + __NAME + | |||
'" id="' + __NAME + 'OFF" value="0"' + | |||
(__VALUE ? __ALTACTION : ' CHECKED') + | |||
' /><label for="' + __NAME + 'OFF">' + | |||
__CONFIG.AltLabel + '</label>'; | |||
return [ __ELEMENTON, __ELEMENTOFF ]; | |||
} | } | ||
// | // Zeigt eine Option auf der Seite als Checkbox an | ||
// opt: Anzuzeigende Option | |||
// | // return String mit dem HTML-Code | ||
// return | function getOptionCheckbox(opt) { | ||
function | const __CONFIG = getOptConfig(opt); | ||
const | const __NAME = getOptName(opt); | ||
const __VALUE = getOptValue(opt, false); | |||
const __ACTION = getFormActionEvent(opt, __VALUE, ! __VALUE, "click", false); | |||
const __FORMLABEL = getValue(__CONFIG.FormLabel, __CONFIG.Label); | |||
return | return '<input type="checkbox" name="' + __NAME + | ||
'" id="' + __NAME + '" value="' + __VALUE + '"' + | |||
(__VALUE ? ' CHECKED' : "") + __ACTION + ' /><label for="' + | |||
__NAME + '">' + __FORMLABEL + '</label>'; | |||
} | } | ||
// | // Zeigt eine Option auf der Seite als Daten-Textfeld an | ||
// opt: Anzuzeigende Option | |||
// | // return String mit dem HTML-Code | ||
// return | function getOptionTextarea(opt) { | ||
function | const __CONFIG = getOptConfig(opt); | ||
const __NAME = getOptName(opt); | |||
const __VALUE = getOptValue(opt); | |||
const __ACTION = getFormActionEvent(opt, false, undefined, "submit", undefined); | |||
const __SUBMIT = getValue(__CONFIG.Submit, ""); | |||
const __ONSUBMIT = ((__SUBMIT.length > 0) ? ' onKeyDown="' + __SUBMIT + '"': ""); | |||
const __FORMLABEL = getValue(__CONFIG.FormLabel, __CONFIG.Label); | |||
const __ELEMENTLABEL = '<label for="' + __NAME + '">' + __FORMLABEL + '</label>'; | |||
const __ELEMENTTEXT = '<textarea name="' + __NAME + '" id="' + __NAME + '" cols="' + __CONFIG.Cols + | |||
'" rows="' + __CONFIG.Rows + '"' + __ONSUBMIT + __ACTION + '>' + | |||
JSON.stringify(__VALUE, __CONFIG.Replace, __CONFIG.Space) + '</textarea>'; | |||
return [ __ELEMENTLABEL, __ELEMENTTEXT ]; | |||
} | } | ||
// | // Zeigt eine Option auf der Seite als Button an | ||
// | // opt: Anzuzeigende Option | ||
// | // return String mit dem HTML-Code | ||
function getOptionButton(opt) { | |||
const __CONFIG = getOptConfig(opt); | |||
const __NAME = getOptName(opt); | |||
const __VALUE = getOptValue(opt, false); | |||
const __ACTION = getFormActionEvent(opt, __VALUE, ! __VALUE, "click", false); | |||
const __BUTTONLABEL = (__VALUE ? __CONFIG.AltLabel : __CONFIG.Label); | |||
( | const __FORMLABEL = getValue(__CONFIG.FormLabel, __CONFIG.Label); | ||
return value; | return '<label for="' + __NAME + '">' + __FORMLABEL + | ||
'</label><input type="button" name="' + __NAME + | |||
'" id="' + __NAME + '" value="' + __BUTTONLABEL + '"' + | |||
__ACTION + '/>'; | |||
} | } | ||
// | // Zeigt eine Option auf der Seite an (je nach Typ) | ||
// | // opt: Anzuzeigende Option | ||
// return String mit dem HTML-Code | |||
// | function getOptionElement(opt) { | ||
const __CONFIG = getOptConfig(opt); | |||
const __TYPE = getValue(__CONFIG.FormType, __CONFIG.Type); | |||
let element = ""; | |||
if (! __CONFIG.Hidden) { | |||
switch (__TYPE) { | |||
case __OPTTYPES.MC : element = getOptionSelect(opt); | |||
} | break; | ||
case __OPTTYPES.SW : if (__CONFIG.FormLabel !== undefined) { | |||
element = getOptionCheckbox(opt); | |||
} else { | |||
element = getOptionRadio(opt); | |||
} | |||
break; | |||
case __OPTTYPES.TF : element = getOptionCheckbox(opt); | |||
break; | |||
case __OPTTYPES.SD : element = getOptionTextarea(opt); | |||
break; | |||
case __OPTTYPES.SI : element = getOptionButton(opt); | |||
break; | |||
default : break; | |||
} | |||
if (element.length === 2) { | |||
element = '<div>' + element[0] + '<br />' + element[1] + '</div>'; | |||
} | |||
} | |||
return element; | |||
} | |||
// Baut das Benutzermenu auf der Seite auf | |||
// optSet: Gesetzte Optionen | |||
// optParams: Eventuell notwendige Parameter | |||
// 'showForm': Checkliste der auf der Seite sichtbaren Optionen (true fuer sichtbar) | |||
// 'hideForm': Checkliste der auf der Seite unsichtbaren Optionen (true fuer unsichtbar) | |||
// 'formWidth': Anzahl der Elemente pro Zeile | |||
// 'formBreak': Elementnummer des ersten Zeilenumbruchs | |||
// return String mit dem HTML-Code | |||
function getForm(optSet, optParams = { }) { | |||
const __FORM = '<form id="options" method="POST"><table><tbody><tr>'; | |||
const __FORMEND = '</tr></tbody></table></form>'; | |||
const __FORMWIDTH = getValue(optParams.formWidth, 3); | |||
const __FORMBREAK = getValue(optParams.formBreak, __FORMWIDTH); | |||
const __SHOWFORM = getOptValue(optSet.showForm, true) ? optParams.showForm : { 'showForm' : true }; | |||
let form = __FORM; | |||
let count = 0; // Bisher angezeigte Optionen | |||
let column = 0; // Spalte der letzten Option (1-basierend) | |||
for (let opt in optSet) { | |||
if (checkVisible(opt, __SHOWFORM, optParams.hideForm)) { | |||
const __ELEMENT = getOptionElement(optSet[opt]); | |||
const __TDOPT = (__ELEMENT.indexOf('|') < 0) ? ' colspan="2"' : ""; | |||
if (__ELEMENT.length > 0) { | |||
if (++count > __FORMBREAK) { | |||
if (++column > __FORMWIDTH) { | |||
column = 1; | |||
} | |||
} | |||
if (column === 1) { | |||
form += '</tr><tr>'; | |||
} | |||
form += '\n<td' + __TDOPT + '>' + __ELEMENT.replace('|', '</td><td>') + '</td>'; | |||
} | |||
} | } | ||
} | } | ||
form += '\n' + __FORMEND; | |||
return | return form; | ||
} | } | ||
// | // Fuegt das Script in die Seite ein | ||
// optSet: Gesetzte Optionen | |||
// optSet: | // optParams: Eventuell notwendige Parameter | ||
// | // 'showForm': Checkliste der auf der Seite sichtbaren Optionen (true fuer sichtbar) | ||
// | // 'hideForm': Checkliste der auf der Seite unsichtbaren Optionen (true fuer unsichtbar) | ||
// | // return String mit dem HTML-Code fuer das Script | ||
// return | function getScript(optSet, optParams = { }) { | ||
//const __SCRIPT = '<script type="text/javascript">function activateMenu() { console.log("TADAAA!"); }</script>'; | |||
const | //const __SCRIPT = '<script type="text/javascript">\n\tfunction doActionNxt(key, value) { alert("SET " + key + " = " + value); }\n\tfunction doActionNxt(key, value) { alert("SET " + key + " = " + value); }\n\tfunction doActionRst(key, value) { alert("RESET"); }\n</script>'; | ||
const | //const __FORM = '<form method="POST"><input type="button" id="showOpts" name="showOpts" value="Optionen anzeigen" onclick="activateMenu()" /></form>'; | ||
const | const __SCRIPT = ""; | ||
//window.eval('function activateMenu() { console.log("TADAAA!"); }'); | |||
return __SCRIPT; | |||
} | |||
// Zeigt das Optionsmenu auf der Seite an (im Gegensatz zum Benutzermenu) | |||
// anchor: Element, das als Anker fuer die Anzeige dient | |||
// optSet: Gesetzte Optionen | |||
// optParams: Eventuell notwendige Parameter | |||
// 'showForm': Checkliste der auf der Seite sichtbaren Optionen (true fuer sichtbar) | |||
// 'hideForm': Checkliste der auf der Seite unsichtbaren Optionen (true fuer unsichtbar) | |||
// 'formWidth': Anzahl der Elemente pro Zeile | |||
// 'formBreak': Elementnummer des ersten Zeilenumbruchs | |||
function buildForm(anchor, optSet, optParams = { }) { | |||
console.log("buildForm()"); | |||
const __FORM = getForm(optSet, optParams); | |||
const __SCRIPT = getScript(optSet, optParams); | |||
addForm(anchor, __FORM, __SCRIPT); | |||
} | } | ||
// | // Informationen zu hinzugefuegten Forms | ||
const __FORMS = { }; | |||
// | // Zeigt das Optionsmenu auf der Seite an (im Gegensatz zum Benutzermenu) | ||
// | // anchor: Element, das als Anker fuer die Anzeige dient | ||
// | // form: HTML-Form des Optionsmenu (hinten angefuegt) | ||
// | // script: Script mit Reaktionen | ||
function addForm(anchor, form = "", script = "") { | |||
function | const __OLDFORM = __FORMS[anchor]; | ||
const __REST = (__OLDFORM === undefined) ? anchor.innerHTML : | |||
anchor.innerHTML.substring(0, anchor.innerHTML.length - __OLDFORM.Script.length - __OLDFORM.Form.length); | |||
} | |||
__FORMS[anchor] = { 'Script' : script, 'Form' : form }; | |||
anchor.innerHTML = __REST + script + form; | |||
} | } | ||
// | // ==================== 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 fuer '?') | |||
}; | |||
// Funktionen *************************************************************************** | |||
// | // Erschafft die Spieler-Objekte und fuellt sie mit Werten (reloadData: true = Teamuebersicht, false = Spielereinzelwerte) | ||
function init(playerRows, optSet, colIdx, offsetUpper = 1, offsetLower = 0, reloadData = false) { | |||
const __SAISON = getOptValue(optSet.saison); | |||
function | const __CURRZAT = getOptValue(optSet.aktuellerZat); | ||
const | const __BIRTHDAYS = getOptValue(optSet.birthdays, []); | ||
const | const __TCLASSES = getOptValue(optSet.tClasses, []); | ||
const __PROGRESSES = getOptValue(optSet.progresses, []); | |||
const __ZATAGES = getOptValue(optSet.zatAges, []); | |||
const __TRAINIERT = getOptValue(optSet.trainiert, []); | |||
const __POSITIONS = getOptValue(optSet.positions, []); | |||
const __PLAYERS = []; | |||
for (let i = offsetUpper, j = 0; i < playerRows.length - offsetLower; i++, j++) { | |||
const | const __CELLS = playerRows[i].cells; | ||
const __AGE = getIntFromHTML(__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], __TCLASSES[j], __PROGRESSES[j]); | |||
if (reloadData) { | |||
__NEWPLAYER.setZusatz(__ZATAGES[j], __TRAINIERT[j], __POSITIONS[j]); | |||
} | } | ||
__PLAYERS[j] = __NEWPLAYER; | |||
} | } | ||
if (reloadData) { | |||
storePlayerData(__PLAYERS, playerRows, optSet, colIdx, offsetUpper, offsetLower); | |||
if ( | |||
} else { | } else { | ||
calcPlayerData(__PLAYERS, optSet); | |||
} | } | ||
return __PLAYERS; | |||
} | } | ||
// | // Berechnet die abgeleiteten Werte in den Spieler-Objekten neu und speichert diese | ||
function calcPlayerData(players, optSet) { | |||
const __ZATAGES = []; | |||
const __TRAINIERT = []; | |||
const __POSITIONS = []; | |||
for (let i = 0; i < players.length; i++) { | |||
const __ZUSATZ = players[i].calcZusatz(); | |||
__ZATAGES[i] = __ZUSATZ.zatAge; | |||
__TRAINIERT[i] = __ZUSATZ.trainiert; | |||
__POSITIONS[i] = __ZUSATZ.bestPos; | |||
} | } | ||
setOpt(optSet.zatAges, __ZATAGES, false); | |||
setOpt(optSet.trainiert, __TRAINIERT, false); | |||
setOpt(optSet.positions, __POSITIONS, false); | |||
} | } | ||
// ===== | // Berechnet die abgeleiteten Werte in den Spieler-Objekten neu und speichert diese | ||
function storePlayerData(players, playerRows, optSet, colIdx, offsetUpper = 1, offsetLower = 0) { | |||
const __BIRTHDAYS = []; | |||
const __TCLASSES = []; | |||
const __PROGRESSES = []; | |||
for (let i = offsetUpper; i < playerRows.length - offsetLower; i++) { | |||
const __CELLS = playerRows[i].cells; | |||
__BIRTHDAYS[i - offsetUpper] = getIntFromHTML(__CELLS, colIdx.Geb); | |||
__TCLASSES[i - offsetUpper] = getTalentFromHTML(__CELLS, colIdx.Tal); | |||
__PROGRESSES[i - offsetUpper] = getStringFromHTML(__CELLS, colIdx.Auf); | |||
} | |||
setOpt(optSet.birthdays, __BIRTHDAYS, false); | |||
setOpt(optSet.tClasses, __TCLASSES, false); | |||
setOpt(optSet.progresses, __PROGRESSES, false); | |||
} | |||
// | // 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, showCol = undefined) { | |||
const | const __SHOWALL = (showCol === undefined) || (showCol === true); | ||
const __SHOWCOL = getValue(showCol, { }); | |||
this.geb = getValue(__SHOWCOL.zeigeGeb, __SHOWALL) && getOptValue(optSet.zeigeGeb); | |||
this.tal = getValue(__SHOWCOL.zeigeTal, __SHOWALL) && getOptValue(optSet.zeigeTal); | |||
this.quo = getValue(__SHOWCOL.zeigeQuote, __SHOWALL) && getOptValue(optSet.zeigeQuote); | |||
this.aufw = getValue(__SHOWCOL.zeigeAufw, __SHOWALL) && getOptValue(optSet.zeigeAufw); | |||
this.alter = getValue(__SHOWCOL.zeigeAlter, __SHOWALL) && getOptValue(optSet.zeigeAlter); | |||
this.skill = getValue(__SHOWCOL.zeigeSkill, __SHOWALL) && getOptValue(optSet.zeigeSkill); | |||
this.pos = getValue(__SHOWCOL.zeigePosition, __SHOWALL) && getOptValue(optSet.zeigePosition); | |||
this.anzOpti = getValue(__SHOWCOL.zeigeOpti, __SHOWALL) ? getOptValue(optSet.anzahlOpti) : 0; | |||
this.anzMw = getValue(__SHOWCOL.zeigeMW, __SHOWALL) ? getOptValue(optSet.anzahlMW) : 0; | |||
this.skillE = getValue(__SHOWCOL.zeigeSkillEnde, __SHOWALL) && getOptValue(optSet.zeigeSkillEnde); | |||
this.anzOptiE = getValue(__SHOWCOL.zeigeOptiEnde, __SHOWALL) ? getOptValue(optSet.anzahlOptiEnde) : 0; | |||
this.anzMwE = getValue(__SHOWCOL.zeigeMWEnde, __SHOWALL) ? getOptValue(optSet.anzahlMWEnde) : 0; | |||
this.kennzE = getOptValue(optSet.kennzeichenEnde); | |||
this.toString = function() { | |||
let result = "Skillschnitt\t\t" + this.skill + '\n'; | |||
result += "Beste Position\t" + this.pos + '\n'; | |||
result += "Optis\t\t\t" + this.anzOpti + '\n'; | |||
result += "Marktwerte\t\t" + this.anzMw + '\n'; | |||
result += "Skillschnitt Ende\t" + this.skillE + '\n'; | |||
result += "Optis Ende\t\t" + this.anzOptiE + '\n'; | |||
result += "Marktwerte Ende\t" + 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.tal) { | ||
this.addAndFillCell(headers, "Talent", titleColor); | |||
} | |||
if (this.quo) { | |||
this.addAndFillCell(headers, "Quote", titleColor); | |||
} | |||
if (this.aufw) { | |||
this.addAndFillCell(headers, "Aufwertung", titleColor); | |||
} | |||
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); | |||
} | |||
for (let i = 1; i <= 6; i++) { | |||
if (i <= this.anzOpti) { | |||
this.addAndFillCell(headers, "Opti " + i, titleColor); | |||
} | |||
if (i <= this.anzMw) { | |||
this.addAndFillCell(headers, "MW " + i, titleColor); | |||
} | |||
} | |||
// | // Titel fuer die Werte mit Ende 18 | ||
if (this.skillE) { | |||
this.addAndFillCell(headers, "Skill" + this.kennzE, titleColor); | |||
} | |||
for (let i = 1; i <= 6; i++) { | |||
if (i <= this.anzOptiE) { | |||
this.addAndFillCell(headers, "Opti " + i + this.kennzE, titleColor); | |||
} | |||
if (i <= this.anzMwE) { | |||
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 = getColor(player.getPos()); | |||
// | // Aktuelle Werte | ||
if (this.tal) { | |||
this.addAndFillCell(playerRow, player.getTalent(), __COLOR); | |||
} | |||
if (this.quo) { | |||
this.addAndFillCell(playerRow, player.getAufwertungsSchnitt(), __COLOR, 2); | |||
} | |||
if (this.aufw) { | |||
this.addAndFillCell(playerRow, player.getAufwert(), __COLOR); | |||
} | |||
if (this.geb) { | |||
this.addAndFillCell(playerRow, player.getGeb(), __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(), __POS1COLOR); | |||
} | |||
for (let i = 1; i <= 6; i++) { | |||
const __POSI = ((i === 1) ? player.getPos() : player.getPos(i)); | |||
const __COLI = getColor(__POSI); | |||
if (i <= this.anzOpti) { | |||
} | if ((i === 1) || ! player.isGoalie) { | ||
// Opti anzeigen | |||
this.addAndFillCell(playerRow, player.getOpti(__POSI), __COLI, 2); | |||
} else { | |||
// TOR, aber nicht bester Opti -> nur Zelle hinzufuegen | |||
this.addCell(playerRow); | |||
} | |||
} | |||
if (i <= this.anzMw) { | |||
if ((i === 1) || ! player.isGoalie) { | |||
// MW anzeigen | |||
this.addAndFillCell(playerRow, player.getMarketValue(__POSI), __COLI, 0); | |||
} else { | |||
// TOR, aber nicht bester MW -> nur Zelle hinzufuegen | |||
this.addCell(playerRow); | |||
} | |||
} | |||
} | |||
// | // Werte mit Ende 18 | ||
if (this.skillE) { | |||
this.addAndFillCell(playerRow, player.getSkill(__TIME.end), __COLOR, 2); | |||
} | } | ||
for (let i = 1; i <= 6; i++) { | |||
const __POSI = ((i === 1) ? player.getPos() : player.getPos(i)); | |||
const __COLI = getColor(__POSI); | |||
if (i <= this.anzOptiE) { | |||
if ((i === 1) || ! player.isGoalie) { | |||
// Opti anzeigen | |||
this.addAndFillCell(playerRow, player.getOpti(__POSI, __TIME.end), __COLI, 2); | |||
} else { | |||
// TOR, aber nicht bester Opti -> nur Zelle hinzufuegen | |||
this.addCell(playerRow); | |||
} | |||
} | |||
if (i <= this.anzMwE) { | |||
if ((i === 1) || ! player.isGoalie) { | |||
// MW anzeigen | |||
this.addAndFillCell(playerRow, player.getMarketValue(__POSI, __TIME.end), __COLI, 0); | |||
} else { | |||
// TOR, aber nicht bester MW -> nur Zelle hinzufuegen | |||
this.addCell(playerRow); | |||
} | |||
} | |||
} | |||
}; // 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.talent: Talent als Zahl (-1=wenig, 0=normal, +1=hoch) | |||
// this.aufwert: Aufwertungsstring | |||
// this.mwFormel: Benutzte MW-Formel, siehe __MWFORMEL | |||
// this.positions[][]: Positionstext und Opti; TOR-Index ist 5 | |||
// this.skillsEnd[]: Berechnet aus this.skills, this.age und aktuellerZat | |||
// in this calcZusatz()/setZusatz() definiert: | |||
// this.trainiert: Anzahl der erfolgreichen Trainingspunkte | |||
// this.bestPos: erster (bester) Positionstext | |||
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, tclass, progresses) { | |||
this.zatGeb = gebZAT; | |||
this.zatAge = this.calcZatAge(currZAT); | |||
this.talent = tclass; | |||
this.aufwert = progresses; | |||
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 __ADDRATIO = (this.getZatDone(__TIME.end) - this.getZatDone()) / this.getZatDone(); | |||
for (let i in this.skills) { | |||
const __SKILL = this.skills[i]; | |||
let progSkill = __SKILL; | |||
if (isTrainableSkill(i)) { | |||
// Auf ganze Zahl runden und parseInt(), da das sonst irgendwie als String interpretiert wird | |||
const __ADDSKILL = getMulValue(__ADDRATIO, __SKILL, 0, NaN); | |||
progSkill += __ADDSKILL; | |||
} | |||
this.skillsEnd[i] = Math.min(progSkill, 99); | |||
} | |||
}; // Ende this.initPlayer() | |||
// Setzt Nebenwerte fuer den Spieler (geht ohne initPlayer()) | |||
} | this.setZusatz = function(zatAge, trainiert, bestPos) { | ||
this.zatAge = zatAge; | |||
this.trainiert = trainiert; | |||
this.bestPos = bestPos; | |||
}; | |||
// | // Ermittelt Nebenwerte fuer den Spieler und gibt sie alle zurueck (nach initPlayer()) | ||
this.calcZusatz = function() { | |||
// | // this.zatAge bereits in initPlayer() berechnet | ||
this.trainiert = this.getTrainiert(true); // neu berechnet aus Skills | |||
this.bestPos = this.getPos(-1); // hier: -1 explizit angeben, da neu ermittelt (this.bestPos noch nicht belegt) | |||
return { | |||
return | zatAge : this.zatAge, | ||
trainiert : this.trainiert, | |||
bestPos : this.bestPos | |||
} | }; | ||
}; | |||
this.getGeb = function() { | |||
return (this.zatGeb < 0) ? '?' : this.zatGeb; | |||
}; | |||
// | this.calcZatAge = function(currZAT) { | ||
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.getZatAge = function(when = __TIME.now) { | |||
if (when === __TIME.end) { | |||
return (18 - 12) * 72 - 1; // (max.) Trainings-ZATs bis Ende 18 | |||
} else { | |||
return this.zatAge; | |||
} | |||
}; | |||
this.getZatDone = function(when = __TIME.now) { | |||
return Math.max(0, this.getZatAge(when)); | |||
}; | |||
this.getAge = function(when = __TIME.now) { | |||
if (this.mwFormel === __MWFORMEL.alt) { | |||
return (when === __TIME.end) ? 18 : this.age; | |||
} else { // Geburtstage ab Saison 10... | |||
return (13.00 + this.getZatAge(when) / 72); | |||
} | } | ||
}; | |||
this.getTrainiert = function(recalc = false) { | |||
let sum = 0; | |||
function | |||
if (recalc || (this.trainiert === undefined)) { | |||
for (let i in this.skills) { | |||
if (isTrainableSkill(i)) { | |||
sum += this.skills[i]; | |||
} | |||
} | |||
} else { | } else { | ||
sum += this.trainiert; | |||
} | } | ||
return sum; | |||
} | }; | ||
this.getAufwertungsSchnitt = function() { | |||
return parseFloat(this.getTrainiert() / this.getZatDone()); | |||
}; | |||
function | |||
this.getPos = function(idx = undefined) { | |||
const __IDXOFFSET = 1; | |||
switch (getValue(idx, 0)) { | |||
return | case -1 : return (this.bestPos = this.positions[isGoalie ? 5 : 0][0]); | ||
case 0 : return this.bestPos; | |||
return | default : return this.positions[idx - __IDXOFFSET][0]; | ||
} | |||
} | }; | ||
this.getTalent = function() { | |||
return (this.talent < 0) ? "wenig" : (this.talent > 0) ? "hoch" : "normal"; | |||
}; | |||
this.getAufwert = function() { | |||
return (this.aufwert.length > 0) ? this.aufwert : "keine"; | |||
}; | |||
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); | |||
function | 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 eine Zahl aus der Spalte einer Zeile der Tabelle aus (z.B. Alter, Geburtsdatum) | |||
// cells: Die Zellen einer Zeile | |||
// colIdxInt: Spaltenindex der gesuchten Werte | |||
// return Spalteneintrag als Zahl (-1 fuer "keine Zahl", undefined fuer "nicht gefunden") | |||
function getIntFromHTML(cells, colIdxInt) { | |||
const __CELL = cells[colIdxInt]; | |||
const __TEXT = getValue(__CELL, { }).textContent; | |||
if (__TEXT !== undefined) { | |||
try { | |||
} | const __VALUE = parseInt(__TEXT, 10); | ||
if (! isNaN(__VALUE)) { | |||
return __VALUE; | |||
} | |||
} catch (ex) { } | |||
return -1; | |||
} | } | ||
return | return undefined; | ||
} | } | ||
// | // Liest eine Dezimalzahl aus der Spalte einer Zeile der Tabelle aus | ||
// | // cells: Die Zellen einer Zeile | ||
// | // colIdxInt: Spaltenindex der gesuchten Werte | ||
// return | // return Spalteneintrag als Dezimalzahl (undefined fuer "keine Zahl" oder "nicht gefunden") | ||
function | function getFloatFromHTML(cells, colIdxFloat) { | ||
const __CELL = cells[colIdxFloat]; | |||
const __TEXT = getValue(__CELL, { }).textContent; | |||
if ( | if (__TEXT !== undefined) { | ||
try { | |||
return parseFloat(__TEXT); | |||
} catch (ex) { } | |||
} | |||
} | } | ||
return | return undefined; | ||
} | } | ||
// | // Liest einen String aus der Spalte einer Zeile der Tabelle aus | ||
// cells: Die Zellen einer Zeile | |||
// | // colIdxStr: Spaltenindex der gesuchten Werte | ||
// | // return Spalteneintrag als String ("" fuer "nicht gefunden") | ||
// return | function getStringFromHTML(cells, colIdxStr) { | ||
function | const __CELL = cells[colIdxStr]; | ||
const __TEXT = getValue(__CELL, { }).textContent; | |||
return getValue(__TEXT.toString(), ""); | |||
} | |||
// Liest die Talentklasse ("wenig", "normal", "hoch") aus der Spalte einer Zeile der Tabelle aus | |||
// cells: Die Zellen einer Zeile | |||
// colIdxStr: Spaltenindex der gesuchten Werte | |||
// return Talent als Zahl (-1=wenig, 0=normal, +1=hoch) | |||
function getTalentFromHTML(cells, colIdxTal) { | |||
const __TEXT = getStringFromHTML(cells, colIdxTal); | |||
return parseInt((__TEXT === "wenig") ? -1 : (__TEXT === "hoch") ? +1 : 0, 10); | |||
} | |||
// Liest die Einzelskills aus der Spalte einer Zeile der Tabelle aus | |||
// cells: Die Zellen einer Zeile | |||
// colIdx: Liste von Spaltenindices der gesuchten Werte mit den Eintraegen | |||
// 'Einz' (erste Spalte) und 'Zus' (Spalte hinter dem letzten Eintrag) | |||
// return Skills als Array von Zahlen | |||
function getSkillsFromHTML(cells, colIdx) { | |||
const __RESULT = []; | |||
for (let i = colIdx.Einz; i < colIdx.Zus; i++) { | |||
__RESULT[i - colIdx.Einz] = getIntFromHTML(cells, i); | |||
} | } | ||
return | return __RESULT; | ||
} | } | ||
// Liest aus, ob der Spieler Torwart oder Feldspieler ist | |||
// return Angabe, der Spieler Torwart oder Feldspieler ist | |||
function isGoalieFromHTML(cells, colIdxClass) { | |||
return (cells[colIdxClass].className === "TOR"); | |||
} | |||
// return | |||
// 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 | 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]; | |||
const __IDX = parseInt(idx, 10); | |||
// | let result = false; | ||
function | |||
if ( | for (let idxTrainable of __TRAINABLESKILLS) { | ||
if (__IDX === idxTrainable) { | |||
result = true; | |||
break; | |||
} | |||
} | } | ||
return | 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 []; | |||
} | |||
} | |||
switch ( | // 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 interne IDs auf den Seiten ==================== | ||
const __GAMETYPES = { // "Blind FSS gesucht!" | |||
'unbekannt' : -1, | |||
} | "reserviert" : 0, | ||
"Frei" : 0, | |||
"spielfrei" : 0, | |||
"Friendly" : 1, | |||
"Liga" : 2, | |||
"LP" : 3, | |||
"OSEQ" : 4, | |||
"OSE" : 5, | |||
"OSCQ" : 6, | |||
"OSC" : 7 | |||
}; | |||
const __LIGANRN = { | |||
'unbekannt' : 0, | |||
'1. Liga' : 1, | |||
'2. Liga A' : 2, | |||
'2. Liga B' : 3, | |||
'3. Liga A' : 4, | |||
'3. Liga B' : 5, | |||
'3. Liga C' : 6, | |||
'3. Liga D' : 7 | |||
}; | |||
const __LANDNRN = { | |||
'unbekannt' : 0, | |||
'Albanien' : 45, | |||
'Andorra' : 95, | |||
'Armenien' : 83, | |||
'Aserbaidschan' : 104, | |||
'Belgien' : 12, | |||
'Bosnien-Herzegowina' : 66, | |||
'Bulgarien' : 42, | |||
'D\xE4nemark' : 8, | |||
'Deutschland' : 6, | |||
'England' : 1, | |||
'Estland' : 57, | |||
'Far\xF6er' : 68, | |||
'Finnland' : 40, | |||
'Frankreich' : 32, | |||
'Georgien' : 49, | |||
'Griechenland' : 30, | |||
'Irland' : 5, | |||
'Island' : 29, | |||
'Israel' : 23, | |||
'Italien' : 10, | |||
'Kasachstan' : 105, | |||
'Kroatien' : 24, | |||
'Lettland' : 97, | |||
'Liechtenstein' : 92, | |||
'Litauen' : 72, | |||
'Luxemburg' : 93, | |||
'Malta' : 69, | |||
'Mazedonien' : 86, | |||
'Moldawien' : 87, | |||
'Niederlande' : 11, | |||
'Nordirland' : 4, | |||
'Norwegen' : 9, | |||
'\xD6sterreich' : 14, | |||
'Polen' : 25, | |||
'Portugal' : 17, | |||
'Rum\xE4nien' : 28, | |||
'Russland' : 19, | |||
'San Marino' : 98, | |||
'Schottland' : 2, | |||
'Schweden' : 27, | |||
'Schweiz' : 37, | |||
'Serbien und Montenegro' : 41, | |||
'Slowakei' : 70, | |||
'Slowenien' : 21, | |||
'Spanien' : 13, | |||
'Tschechien' : 18, | |||
'T\xFCrkei' : 39, | |||
'Ukraine' : 20, | |||
'Ungarn' : 26, | |||
'Wales' : 3, | |||
'Weissrussland' : 71, | |||
'Zypern' : 38 | |||
}; | |||
// ==================== Abschnitt fuer Daten des Spielplans ==================== | |||
// Gibt die ID fuer den Namen eines Wettbewerbs zurueck | |||
// gameType: Name des Wettbewerbs eines Spiels | |||
// return OS2-ID fuer den Spieltyp (1 bis 7), 0 fuer spielfrei/Frei/reserviert, -1 fuer ungueltig | |||
function getGameTypeID(gameType) { | |||
return getValue(__GAMETYPES[gameType], __GAMETYPES.unbekannt); | |||
} | } | ||
// | // Gibt die ID des Landes mit dem uebergebenen Namen zurueck. | ||
// land: Name des Landes | |||
// | // return OS2-ID des Landes, 0 fuer ungueltig | ||
// | function getLandNr(land) { | ||
return getValue(__LANDNRN[land], __LANDNRN.unbekannt); | |||
function | |||
return | |||
} | } | ||
// | // Gibt die ID der Liga mit dem uebergebenen Namen zurueck. | ||
// land: Name der Liga | |||
// return OS2-ID der Liga, 0 fuer ungueltig | |||
function getLigaNr(liga) { | |||
return getValue(__LIGANRN[liga], __LIGANRN.unbekannt); | |||
// | |||
// return | |||
function | |||
return | |||
} | } | ||
// | // ==================== Abschnitt fuer sonstige Parameter ==================== | ||
const __TEAMSEARCHHAUPT = { // Parameter zum Team "<b>Willkommen im Managerbüro von TEAM</b><br>LIGA LAND<a href=..." | |||
} | 'Zeile' : 0, | ||
'Spalte' : 1, | |||
'start' : " von ", | |||
'middle' : "</b><br>", | |||
'liga' : ". Liga", | |||
'land' : ' ', | |||
'end' : "<a href=" | |||
}; | |||
// | const __TEAMSEARCHTEAM = { // Parameter zum Team "<b>TEAM - LIGA <a href=...>LAND</a></b>" | ||
// | 'Zeile' : 0, | ||
// | 'Spalte' : 0, | ||
'start' : "<b>", | |||
'middle' : " - ", | |||
'liga' : ". Liga", | |||
'land' : 'target="_blank">', | |||
'end' : "</a></b>" | |||
}; | |||
// 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 "startTEAMmiddleLIGA...landLANDend", LIGA = "#liga[ (A|B|C|D)]" | |||
// teamSeach: Muster fuer die Suche, die Eintraege fuer 'start', 'middle', 'liga', 'land' und 'end' enthaelt | |||
// return Im Beispiel { 'Team' : "TEAM", 'Liga' : "LIGA", 'Land' : "LAND", 'LdNr' : LAND-NUMMER, 'LgNr' : LIGA-NUMMER }, | |||
// z.B. { 'Team' : "Choromonets Odessa", 'Liga' : "1. Liga", 'Land' : "Ukraine", 'LdNr' : 20, 'LgNr' : 1 } | |||
function getTeamParamsFromTable(table, teamSearch = undefined) { | |||
const __TEAMSEARCH = getValue(teamSearch, __TEAMSEARCHHAUPT); | |||
const __TEAMCELLROW = getValue(__TEAMSEARCH.Zeile, 0); | |||
const __TEAMCELLCOL = getValue(__TEAMSEARCH.Spalte, 0); | |||
const __TEAMCELLSTR = table.rows[__TEAMCELLROW].cells[__TEAMCELLCOL].innerHTML; | |||
const __SEARCHSTART = __TEAMSEARCH.start; | |||
const __SEARCHMIDDLE = __TEAMSEARCH.middle; | |||
const __SEARCHLIGA = __TEAMSEARCH.liga; | |||
const __SEARCHLAND = __TEAMSEARCH.land; | |||
const __SEARCHEND = __TEAMSEARCH.end; | |||
const __INDEXSTART = __TEAMCELLSTR.indexOf(__SEARCHSTART); | |||
const __INDEXEND = __TEAMCELLSTR.indexOf(__SEARCHEND); | |||
let teamParams = __TEAMCELLSTR.substring(__INDEXSTART + __SEARCHSTART.length, __INDEXEND); | |||
const __INDEXLIGA = teamParams.indexOf(__SEARCHLIGA); | |||
const __INDEXMIDDLE = teamParams.indexOf(__SEARCHMIDDLE); | |||
let land = (__INDEXLIGA > 0) ? teamParams.substring(__INDEXLIGA + __SEARCHLIGA.length) : undefined; | |||
const __TEAM = (__INDEXMIDDLE > 0) ? teamParams.substring(0, __INDEXMIDDLE) : undefined; | |||
let liga = ((__INDEXLIGA > 0) && (__INDEXMIDDLE > 0)) ? teamParams.substring(__INDEXMIDDLE + __SEARCHMIDDLE.length) : undefined; | |||
if (land !== undefined) { | |||
if (land.charAt(2) === ' ') { // Land z.B. hinter "2. Liga A " statt "1. Liga " | |||
land = land.substr(2); | |||
} | |||
if (liga !== undefined) { | |||
liga = liga.substring(0, liga.length - land.length); | |||
} | |||
const __INDEXLAND = land.indexOf(__SEARCHLAND); | |||
if (__INDEXLAND > -1) { | |||
land = land.substr(__INDEXLAND + __SEARCHLAND.length); | |||
} | |||
} | |||
const __RET = { | |||
'Team' : __TEAM, | |||
'Liga' : liga, | |||
'Land' : land, | |||
'LdNr' : getLandNr(land), | |||
'LgNr' : getLigaNr(liga) | |||
}; | |||
return __RET; | |||
} | } | ||
// | // Verarbeitet die URL der Seite und ermittelt die Nummer der gewuenschten Unterseite | ||
// | // url: Adresse der Seite | ||
// | // return Parameter aus der URL der Seite als Nummer | ||
// | function getPageIdFromURL(url) { | ||
// Variablen zur Identifikation der Seite | |||
const __SUCH = "page="; | |||
const __INDEXS = url.lastIndexOf(__SUCH); | |||
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 + __SUCH.length, url.length), 10); | |||
} else { | |||
// Wert von page setzt sich aus allen Zeichen zwischen "page=" und '&' zusammen | |||
page = parseInt(url.substring(__INDEXS + __SUCH.length, url.indexOf('&', __INDEXS)), 10); | |||
} | |||
} | } | ||
return | return page; | ||
} | } | ||
// | // Gibt die laufende Nummer des ZATs im Text einer Zelle zurueck | ||
// cell: Tabellenzelle mit der ZAT-Nummer im Text | |||
// | // return ZAT-Nummer im Text | ||
// return | function getZATNrFromCell(cell) { | ||
function | 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 __TEAMPARAMS = getTeamParamsFromTable(getTable(1), __TEAMSEARCHHAUPT); // Link mit Team, Liga, Land... | |||
buildOptions(__OPTCONFIG, __OPTSET, { | |||
'teamParams' : __TEAMPARAMS, | |||
'hideMenu' : true | |||
}); | |||
const __NEXTZAT = getZATNrFromCell(getRows(0)[2].cells[0]); // "Der naechste ZAT ist ZAT xx und ..." | |||
const __CURRZAT = __NEXTZAT - 1; | |||
const __DATAZAT = getOptValue(__OPTSET.datenZat); | |||
if (__CURRZAT >= 0) { | |||
console.log("Aktueller ZAT: " + __CURRZAT); | |||
// Neuen aktuellen ZAT speichern... | |||
setOpt(__OPTSET.aktuellerZat, __CURRZAT, false); | |||
if (! | if (__CURRZAT !== __DATAZAT) { | ||
console.log(__DATAZAT + " => " + __CURRZAT); | |||
// ... und ZAT-bezogene Daten als veraltet markieren | |||
deleteOptions(__OPTSET, __DATAOPTS, true, true); | |||
// Neuen Daten-ZAT speichern... | |||
setOpt(__OPTSET.datenZat, __CURRZAT, false); | |||
} | } | ||
} | } | ||
} | } | ||
// | // Verarbeitet Ansicht "Teamuebersicht" | ||
// | function procTeamuebersicht() { | ||
const __ROWOFFSETUPPER = 1; // Header-Zeile | |||
const __ROWOFFSETLOWER = 1; // Ziehen-Button | |||
const | |||
const __COLUMNINDEX = { | |||
'Age' : 0, | |||
'Geb' : 1, | |||
'Flg' : 2, | |||
'Land' : 3, | |||
'U' : 4, | |||
'Skill' : 5, | |||
'Tal' : 6, | |||
'Akt' : 7, | |||
'Auf' : 8, | |||
'Zus' : 9 | |||
}; | |||
if (getElement('transfer') !== undefined) { | |||
console.log("Ziehen-Seite"); | |||
} else if (getRows(1) === undefined) { | |||
console.log("Diese Seite ist ohne Team nicht verf\xFCgbar!"); | |||
} else { | |||
buildOptions(__OPTCONFIG, __OPTSET, { | |||
'menuAnchor' : getTable(0, "div"), | |||
'showForm' : { | |||
'sepStyle' : true, | |||
'sepColor' : true, | |||
'sepWidth' : true, | |||
'aktuellerZat' : true, | |||
'team' : true, | |||
'zeigeAlter' : true, | |||
'zeigeQuote' : true, | |||
'zeigePosition' : true, | |||
'zatAges' : true, | |||
'trainiert' : true, | |||
'positions' : true, | |||
'reset' : true, | |||
'showForm' : true | |||
}, | |||
'formWidth' : 1 | |||
}); | |||
const __COLMAN = new ColumnManager(__OPTSET, { | |||
'zeigeAlter' : getOptValue(__OPTSET.zatAges, false, true), | |||
'zeigeQuote' : getOptValue(__OPTSET.trainiert, false, true), | |||
'zeigePosition' : getOptValue(__OPTSET.positions, false, true) | |||
}); | |||
const __ROWS = getRows(1); | |||
const __HEADERS = __ROWS[0]; | |||
const __TITLECOLOR = getColor("LEI"); // "#FFFFFF" | |||
__COLMAN.addTitles(__HEADERS, __TITLECOLOR); | |||
const __PLAYERS = init(__ROWS, __OPTSET, __COLUMNINDEX, __ROWOFFSETUPPER, __ROWOFFSETLOWER, true); | |||
for (let i = 0; i < __PLAYERS.length; i++) { | |||
__COLMAN.addValues(__PLAYERS[i], __ROWS[i + __ROWOFFSETUPPER], __TITLECOLOR); | |||
} | } | ||
// Format der Trennlinie zwischen den Monaten... | |||
const __BORDERSTRING = getOptValue(__OPTSET.sepStyle) + ' ' + getOptValue(__OPTSET.sepColor) + ' ' + getOptValue(__OPTSET.sepWidth); | |||
separateGroups(__ROWS, __BORDERSTRING, __COLUMNINDEX.Age, __ROWOFFSETUPPER, __ROWOFFSETLOWER, -1, 0); | |||
} | } | ||
} | } | ||
// Verarbeitet Ansicht "Spielereinzelwerte" | |||
function procSpielereinzelwerte() { | |||
const __ROWOFFSETUPPER = 1; // Header-Zeile | |||
const __ROWOFFSETLOWER = 0; | |||
// Verarbeitet Ansicht " | |||
function | |||
const __ROWOFFSETUPPER = 1; // Header-Zeile | |||
const __ROWOFFSETLOWER = | |||
const __COLUMNINDEX = { | 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 | |||
}; | |||
if (getRows(1) === undefined) { | |||
console.log("Diese Seite ist ohne Team nicht verf\xFCgbar!"); | |||
} else { | } else { | ||
buildOptions(__OPTCONFIG, __OPTSET, { | |||
'menuAnchor' : getTable(0, "div"), | |||
'hideForm' : { | |||
'zatAges' : true, | |||
'trainiert' : true, | |||
'positions' : true | |||
}, | |||
'formWidth' : 1 | |||
}); | |||
const __COLMAN = new ColumnManager(__OPTSET); | |||
const __ROWS = getRows(1); | |||
const __HEADERS = __ROWS[0]; | |||
const __TITLECOLOR = getColor("LEI"); // "#FFFFFF" | |||
__COLMAN.addTitles(__HEADERS, __TITLECOLOR); | |||
const __PLAYERS = init(__ROWS, __OPTSET, __COLUMNINDEX, __ROWOFFSETUPPER, __ROWOFFSETLOWER, false); | |||
for (let i = 0; i < __PLAYERS.length; i++) { | |||
__COLMAN.addValues(__PLAYERS[i], __ROWS[i + __ROWOFFSETUPPER], __TITLECOLOR); | |||
} | |||
} | |||
// Format der Trennlinie zwischen den Monaten... | |||
const __BORDERSTRING = getOptValue(__OPTSET.sepStyle) + ' ' + getOptValue(__OPTSET.sepColor) + ' ' + getOptValue(__OPTSET.sepWidth); | |||
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 *** | // *** EOF *** | ||
</pre> | </pre> |