It is currently Thu Feb 22, 2024 3:57 am

All times are UTC - 8 hours [ DST ]




Post new topic Reply to topic  [ 27 posts ]  Go to page 1, 2  Next
Author Message
Offline
 Post subject: Enhanced rankings at goratings.org -Update: Added Age column
Post #1 Posted: Fri Mar 18, 2022 9:35 am 
Beginner

Posts: 19
Liked others: 11
Was liked: 18
Rank: KGS 2 dan
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!


Last edited by Toukopouko on Mon Mar 21, 2022 10:40 am, edited 2 times in total.

This post by Toukopouko was liked by 3 people: Elom0, gazzawhite, pajaro
Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org
Post #2 Posted: Sat Mar 19, 2022 4:16 am 
Lives in gote

Posts: 530
Liked others: 27
Was liked: 142
KGS: pajaro
IGS: pajaro
Very interesting, although I won't try it myself.

Have you tried submitting it to Rémi Coulom?

Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org
Post #3 Posted: Sat Mar 19, 2022 12:47 pm 
Beginner

Posts: 19
Liked others: 11
Was liked: 18
Rank: KGS 2 dan
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:


This post by Toukopouko was liked by: gazzawhite
Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org -Update: Added Age co
Post #4 Posted: Mon Mar 21, 2022 10:35 am 
Beginner

Posts: 19
Liked others: 11
Was liked: 18
Rank: KGS 2 dan
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:


Last edited by Toukopouko on Wed Mar 23, 2022 10:17 am, edited 3 times in total.

This post by Toukopouko was liked by 2 people: Elom0, gazzawhite
Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org -Update: Added Age co
Post #5 Posted: Mon Mar 21, 2022 10:58 am 
Lives in sente

Posts: 720
Liked others: 1011
Was liked: 30
Rank: BGA 3 kyu
KGS: Elom, Windnwater
OGS: Elom, Elom0
Online playing schedule: The OGS data looks pretty so I'll pause for now before I change it.
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!

Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org -Update: Added Age co
Post #6 Posted: Mon Mar 21, 2022 11:27 am 
Beginner

Posts: 19
Liked others: 11
Was liked: 18
Rank: KGS 2 dan
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!

Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org -Update: Added Age co
Post #7 Posted: Mon Mar 21, 2022 12:06 pm 
Lives in sente

Posts: 720
Liked others: 1011
Was liked: 30
Rank: BGA 3 kyu
KGS: Elom, Windnwater
OGS: Elom, Elom0
Online playing schedule: The OGS data looks pretty so I'll pause for now before I change it.
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 . . .

Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org -Update: Added Age co
Post #8 Posted: Mon Mar 21, 2022 12:12 pm 
Beginner

Posts: 19
Liked others: 11
Was liked: 18
Rank: KGS 2 dan
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!


This post by Toukopouko was liked by: Elom0
Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org
Post #9 Posted: Mon Mar 21, 2022 12:26 pm 
Lives in gote

Posts: 530
Liked others: 27
Was liked: 142
KGS: pajaro
IGS: pajaro
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?

Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org
Post #10 Posted: Mon Mar 21, 2022 12:33 pm 
Beginner

Posts: 19
Liked others: 11
Was liked: 18
Rank: KGS 2 dan
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:

Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org
Post #11 Posted: Wed Mar 23, 2022 4:33 am 
Beginner

Posts: 19
Liked others: 11
Was liked: 18
Rank: KGS 2 dan
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: )

Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org -Update: Added Age co
Post #12 Posted: Wed Mar 23, 2022 5:53 am 
Lives in sente

Posts: 720
Liked others: 1011
Was liked: 30
Rank: BGA 3 kyu
KGS: Elom, Windnwater
OGS: Elom, Elom0
Online playing schedule: The OGS data looks pretty so I'll pause for now before I change it.
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: !


This post by Elom0 was liked by: Toukopouko
Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org -Update: Added Age co
Post #13 Posted: Wed Mar 23, 2022 10:20 am 
Beginner

Posts: 19
Liked others: 11
Was liked: 18
Rank: KGS 2 dan
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

Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org -Update: Added Age co
Post #14 Posted: Wed May 18, 2022 7:13 am 
Lives in sente

Posts: 720
Liked others: 1011
Was liked: 30
Rank: BGA 3 kyu
KGS: Elom, Windnwater
OGS: Elom, Elom0
Online playing schedule: The OGS data looks pretty so I'll pause for now before I change it.
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.

Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org -Update: Added Age co
Post #15 Posted: Thu Jun 09, 2022 8:07 am 
Lives in sente

Posts: 720
Liked others: 1011
Was liked: 30
Rank: BGA 3 kyu
KGS: Elom, Windnwater
OGS: Elom, Elom0
Online playing schedule: The OGS data looks pretty so I'll pause for now before I change it.
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 . . .

Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org -Update: Added Age co
Post #16 Posted: Fri Jun 10, 2022 4:52 am 
Lives in sente

Posts: 720
Liked others: 1011
Was liked: 30
Rank: BGA 3 kyu
KGS: Elom, Windnwater
OGS: Elom, Elom0
Online playing schedule: The OGS data looks pretty so I'll pause for now before I change it.
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 8945 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 8945 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 8944 times ]


Last edited by Elom0 on Fri Jun 10, 2022 6:23 am, edited 3 times in total.
Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org -Update: Added Age co
Post #17 Posted: Fri Jun 10, 2022 6:20 am 
Lives in sente

Posts: 720
Liked others: 1011
Was liked: 30
Rank: BGA 3 kyu
KGS: Elom, Windnwater
OGS: Elom, Elom0
Online playing schedule: The OGS data looks pretty so I'll pause for now before I change it.
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 8945 times ]

Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org -Update: Added Age co
Post #18 Posted: Fri Jun 10, 2022 6:52 am 
Lives in gote

Posts: 612
Liked others: 148
Was liked: 117
Rank: OGS ddk
KGS: Ferran
IGS: Ferran
OGS: Ferran
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

_________________
玄 又 玄


This post by Ferran was liked by: Elom0
Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org -Update: Added Age co
Post #19 Posted: Sat Jun 11, 2022 9:54 pm 
Lives in sente

Posts: 720
Liked others: 1011
Was liked: 30
Rank: BGA 3 kyu
KGS: Elom, Windnwater
OGS: Elom, Elom0
Online playing schedule: The OGS data looks pretty so I'll pause for now before I change it.
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();


Last edited by Elom0 on Wed Feb 22, 2023 7:12 am, edited 2 times in total.
Top
 Profile  
 
Offline
 Post subject: Re: Enhanced rankings at goratings.org -Update: Added Age co
Post #20 Posted: Thu Aug 11, 2022 4:59 am 
Lives in sente

Posts: 720
Liked others: 1011
Was liked: 30
Rank: BGA 3 kyu
KGS: Elom, Windnwater
OGS: Elom, Elom0
Online playing schedule: The OGS data looks pretty so I'll pause for now before I change it.
Ah, goratings.org seems to be out of service at the moment . . .

Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 27 posts ]  Go to page 1, 2  Next

All times are UTC - 8 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group