Life In 19x19
http://www.lifein19x19.com/

Enhanced rankings at goratings.org -Update: Added Age column
http://www.lifein19x19.com/viewtopic.php?f=13&t=18650
Page 1 of 2

Author:  Toukopouko [ Fri Mar 18, 2022 9:35 am ]
Post subject:  Enhanced rankings at goratings.org -Update: Added Age column

Hey,

I made a small script that adds gender and country/region filters to goratings.org.

Image

How to use in Chrome Browser?
Please note! An updated version of the script is in post #4
1. Add a new bookmark in Chrome (Right click the bookmark bar and select "Add Page..."). Add a name (for example "Enhance Ratings").
2. Copy-paste the following script to the URL part of the bookmark. Save.
Code:
javascript:function fn(){ tables = Array.from(document.getElementsByTagName("tbody")); rankingTable = tables.at(-1); rankingTableRows = Array.from(rankingTable.children); if (rankingTableRows[0].children.length > 5) { console.log("Already initialized.."); } else { console.log("Initializing the enhanced rankings.."); gender = "all"; flag = "all"; function updateTable() { rank = 1; rankingTableRows.slice(1).forEach(el => { elGender = el.children[3]?.children[0]?.textContent === "♂" ? "men" : "women"; elFlag = el.children[4]?.children[0]?.alt; if (!['cn', 'jp', 'kr', 'tw'].includes(elFlag)) { elFlag = "other"; } if ((gender === "all" || elGender === gender) && (flag == "all" || elFlag === flag)) { el.children[0].textContent = rank++; el.style.display = "table-row"; } else { el.style.display = "none"; } }); } function createGenderSelect(parentEl) { const genderSelect = document.createElement("SELECT"); genderSelect.setAttribute("id", "genderSelect"); const all = document.createElement("option"); const men = document.createElement("option"); const women = document.createElement("option"); all.setAttribute("value", "all"); men.setAttribute("value", "men"); women.setAttribute("value", "women"); all.textContent = "All"; men.textContent = "Men"; women.textContent = "Women"; genderSelect.append(all, men, women); genderSelect.onchange = function(event){gender = event.target.value; updateTable();}; parentEl.setAttribute('style', 'white-space: pre;'); parentEl.textContent = "Gender\r\n"; parentEl.appendChild(genderSelect); } function createFlagSelect(parentEl) { const flagSelect = document.createElement("SELECT"); flagSelect.setAttribute("id", "flagSelect"); const all = document.createElement("option"); const china = document.createElement("option"); const japan = document.createElement("option"); const korea = document.createElement("option"); const taiwan = document.createElement("option"); const other = document.createElement("option"); all.setAttribute("value", "all"); china.setAttribute("value", "cn"); japan.setAttribute("value", "jp"); korea.setAttribute("value", "kr"); taiwan.setAttribute("value", "tw"); other.setAttribute("value", "other"); all.textContent = "All"; china.textContent = "China"; japan.textContent = "Japan"; korea.textContent = "Korea"; taiwan.textContent = "Taiwan"; other.textContent = "Other"; flagSelect.append(all, china, japan, korea, taiwan, other); flagSelect.onchange = function(event){flag = event.target.value; updateTable();}; parentEl.setAttribute('style', 'white-space: pre;'); parentEl.textContent = "Flag\r\n"; parentEl.appendChild(flagSelect); } header = rankingTableRows[0]; headerRow = header.children; headerRow[0].setAttribute('style', 'white-space: pre;'); headerRow[0].textContent = "Overall\r\nRank"; createGenderSelect(headerRow[2]); createFlagSelect(headerRow[3]); newRank = headerRow[0].cloneNode(); newRank.textContent = "Rank"; header.prepend(newRank); rank = 1; rankingTableRows.slice(1).forEach(el => { copyEl = el.children[0].cloneNode(); copyEl.textContent = rank++; el.prepend(copyEl); }); } } fn();

3. Navigate to https://www.goratings.org/en/. Click the bookmark you saved. Voila!

Full Code
Here is an easier-to-read version of the code (without the javascript: prefix). Feel free to inspect or improve, but please share with everyone if you make something cool :tmbup:
Code:
function fn(){
tables = Array.from(document.getElementsByTagName("tbody"));
rankingTable = tables.at(-1);
rankingTableRows = Array.from(rankingTable.children);
if (rankingTableRows[0].children.length > 5) {
    console.log("Already initialized..");
} else {
    console.log("Initializing the enhanced rankings..");
    gender = "all";
    flag = "all";

    function updateTable() {
        rank = 1;
        rankingTableRows.slice(1).forEach(el => {
            elGender = el.children[3]?.children[0]?.textContent === "♂" ? "men" : "women";
            elFlag = el.children[4]?.children[0]?.alt;
            if (!['cn', 'jp', 'kr', 'tw'].includes(elFlag)) {
                elFlag = "other";
            }
           
            if ((gender === "all" || elGender === gender) &&
                (flag == "all" || elFlag === flag)) {
                el.children[0].textContent = rank++;
                el.style.display = "table-row";
            } else {
                el.style.display = "none";
            }
        });
    }

    function createGenderSelect(parentEl) {
      const genderSelect = document.createElement("SELECT");
      genderSelect.setAttribute("id", "genderSelect");
   
      const all = document.createElement("option");
      const men = document.createElement("option");
      const women = document.createElement("option");
      all.setAttribute("value", "all");
      men.setAttribute("value", "men");
      women.setAttribute("value", "women");
      all.textContent = "All";
      men.textContent = "Men";
      women.textContent = "Women";
      genderSelect.append(all, men, women);
      genderSelect.onchange = function(event){gender = event.target.value; updateTable();};
      parentEl.setAttribute('style', 'white-space: pre;');
      parentEl.textContent = "Gender\r\n";
      parentEl.appendChild(genderSelect);
    }

    function createFlagSelect(parentEl) {
      const flagSelect = document.createElement("SELECT");
      flagSelect.setAttribute("id", "flagSelect");
   
      const all = document.createElement("option");
      const china = document.createElement("option");
      const japan = document.createElement("option");
      const korea = document.createElement("option");
      const taiwan = document.createElement("option");
      const other = document.createElement("option");
      all.setAttribute("value", "all");
      china.setAttribute("value", "cn");
      japan.setAttribute("value", "jp");
      korea.setAttribute("value", "kr");
      taiwan.setAttribute("value", "tw");
      other.setAttribute("value", "other");
      all.textContent = "All";
      china.textContent = "China";
      japan.textContent = "Japan";
      korea.textContent = "Korea";
      taiwan.textContent = "Taiwan";
      other.textContent = "Other";
      flagSelect.append(all, china, japan, korea, taiwan, other);
      flagSelect.onchange = function(event){flag = event.target.value; updateTable();};
      parentEl.setAttribute('style', 'white-space: pre;');
      parentEl.textContent = "Flag\r\n";
      parentEl.appendChild(flagSelect);
    }
   
    header = rankingTableRows[0];
    headerRow = header.children;
    headerRow[0].setAttribute('style', 'white-space: pre;');
    headerRow[0].textContent = "Overall\r\nRank";
    createGenderSelect(headerRow[2]);
    createFlagSelect(headerRow[3]);
    newRank = headerRow[0].cloneNode();
    newRank.textContent = "Rank";
    header.prepend(newRank);
   
    rank = 1;
    rankingTableRows.slice(1).forEach(el => {
        copyEl = el.children[0].cloneNode();
        copyEl.textContent = rank++;
        el.prepend(copyEl);
    });
}
}
fn();


Please Note! Always be cautious when you copy-paste scripts from online!

Author:  pajaro [ Sat Mar 19, 2022 4:16 am ]
Post subject:  Re: Enhanced rankings at goratings.org

Very interesting, although I won't try it myself.

Have you tried submitting it to Rémi Coulom?

Author:  Toukopouko [ Sat Mar 19, 2022 12:47 pm ]
Post subject:  Re: Enhanced rankings at goratings.org

pajaro wrote:
Have you tried submitting it to Rémi Coulom?
Hey thanks! I just sent him an email! Let's see what he thinks!

Btw. I have some other ideas for the website too! Ideas that stats nerds like me would love. If I have free time next week, I'll try to implement something :study:

Author:  Toukopouko [ Mon Mar 21, 2022 10:35 am ]
Post subject:  Re: Enhanced rankings at goratings.org -Update: Added Age co

An update!
1. A new column: Age
2. You can now sort by Age or Elo.
3. Age column also has filters, so you can get rankings for different age groups.

Here are the ratings for women under 18:
Image

Please let me know what you think :tmbup:

How to use in Chrome browser?
1. Add age data to Chrome local storage.
1a. First, navigate to https://www.goratings.org/en/ (The local storage is site specific, so the website has to be open before adding data to the storage!)
1b. Then, open Chrome devtools console: Click the three dots ⋮ in the upper right-hand corner of the browser window. Choose More Tools -> Developer Tools. Make sure that Console-tab is open.
1c. Finally copy-paste the following code to the console and press enter. It adds the date of birth data to goratings local storage for age calculation. (You only need to do this step once, unless you erase your browsing data)

Please Note! This was updated on 2022-03-23! You have to re-do this step to get the latest birthdays!
Code:
window.localStorage.setItem('dobs', '{"p6":"1977-09-19","p11":"1964-08-26","p18":"1975-07-29","p24":"1984-12-10","p25":"1960-03-20","p30":"1966-04-25","p32":"1963-05-25","p36":"1942-05-06","p41":"1971-12-08","p43":"1977-11-23","p44":"1968-05-24","p48":"1958-05-05","p49":"1953-02-01","p50":"1952-09-10","p51":"1959-04-05","p52":"1967-03-04","p53":"1984-05-14","p55":"1968-03-08","p58":"1982-03-27","p61":"1970-10-18","p62":"1941-10-20","p64":"1978-09-06","p65":"1972-09-09","p66":"1973-03-09","p69":"1977-12-26","p70":"1961-11-22","p71":"1958-11-07","p73":"1946-09-02","p78":"1983-01-26","p82":"1951-01-01","p88":"1962-03-17","p90":"1966-02-11","p92":"1967-04-16","p93":"1976-08-14","p95":"1970-04-18","p98":"1956-06-20","p99":"1982-11-27","p100":"1985-06-07","p107":"1952-09-17","p108":"1980-01-20","p109":"1968-06-22","p114":"1985-07-15","p115":"1963-12-28","p116":"1977-10-07","p118":"1985-11-09","p119":"1960-03-13","p120":"1984-12-27","p124":"1952-08-17","p125":"1985-04-01","p127":"1983-11-04","p128":"1984-03-27","p129":"1969-06-03","p133":"1984","p136":"1980-02-23","p139":"1974-07-28","p144":"1979-09-25","p149":"1953-03-10","p150":"1962-01-26","p155":"1976-11-07","p156":"1951-01-15","p158":"1942-05-12","p159":"1975-05-12","p161":"1985-03-12","p162":"1963-05-06","p164":"1972-09-29","p172":"1970-06-22","p175":"1976-10-26","p176":"1987-03-30","p178":"1991-07-03","p179":"1983-02-03","p180":"1977-06-22","p181":"1969-05-01","p182":"1981-01-07","p184":"1982-01-18","p186":"1979-06-02","p190":"1981-08-24","p192":"1949-04-02","p194":"1979-01-24","p195":"1957-11-15","p196":"1956-04-28","p197":"1970-12-21","p201":"1973-03-23","p202":"1966-03-29","p203":"1957-12-09","p205":"1962-02-17","p206":"1958-02-07","p208":"1982-11-25","p222":"1948-08-15","p223":"1958-08-12","p230":"1959-04-08","p235":"1958-08-03","p236":"1970-03-30","p237":"1977-05-18","p241":"1985-10-28","p243":"1949-08-13","p244":"1940-08-02","p250":"1980-02-25","p251":"1972-02-11","p253":"1984-09-10","p254":"1959-12-11","p255":"1970-04-29","p256":"1966-10-20","p257":"1971-02-12","p258":"1977-11-23","p259":"1952-05-22","p261":"1974-12-10","p262":"1978-02-02","p267":"1987-11-20","p268":"1980-11-14","p270":"1952-03-30","p273":"1969-06-24","p274":"1949-11-29","p275":"1966-08-07","p276":"1969-07-04","p277":"1968-08-14","p278":"1986-07-02","p280":"1955-01-29","p283":"1954-08-23","p284":"1966-03-22","p285":"1979-08-06","p286":"1977-06-20","p287":"1974-08-14","p288":"1944-06-25","p289":"1961-11-27","p294":"1956-02-10","p295":"1957-01-10","p297":"1989-12-16","p298":"1963-01-03","p299":"1986-09-07","p300":"1984-08-28","p302":"1985-10-27","p303":"1987-08-23","p304":"1957-09-08","p305":"1955-01-04","p307":"1974-08-05","p308":"1969-01-19","p310":"1982-09-26","p313":"1989-01-23","p314":"1972-12-07","p315":"1986-07-02","p316":"1979-09-11","p317":"1964-03-21","p324":"1966-10-02","p327":"1989-01-31","p330":"1974-06-22","p333":"1953-06-04","p334":"1976-05-22","p335":"1964-09-07","p340":"1987-08-07","p341":"1969-09-23","p345":"1988-09-12","p347":"1959-06-14","p349":"1981-08-31","p350":"1960-10-16","p351":"1976-07-31","p352":"1980-09-08","p353":"1949-05-05","p355":"1971-05-23","p358":"1987-05-18","p359":"1980-07-04","p360":"1980-09-10","p363":"1968-04-14","p366":"1971-10-19","p367":"1983-09-23","p372":"1978-04-12","p379":"1988-12-24","p381":"1991-03-08","p383":"1988-01-18","p384":"1981-08-23","p410":"1987-02-12","p418":"1981","p433":"1991-01-15","p434":"1988-01-22","p440":"1974-06-05","p449":"1991-01-11","p458":"1990-07-31","p463":"1987-04-11","p466":"1988-06-08","p468":"1990-01-18","p469":"1983-12","p487":"1988-09-05","p489":"1979-02-04","p498":"1988-01-24","p508":"1988-07-29","p511":"1975-09-24","p520":"1983-06-16","p538":"1985-07-30","p539":"1970-04-11","p553":"1978-10-18","p555":"1958-06-02","p558":"1945-08-03","p560":"1956-10-27","p567":"1967-07-19","p568":"1956-01-01","p569":"1989-09-19","p571":"1982-12-24","p572":"1988-10-05","p575":"1983-11-23","p576":"1987-10-23","p577":"1981-10-05","p580":"1991-12-04","p581":"1974-11-17","p583":"1983-11-07","p585":"1989-01-30","p598":"1977-06-15","p600":"1983-04-24","p601":"1989-05-24","p602":"1984-03-22","p603":"1983-10-01","p604":"1981-10-22","p605":"1961-11-08","p611":"1950-06-29","p613":"1959-05-30","p617":"1956-10-24","p618":"1952-11-13","p624":"1947-03-12","p639":"1950-02-23","p648":"1957-02-12","p651":"1952-11-11","p655":"1956-07-27","p658":"1954-10-08","p663":"1960-09-12","p666":"1984-07-11","p669":"1955-11-18","p672":"1978-07-27","p676":"1986-09-02","p697":"1965-04-05","p698":"1978-10-31","p699":"1970-05-19","p705":"1971-11-25","p707":"1972-10-28","p740":"1969-03-09","p765":"1976-01-16","p766":"1974-01-14","p769":"1980-09-20","p770":"1970-04-05","p771":"1948-01-02","p772":"1972-11-19","p773":"1966-09-22","p774":"1965-06-09","p777":"1970-05-08","p778":"1970-05-01","p779":"1973-04-10","p782":"1984-05-25","p783":"1969-09-08","p784":"1975-02-22","p786":"1971-08-05","p787":"1971-04-17","p789":"1972-06-16","p790":"1973-07-09","p792":"1985-08-25","p793":"1977-08-16","p794":"1975-12-16","p795":"1974-05-14","p796":"1949-01-09","p797":"1968-07-08","p800":"1964-08-12","p811":"1954-06-22","p813":"1961-08-07","p816":"1978-06-10","p817":"1966-11-23","p818":"1961-12-30","p820":"1972-10-02","p821":"1944-01-15","p827":"1937-07-04","p834":"1963-01-20","p836":"1965-08-11","p837":"1983-07-14","p838":"1973-08-21","p839":"1978-11-21","p851":"1943-02-18","p852":"1963-06-27","p861":"1978-03-31","p862":"1989-06-13","p869":"1957-08-04","p870":"1979-02-15","p872":"1971-05-14","p878":"1954-09-28","p887":"1973-02-08","p888":"1987-04-10","p889":"1985-08-19","p890":"1978-06-12","p891":"1980-02-09","p892":"1970-01-03","p893":"1989-04-16","p895":"1986-10-02","p896":"1981-08-02","p897":"1993-01-15","p911":"1970-12-25","p913":"1990-12-14","p914":"1975-02-04","p917":"1950-06-05","p923":"1942-12-07","p928":"1927-03-06","p936":"1963-11-11","p937":"1971-12-21","p951":"1967-05-03","p956":"1965-09-13","p957":"1975-07-23","p959":"1972-12-12","p960":"1989-11-16","p963":"1989-09-09","p964":"1991-10-17","p967":"1993-09-12","p968":"1991-09-21","p970":"1990-04-12","p971":"1990-01-31","p981":"1992-01-01","p984":"1951-09-19","p985":"1983-06-11","p988":"1989-11-07","p990":"1981-09-24","p991":"1979-11-26","p992":"1989-09-08","p993":"1992-01-14","p994":"1987-12-24","p995":"1993-03-10","p997":"1989-07-21","p999":"1990-07-06","p1000":"1980-11-15","p1001":"1981-02-15","p1003":"1988-11-27","p1004":"1985-06-01","p1006":"1980-04-02","p1007":"1981-11-19","p1009":"1988-03-18","p1010":"1988-06-16","p1012":"1977-04-06","p1013":"1979-01-16","p1015":"1964-11-06","p1016":"1970-07-05","p1017":"1974-08-06","p1018":"1973-11-25","p1020":"1963-03-19","p1023":"1977-09-27","p1025":"1978-07-11","p1027":"1991-07-10","p1028":"1988-05-26","p1032":"1961-07-12","p1039":"1988-03-02","p1044":"1987-01-07","p1045":"1994-12-20","p1046":"1991-12-03","p1047":"1990-08-25","p1051":"1991-03-23","p1059":"1974-07-27","p1061":"2003-04-23","p1062":"1989-02-10","p1064":"1976-11-09","p1065":"1984-03-29","p1066":"1962-04-26","p1069":"1990-12-06","p1071":"1991-11-08","p1072":"1987-02-16","p1073":"1991-07-15","p1074":"1992-07-25","p1078":"1989-10-23","p1082":"1994-04-08","p1083":"1983-03-03","p1086":"1988-05-16","p1087":"1990-05-02","p1089":"1974-06-14","p1090":"1993-01-11","p1095":"1987-06-10","p1096":"1977-04-29","p1099":"1992-08-11","p1100":"1988-04-02","p1101":"1994-07-05","p1105":"1990-08-01","p1107":"1990-02-19","p1108":"1993-06-23","p1110":"1991-03-09","p1113":"1989-07-26","p1114":"1995-06-19","p1116":"1982-07-07","p1117":"1990-01-01","p1119":"1977-08-13","p1120":"1991-05-13","p1122":"1990-12-20","p1123":"1986-07-09","p1125":"1987-01-21","p1128":"1989-05-30","p1132":"1991-11-26","p1135":"1994-06-17","p1137":"1988-06-11","p1141":"1989-04-22","p1142":"1990-11-03","p1143":"1994-05-26","p1145":"1986-07-09","p1146":"1989-03-27","p1147":"1991-07-22","p1149":"1993-04-20","p1151":"1992-08-06","p1152":"1992-10-28","p1155":"1996-01-08","p1157":"1992-05-14","p1160":"1989-07-20","p1162":"1990-05-11","p1163":"1990-06-03","p1164":"1994-03-01","p1166":"1992-09-30","p1168":"1966-12-03","p1169":"1991-03-24","p1171":"1994-04-23","p1173":"1991-09-16","p1175":"1995-02-01","p1176":"1991-04-12","p1178":"1992-05-08","p1180":"1995-11-08","p1184":"1992-04-19","p1186":"1989-03-06","p1187":"1994-02-27","p1188":"1994-03-15","p1189":"1991-11-03","p1190":"1991-04-15","p1191":"1987-07-07","p1193":"1998-10-19","p1194":"1996-08-06","p1195":"1997-08-02","p1197":"1995-01-30","p1200":"1989-01-01","p1202":"1991-09-21","p1206":"1978-11-23","p1209":"1981-07-31","p1210":"1992-07-23","p1213":"1967-10-28","p1220":"1992-01-01","p1221":"1990-09-19","p1222":"1992-07-31","p1223":"1996-10-07","p1224":"1998-09-18","p1225":"1997-11-23","p1227":"1992-11-02","p1229":"1989-02-08","p1230":"1995-05-14","p1231":"1997-06-10","p1232":"1997-01-15","p1234":"1989-09-18","p1235":"1996-01-26","p1236":"1994-05-19","p1240":"1984-10-03","p1243":"1996-08-05","p1246":"1989-08-13","p1248":"1991-02-13","p1250":"1996-04-26","p1251":"1997-02-07","p1252":"1973-10-04","p1253":"1998-03-13","p1254":"1993-03-24","p1255":"1996-01-15","p1257":"1994-11-29","p1259":"1998-02-04","p1261":"1995-04-08","p1262":"1996-02-21","p1264":"1996-05-15","p1265":"1990-08-21","p1269":"1995-08-02","p1274":"1994-06-29","p1275":"1997-12-10","p1276":"1998-09-26","p1278":"1997-12-16","p1282":"1998-10-20","p1283":"1997-01-28","p1284":"1994-11-11","p1286":"1991-05-14","p1287":"1995-05-16","p1288":"1992-07-07","p1290":"1997-01-14","p1292":"1997-05-11","p1295":"1996-08-08","p1297":"1990-04-08","p1298":"1994-06-05","p1300":"1992-08-20","p1302":"1992-11-09","p1303":"1992-10-01","p1304":"1996-03-14","p1307":"1995-01-28","p1308":"1988-09-18","p1309":"1993-01-05","p1310":"1996-06-14","p1312":"1994-10-30","p1313":"2000-03-17","p1314":"1999-01-11","p1315":"1998-06-11","p1316":"1991-06-11","p1317":"1989-04-08","p1320":"1987-09-20","p1321":"1998-01-31","p1322":"1995-08-11","p1325":"1990-05-07","p1327":"1997-11-26","p1328":"1990-04-17","p1330":"1996-10-07","p1331":"1996-01-18","p1332":"1991-01-20","p1333":"1996-08-22","p1334":"1998-01-01","p1335":"1996-03-24","p1340":"1992-08-31","p1341":"1996-03-21","p1342":"1992-12-31","p1344":"1991-02-02","p1345":"1995-07-27","p1346":"1995-12-24","p1347":"1996-11-27","p1349":"1993-03-19","p1351":"1997-12-02","p1352":"1998-08-09","p1353":"1993-12-06","p1355":"1969-10-20","p1363":"1999-06-04","p1364":"1997-04-07","p1366":"1988-11-14","p1381":"1994-04-07","p1383":"1996-02-14","p1389":"1997-01-04","p1391":"1999-02-08","p1392":"1994-02-21","p1394":"1991","p1395":"1974-02-27","p1399":"1999-11-22","p1400":"1996-06-10","p1401":"1995-11-08","p1402":"1995-04-08","p1403":"1996-11-27","p1405":"1996-04-27","p1423":"2000-04-10","p1426":"1998-09-16","p1427":"2000-12-20","p1428":"1986-08-10","p1429":"1995-03-09","p1435":"1999-09-07","p1436":"2000-10-12","p1441":"1994-11-22","p1447":"1995-10-18","p1449":"1995-04-13","p1450":"1994-02-25","p1451":"1997-12-24","p1456":"1997-04-16","p1457":"1996-11-17","p1464":"1997-06-20","p1465":"1996-07-17","p1488":"1998-04-27","p1494":"2000-05-29","p1495":"2001-12-23","p1497":"1998-07-23","p1500":"1996-08-06","p1502":"1998-09-03","p1504":"2000-01-05","p1506":"1997-01-15","p1507":"2000-01-14","p1508":"1998-07-11","p1511":"2000-06-13","p1520":"1991-05-31","p1522":"1991-03-13","p1524":"1995","p1525":"1994-03-19","p1528":"1994-12-23","p1529":"1999-05-01","p1530":"1993-01-24","p1533":"1993-09-07","p1534":"2000-06-15","p1535":"1996-01-26","p1536":"1998-03-04","p1537":"1996-03-24","p1539":"1998-01-03","p1540":"1999-11-09","p1541":"1992-03-08","p1542":"1997-01-05","p1544":"1999-01-29","p1545":"1989-07-19","p1554":"1999-01-16","p1555":"1992-07-09","p1557":"1990-09-04","p1558":"1994-12-09","p1559":"1995-09-30","p1560":"1983-04-07","p1563":"2001-08-10","p1565":"1986-04-07","p1569":"1985-03-08","p1582":"2001-07-18","p1583":"1996-12-27","p1584":"1999-09-27","p1585":"1997-02-14","p1586":"1993-08-01","p1588":"1969-11-26","p1591":"1993-04-01","p1592":"1999-04-26","p1593":"2000-05-17","p1595":"2000-10-12","p1596":"2002-01-24","p1598":"1999-12-31","p1599":"2001-02-13","p1601":"2000-02-10","p1602":"1998-08-23","p1603":"1997-07-12","p1606":"1996-05-07","p1607":"1999-07-31","p1609":"2000-03-14","p1614":"1996-02-28","p1615":"2000-07-05","p1619":"1998-02-23","p1620":"1998-02-14","p1621":"1996-04-16","p1622":"1997-07-09","p1627":"1997-04-10","p1629":"1993-12-28","p1630":"1948-04-06","p1631":"2000-05-10","p1637":"2001-01-19","p1638":"1998-06-14","p1639":"1993-09-26","p1642":"1998-01-19","p1644":"1996-12-14","p1646":"2002-07-01","p1647":"2002-03-21","p1657":"2001-03-27","p1658":"1999-04-29","p1660":"1998-07-06","p1662":"1995-02-10","p1667":"1999-05-12","p1669":"1998-10-25","p1671":"2001-03-04","p1682":"2000-09-10","p1684":"1999-11-29","p1685":"1993-05-11","p1689":"1996-12-31","p1690":"1998-01-11","p1691":"1993-12-03","p1692":"2001-04-30","p1693":"1998-03-21","p1694":"2000-08-31","p1695":"2000-09-05","p1696":"1993-11-14","p1697":"1994-10-19","p1698":"1995-04-10","p1702":"1989-07-13","p1705":"2004-01-05","p1706":"2002-04-08","p1707":"2001-11-14","p1708":"2001-08-09","p1710":"2001-03-29","p1712":"1998-03-14","p1713":"1997-09-08","p1714":"1996-03-27","p1715":"1999-07-23","p1719":"2000-01-14","p1731":"1998-09-28","p1735":"2000-04-26","p1739":"1989-06-28","p1742":"1991-06-17","p1746":"2004-02-02","p1749":"1998-04-11","p1750":"2002-08-26","p1752":"2000-12-11","p1753":"2001-02-12","p1754":"2001-10-26","p1759":"2002-01-31","p1760":"2000-11-10","p1761":"2001-09-18","p1762":"2000-09-13","p1765":"2001-05-19","p1768":"2002-12-24","p1770":"1997-01-11","p1771":"1998-10-04","p1777":"1996-05-28","p1778":"1993-12-21","p1779":"2003-10-17","p1782":"1999-04-10","p1783":"1997-11-19","p1787":"2002-02-02","p1789":"1996-06-13","p1798":"1992-02-11","p1800":"1995-08-20","p1801":"1994","p1802":"2001-10-22","p1812":"1998-08-08","p1814":"1997-02-04","p1823":"2001-11-28","p1824":"2001-08-07","p1825":"1997-12-02","p1826":"1998-03-26","p1827":"1999-10-16","p1832":"2002-10-06","p1840":"2001-08-27","p1844":"2000-10-06","p1850":"2002-08-23","p1853":"1997-06-10","p1854":"1999-03-02","p1856":"1994-04-02","p1860":"2002-08-30","p1862":"2000-06-21","p1863":"2001-04-09","p1864":"2004-02-18","p1866":"2002-06-05","p1869":"2001-08-27","p1872":"1998-10-08","p1873":"1999-09-28","p1874":"2001-08-15","p1877":"2002-03-26","p1878":"1999-01-24","p1882":"2005-02-01","p1889":"1993-02-11","p1890":"1999-01-10","p1892":"1991-10-24","p1894":"2003-01-02","p1896":"2003-04-16","p1909":"2002-01-03","p1912":"1999-06-02","p1913":"2001-04-02","p1915":"2001-04-12","p1916":"1993-11-09","p1918":"2001-05-08","p1919":"2001-08-29","p1923":"2003-02-12","p1926":"2007-05-27","p1933":"2001-11-06","p1934":"2002-09-04","p1937":"2001-03-19","p1938":"2003-06-03","p1939":"2000-10-07","p1940":"2004-01-08","p1943":"2001-06-14","p1945":"2004-04-14","p1947":"2002-12-06","p1956":"2000-07-09","p1966":"2001-09-13","p1969":"2002-05-30","p1974":"1997-11-08","p1978":"2001-05-27","p1979":"2001-02-03","p1996":"2003-01-30","p2002":"2004-04-14","p2009":"1993-07-29","p2010":"1989","p2015":"2000-01-30","p2020":"2000-07-29","p2022":"1999-01-28","p2025":"2001-06-05","p2026":"2002-10-07","p2027":"2006-11-22","p2030":"2004-08-20","p2032":"2004-06-23","p2033":"2005-09-28","p2035":"2001-07-13","p2037":"2005-01-26","p2038":"2004-03-12","p2040":"2003-08-12","p2043":"2006-10-08","p2044":"2003-12-13","p2047":"2003-01-25","p2048":"2000-01-13","p2050":"1999-03-16","p2060":"2000-11-11","p2061":"2004-01-18","p2062":"2004-03-28","p2065":"2003-12-18","p2068":"2001-09-18","p2070":"1997-05-05","p2076":"2003-11-12","p2077":"2006-12-26","p2078":"1998-10-10","p2108":"2002-10-16","p2120":"2003-04-30","p2121":"1997-10-16","p2123":"2004-06-26","p2124":"1999-12-23","p2128":"2005-06-12","p2129":"2003-06-04","p2130":"2003-04-07","p2131":"2003-12-23","p2132":"2004-01-18","p2137":"2009-03-02","p2138":"2002-08-14","p2139":"2002-09-22","p2140":"2001-09-23","p2141":"1997-01-02","p2142":"2000-06-12","p2145":"2000","p2146":"2006-06-24","p2147":"1999-12-17","p2148":"2000-04-28","p2149":"1999-05-05","p2150":"2004-10-20","p2153":"2005-09-06","p2157":"1993-03-20","p2158":"2005-01-04","p2161":"2006-10-26","p2164":"2006-01-30","p2165":"2006-04-07","p2166":"2002-02-02","p2169":"2005-10-31","p2172":"2004-07-15","p2175":"2006-02-02","p2176":"2004-06-12","p2177":"1992-11-10","p2178":"2002-06-23","p2180":"2005-03-16","p2186":"2005-08-12","p2189":"2004-07-14","p2190":"2002-09-15","p2191":"2000-02-16","p2193":"2001-03-26","p2195":"2005-06-03","p2197":"2003-02-10","p2198":"2001-08-11","p2199":"1999-02-15","p2200":"2001-12-13","p2202":"2004-01-20","p2203":"2002-07-25","p2204":"2005-12-22","p2205":"2006-02-19","p2206":"2001-05-10","p2207":"1982-08-02","p2209":"1998-05-08","p2210":"2006-07-23","p2211":"2005-03-19","p2212":"2005-06-07","p2213":"1999","p2215":"2002-02-19","p2216":"2000-12-12","p2218":"1999","p2219":"2004-11-14","p2221":"2004-08-17","p2223":"2001-08-29","p2225":"1998-05-13","p2228":"2006-02-18","p2230":"2004-09-21","p2231":"2001-02-24","p2247":"2001-07-04","p2249":"1997-08-03","p2250":"2006-03-24","p2252":"2007-05-11","p2254":"2009-03-03","p2255":"2004-04-20","p2256":"2007-03-06","p2257":"2005-07-06","p2258":"2001-05-04","p2259":"2005-03-27","p2260":"2004-11-01","p2261":"2006-04-20","p2262":"2003-10-29","p2263":"2004-04-05","p2267":"2005-02-14","p2269":"2008-04-05","p2270":"2007-06-27","p2271":"2008-06-11","p2272":"2004-06-01","p2273":"2007-10-28","p2274":"2004-11-25","p2276":"2006-10-19","p2277":"2006-09-10","p2278":"2003-01-16","p2279":"2007-02-19","p2280":"2004-07-06","p2281":"2005-10-02","p2283":"2006-07-18","p2284":"2002-06-21","p2285":"2006-10-03","p2286":"2004-01-16","p2287":"2007-11-20","p2292":"1992","p2294":"2006-12-23","p2295":"2010-02-04","p2296":"2003-02-02","p2297":"2005-02-19","p2299":"2007-06-04","p2300":"2002-08-12","p2302":"2006-07-28","p2303":"2005-01-15","p2304":"2007-07-10","p2306":"2007","p2308":"1996-03-01","p2309":"2006-06-09","p2310":"2007-08-18","p2311":"2008-02-25","p2313":"2002-08-16","p2314":"2008-03-14","p2317":"2004-12-12","p2318":"2008-04-15","p2319":"2007-12-26","p2320":"2007-04-18","p2321":"2005","p2322":"2005-07-04","p2323":"2009-07-25","p2325":"2008-10-13","p2328":"2004-06-16","p2340":"1998-03-09","p2342":"1998-08-26","p2343":"2005-07-20","p2344":"1988-11-14","p2345":"2003-05-15","p2346":"2006-05-17","p2347":"2010-08-05","p2349":"2002","p1717":"1994-03-10","p1060":"1990-05-07","p578":"1985-04-24"}');
2. Add the UPDATED script to a chrome bookmark
2a. First, right click the bookmark bar and select "Add Page...". (or simply edit a bookmark if you have added it earlier). Add a name (for example "Enhance Ratings").
2b. Copy-paste the following UPDATED script to the URL part of the bookmark. Save.
Code:
javascript:function fn(){ missingAge = []; tables = Array.from(document.getElementsByTagName("tbody")); rankingTable = tables.at(-1); rankingTableRows = Array.from(rankingTable.children); if (rankingTableRows[0].children.length > 5) { console.log("Already initialized.."); } else { console.log("Initializing the enhanced rankings.."); dobDataEnabled = window.localStorage.hasOwnProperty('dobs'); if (dobDataEnabled) { dobData = JSON.parse(window.localStorage.getItem('dobs')); } gender = "all"; flag = "all"; isAgeFilter = false; sortCol = "Rank"; isSortAsc = false; function sortTable(newSortCol) { if (sortCol === newSortCol) { isSortAsc = !isSortAsc; } else { isSortAsc = newSortCol === "Age"; } sortCol = newSortCol; columnIndex = sortCol === "Age" ? 6 : 5; if (sortCol === "Age") { document.getElementById("age-sort-icon").textContent = isSortAsc ? "↑" : "↓"; document.getElementById("rank-sort-icon").textContent = "⇅"; } else { document.getElementById("rank-sort-icon").textContent = isSortAsc ? "↑" : "↓"; document.getElementById("age-sort-icon").textContent = "⇅"; } sortRows = Array.from(rankingTable.children); function sorter(a,b) { a = parseFloat(a.children[columnIndex].textContent); b = parseFloat(b.children[columnIndex].textContent); if (isNaN(a) && isNaN(b)) return 0; if (isNaN(a)) return 1; if (isNaN(b)) return -1; if (a < b) return isSortAsc ? -1 : 1; if (a > b) return isSortAsc ? 1 : -1; return 0; } sorted = sortRows.slice(1).sort(sorter); sorted.forEach(e => rankingTable.appendChild(e)); } function updateTable() { rank = 1; rankingTableRows.slice(1).forEach(el => { elGender = el.children[3]?.children[0]?.textContent === "♂" ? "men" : "women"; elFlag = el.children[4]?.children[0]?.alt; if (!['cn', 'jp', 'kr', 'tw'].includes(elFlag)) { elFlag = "other"; } ageOk = true; if (isAgeFilter) { age = parseFloat(el.children[6].textContent); minAge = document.getElementById('min-age').value; maxAge = document.getElementById('max-age').value; minAge = parseFloat(minAge); maxAge = parseFloat(maxAge); if (isNaN(age) || age < minAge || age > maxAge) { ageOk = false; } } if ((gender === "all" || elGender === gender) && (flag == "all" || elFlag === flag) && ageOk) { el.children[0].textContent = rank++; el.style.display = "table-row"; } else { el.style.display = "none"; } }); } function createGenderSelect(parentEl) { const genderSelect = document.createElement("SELECT"); genderSelect.setAttribute("id", "genderSelect"); const all = document.createElement("option"); const men = document.createElement("option"); const women = document.createElement("option"); all.setAttribute("value", "all"); men.setAttribute("value", "men"); women.setAttribute("value", "women"); all.textContent = "All"; men.textContent = "Men"; women.textContent = "Women"; genderSelect.append(all, men, women); genderSelect.onchange = (event) => {gender = event.target.value; updateTable();}; parentEl.setAttribute('style', 'white-space: pre;'); parentEl.textContent = "Gender\r\n"; parentEl.appendChild(genderSelect); } function createFlagSelect(parentEl) { const flagSelect = document.createElement("SELECT"); flagSelect.setAttribute("id", "flagSelect"); const all = document.createElement("option"); const china = document.createElement("option"); const japan = document.createElement("option"); const korea = document.createElement("option"); const taiwan = document.createElement("option"); const other = document.createElement("option"); all.setAttribute("value", "all"); china.setAttribute("value", "cn"); japan.setAttribute("value", "jp"); korea.setAttribute("value", "kr"); taiwan.setAttribute("value", "tw"); other.setAttribute("value", "other"); all.textContent = "All"; china.textContent = "China"; japan.textContent = "Japan"; korea.textContent = "Korea"; taiwan.textContent = "Taiwan"; other.textContent = "Other"; flagSelect.append(all, china, japan, korea, taiwan, other); flagSelect.onchange = (event) => {flag = event.target.value; updateTable();}; parentEl.setAttribute('style', 'white-space: pre;'); parentEl.textContent = "Flag\r\n"; parentEl.appendChild(flagSelect); } header = rankingTableRows[0]; headerRow = header.children; headerRow[0].setAttribute('style', 'white-space: pre;'); headerRow[0].textContent = "World\r\nRank"; sortIcon = document.createElement("SPAN"); sortIcon.id = "rank-sort-icon"; sortIcon.textContent = "↓"; sortIcon.style.fontSize = "18px"; headerRow[4].append(sortIcon); headerRow[4].onclick = () => {sortTable("Rank")}; headerRow[4].style.cursor = "pointer"; createGenderSelect(headerRow[2]); createFlagSelect(headerRow[3]); rankColumn = headerRow[0].cloneNode(); rankColumn.textContent = "Rank"; header.prepend(rankColumn); if (dobDataEnabled) { ageColumn = headerRow[0].cloneNode(); sortIcon = document.createElement("SPAN"); sortIcon.id = "age-sort-icon"; sortIcon.textContent = "⇅"; sortIcon.style.fontSize = "18px"; filterIcon = document.createElement("SPAN"); filterIcon.id = "age-filter-icon"; filterIcon.textContent = "⚙"; filterIcon.style.fontSize = "24px"; filterIcon.style.cursor = "pointer"; filterIcon.onclick = () => {isAgeFilter = true; filterIcon.style.display = "none"; filterDiv.style.display = "inline-block"; closeFilterIcon.style.display = "inline"; updateTable();}; minAge = document.createElement("input"); minAge.id = "min-age"; minAge.value; minAge.size = 4; minAge.onblur = () => {updateTable();}; minAgeLabel = document.createElement("label"); minAgeLabel.textContent = "Min:"; minAgeLabel.style.fontWeight = 400; minAgeLabel.setAttribute("for", "min-age"); maxAge = document.createElement("input"); maxAge.id = "max-age"; maxAge.value; maxAge.size = 4; maxAge.onblur = () => {updateTable();}; maxAgeLabel = document.createElement("label"); maxAgeLabel.style.fontWeight = 400; maxAgeLabel.textContent = "Max:"; maxAgeLabel.setAttribute("for", "max-age"); closeFilterIcon = document.createElement("SPAN"); closeFilterIcon.id = "age-filter-close-icon"; closeFilterIcon.textContent = "X"; closeFilterIcon.style.fontSize = "18px"; closeFilterIcon.style.color = "red"; closeFilterIcon.style.display = "none"; closeFilterIcon.style.cursor = "pointer"; closeFilterIcon.onclick = () => {isAgeFilter = false; filterIcon.style.display = "inline"; filterDiv.style.display = "none"; closeFilterIcon.style.display = "none"; updateTable();}; br = document.createElement("BR"); ageDiv = document.createElement("DIV"); ageDiv.style.display = "inline-block"; ageDiv.textContent = "Age"; ageDiv.append(sortIcon); ageDiv.onclick = () => {sortTable("Age")}; ageDiv.style.cursor = "pointer"; filterDiv = document.createElement("DIV"); filterDiv.append(minAgeLabel, minAge, br, maxAgeLabel, maxAge); filterDiv.style.display = "none"; ageColumn.append(ageDiv, filterIcon, filterDiv, closeFilterIcon); header.append(ageColumn); } rank = 1; rankingTableRows.slice(1).forEach(el => { playerId = el.children[1].children[0].href.split("/").at(-1).split(".")[0]; rankCell = el.children[0].cloneNode(); rankCell.textContent = rank++; el.prepend(rankCell); if (dobDataEnabled) { ageCell = el.children[0].cloneNode(); dob = dobData['p' + playerId]; if (dob === '-' || !dob) { missingAge.push(playerId); age = "-"; title = "N/A"; } else { age = ((Date.now() - new Date(dob)) / (1000 * 60*60*24*365.25)).toFixed(1); title = `Date of Birth: ${dob}`; } ageCell.textContent = age; ageCell.title = title; el.append(ageCell); } }); console.log({missingAge}); } } fn();
3. Navigate to https://www.goratings.org/en/. Click the bookmark you saved. Voila! (If the age column doesnt appear, please try repeating steps 1 and 2. Let me know if there are any problems!).

Full Code (without the javascript: prefix)
Feel free to inspect or improve. Please share if you made something cool :tmbup:
Code:
function fn(){
missingAge = [];
tables = Array.from(document.getElementsByTagName("tbody"));
rankingTable = tables.at(-1);
rankingTableRows = Array.from(rankingTable.children);
if (rankingTableRows[0].children.length > 5) {
    console.log("Already initialized..");
} else {
    console.log("Initializing the enhanced rankings..");
    dobDataEnabled = window.localStorage.hasOwnProperty('dobs');
    if (dobDataEnabled) {
        dobData = JSON.parse(window.localStorage.getItem('dobs'));
    }
    gender = "all";
    flag = "all";
    isAgeFilter = false;
    sortCol = "Rank";
    isSortAsc = false;

    function sortTable(newSortCol) {
        if (sortCol === newSortCol) {
            isSortAsc = !isSortAsc;
        } else {
            isSortAsc = newSortCol === "Age";
        }
        sortCol = newSortCol;
        columnIndex = sortCol === "Age" ? 6 : 5;

        if (sortCol === "Age") {
            document.getElementById("age-sort-icon").textContent = isSortAsc ? "↑" : "↓";
            document.getElementById("rank-sort-icon").textContent = "⇅";
        } else {
            document.getElementById("rank-sort-icon").textContent = isSortAsc ? "↑" : "↓";
            document.getElementById("age-sort-icon").textContent = "⇅";
        }

        sortRows = Array.from(rankingTable.children);

        function sorter(a,b) {
            a = parseFloat(a.children[columnIndex].textContent);
            b = parseFloat(b.children[columnIndex].textContent);
            if (isNaN(a) && isNaN(b)) return 0;
            if (isNaN(a)) return 1;
            if (isNaN(b)) return -1;
           
            if (a < b) return isSortAsc ? -1 : 1;
            if (a > b) return isSortAsc ? 1 : -1;
            return 0;
        }

        sorted = sortRows.slice(1).sort(sorter);
        sorted.forEach(e => rankingTable.appendChild(e));
    }
   
    function updateTable() {
        rank = 1;
        rankingTableRows.slice(1).forEach(el => {
            elGender = el.children[3]?.children[0]?.textContent === "♂" ? "men" : "women";
            elFlag = el.children[4]?.children[0]?.alt;
            if (!['cn', 'jp', 'kr', 'tw'].includes(elFlag)) {
                elFlag = "other";
            }

            ageOk = true;
            if (isAgeFilter) {
                age = parseFloat(el.children[6].textContent);
                minAge = document.getElementById('min-age').value;
                maxAge = document.getElementById('max-age').value;
                minAge = parseFloat(minAge);
                maxAge = parseFloat(maxAge);
                if (isNaN(age) || age < minAge || age > maxAge) {
                    ageOk = false;   
                }
            }
           
            if ((gender === "all" || elGender === gender) &&
                (flag == "all" || elFlag === flag) && ageOk) {
                el.children[0].textContent = rank++;
                el.style.display = "table-row";
            } else {
                el.style.display = "none";
            }
        });
    }

    function createGenderSelect(parentEl) {
      const genderSelect = document.createElement("SELECT");
      genderSelect.setAttribute("id", "genderSelect");
   
      const all = document.createElement("option");
      const men = document.createElement("option");
      const women = document.createElement("option");
      all.setAttribute("value", "all");
      men.setAttribute("value", "men");
      women.setAttribute("value", "women");
      all.textContent = "All";
      men.textContent = "Men";
      women.textContent = "Women";
      genderSelect.append(all, men, women);
      genderSelect.onchange = (event) => {gender = event.target.value; updateTable();};
      parentEl.setAttribute('style', 'white-space: pre;');
      parentEl.textContent = "Gender\r\n";
      parentEl.appendChild(genderSelect);
    }

    function createFlagSelect(parentEl) {
      const flagSelect = document.createElement("SELECT");
      flagSelect.setAttribute("id", "flagSelect");
   
      const all = document.createElement("option");
      const china = document.createElement("option");
      const japan = document.createElement("option");
      const korea = document.createElement("option");
      const taiwan = document.createElement("option");
      const other = document.createElement("option");
      all.setAttribute("value", "all");
      china.setAttribute("value", "cn");
      japan.setAttribute("value", "jp");
      korea.setAttribute("value", "kr");
      taiwan.setAttribute("value", "tw");
      other.setAttribute("value", "other");
      all.textContent = "All";
      china.textContent = "China";
      japan.textContent = "Japan";
      korea.textContent = "Korea";
      taiwan.textContent = "Taiwan";
      other.textContent = "Other";
      flagSelect.append(all, china, japan, korea, taiwan, other);
      flagSelect.onchange = (event) => {flag = event.target.value; updateTable();};
      parentEl.setAttribute('style', 'white-space: pre;');
      parentEl.textContent = "Flag\r\n";
      parentEl.appendChild(flagSelect);
    }
   
    header = rankingTableRows[0];
    headerRow = header.children;
    headerRow[0].setAttribute('style', 'white-space: pre;');
    headerRow[0].textContent = "World\r\nRank";
    sortIcon = document.createElement("SPAN");
    sortIcon.id = "rank-sort-icon";
    sortIcon.textContent = "↓";
    sortIcon.style.fontSize = "18px";
    headerRow[4].append(sortIcon);
    headerRow[4].onclick = () => {sortTable("Rank")};
    headerRow[4].style.cursor = "pointer";
    createGenderSelect(headerRow[2]);
    createFlagSelect(headerRow[3]);
    rankColumn = headerRow[0].cloneNode();
    rankColumn.textContent = "Rank";
    header.prepend(rankColumn);

    if (dobDataEnabled) {
        ageColumn = headerRow[0].cloneNode();
        sortIcon = document.createElement("SPAN");
        sortIcon.id = "age-sort-icon";
        sortIcon.textContent = "⇅";
        sortIcon.style.fontSize = "18px";
        filterIcon = document.createElement("SPAN");
        filterIcon.id = "age-filter-icon";
        filterIcon.textContent = "⚙";
        filterIcon.style.fontSize = "24px";
        filterIcon.style.cursor = "pointer";
        filterIcon.onclick = () => {isAgeFilter = true; filterIcon.style.display = "none"; filterDiv.style.display = "inline-block"; closeFilterIcon.style.display = "inline"; updateTable();};
        minAge = document.createElement("input");
        minAge.id = "min-age";
        minAge.value;
        minAge.size = 4;
        minAge.onblur = () => {updateTable();};
        minAgeLabel = document.createElement("label");
        minAgeLabel.textContent = "Min:";
        minAgeLabel.style.fontWeight = 400;
        minAgeLabel.setAttribute("for", "min-age");
        maxAge = document.createElement("input");
        maxAge.id = "max-age";
        maxAge.value;
        maxAge.size = 4;
        maxAge.onblur = () => {updateTable();};
        maxAgeLabel = document.createElement("label");
        maxAgeLabel.style.fontWeight = 400;
        maxAgeLabel.textContent = "Max:";
        maxAgeLabel.setAttribute("for", "max-age");
        closeFilterIcon = document.createElement("SPAN");
        closeFilterIcon.id = "age-filter-close-icon";
        closeFilterIcon.textContent = "X";
        closeFilterIcon.style.fontSize = "18px";
        closeFilterIcon.style.color = "red";
        closeFilterIcon.style.display = "none";
        closeFilterIcon.style.cursor = "pointer";
        closeFilterIcon.onclick = () => {isAgeFilter = false; filterIcon.style.display = "inline"; filterDiv.style.display = "none"; closeFilterIcon.style.display = "none"; updateTable();};
        br = document.createElement("BR");
        ageDiv = document.createElement("DIV");
        ageDiv.style.display = "inline-block";
        ageDiv.textContent = "Age";
        ageDiv.append(sortIcon);
        ageDiv.onclick = () => {sortTable("Age")};
        ageDiv.style.cursor = "pointer";
        filterDiv = document.createElement("DIV");
        filterDiv.append(minAgeLabel, minAge, br, maxAgeLabel, maxAge);
        filterDiv.style.display = "none";
        ageColumn.append(ageDiv, filterIcon, filterDiv, closeFilterIcon);
       
        header.append(ageColumn);
    }
   
    rank = 1;
    rankingTableRows.slice(1).forEach(el => {
        playerId = el.children[1].children[0].href.split("/").at(-1).split(".")[0];
        rankCell = el.children[0].cloneNode();
        rankCell.textContent = rank++;
        el.prepend(rankCell);
        if (dobDataEnabled) {
            ageCell = el.children[0].cloneNode();
            dob = dobData['p' + playerId];
            if (dob === '-' || !dob) {
                missingAge.push(playerId);
                age = "-";
                title = "N/A";
            } else {
                age = ((Date.now() - new Date(dob)) / (1000 * 60*60*24*365.25)).toFixed(1);
                title = `Date of Birth: ${dob}`;
            }
            ageCell.textContent = age;
            ageCell.title = title;
           
            el.append(ageCell);
        }
    });
    console.log({missingAge});
}
}
fn();


Please note:
1. Always be cautious if you copy paste scripts online!
2. Some dates of births only have the year!! Feel free to contribute! :roll:

Author:  Elom0 [ Mon Mar 21, 2022 10:58 am ]
Post subject:  Re: Enhanced rankings at goratings.org -Update: Added Age co

Wow, these are really great :clap:!

I could do the first one last time around easily on a browser other than chrome, just this one I'd have to figure out now. But the first one has been more than useful!

Author:  Toukopouko [ Mon Mar 21, 2022 11:27 am ]
Post subject:  Re: Enhanced rankings at goratings.org -Update: Added Age co

Elom0 wrote:
Wow, these are really great :clap:!

I could do the first one last time around easily on a browser other than chrome, just this one I'd have to figure out now. But the first one has been more than useful!
Thanks!

All major browsers should support localStorage and they surely have a console to access it. Bookmarking a script may have some character limitations hmm :scratch:

Let me know if I can be of any help!

Author:  Elom0 [ Mon Mar 21, 2022 12:06 pm ]
Post subject:  Re: Enhanced rankings at goratings.org -Update: Added Age co

Toukopouko wrote:
Elom0 wrote:
Wow, these are really great :clap:!

I could do the first one last time around easily on a browser other than chrome, just this one I'd have to figure out now. But the first one has been more than useful!
Thanks!

All major browsers should support localStorage and they surely have a console to access it. Bookmarking a script may have some character limitations hmm :scratch:

Let me know if I can be of any help!


Great! I'm using brave for easy access to ecosia, perhaps I made an error somewhere pasting it into the console, or the name of the store is slightly different from chrome and other's window.localStorage.setItem, which is what I'm checking next . . .

Author:  Toukopouko [ Mon Mar 21, 2022 12:12 pm ]
Post subject:  Re: Enhanced rankings at goratings.org -Update: Added Age co

Elom0 wrote:
Great! I'm using brave for easy access to ecosia, perhaps I made an error somewhere pasting it into the console, or the name of the store is slightly different from chrome and other's window.localStorage.setItem, which is what I'm checking next . . .


Hmm! One thing I forgot in the instructions! You have to be at goratings.org before adding the data to the local storage! (The storage is site specific!). I hope this helps and sorry about that!

Edit: Updated the instructions!

Author:  pajaro [ Mon Mar 21, 2022 12:26 pm ]
Post subject:  Re: Enhanced rankings at goratings.org

Toukopouko wrote:
pajaro wrote:
Have you tried submitting it to Rémi Coulom?
Hey thanks! I just sent him an email! Let's see what he thinks!


Has he replied?

Author:  Toukopouko [ Mon Mar 21, 2022 12:33 pm ]
Post subject:  Re: Enhanced rankings at goratings.org

pajaro wrote:
Toukopouko wrote:
pajaro wrote:
Have you tried submitting it to Rémi Coulom?
Hey thanks! I just sent him an email! Let's see what he thinks!


Has he replied?
Not yet. I emailed him on Saturday and it is only Monday. I will let you know :tmbup:

Author:  Toukopouko [ Wed Mar 23, 2022 4:33 am ]
Post subject:  Re: Enhanced rankings at goratings.org

pajaro wrote:
Has he replied?

He replied. Unfortunately he is too busy at the moment. Maybe he has more time in the future.

However, you can use my scripts as a workaround, (Or if someone else comes up with a better solution :scratch: )

Author:  Elom0 [ Wed Mar 23, 2022 5:53 am ]
Post subject:  Re: Enhanced rankings at goratings.org -Update: Added Age co

Toukopouko wrote:
Elom0 wrote:
Great! I'm using brave for easy access to ecosia, perhaps I made an error somewhere pasting it into the console, or the name of the store is slightly different from chrome and other's window.localStorage.setItem, which is what I'm checking next . . .


Hmm! One thing I forgot in the instructions! You have to be at goratings.org before adding the data to the local storage! (The storage is site specific!). I hope this helps and sorry about that!

Edit: Updated the instructions!


Wow it works now :clap: !

Author:  Toukopouko [ Wed Mar 23, 2022 10:20 am ]
Post subject:  Re: Enhanced rankings at goratings.org -Update: Added Age co

An update:
I added most of the missing birthdays! Some birthdays still only have the year part only! Feel free to contribute!

To get the latest data, please, re-do the step1 in the post #4

Author:  Elom0 [ Wed May 18, 2022 7:13 am ]
Post subject:  Re: Enhanced rankings at goratings.org -Update: Added Age co

It would probably be a bit to tricky to implement so this is not a request, but maybe in the slightly far future it might be possible to select multiple flags at once!

It might be a bit interesting checking rankings between Korea and China (both parts), but most intersting may be rankings between Taiwan and Japan which could be very interesting . . ! (Amongst Japanese and Taiwanese professionals combined Xu Haohong is 3rd!). Although honestly so many Taiwanese are top Japanese pros, that perhaps it's best to often treat Taiwan and Japan as one and the same group.

Author:  Elom0 [ Thu Jun 09, 2022 8:07 am ]
Post subject:  Re: Enhanced rankings at goratings.org -Update: Added Age co

Elom0 wrote:
It would probably be a bit to tricky to implement so this is not a request, but maybe in the slightly far future it might be possible to select multiple flags at once!

It might be a bit interesting checking rankings between Korea and China (both parts), but most intersting may be rankings between Taiwan and Japan which could be very interesting . . ! (Amongst Japanese and Taiwanese professionals combined Xu Haohong is 3rd!). Although honestly so many Taiwanese are top Japanese pros, that perhaps it's best to often treat Taiwan and Japan as one and the same group.


This is a miracle for incompetent at programming me but this might work

Code:
javascript:function fn(){ missingAge = []; tables = Array.from(document.getElementsByTagName("tbody")); rankingTable = tables.at(-1); rankingTableRows = Array.from(rankingTable.children); if (rankingTableRows[0].children.length > 5) { console.log("Already initialized.."); } else { console.log("Initializing the enhanced rankings.."); dobDataEnabled = window.localStorage.hasOwnProperty('dobs'); if (dobDataEnabled) { dobData = JSON.parse(window.localStorage.getItem('dobs')); } gender = "all"; flag = "all"; isAgeFilter = false; sortCol = "Rank"; isSortAsc = false; function sortTable(newSortCol) { if (sortCol === newSortCol) { isSortAsc = !isSortAsc; } else { isSortAsc = newSortCol === "Age"; } sortCol = newSortCol; columnIndex = sortCol === "Age" ? 6 : 5; if (sortCol === "Age") { document.getElementById("age-sort-icon").textContent = isSortAsc ? "↑" : "↓"; document.getElementById("rank-sort-icon").textContent = "⇅"; } else { document.getElementById("rank-sort-icon").textContent = isSortAsc ? "↑" : "↓"; document.getElementById("age-sort-icon").textContent = "⇅"; } sortRows = Array.from(rankingTable.children); function sorter(a,b) { a = parseFloat(a.children[columnIndex].textContent); b = parseFloat(b.children[columnIndex].textContent); if (isNaN(a) && isNaN(b)) return 0; if (isNaN(a)) return 1; if (isNaN(b)) return -1; if (a < b) return isSortAsc ? -1 : 1; if (a > b) return isSortAsc ? 1 : -1; return 0; } sorted = sortRows.slice(1).sort(sorter); sorted.forEach(e => rankingTable.appendChild(e)); } function updateTable() { rank = 1; rankingTableRows.slice(1).forEach(el => { elGender = el.children[3]?.children[0]?.textContent === "♂" ? "men" : "women"; elFlag = el.children[4]?.children[0]?.alt; if (!['cn', 'jp', 'kr', 'tw'].includes(elFlag)) { elFlag = "other"; } ageOk = true; if (isAgeFilter) { age = parseFloat(el.children[6].textContent); minAge = document.getElementById('min-age').value; maxAge = document.getElementById('max-age').value; minAge = parseFloat(minAge); maxAge = parseFloat(maxAge); if (isNaN(age) || age < minAge || age > maxAge) { ageOk = false; } } if ((gender === "all" || elGender === gender) && (flag == "all" || elFlag === flag) && ageOk) { el.children[0].textContent = rank++; el.style.display = "table-row"; } else { el.style.display = "none"; } }); } function createGenderSelect(parentEl) { const genderSelect = document.createElement("SELECT"); genderSelect.setAttribute("id", "genderSelect"); const all = document.createElement("option"); const men = document.createElement("option"); const women = document.createElement("option"); all.setAttribute("value", "all"); men.setAttribute("value", "men"); women.setAttribute("value", "women"); all.textContent = "All"; men.textContent = "Men"; women.textContent = "Women"; genderSelect.append(all, men, women); genderSelect.onchange = (event) => {gender = event.target.value; updateTable();}; parentEl.setAttribute('style', 'white-space: pre;'); parentEl.textContent = "Gender\r\n"; parentEl.appendChild(genderSelect); } function createFlagSelect(parentEl) { const flagSelect = document.createElement("SELECT"); flagSelect.setAttribute("id", "flagSelect"); const all = document.createElement("option"); const china = document.createElement("option"); const japan = document.createElement("option"); const korea = document.createElement("option"); const taiwan = document.createElement("option"); const other = document.createElement("option"); const chinato = document.createElement("option"); const japanto = document.createElement("option", "option", "option"); const koreato = document.createElement("option"); const taiwano = document.createElement("option"); all.setAttribute("value", "all"); china.setAttribute("value", "cn"); japan.setAttribute("value", "jp"); korea.setAttribute("value", "kr"); taiwan.setAttribute("value", "tw"); chinato.setAttribute("value", "cn", "tw", "other"); japanto.setAttribute("value", "jp", "value", "tw", "value", "other"); koreato.setAttribute("value", "kr",  "tw", "other"); taiwano.setAttribute("value", "tw", "other"); other.setAttribute("value", "other"); all.textContent = "All"; china.textContent = "China"; japan.textContent = "Japan"; korea.textContent = "Korea"; taiwan.textContent = "Taiwan"; other.textContent = "Other"; all.textContent = "All"; chinato.textContent = "China and Taiwan and Others"; japanto.textContent = "Japan and Taiwan and Others"; koreato.textContent = "Korea and Taiwan and Others"; taiwano.textContent = "Taiwan and Others"; flagSelect.append(all, china, japan, korea, taiwan, chinato, koreato, japanto, other); flagSelect.onchange = (event) => {flag = event.target.value; updateTable();}; parentEl.setAttribute('style', 'white-space: pre;'); parentEl.textContent = "Flag\r\n"; parentEl.appendChild(flagSelect); } header = rankingTableRows[0]; headerRow = header.children; headerRow[0].setAttribute('style', 'white-space: pre;'); headerRow[0].textContent = "World\r\nRank"; sortIcon = document.createElement("SPAN"); sortIcon.id = "rank-sort-icon"; sortIcon.textContent = "↓"; sortIcon.style.fontSize = "18px"; headerRow[4].append(sortIcon); headerRow[4].onclick = () => {sortTable("Rank")}; headerRow[4].style.cursor = "pointer"; createGenderSelect(headerRow[2]); createFlagSelect(headerRow[3]); rankColumn = headerRow[0].cloneNode(); rankColumn.textContent = "Rank"; header.prepend(rankColumn); if (dobDataEnabled) { ageColumn = headerRow[0].cloneNode(); sortIcon = document.createElement("SPAN"); sortIcon.id = "age-sort-icon"; sortIcon.textContent = "⇅"; sortIcon.style.fontSize = "18px"; filterIcon = document.createElement("SPAN"); filterIcon.id = "age-filter-icon"; filterIcon.textContent = "⚙"; filterIcon.style.fontSize = "24px"; filterIcon.style.cursor = "pointer"; filterIcon.onclick = () => {isAgeFilter = true; filterIcon.style.display = "none"; filterDiv.style.display = "inline-block"; closeFilterIcon.style.display = "inline"; updateTable();}; minAge = document.createElement("input"); minAge.id = "min-age"; minAge.value; minAge.size = 4; minAge.onblur = () => {updateTable();}; minAgeLabel = document.createElement("label"); minAgeLabel.textContent = "Min:"; minAgeLabel.style.fontWeight = 400; minAgeLabel.setAttribute("for", "min-age"); maxAge = document.createElement("input"); maxAge.id = "max-age"; maxAge.value; maxAge.size = 4; maxAge.onblur = () => {updateTable();}; maxAgeLabel = document.createElement("label"); maxAgeLabel.style.fontWeight = 400; maxAgeLabel.textContent = "Max:"; maxAgeLabel.setAttribute("for", "max-age"); closeFilterIcon = document.createElement("SPAN"); closeFilterIcon.id = "age-filter-close-icon"; closeFilterIcon.textContent = "X"; closeFilterIcon.style.fontSize = "18px"; closeFilterIcon.style.color = "red"; closeFilterIcon.style.display = "none"; closeFilterIcon.style.cursor = "pointer"; closeFilterIcon.onclick = () => {isAgeFilter = false; filterIcon.style.display = "inline"; filterDiv.style.display = "none"; closeFilterIcon.style.display = "none"; updateTable();}; br = document.createElement("BR"); ageDiv = document.createElement("DIV"); ageDiv.style.display = "inline-block"; ageDiv.textContent = "Age"; ageDiv.append(sortIcon); ageDiv.onclick = () => {sortTable("Age")}; ageDiv.style.cursor = "pointer"; filterDiv = document.createElement("DIV"); filterDiv.append(minAgeLabel, minAge, br, maxAgeLabel, maxAge); filterDiv.style.display = "none"; ageColumn.append(ageDiv, filterIcon, filterDiv, closeFilterIcon); header.append(ageColumn); } rank = 1; rankingTableRows.slice(1).forEach(el => { playerId = el.children[1].children[0].href.split("/").at(-1).split(".")[0]; rankCell = el.children[0].cloneNode(); rankCell.textContent = rank++; el.prepend(rankCell); if (dobDataEnabled) { ageCell = el.children[0].cloneNode(); dob = dobData['p' + playerId]; if (dob === '-' || !dob) { missingAge.push(playerId); age = "-"; title = "N/A"; } else { age = ((Date.now() - new Date(dob)) / (1000 * 60*60*24*365.25)).toFixed(1); title = `Date of Birth: ${dob}`; } ageCell.textContent = age; ageCell.title = title; el.append(ageCell); } }); console.log({missingAge}); } } fn();


Code:
function fn(){
missingAge = [];
tables = Array.from(document.getElementsByTagName("tbody"));
rankingTable = tables.at(-1);
rankingTableRows = Array.from(rankingTable.children);
if (rankingTableRows[0].children.length > 5) {
    console.log("Already initialized..");
} else {
    console.log("Initializing the enhanced rankings..");
    dobDataEnabled = window.localStorage.hasOwnProperty('dobs');
    if (dobDataEnabled) {
        dobData = JSON.parse(window.localStorage.getItem('dobs'));
    }
    gender = "all";
    flag = "all";
    isAgeFilter = false;
    sortCol = "Rank";
    isSortAsc = false;

    function sortTable(newSortCol) {
        if (sortCol === newSortCol) {
            isSortAsc = !isSortAsc;
        } else {
            isSortAsc = newSortCol === "Age";
        }
        sortCol = newSortCol;
        columnIndex = sortCol === "Age" ? 6 : 5;

        if (sortCol === "Age") {
            document.getElementById("age-sort-icon").textContent = isSortAsc ? "↑" : "↓";
            document.getElementById("rank-sort-icon").textContent = "⇅";
        } else {
            document.getElementById("rank-sort-icon").textContent = isSortAsc ? "↑" : "↓";
            document.getElementById("age-sort-icon").textContent = "⇅";
        }

        sortRows = Array.from(rankingTable.children);

        function sorter(a,b) {
            a = parseFloat(a.children[columnIndex].textContent);
            b = parseFloat(b.children[columnIndex].textContent);
            if (isNaN(a) && isNaN(b)) return 0;
            if (isNaN(a)) return 1;
            if (isNaN(b)) return -1;
           
            if (a < b) return isSortAsc ? -1 : 1;
            if (a > b) return isSortAsc ? 1 : -1;
            return 0;
        }

        sorted = sortRows.slice(1).sort(sorter);
        sorted.forEach(e => rankingTable.appendChild(e));
    }
   
    function updateTable() {
        rank = 1;
        rankingTableRows.slice(1).forEach(el => {
            elGender = el.children[3]?.children[0]?.textContent === "♂" ? "men" : "women";
            elFlag = el.children[4]?.children[0]?.alt;
            if (!['cn', 'jp', 'kr', 'tw'].includes(elFlag)) {
                elFlag = "other";
            }

            ageOk = true;
            if (isAgeFilter) {
                age = parseFloat(el.children[6].textContent);
                minAge = document.getElementById('min-age').value;
                maxAge = document.getElementById('max-age').value;
                minAge = parseFloat(minAge);
                maxAge = parseFloat(maxAge);
                if (isNaN(age) || age < minAge || age > maxAge) {
                    ageOk = false;   
                }
            }
           
            if ((gender === "all" || elGender === gender) &&
                (flag == "all" || elFlag === flag) && ageOk) {
                el.children[0].textContent = rank++;
                el.style.display = "table-row";
            } else {
                el.style.display = "none";
            }
        });
    }

    function createGenderSelect(parentEl) {
      const genderSelect = document.createElement("SELECT");
      genderSelect.setAttribute("id", "genderSelect");
   
      const all = document.createElement("option");
      const men = document.createElement("option");
      const women = document.createElement("option");
      all.setAttribute("value", "all");
      men.setAttribute("value", "men");
      women.setAttribute("value", "women");
      all.textContent = "All";
      men.textContent = "Men";
      women.textContent = "Women";
      genderSelect.append(all, men, women);
      genderSelect.onchange = (event) => {gender = event.target.value; updateTable();};
      parentEl.setAttribute('style', 'white-space: pre;');
      parentEl.textContent = "Gender\r\n";
      parentEl.appendChild(genderSelect);
    }

    function createFlagSelect(parentEl) {
      const flagSelect = document.createElement("SELECT");
      flagSelect.setAttribute("id", "flagSelect");
   
      const all = document.createElement("option");
      const china = document.createElement("option");
      const japan = document.createElement("option");
      const korea = document.createElement("option");
      const taiwan = document.createElement("option");
      const other = document.createElement("option");
      const chinato = document.createElement("option");
      const japanto = document.createElement("option", "option");
      const koreato = document.createElement("option");
      const taiwano = document.createElement("option");
      all.setAttribute("value", "all");
      china.setAttribute("value", "cn");
      japan.setAttribute("value", "jp");
      korea.setAttribute("value", "kr");
      taiwan.setAttribute("value", "tw");
      chinato.setAttribute("value", "cn", "tw", "other");
      japanto.setAttribute("value", "jp", "value "tw", "value "other");
      koreato.setAttribute("value", "kr",  "tw", "other");
      taiwano.setAttribute("value", "tw", "other");
      other.setAttribute("value", "other");
      all.textContent = "All";
      china.textContent = "China";
      japan.textContent = "Japan";
      korea.textContent = "Korea";
      taiwan.textContent = "Taiwan";
      other.textContent = "Other";
      all.textContent = "All";
      chinato.textContent = "China and Taiwan and Others";
      japanto.textContent = "Japan and Taiwan and Others";
      koreato.textContent = "Korea and Taiwan and Others";
      taiwano.textContent = "Taiwan and Others";
      flagSelect.append(all, china, japan, korea, taiwan, chinato, koreato, japanto, other);
      flagSelect.onchange = (event) => {flag = event.target.value; updateTable();};
      parentEl.setAttribute('style', 'white-space: pre;');
      parentEl.textContent = "Flag\r\n";
      parentEl.appendChild(flagSelect);
    }
   
    header = rankingTableRows[0];
    headerRow = header.children;
    headerRow[0].setAttribute('style', 'white-space: pre;');
    headerRow[0].textContent = "World\r\nRank";
    sortIcon = document.createElement("SPAN");
    sortIcon.id = "rank-sort-icon";
    sortIcon.textContent = "↓";
    sortIcon.style.fontSize = "18px";
    headerRow[4].append(sortIcon);
    headerRow[4].onclick = () => {sortTable("Rank")};
    headerRow[4].style.cursor = "pointer";
    createGenderSelect(headerRow[2]);
    createFlagSelect(headerRow[3]);
    rankColumn = headerRow[0].cloneNode();
    rankColumn.textContent = "Rank";
    header.prepend(rankColumn);

    if (dobDataEnabled) {
        ageColumn = headerRow[0].cloneNode();
        sortIcon = document.createElement("SPAN");
        sortIcon.id = "age-sort-icon";
        sortIcon.textContent = "⇅";
        sortIcon.style.fontSize = "18px";
        filterIcon = document.createElement("SPAN");
        filterIcon.id = "age-filter-icon";
        filterIcon.textContent = "⚙";
        filterIcon.style.fontSize = "24px";
        filterIcon.style.cursor = "pointer";
        filterIcon.onclick = () => {isAgeFilter = true; filterIcon.style.display = "none"; filterDiv.style.display = "inline-block"; closeFilterIcon.style.display = "inline"; updateTable();};
        minAge = document.createElement("input");
        minAge.id = "min-age";
        minAge.value;
        minAge.size = 4;
        minAge.onblur = () => {updateTable();};
        minAgeLabel = document.createElement("label");
        minAgeLabel.textContent = "Min:";
        minAgeLabel.style.fontWeight = 400;
        minAgeLabel.setAttribute("for", "min-age");
        maxAge = document.createElement("input");
        maxAge.id = "max-age";
        maxAge.value;
        maxAge.size = 4;
        maxAge.onblur = () => {updateTable();};
        maxAgeLabel = document.createElement("label");
        maxAgeLabel.style.fontWeight = 400;
        maxAgeLabel.textContent = "Max:";
        maxAgeLabel.setAttribute("for", "max-age");
        closeFilterIcon = document.createElement("SPAN");
        closeFilterIcon.id = "age-filter-close-icon";
        closeFilterIcon.textContent = "X";
        closeFilterIcon.style.fontSize = "18px";
        closeFilterIcon.style.color = "red";
        closeFilterIcon.style.display = "none";
        closeFilterIcon.style.cursor = "pointer";
        closeFilterIcon.onclick = () => {isAgeFilter = false; filterIcon.style.display = "inline"; filterDiv.style.display = "none"; closeFilterIcon.style.display = "none"; updateTable();};
        br = document.createElement("BR");
        ageDiv = document.createElement("DIV");
        ageDiv.style.display = "inline-block";
        ageDiv.textContent = "Age";
        ageDiv.append(sortIcon);
        ageDiv.onclick = () => {sortTable("Age")};
        ageDiv.style.cursor = "pointer";
        filterDiv = document.createElement("DIV");
        filterDiv.append(minAgeLabel, minAge, br, maxAgeLabel, maxAge);
        filterDiv.style.display = "none";
        ageColumn.append(ageDiv, filterIcon, filterDiv, closeFilterIcon);
       
        header.append(ageColumn);
    }
   
    rank = 1;
    rankingTableRows.slice(1).forEach(el => {
        playerId = el.children[1].children[0].href.split("/").at(-1).split(".")[0];
        rankCell = el.children[0].cloneNode();
        rankCell.textContent = rank++;
        el.prepend(rankCell);
        if (dobDataEnabled) {
            ageCell = el.children[0].cloneNode();
            dob = dobData['p' + playerId];
            if (dob === '-' || !dob) {
                missingAge.push(playerId);
                age = "-";
                title = "N/A";
            } else {
                age = ((Date.now() - new Date(dob)) / (1000 * 60*60*24*365.25)).toFixed(1);
                title = `Date of Birth: ${dob}`;
            }
            ageCell.textContent = age;
            ageCell.title = title;
           
            el.append(ageCell);
        }
    });
    console.log({missingAge});
}
}
fn();


Hmm actually I can't seem to make it work . . .

Author:  Elom0 [ Fri Jun 10, 2022 4:52 am ]
Post subject:  Re: Enhanced rankings at goratings.org -Update: Added Age co

Okay I'm terrible at programming so I can't seem to make it work.

But I found out by happy accident that I can just manually change the alt to jp for a few.

Seki Kotaro, a title holder, is ranked in the 30's . . . Ryan is one place ahead of Xie Yimin at 141.
But none of the European League or Transatlantic League games are in the go4go database . . . huh?
Also there don't seem to be games from the American Go Congresses and few from the European Go Congress.

Attachment:
Web capture_10-6-2022_141544_www.goratings.org.jpeg
Web capture_10-6-2022_141544_www.goratings.org.jpeg [ 1.55 MiB | Viewed 11178 times ]
Attachment:
Web capture_10-6-2022_141645_www.goratings.org.jpeg
Web capture_10-6-2022_141645_www.goratings.org.jpeg [ 1.6 MiB | Viewed 11178 times ]
Attachment:
Web capture_10-6-2022_142239_www.goratings.org.jpeg
Web capture_10-6-2022_142239_www.goratings.org.jpeg [ 1.41 MiB | Viewed 11177 times ]

Author:  Elom0 [ Fri Jun 10, 2022 6:20 am ]
Post subject:  Re: Enhanced rankings at goratings.org -Update: Added Age co

Top 25 Japanese&Taiwanese pros with top two female pros
Attachment:
Web capture_10-6-2022_125155_www.goratings.org.jpeg
Web capture_10-6-2022_125155_www.goratings.org.jpeg [ 267.59 KiB | Viewed 11178 times ]

Author:  Ferran [ Fri Jun 10, 2022 6:52 am ]
Post subject:  Re: Enhanced rankings at goratings.org -Update: Added Age co

Elom0 wrote:
But none of the European League or Transatlantic League games are in the go4go database . . . huh?


This was raised back when I posted the results of the League. I think I stopped at the third. I don't recall any solid information.

Take care

Author:  Elom0 [ Sat Jun 11, 2022 9:54 pm ]
Post subject:  Re: Enhanced rankings at goratings.org -Update: Added Age co

Okay I just found a shoddy workaround instead, putting this in the bookmark bar should work.

Normal Version
Code:
javascript:function fn(){ missingAge = []; tables = Array.from(document.getElementsByTagName("tbody")); rankingTable = tables.at(-1); rankingTableRows = Array.from(rankingTable.children); if (rankingTableRows[0].children.length > 5) { console.log("Already initialized.."); } else { console.log("Initializing the enhanced rankings.."); dobDataEnabled = window.localStorage.hasOwnProperty('dobs'); if (dobDataEnabled) { dobData = JSON.parse(window.localStorage.getItem('dobs')); } gender = "all"; flag = "all"; isAgeFilter = false; sortCol = "Rank"; isSortAsc = false; function sortTable(newSortCol) { if (sortCol === newSortCol) { isSortAsc = !isSortAsc; } else { isSortAsc = newSortCol === "Age"; } sortCol = newSortCol; columnIndex = sortCol === "Age" ? 6 : 5; if (sortCol === "Age") { document.getElementById("age-sort-icon").textContent = isSortAsc ? "↑" : "↓"; document.getElementById("rank-sort-icon").textContent = "⇅"; } else { document.getElementById("rank-sort-icon").textContent = isSortAsc ? "↑" : "↓"; document.getElementById("age-sort-icon").textContent = "⇅"; } sortRows = Array.from(rankingTable.children); function sorter(a,b) { a = parseFloat(a.children[columnIndex].textContent); b = parseFloat(b.children[columnIndex].textContent); if (isNaN(a) && isNaN(b)) return 0; if (isNaN(a)) return 1; if (isNaN(b)) return -1; if (a < b) return isSortAsc ? -1 : 1; if (a > b) return isSortAsc ? 1 : -1; return 0; } sorted = sortRows.slice(1).sort(sorter); sorted.forEach(e => rankingTable.appendChild(e)); } function updateTable() { rank = 1; rankingTableRows.slice(1).forEach(el => { elGender = el.children[2]?.children[0]?.textContent === "♂" ? "men" : "women"; elFlag = el.children[3]?.children[0]?.alt; if (!['cn', 'kr'].includes(elFlag)) { elFlag = "other"; } ageOk = true; if (isAgeFilter) { age = parseFloat(el.children[6].textContent); minAge = document.getElementById('min-age').value; maxAge = document.getElementById('max-age').value; minAge = parseFloat(minAge); maxAge = parseFloat(maxAge); if (isNaN(age) || age < minAge || age > maxAge) { ageOk = false; } } if ((gender === "all" || elGender === gender) && (flag == "all" || elFlag === flag) && ageOk) { el.children[0].textContent = rank++; el.style.display = "table-row"; } else { el.style.display = "none"; } }); } function createGenderSelect(parentEl) { const genderSelect = document.createElement("SELECT"); genderSelect.setAttribute("id", "genderSelect"); const all = document.createElement("option"); const women = document.createElement("option"); all.setAttribute("value", "all"); women.setAttribute("value", "women"); all.textContent = "♂♀"; women.textContent = "♀"; genderSelect.append(all, women); genderSelect.onchange = (event) => {gender = event.target.value; updateTable();}; parentEl.setAttribute('style', 'white-space: pre;'); parentEl.textContent = "♂♀\r\n"; parentEl.appendChild(genderSelect); } function createFlagSelect(parentEl) { const flagSelect = document.createElement("SELECT"); flagSelect.setAttribute("id", "flagSelect"); const all = document.createElement("option"); const china = document.createElement("option"); const korea = document.createElement("option"); const other = document.createElement("option"); all.setAttribute("value", "all"); china.setAttribute("value", "cn"); korea.setAttribute("value", "kr");  other.setAttribute("value", "other"); all.textContent = "All"; china.textContent = "China"; korea.textContent = "Korea"; other.textContent = "Other"; flagSelect.append(all, china, korea, other); flagSelect.onchange = (event) => {flag = event.target.value; updateTable();}; parentEl.setAttribute('style', 'white-space: pre;'); parentEl.textContent = "Flag\r\n"; parentEl.appendChild(flagSelect); } header = rankingTableRows[0]; headerRow = header.children; headerRow[0].setAttribute('style', 'white-space: pre;'); headerRow[0].textContent = "Pool\r\nRank"; sortIcon = document.createElement("SPAN"); sortIcon.id = "rank-sort-icon"; sortIcon.textContent = "↓"; sortIcon.style.fontSize = "18px"; headerRow[4].append(sortIcon); headerRow[4].onclick = () => {sortTable("Rank")}; headerRow[4].style.cursor = "pointer"; createGenderSelect(headerRow[2]); createFlagSelect(headerRow[3]); rankColumn = headerRow[0].cloneNode(); rankColumn.textContent = "World\r\nRank"; header.append(rankColumn); if (dobDataEnabled) { ageColumn = headerRow[0].cloneNode(); sortIcon = document.createElement("SPAN"); sortIcon.id = "age-sort-icon"; sortIcon.textContent = "⇅"; sortIcon.style.fontSize = "18px"; filterIcon = document.createElement("SPAN"); filterIcon.id = "age-filter-icon"; filterIcon.textContent = "⚙"; filterIcon.style.fontSize = "24px"; filterIcon.style.cursor = "pointer"; filterIcon.onclick = () => {isAgeFilter = true; filterIcon.style.display = "none"; filterDiv.style.display = "inline-block"; closeFilterIcon.style.display = "inline"; updateTable();}; minAge = document.createElement("input"); minAge.id = "min-age"; minAge.value; minAge.size = 4; minAge.onblur = () => {updateTable();}; minAgeLabel = document.createElement("label"); minAgeLabel.textContent = "Min:"; minAgeLabel.style.fontWeight = 400; minAgeLabel.setAttribute("for", "min-age"); maxAge = document.createElement("input"); maxAge.id = "max-age"; maxAge.value; maxAge.size = 4; maxAge.onblur = () => {updateTable();}; maxAgeLabel = document.createElement("label"); maxAgeLabel.style.fontWeight = 400; maxAgeLabel.textContent = "Max:"; maxAgeLabel.setAttribute("for", "max-age"); closeFilterIcon = document.createElement("SPAN"); closeFilterIcon.id = "age-filter-close-icon"; closeFilterIcon.textContent = "X"; closeFilterIcon.style.fontSize = "18px"; closeFilterIcon.style.color = "red"; closeFilterIcon.style.display = "none"; closeFilterIcon.style.cursor = "pointer"; closeFilterIcon.onclick = () => {isAgeFilter = false; filterIcon.style.display = "inline"; filterDiv.style.display = "none"; closeFilterIcon.style.display = "none"; updateTable();}; br = document.createElement("BR"); ageDiv = document.createElement("DIV"); ageDiv.style.display = "inline-block"; ageDiv.textContent = "Age"; ageDiv.append(sortIcon); ageDiv.onclick = () => {sortTable("Age")}; ageDiv.style.cursor = "pointer"; filterDiv = document.createElement("DIV"); filterDiv.append(minAgeLabel, minAge, br, maxAgeLabel, maxAge); filterDiv.style.display = "none"; ageColumn.append(ageDiv, filterIcon, filterDiv, closeFilterIcon); header.append(ageColumn); } rank = 1; rankingTableRows.slice(1).forEach(el => { playerId = el.children[1].children[0].href.split("/").at(-1).split(".")[0]; rankCell = el.children[0].cloneNode(); rankCell.textContent = rank++; el.append(rankCell); if (dobDataEnabled) { ageCell = el.children[0].cloneNode(); dob = dobData['p' + playerId]; if (dob === '-' || !dob) { missingAge.push(playerId); age = "-"; title = "N/A"; } else { age = ((Date.now() - new Date(dob)) / (1000 * 60*60*24*365.25)).toFixed(1); title = `Date of Birth: ${dob}`; } ageCell.textContent = age; ageCell.title = title; el.append(ageCell); } }); console.log({missingAge}); } } fn();



Code:
function fn(){
missingAge = [];
tables = Array.from(document.getElementsByTagName("tbody"));
rankingTable = tables.at(-1);
rankingTableRows = Array.from(rankingTable.children);
if (rankingTableRows[0].children.length > 5) {
    console.log("Already initialized..");
} else {
    console.log("Initializing the enhanced rankings..");
    dobDataEnabled = window.localStorage.hasOwnProperty('dobs');
    if (dobDataEnabled) {
        dobData = JSON.parse(window.localStorage.getItem('dobs'));
    }
    gender = "all";
    flag = "all";
    isAgeFilter = false;
    sortCol = "Rank";
    isSortAsc = false;

    function sortTable(newSortCol) {
        if (sortCol === newSortCol) {
            isSortAsc = !isSortAsc;
        } else {
            isSortAsc = newSortCol === "Age";
        }
        sortCol = newSortCol;
        columnIndex = sortCol === "Age" ? 6 : 5;

        if (sortCol === "Age") {
            document.getElementById("age-sort-icon").textContent = isSortAsc ? "↑" : "↓";
            document.getElementById("rank-sort-icon").textContent = "⇅";
        } else {
            document.getElementById("rank-sort-icon").textContent = isSortAsc ? "↑" : "↓";
            document.getElementById("age-sort-icon").textContent = "⇅";
        }

        sortRows = Array.from(rankingTable.children);

        function sorter(a,b) {
            a = parseFloat(a.children[columnIndex].textContent);
            b = parseFloat(b.children[columnIndex].textContent);
            if (isNaN(a) && isNaN(b)) return 0;
            if (isNaN(a)) return 1;
            if (isNaN(b)) return -1;
           
            if (a < b) return isSortAsc ? -1 : 1;
            if (a > b) return isSortAsc ? 1 : -1;
            return 0;
        }

        sorted = sortRows.slice(1).sort(sorter);
        sorted.forEach(e => rankingTable.appendChild(e));
    }
   
    function updateTable() {
        rank = 1;
        rankingTableRows.slice(1).forEach(el => {
            elGender = el.children[2]?.children[0]?.textContent === "♂" ? "men" : "women";
            elFlag = el.children[3]?.children[0]?.alt;
            if (!['cn', 'kr',].includes(elFlag)) {
                elFlag = "other";
            }

            ageOk = true;
            if (isAgeFilter) {
                age = parseFloat(el.children[6].textContent);
                minAge = document.getElementById('min-age').value;
                maxAge = document.getElementById('max-age').value;
                minAge = parseFloat(minAge);
                maxAge = parseFloat(maxAge);
                if (isNaN(age) || age < minAge || age > maxAge) {
                    ageOk = false;   
                }
            }
           
            if ((gender === "all" || elGender === gender) &&
                (flag == "all" || elFlag === flag) && ageOk) {
                el.children[0].textContent = rank++;
                el.style.display = "table-row";
            } else {
                el.style.display = "none";
            }
        });
    }

    function createGenderSelect(parentEl) {
      const genderSelect = document.createElement("SELECT");
      genderSelect.setAttribute("id", "genderSelect");
   
      const all = document.createElement("option");
      const women = document.createElement("option");
      all.setAttribute("value", "all");
      women.setAttribute("value", "women");
      all.textContent = "♂♀";
      women.textContent = "♀";
      genderSelect.append(all, women);
      genderSelect.onchange = (event) => {gender = event.target.value; updateTable();};
      parentEl.setAttribute('style', 'white-space: pre;');
      parentEl.textContent = "♂♀\r\n";
      parentEl.appendChild(genderSelect);
    }

    function createFlagSelect(parentEl) {
      const flagSelect = document.createElement("SELECT");
      flagSelect.setAttribute("id", "flagSelect");
   
      const all = document.createElement("option");
      const china = document.createElement("option");
      const korea = document.createElement("option");
      const other = document.createElement("option");
      all.setAttribute("value", "all");
      china.setAttribute("value", "cn");
      korea.setAttribute("value", "kr");
      other.setAttribute("value", "other");
      all.textContent = "All";
      china.textContent = "China";
      korea.textContent = "Korea";
      other.textContent = "Other";
      flagSelect.append(all, china, korea, other);
      flagSelect.onchange = (event) => {flag = event.target.value; updateTable();};
      parentEl.setAttribute('style', 'white-space: pre;');
      parentEl.textContent = "Flag\r\n";
      parentEl.appendChild(flagSelect);
    }
   
    header = rankingTableRows[0];
    headerRow = header.children;
    headerRow[0].setAttribute('style', 'white-space: pre;');
    headerRow[0].textContent = "Pool\r\nRank";
    sortIcon = document.createElement("SPAN");
    sortIcon.id = "rank-sort-icon";
    sortIcon.textContent = "↓";
    sortIcon.style.fontSize = "18px";
    headerRow[4].append(sortIcon);
    headerRow[4].onclick = () => {sortTable("Rank")};
    headerRow[4].style.cursor = "pointer";
    createGenderSelect(headerRow[2]);
    createFlagSelect(headerRow[3]);
    rankColumn = headerRow[0].cloneNode();
    rankColumn.textContent = "World\r\Rank";
    header.append(rankColumn);

    if (dobDataEnabled) {
        ageColumn = headerRow[0].cloneNode();
        sortIcon = document.createElement("SPAN");
        sortIcon.id = "age-sort-icon";
        sortIcon.textContent = "⇅";
        sortIcon.style.fontSize = "18px";
        filterIcon = document.createElement("SPAN");
        filterIcon.id = "age-filter-icon";
        filterIcon.textContent = "⚙";
        filterIcon.style.fontSize = "24px";
        filterIcon.style.cursor = "pointer";
        filterIcon.onclick = () => {isAgeFilter = true; filterIcon.style.display = "none"; filterDiv.style.display = "inline-block"; closeFilterIcon.style.display = "inline"; updateTable();};
        minAge = document.createElement("input");
        minAge.id = "min-age";
        minAge.value;
        minAge.size = 4;
        minAge.onblur = () => {updateTable();};
        minAgeLabel = document.createElement("label");
        minAgeLabel.textContent = "Min:";
        minAgeLabel.style.fontWeight = 400;
        minAgeLabel.setAttribute("for", "min-age");
        maxAge = document.createElement("input");
        maxAge.id = "max-age";
        maxAge.value;
        maxAge.size = 4;
        maxAge.onblur = () => {updateTable();};
        maxAgeLabel = document.createElement("label");
        maxAgeLabel.style.fontWeight = 400;
        maxAgeLabel.textContent = "Max:";
        maxAgeLabel.setAttribute("for", "max-age");
        closeFilterIcon = document.createElement("SPAN");
        closeFilterIcon.id = "age-filter-close-icon";
        closeFilterIcon.textContent = "X";
        closeFilterIcon.style.fontSize = "18px";
        closeFilterIcon.style.color = "red";
        closeFilterIcon.style.display = "none";
        closeFilterIcon.style.cursor = "pointer";
        closeFilterIcon.onclick = () => {isAgeFilter = false; filterIcon.style.display = "inline"; filterDiv.style.display = "none"; closeFilterIcon.style.display = "none"; updateTable();};
        br = document.createElement("BR");
        ageDiv = document.createElement("DIV");
        ageDiv.style.display = "inline-block";
        ageDiv.textContent = "Age";
        ageDiv.append(sortIcon);
        ageDiv.onclick = () => {sortTable("Age")};
        ageDiv.style.cursor = "pointer";
        filterDiv = document.createElement("DIV");
        filterDiv.append(minAgeLabel, minAge, br, maxAgeLabel, maxAge);
        filterDiv.style.display = "none";
        ageColumn.append(ageDiv, filterIcon, filterDiv, closeFilterIcon);
       
        header.append(ageColumn);
    }
   
    rank = 1;
    rankingTableRows.slice(1).forEach(el => {
        playerId = el.children[1].children[0].href.split("/").at(-1).split(".")[0];
        rankCell = el.children[0].cloneNode();
        rankCell.textContent = rank++;
        el.append(rankCell);
        if (dobDataEnabled) {
            ageCell = el.children[0].cloneNode();
            dob = dobData['p' + playerId];
            if (dob === '-' || !dob) {
                missingAge.push(playerId);
                age = "-";
                title = "N/A";
            } else {
                age = ((Date.now() - new Date(dob)) / (1000 * 60*60*24*365.25)).toFixed(1);
                title = `Date of Birth: ${dob}`;
            }
            ageCell.textContent = age;
            ageCell.title = title;
           
            el.append(ageCell);
        }
    });
    console.log({missingAge});
}
}
fn();


Beijing-controlled China v Rest of World version
Code:
javascript:function fn(){ missingAge = []; tables = Array.from(document.getElementsByTagName("tbody")); rankingTable = tables.at(-1); rankingTableRows = Array.from(rankingTable.children); if (rankingTableRows[0].children.length > 5) { console.log("Already initialized.."); } else { console.log("Initializing the enhanced rankings.."); dobDataEnabled = window.localStorage.hasOwnProperty('dobs'); if (dobDataEnabled) { dobData = JSON.parse(window.localStorage.getItem('dobs')); } gender = "all"; flag = "all"; isAgeFilter = false; sortCol = "Rank"; isSortAsc = false; function sortTable(newSortCol) { if (sortCol === newSortCol) { isSortAsc = !isSortAsc; } else { isSortAsc = newSortCol === "Age"; } sortCol = newSortCol; columnIndex = sortCol === "Age" ? 6 : 5; if (sortCol === "Age") { document.getElementById("age-sort-icon").textContent = isSortAsc ? "↑" : "↓"; document.getElementById("rank-sort-icon").textContent = "⇅"; } else { document.getElementById("rank-sort-icon").textContent = isSortAsc ? "↑" : "↓"; document.getElementById("age-sort-icon").textContent = "⇅"; } sortRows = Array.from(rankingTable.children); function sorter(a,b) { a = parseFloat(a.children[columnIndex].textContent); b = parseFloat(b.children[columnIndex].textContent); if (isNaN(a) && isNaN(b)) return 0; if (isNaN(a)) return 1; if (isNaN(b)) return -1; if (a < b) return isSortAsc ? -1 : 1; if (a > b) return isSortAsc ? 1 : -1; return 0; } sorted = sortRows.slice(1).sort(sorter); sorted.forEach(e => rankingTable.appendChild(e)); } function updateTable() { rank = 1; rankingTableRows.slice(1).forEach(el => { elGender = el.children[2]?.children[0]?.textContent === "♂" ? "men" : "women"; elFlag = el.children[3]?.children[0]?.alt; if (!['cn'].includes(elFlag)) { elFlag = "other"; } ageOk = true; if (isAgeFilter) { age = parseFloat(el.children[6].textContent); minAge = document.getElementById('min-age').value; maxAge = document.getElementById('max-age').value; minAge = parseFloat(minAge); maxAge = parseFloat(maxAge); if (isNaN(age) || age < minAge || age > maxAge) { ageOk = false; } } if ((gender === "all" || elGender === gender) && (flag == "all" || elFlag === flag) && ageOk) { el.children[0].textContent = rank++; el.style.display = "table-row"; } else { el.style.display = "none"; } }); } function createGenderSelect(parentEl) { const genderSelect = document.createElement("SELECT"); genderSelect.setAttribute("id", "genderSelect"); const all = document.createElement("option"); const women = document.createElement("option"); all.setAttribute("value", "all"); women.setAttribute("value", "women"); all.textContent = "♂♀"; women.textContent = "♀"; genderSelect.append(all, women); genderSelect.onchange = (event) => {gender = event.target.value; updateTable();}; parentEl.setAttribute('style', 'white-space: pre;'); parentEl.textContent = "♂♀\r\n"; parentEl.appendChild(genderSelect); } function createFlagSelect(parentEl) { const flagSelect = document.createElement("SELECT"); flagSelect.setAttribute("id", "flagSelect"); const all = document.createElement("option"); const china = document.createElement("option"); const korea = document.createElement("option"); const other = document.createElement("option"); all.setAttribute("value", "all"); china.setAttribute("value", "cn");  other.setAttribute("value", "other"); all.textContent = "All"; china.textContent = "China"; other.textContent = "Other"; flagSelect.append(all, china, other); flagSelect.onchange = (event) => {flag = event.target.value; updateTable();}; parentEl.setAttribute('style', 'white-space: pre;'); parentEl.textContent = "Flag\r\n"; parentEl.appendChild(flagSelect); } header = rankingTableRows[0]; headerRow = header.children; headerRow[0].setAttribute('style', 'white-space: pre;'); headerRow[0].textContent = "Pool\r\nRank"; sortIcon = document.createElement("SPAN"); sortIcon.id = "rank-sort-icon"; sortIcon.textContent = "↓"; sortIcon.style.fontSize = "18px"; headerRow[4].append(sortIcon); headerRow[4].onclick = () => {sortTable("Rank")}; headerRow[4].style.cursor = "pointer"; createGenderSelect(headerRow[2]); createFlagSelect(headerRow[3]); rankColumn = headerRow[0].cloneNode(); rankColumn.textContent = "World\r\nRank"; header.append(rankColumn); if (dobDataEnabled) { ageColumn = headerRow[0].cloneNode(); sortIcon = document.createElement("SPAN"); sortIcon.id = "age-sort-icon"; sortIcon.textContent = "⇅"; sortIcon.style.fontSize = "18px"; filterIcon = document.createElement("SPAN"); filterIcon.id = "age-filter-icon"; filterIcon.textContent = "⚙"; filterIcon.style.fontSize = "24px"; filterIcon.style.cursor = "pointer"; filterIcon.onclick = () => {isAgeFilter = true; filterIcon.style.display = "none"; filterDiv.style.display = "inline-block"; closeFilterIcon.style.display = "inline"; updateTable();}; minAge = document.createElement("input"); minAge.id = "min-age"; minAge.value; minAge.size = 4; minAge.onblur = () => {updateTable();}; minAgeLabel = document.createElement("label"); minAgeLabel.textContent = "Min:"; minAgeLabel.style.fontWeight = 400; minAgeLabel.setAttribute("for", "min-age"); maxAge = document.createElement("input"); maxAge.id = "max-age"; maxAge.value; maxAge.size = 4; maxAge.onblur = () => {updateTable();}; maxAgeLabel = document.createElement("label"); maxAgeLabel.style.fontWeight = 400; maxAgeLabel.textContent = "Max:"; maxAgeLabel.setAttribute("for", "max-age"); closeFilterIcon = document.createElement("SPAN"); closeFilterIcon.id = "age-filter-close-icon"; closeFilterIcon.textContent = "X"; closeFilterIcon.style.fontSize = "18px"; closeFilterIcon.style.color = "red"; closeFilterIcon.style.display = "none"; closeFilterIcon.style.cursor = "pointer"; closeFilterIcon.onclick = () => {isAgeFilter = false; filterIcon.style.display = "inline"; filterDiv.style.display = "none"; closeFilterIcon.style.display = "none"; updateTable();}; br = document.createElement("BR"); ageDiv = document.createElement("DIV"); ageDiv.style.display = "inline-block"; ageDiv.textContent = "Age"; ageDiv.append(sortIcon); ageDiv.onclick = () => {sortTable("Age")}; ageDiv.style.cursor = "pointer"; filterDiv = document.createElement("DIV"); filterDiv.append(minAgeLabel, minAge, br, maxAgeLabel, maxAge); filterDiv.style.display = "none"; ageColumn.append(ageDiv, filterIcon, filterDiv, closeFilterIcon); header.append(ageColumn); } rank = 1; rankingTableRows.slice(1).forEach(el => { playerId = el.children[1].children[0].href.split("/").at(-1).split(".")[0]; rankCell = el.children[0].cloneNode(); rankCell.textContent = rank++; el.append(rankCell); if (dobDataEnabled) { ageCell = el.children[0].cloneNode(); dob = dobData['p' + playerId]; if (dob === '-' || !dob) { missingAge.push(playerId); age = "-"; title = "N/A"; } else { age = ((Date.now() - new Date(dob)) / (1000 * 60*60*24*365.25)).toFixed(1); title = `Date of Birth: ${dob}`; } ageCell.textContent = age; ageCell.title = title; el.append(ageCell); } }); console.log({missingAge}); } } fn();



Code:
function fn(){
missingAge = [];
tables = Array.from(document.getElementsByTagName("tbody"));
rankingTable = tables.at(-1);
rankingTableRows = Array.from(rankingTable.children);
if (rankingTableRows[0].children.length > 5) {
    console.log("Already initialized..");
} else {
    console.log("Initializing the enhanced rankings..");
    dobDataEnabled = window.localStorage.hasOwnProperty('dobs');
    if (dobDataEnabled) {
        dobData = JSON.parse(window.localStorage.getItem('dobs'));
    }
    gender = "all";
    flag = "all";
    isAgeFilter = false;
    sortCol = "Rank";
    isSortAsc = false;

    function sortTable(newSortCol) {
        if (sortCol === newSortCol) {
            isSortAsc = !isSortAsc;
        } else {
            isSortAsc = newSortCol === "Age";
        }
        sortCol = newSortCol;
        columnIndex = sortCol === "Age" ? 6 : 5;

        if (sortCol === "Age") {
            document.getElementById("age-sort-icon").textContent = isSortAsc ? "↑" : "↓";
            document.getElementById("rank-sort-icon").textContent = "⇅";
        } else {
            document.getElementById("rank-sort-icon").textContent = isSortAsc ? "↑" : "↓";
            document.getElementById("age-sort-icon").textContent = "⇅";
        }

        sortRows = Array.from(rankingTable.children);

        function sorter(a,b) {
            a = parseFloat(a.children[columnIndex].textContent);
            b = parseFloat(b.children[columnIndex].textContent);
            if (isNaN(a) && isNaN(b)) return 0;
            if (isNaN(a)) return 1;
            if (isNaN(b)) return -1;
           
            if (a < b) return isSortAsc ? -1 : 1;
            if (a > b) return isSortAsc ? 1 : -1;
            return 0;
        }

        sorted = sortRows.slice(1).sort(sorter);
        sorted.forEach(e => rankingTable.appendChild(e));
    }
   
    function updateTable() {
        rank = 1;
        rankingTableRows.slice(1).forEach(el => {
            elGender = el.children[2]?.children[0]?.textContent === "♂" ? "men" : "women";
            elFlag = el.children[3]?.children[0]?.alt;
            if (!['cn'].includes(elFlag)) {
                elFlag = "other";
            }

            ageOk = true;
            if (isAgeFilter) {
                age = parseFloat(el.children[6].textContent);
                minAge = document.getElementById('min-age').value;
                maxAge = document.getElementById('max-age').value;
                minAge = parseFloat(minAge);
                maxAge = parseFloat(maxAge);
                if (isNaN(age) || age < minAge || age > maxAge) {
                    ageOk = false;   
                }
            }
           
            if ((gender === "all" || elGender === gender) &&
                (flag == "all" || elFlag === flag) && ageOk) {
                el.children[0].textContent = rank++;
                el.style.display = "table-row";
            } else {
                el.style.display = "none";
            }
        });
    }

    function createGenderSelect(parentEl) {
      const genderSelect = document.createElement("SELECT");
      genderSelect.setAttribute("id", "genderSelect");
   
      const all = document.createElement("option");
      const women = document.createElement("option");
      all.setAttribute("value", "all");
      women.setAttribute("value", "women");
      all.textContent = "♂♀";
      women.textContent = "♀";
      genderSelect.append(all, women);
      genderSelect.onchange = (event) => {gender = event.target.value; updateTable();};
      parentEl.setAttribute('style', 'white-space: pre;');
      parentEl.textContent = "♂♀\r\n";
      parentEl.appendChild(genderSelect);
    }

    function createFlagSelect(parentEl) {
      const flagSelect = document.createElement("SELECT");
      flagSelect.setAttribute("id", "flagSelect");
   
      const all = document.createElement("option");
      const china = document.createElement("option");
      const other = document.createElement("option");
      all.setAttribute("value", "all");
      china.setAttribute("value", "cn");
      other.setAttribute("value", "other");
      all.textContent = "All";
      china.textContent = "China";
      other.textContent = "Other";
      flagSelect.append(all, china, other);
      flagSelect.onchange = (event) => {flag = event.target.value; updateTable();};
      parentEl.setAttribute('style', 'white-space: pre;');
      parentEl.textContent = "Flag\r\n";
      parentEl.appendChild(flagSelect);
    }
   
    header = rankingTableRows[0];
    headerRow = header.children;
    headerRow[0].setAttribute('style', 'white-space: pre;');
    headerRow[0].textContent = "Pool\r\nRank";
    sortIcon = document.createElement("SPAN");
    sortIcon.id = "rank-sort-icon";
    sortIcon.textContent = "↓";
    sortIcon.style.fontSize = "18px";
    headerRow[4].append(sortIcon);
    headerRow[4].onclick = () => {sortTable("Rank")};
    headerRow[4].style.cursor = "pointer";
    createGenderSelect(headerRow[2]);
    createFlagSelect(headerRow[3]);
    rankColumn = headerRow[0].cloneNode();
    rankColumn.textContent = "World\r\Rank";
    header.append(rankColumn);

    if (dobDataEnabled) {
        ageColumn = headerRow[0].cloneNode();
        sortIcon = document.createElement("SPAN");
        sortIcon.id = "age-sort-icon";
        sortIcon.textContent = "⇅";
        sortIcon.style.fontSize = "18px";
        filterIcon = document.createElement("SPAN");
        filterIcon.id = "age-filter-icon";
        filterIcon.textContent = "⚙";
        filterIcon.style.fontSize = "24px";
        filterIcon.style.cursor = "pointer";
        filterIcon.onclick = () => {isAgeFilter = true; filterIcon.style.display = "none"; filterDiv.style.display = "inline-block"; closeFilterIcon.style.display = "inline"; updateTable();};
        minAge = document.createElement("input");
        minAge.id = "min-age";
        minAge.value;
        minAge.size = 4;
        minAge.onblur = () => {updateTable();};
        minAgeLabel = document.createElement("label");
        minAgeLabel.textContent = "Min:";
        minAgeLabel.style.fontWeight = 400;
        minAgeLabel.setAttribute("for", "min-age");
        maxAge = document.createElement("input");
        maxAge.id = "max-age";
        maxAge.value;
        maxAge.size = 4;
        maxAge.onblur = () => {updateTable();};
        maxAgeLabel = document.createElement("label");
        maxAgeLabel.style.fontWeight = 400;
        maxAgeLabel.textContent = "Max:";
        maxAgeLabel.setAttribute("for", "max-age");
        closeFilterIcon = document.createElement("SPAN");
        closeFilterIcon.id = "age-filter-close-icon";
        closeFilterIcon.textContent = "X";
        closeFilterIcon.style.fontSize = "18px";
        closeFilterIcon.style.color = "red";
        closeFilterIcon.style.display = "none";
        closeFilterIcon.style.cursor = "pointer";
        closeFilterIcon.onclick = () => {isAgeFilter = false; filterIcon.style.display = "inline"; filterDiv.style.display = "none"; closeFilterIcon.style.display = "none"; updateTable();};
        br = document.createElement("BR");
        ageDiv = document.createElement("DIV");
        ageDiv.style.display = "inline-block";
        ageDiv.textContent = "Age";
        ageDiv.append(sortIcon);
        ageDiv.onclick = () => {sortTable("Age")};
        ageDiv.style.cursor = "pointer";
        filterDiv = document.createElement("DIV");
        filterDiv.append(minAgeLabel, minAge, br, maxAgeLabel, maxAge);
        filterDiv.style.display = "none";
        ageColumn.append(ageDiv, filterIcon, filterDiv, closeFilterIcon);
       
        header.append(ageColumn);
    }
   
    rank = 1;
    rankingTableRows.slice(1).forEach(el => {
        playerId = el.children[1].children[0].href.split("/").at(-1).split(".")[0];
        rankCell = el.children[0].cloneNode();
        rankCell.textContent = rank++;
        el.append(rankCell);
        if (dobDataEnabled) {
            ageCell = el.children[0].cloneNode();
            dob = dobData['p' + playerId];
            if (dob === '-' || !dob) {
                missingAge.push(playerId);
                age = "-";
                title = "N/A";
            } else {
                age = ((Date.now() - new Date(dob)) / (1000 * 60*60*24*365.25)).toFixed(1);
                title = `Date of Birth: ${dob}`;
            }
            ageCell.textContent = age;
            ageCell.title = title;
           
            el.append(ageCell);
        }
    });
    console.log({missingAge});
}
}
fn();

Author:  Elom0 [ Thu Aug 11, 2022 4:59 am ]
Post subject:  Re: Enhanced rankings at goratings.org -Update: Added Age co

Ah, goratings.org seems to be out of service at the moment . . .

Page 1 of 2 All times are UTC - 8 hours [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/