[Обновлено] Инструкция: узнаём свой винрейт, часто используемых героев и историю матчей в разных режимах

Сайт artifactcube.com разработал свою версию скрипта, представленного в оригинальной новости. Теперь информация может отображаться на страницах сайта: доступны различные фильтры и сортировки, а самое главное ей можно делиться с другими игроками. Вот так выглядит профиль со статистикой на сайте.

TH6xFlo.png

Фрагмент профиля

Порядок действий для создания своего профиля со статистикой Artifact:
  1. Переходим на artifactcube.com (впрочем, действия можно выполнить на любой странице сайта)
  2. Нажимаем на ссылку "Click here to copy the script" (если это не сработает, нужно перейти по второй ссылке и скопировать код самостоятельно)
  3. Переходим на свою страницу со статистикой в Steam, вставляем ранее скопированный код в консоль браузера (сочетанием клавиш Ctrl+Shift+I или кликнув в меню Chrome Дополнительные инструменты > Инструменты разработчика) и нажимаем Enter
  4. Когда скрипт закончит парсить ваши матчи, скопировать код из открывшегося окна в текстовое поле на сайте

    1546573863629.png

    Полное содержимое этого окна и надо скопировать на artifactcube.com
  5. Сайт обработает полученную информацию и сгенерирует вашу страницу-профиль

Оригинальная новость:
Несмотря на то, что в Artifact нет внутриигрового профиля со статистикой, а также официального API для этой информации, все матчи записываются в разделе личной статистики Steam. Пользователь reddit создал скрипт, который позволяет преобразовать этот массив информации в удобный для восприятия вид.

Порядок действий (работа скрипта проверена только в браузере Chrome):
  • Перейти по ссылке https://steamcommunity.com/my/gcpd/583950?category=Games&tab=MatchPlayers
  • Открыть консоль (сочетанием клавиш Ctrl+Shift+I или кликнуть в меню Chrome Дополнительные инструменты > Инструменты разработчика)
  • Вставить в консоль следующий код и нажать Enter
    Код:
    var loadingDiv = document.createElement("div");loadingDiv.style="background:white ;border: 1px solid Black; position: fixed; top: 50%; left: 50%; padding: 20px; z-index: 100; display:flex; flex-direction: row; align-items: center;";
    document.body.append(loadingDiv);
    
    var loadingImg = document.createElement("img");
    loadingImg.src="https://steamcommunity-a.akamaihd.net/public/images/login/throbber.gif";
    
    var loadingText = document.createElement("div");
    loadingText.textContent = "loading matches please wait...";
    loadingText.style = "margin-right: 10px;";
    
    loadingDiv.append(loadingText);
    loadingDiv.append(loadingImg);
    
    hero_data = {'Ogre Magi': {'color': 'blue', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10043.4b52a60db821028ba02a7fb728988bec2842397f.png'}, 'Keefe the Bold': {'color': 'red', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set00/4003.2cc81eb5cf6375fdfad19781634a37df496e20c0.png'}, 'Skywrath Mage': {'color': 'blue', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10062.320871aec38db2b973d6fa8933e62d3f44e8e407.png'}, 'Timbersaw': {'color': 'red', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10022.065c0b1ce65b1f201bca225121177c2d19df2c89.png'}, 'Magnus': {'color': 'green', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10067.9130bf7958f290e69cf5bcc960332d44830919ae.png'}, 'Omniknight': {'color': 'green', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10044.5fe4f8195b2a005f6b40ab273b2504782e84d191.png'}, 'Viper': {'color': 'green', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10028.50b8bc7588cab219f86ac87014b2c394d0ee5754.png'}, 'Storm Spirit': {'color': 'black', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10536.f29d6a820bf65991ea122a1efdb61088651d2706.png'}, 'Ursa': {'color': 'red', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10070.0fb457ff9ef3010b7f2743789889339aa74b4152.png'}, 'Prellex': {'color': 'blue', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10053.46d6ca300f26d8e05aaf9d63c590508a723415b5.png'}, 'Lycan': {'color': 'green', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10014.d0b682f37b2b7b777078f811bdf93a6fa5231ac5.png'}, 'Sniper': {'color': 'black', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10050.be0a865d3d49ca386d2a3835cc46eab52a923f47.png'}, 'Meepo': {'color': 'blue', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10004.8e77e6463c971dab1fa01b3761808eb2cf5163b0.png'}, 'Winter Wyvern': {'color': 'black', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10010.ad0a64e7f9814fc0cb1c7e2aa4b217e549239bb6.png'}, 'Venomancer': {'color': 'blue', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10001.c2456641c9dd1b758dd7a0caf5e2a56f727a51f8.png'}, 'Crystal Maiden': {'color': 'blue', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10064.e76bb6f2b597ae16bc8a5efa82eca5ff39afaa29.png'}, 'Zeus': {'color': 'blue', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10065.de19a6f1e68cfcab2f38f25b3d8847866ba87ccb.png'}, 'Beastmaster': {'color': 'red', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10029.9deae28f2a6715b2456e5844e2fdea7aaa28418f.png'}, 'Lion': {'color': 'black', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10060.1b8ab00d3d43fa0aec13c1d4f078c510c2828eed.png'}, 'Bloodseeker': {'color': 'black', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10018.99a88322fecd54fc5fe195cd8a12f49bc64e424c.png'}, 'Sven': {'color': 'red', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10054.f7ec19918c68fa805f4577fd31457b5a8a7da2e5.png'}, 'Tinker': {'color': 'black', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10025.33033b1e8b19d9a934322355077aef6467115d73.png'}, 'Drow Ranger': {'color': 'green', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10032.ac3532fc6482ff603748ddde2fb3564273a3b72e.png'}, "J'Muy the Wise": {'color': 'blue', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set00/4008.35f4da08e371db6ecc077f4aad08113dac8cc4de.png'}, 'Centaur Warrunner': {'color': 'red', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10021.f655334174b3964b58604e3cfa80360e06d83004.png'}, 'Treant Protector': {'color': 'green', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10056.4ea3388b448c9ee13bbbfd7248b46f0c3e71e98a.png'}, 'Farvhan the Dreamer': {'color': 'green', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set00/4000.049cff338ab7274d0dcde4d4e3ec5bc5bcdd2a8e.png'}, 'Dark Seer': {'color': 'green', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10068.e8e173ac8dd4f1d582fe41378232b4c3637ab039.png'}, 'Kanna': {'color': 'blue', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10031.967b53755c3a477cc89b05422018a06d08e837f2.png'}, 'Outworld Devourer': {'color': 'blue', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10046.959caac2a5c3a0e8efeec6af631337a483bb8795.png'}, 'Abaddon': {'color': 'green', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10016.49550e3b17ccf2611eb71b22f58664ae338be8ae.png'}, 'Axe': {'color': 'red', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10020.023febd622949d771d9f6a4322efc339ced8c560.png'}, 'Debbi the Cunning': {'color': 'black', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set00/4005.ceab77c296987994f9dfbc5f27bfcbb3fefde14a.png'}, 'Bristleback': {'color': 'red', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10030.d6427ab9016cda608a66759ed0b5e8a51a532d0f.png'}, 'Lich': {'color': 'black', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10038.26778b9a203a57b0d3ffb1bc75b7a0734e88c6c8.png'}, 'Earthshaker': {'color': 'blue', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10033.7c8e9fa3eccd923d8433ed2b98aef717766ca0d9.png'}, 'Pugna': {'color': 'red', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10048.ca73a1b73aa37fc74a7807a69357e2e5641b01df.png'}, 'Rix': {'color': 'green', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10026.59c2df4317db54a08c492c3d78f23ed9206a2a17.png'}, 'Legion Commander': {'color': 'red', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10069.f0595417e162f98c02cd6ce7b3a45b5413f6639f.png'}, 'Mazzie': {'color': 'red', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10052.16b67615c0229d72fd946e7b9e2407420bbbf67f.png'}, 'Bounty Hunter': {'color': 'black', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10023.503fcb60e0cdc30aa1d5a6f858a4050e3315b5f0.png'}, 'Luna': {'color': 'blue', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10006.ee9329205440996f09bdcc600c6aaeaa8440c44b.png'}, 'Tidehunter': {'color': 'red', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10024.1ffefd6bce93c5753f51eefdd39e1089b810b08b.png'}, 'Sorla Khan': {'color': 'black', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10058.635583094b11fcc0f86d624e9007f4a519179f38.png'}, 'Phantom Assassin': {'color': 'black', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10047.dd94f5bc1b22bef2e9b18264c523d8e28704f728.png'}, 'Chen': {'color': 'green', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10017.c755182fd873b5df7f4d9bf6075dc1065021b560.png'}, 'Enchantress': {'color': 'green', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10036.995dc56212e8e8bf40471d3121262d43a82e7c31.png'}, 'Necrophos': {'color': 'black', 'image': 'https://steamcdn-a.akamaihd.net/apps/583950/icons/set01/10059.66aae3f23e16000eb90086810be1d750ec6babe0.png'}}
    
    div_color = {
        "black": "#999999",
        "red": "#aa3333",
        "green": "#33aa33",
        "blue" : "#6666aa"
    }
    
    matches = {};
    var matchCounter = 0;
    
    var failures = 0;
    
    function GetNextData()
    {
        if (g_sGcContinueToken == null ||  g_sGcContinueToken == undefined)
        {
            ShowAlertDialog( 'Error', 'Failed because the history token is missing. Please inform the script creator.', 'OK' );
        }
        if (g_sessionID == null || g_sessionID == undefined)
        {
            ShowAlertDialog( 'Error', 'Failed because the session token is missing. Please inform the script creator.', 'OK' );
        }
        var request_data = {
            ajax: 1,
            tab: 'MatchPlayers',
            continue_token: g_sGcContinueToken,
            sessionid: g_sessionID
        };
        $J.ajax({
            type: "GET",
            url: "https://steamcommunity.com/my/gcpd/583950",
            data: request_data
        }).done( function( data ) {
            if ( data.success )
            {
                if ( data.html )
                {
                    var resultDataDOM = new DOMParser().parseFromString( data.html , 'text/html').body.firstChild;
    
                    var tableRow = resultDataDOM.rows[resultDataDOM.rows.length-1];
    
                    var matchID = tableRow.cells[0].textContent;
                    var matchTime = tableRow.cells[3].textContent;
                    var outcome = tableRow.cells[5].textContent;
                    var turns = tableRow.cells[6].textContent;
                    var team = tableRow.cells[9].textContent;
                    var tower1 = tableRow.cells[11].textContent;
                    var tower2 = tableRow.cells[12].textContent;
                    var tower3 = tableRow.cells[13].textContent;
                    var ancient = tableRow.cells[14].textContent;
                    var timeLeft = tableRow.cells[15].textContent;
                    var hero1 = tableRow.cells[16].textContent;
                    var hero2 = tableRow.cells[17].textContent;
                    var hero3 = tableRow.cells[18].textContent;
                    var hero4 = tableRow.cells[19].textContent;
                    var hero5 = tableRow.cells[20].textContent;
                    var gauntletID = tableRow.cells[21].textContent;
    
                    match = {};
                    match["matchID"] = matchID;
                    match["matchTime"] = matchTime;
                    match["outcome"] = outcome;
                    match["turns"] = turns;
                    match["team"] = team;
                    match["tower1"] = tower1;
                    match["tower2"] = tower2;
                    match["tower3"] = tower3;
                    match["ancient"] = ancient;
                    match["timeLeft"] = timeLeft;
                    match["hero1"] = hero1;
                    match["hero2"] = hero2;
                    match["hero3"] = hero3;
                    match["hero4"] = hero4;
                    match["hero5"] = hero5;
                    match["gauntletID"] = gauntletID;
                    match["isWin"] = outcome == team;
    
                    if (!(hero1 == "0") && !(hero2 == "0") && !(hero3 == "0") && !(hero4 == "0") && !(hero5 == "0"))
                    {
                        console.log("------------ match ----------");
                        for (var key in match){
                            console.log(key + ": " + match[key]);
                        }
    
                        if (matches[gauntletID] == undefined)
                        {
                            matches[gauntletID] = []
                        }
                        matches[gauntletID].push(match);
                        matchCounter ++;
                    }
    
                }
    
                failures = 0;
    
                if ( data.continue_token )
                {
                    g_sGcContinueToken = data.continue_token;
                    loadingText.textContent = "loading matches please wait... (" + matchCounter + " loaded)";
                    setTimeout(GetNextData, 100);
                }
                else {
                    g_sGcContinueToken = null;
                    setTimeout(processData, 100);
                }
            }
            else
            {
                failures++;
                if (failures > 5)
                {
                    ShowAlertDialog( 'Error', 'Artifact servers have returned invalid data. Sorry. Please try again.', 'OK' );
                }
                else
                {
                    setTimeout(GetNextData, 1000);
                }
            }
        }).fail( function( jqXHR ) {
            if ( jqXHR.status == 429 )
            {
                failures++;
                if (failures > 5)
                {
                    ShowAlertDialog( 'Error', 'Artifact servers have rate-limited you', 'OK' );
                }
                else
                {
                    setTimeout(GetNextData, 1000);
                }
            }
            else
            {
                failures++;
                if (failures > 5)
                {
                    ShowAlertDialog( 'Error', 'Artifact serves have returned an error. Sorry. Please try again.', 'OK' );
                }
                else
                {
                    setTimeout(GetNextData, 1000);
                }
            }
        });
    }
    
    GetNextData();
    function processData() {
        loadingDiv.style = "display: none";
        mainContents = document.getElementById("mainContents");
    
        var resultsDiv = document.createElement("div");
        mainContents.insertBefore(resultsDiv, mainContents.firstChild);
    
        for (var gauntletID in matches)
        {
            var gauntletDiv = document.createElement("div");
            resultsDiv.append(gauntletDiv);
            gauntletDiv.style = "margin-top: 20px;"
            if (gauntletID == 0)
            {
                gauntletDiv.textContent = "-------------------------- Constructed --------------------------";
            }
            else if (gauntletID == 8)
            {
                gauntletDiv.textContent = "-------------------------- Prize Phantom Draft --------------------------";
            }
            else if (gauntletID == 11)
            {
                gauntletDiv.textContent = "-------------------------- Standard Phantom Draft --------------------------";
            }
            else if (gauntletID == 5)
            {
                gauntletDiv.textContent = "-------------------------- Call To Arms --------------------------";
            }
            else if (gauntletID == 9)
            {
                gauntletDiv.textContent = "-------------------------- Keeper Draft --------------------------";
            }
            else {
                gauntletDiv.textContent = "------------- gauntlet #" + gauntletID + " (unknown, let script creator know what mode you think this is) ------------------";
            }
    
            gauntletMatches = matches[gauntletID];
    
            var winCount = 0;
            var i = 0;
            for (i = 0; i < gauntletMatches.length; i++)
            {
                var match = gauntletMatches[i];
                if (match["isWin"] == true)
                {
                    winCount ++;
                }
            }
    
            var gamesDiv = document.createElement("div");
            resultsDiv.append(gamesDiv);
            gamesDiv.textContent = "Games Played: " + gauntletMatches.length;
            var winsDiv = document.createElement("div");
            resultsDiv.append(winsDiv);
            winsDiv.textContent = "Win rate: " + (winCount * 100/gauntletMatches.length).toFixed(3) + "%";
    
            var hero_stats = {}
            for (i = 0; i < gauntletMatches.length; i++)
            {
                var match = gauntletMatches[i];
    
                for (var j = 1; j <= 5; j++)
                {
                    hero = match["hero"+j];
                    if (hero_stats[hero] == undefined)
                    {
                        hero_stats[hero] = {};
                        hero_stats[hero]["num_games"] = 0;
                        hero_stats[hero]["num_wins"] = 0;
                    }
    
                    hero_stats[hero]["num_games"]++;
                    if (match["isWin"] == true)
                    {
                        hero_stats[hero]["num_wins"]++;
                    }
                }
            }
    
            var heroGames = [];
            var heroWinRates = [];
            for (var hero in hero_stats) {
                heroGames.push([hero, hero_stats[hero]["num_games"]]);
                heroWinRates.push([hero, hero_stats[hero]["num_games"], hero_stats[hero]["num_wins"]/hero_stats[hero]["num_games"]]);
            }
    
            heroGames.sort(function(a, b) {
                return b[1] - a[1];
            });
    
            heroWinRates.sort(function(a, b) {
                return b[2] - a[2];
            });
    
            var heroGamesDiv = document.createElement("div");
            resultsDiv.append(heroGamesDiv);
            heroGamesDiv.style = "margin-top: 10px;"
            heroGamesDiv.textContent = " --- Top heroes played ---";
            for (i = 0; i < heroGames.length; i++)
            {
                var heroGamesDiv = document.createElement("div");
                resultsDiv.append(heroGamesDiv);
                heroGamesDiv.style = "color: " + div_color[hero_data[heroGames[i][0]].color];
                heroGamesDiv.textContent = heroGames[i][1] + " - " + heroGames[i][0];
            }
    
            var heroGamesDiv = document.createElement("div");
            resultsDiv.append(heroGamesDiv);
            heroGamesDiv.style = "margin-top: 10px;"
            heroGamesDiv.textContent = " --- Top heroes win rate ---";
            for (i = 0; i < heroWinRates.length; i++)
            {
                var heroGamesDiv = document.createElement("div");
                resultsDiv.append(heroGamesDiv);
                heroGamesDiv.style = "color: " + div_color[hero_data[heroWinRates[i][0]].color];
                heroGamesDiv.textContent = (heroWinRates[i][2]*100).toFixed(1) + "% - " + heroWinRates[i][0] + " (games played: " + heroWinRates[i][1] + " )";
            }
    
            var matchHistoryDiv = document.createElement("div");
            resultsDiv.append(matchHistoryDiv);
            matchHistoryDiv.style = "margin-top: 10px;"
            matchHistoryDiv.textContent = " --- Condensed match history ---";
    
            for (i = 0; i < gauntletMatches.length; i++)
            {
                var match = gauntletMatches[i];
    
                var matchDiv = document.createElement("div");
                resultsDiv.append(matchDiv);
    
                matchDiv.textContent = (match["isWin"] ? "win" : "loss") + " ---- " + match["hero1"] + ", " + match["hero2"] + ", " + match["hero3"] + ", " + match["hero4"] + ", " + match["hero5"];
                matchDiv.style = match["isWin"] ? "color:green" : "color:red"
    
                /*var heroImg = document.createElement("img");
                heroImg.src = hero_data[match.hero1].image;
                resultsDiv.append(heroImg);*/
            }
        }
    }
    • Скрипт начнёт обрабатывать матчи. В зависимости от их количества, это может занять значительное время (на почти 300 матчей ушло больше пяти минут).
      1545914738974.png
    • Важно не обновлять и не закрывать страницу — иначе придётся начинать с начала
    • Скрипт не получает доступа к чувствительной информации (логину/паролю/дк хуку в инвентаре/и т.д.), а также не отправляет её на сторонние сервера
  • После завершения работы на той же странице появится вся нужная нам информация

    sTASKDW.png

    Фрагмент данных, обработанных скриптом
Расшифровка:
  • Полученная информация достаточно понятна даже без знаний языков (Constructed это режим "Личная колода", а перевести названия героев с английского на русский поможет наша библиотека карт — в строку поиска можно вводить английские названия, даже если сами карты отображаются на русском)
  • Автор не смог определить названия состязаний #7 и #10 (в списке они отображаются как gauntlet #7 и gauntlet #10). Можно предположить, что это платный/бесплатный констрактед


Источник: reddit
 
Последнее редактирование:

Читайте также

Поделиться Твитнуть
Присоединяйся к обсуждению
Зарегистрироваться Войти

Комментарии

#2
Во всех обозревателях работает.. В ослике только не проверял.
 
#4
-------------------------- Prize Phantom Draft --------------------------
Games Played: 230
Win rate: 62.174%