├── Dockerfile ├── authentication-one.ipynb ├── authentication-two.ipynb ├── friend-request.ipynb ├── lobby_kd.ipynb ├── match-history.ipynb ├── readme.md ├── recaptcha-sso-token.ipynb └── requirements.txt /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM jupyter/scipy-notebook 2 | ENV COD_PW=${COD_PW} 3 | ENV COP_EMAIL=${COD_EMAIL} -------------------------------------------------------------------------------- /authentication-one.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# How to authenticate to the COD API." 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "Import the necessary libraries. \n", 15 | "We'll use requests for doing our HTTP API calls. \n", 16 | "The package random is used to generate a random device Id." 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": null, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "import requests\n", 26 | "import random\n", 27 | "import os" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": {}, 33 | "source": [ 34 | "The first step in authenticating against the COD API is to generate a random device ID and register it. This will return an authorization_token that we'll have to use in subsequent API calls." 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "device_id = hex(random.getrandbits(128)).lstrip(\"0x\")\n", 44 | "payload = {\"deviceId\": device_id}\n", 45 | "resp = requests.post('https://profile.callofduty.com/cod/mapp/registerDevice', json=payload)\n", 46 | "\n", 47 | "auth_token = resp.json()['data']['authHeader']" 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": {}, 53 | "source": [ 54 | "Next up is actually loggin in. Add the authorization token and your device Id to the relevant headers. \n", 55 | "Use your email and password to login. Here I read my email and password from an environment variable that I exported in my terminal. If you don't know what this just type in your email and password directly. " 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": null, 61 | "metadata": {}, 62 | "outputs": [], 63 | "source": [ 64 | "headers = {\n", 65 | " \"Authorization\": f\"Bearer {auth_token}\",\n", 66 | " \"x_cod_device_id\" : device_id,\n", 67 | "}\n", 68 | "\n", 69 | "data = {'email': os.environ.get('COD_EMAIL'), 'password': os.environ.get('COD_PW')}\n", 70 | "# data = {'email': 'YourEmail', 'password': 'YourSuperSecretPassword'}\n", 71 | "\n", 72 | "resp_login = requests.post('https://profile.callofduty.com/cod/mapp/login', headers=headers, json=data)" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": null, 78 | "metadata": {}, 79 | "outputs": [], 80 | "source": [ 81 | "resp_login.json()" 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "metadata": {}, 87 | "source": [ 88 | "Example: Get your profile data based on your uno." 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": null, 94 | "metadata": {}, 95 | "outputs": [], 96 | "source": [ 97 | "resp_profile = requests.get('https://www.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/uno/uno/14688938695022220470/profile/type/warzone', headers=headers, cookies=resp_login.cookies)\n", 98 | "resp_profile.json()" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": null, 104 | "metadata": {}, 105 | "outputs": [], 106 | "source": [] 107 | } 108 | ], 109 | "metadata": { 110 | "kernelspec": { 111 | "display_name": "Python 3", 112 | "language": "python", 113 | "name": "python3" 114 | }, 115 | "language_info": { 116 | "codemirror_mode": { 117 | "name": "ipython", 118 | "version": 3 119 | }, 120 | "file_extension": ".py", 121 | "mimetype": "text/x-python", 122 | "name": "python", 123 | "nbconvert_exporter": "python", 124 | "pygments_lexer": "ipython3", 125 | "version": "3.8.2" 126 | } 127 | }, 128 | "nbformat": 4, 129 | "nbformat_minor": 2 130 | } 131 | -------------------------------------------------------------------------------- /authentication-two.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "ranging-reply", 6 | "metadata": {}, 7 | "source": [ 8 | "# Second Method of authentication" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "exposed-sweet", 14 | "metadata": {}, 15 | "source": [ 16 | "## Short version (with session)" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "id": "heard-finnish", 22 | "metadata": {}, 23 | "source": [ 24 | "Import required python modules." 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": null, 30 | "id": "organized-gnome", 31 | "metadata": {}, 32 | "outputs": [], 33 | "source": [ 34 | "import requests\n", 35 | "import os" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "id": "expected-frederick", 41 | "metadata": {}, 42 | "source": [ 43 | "For the short version we are using the [Session](https://requests.readthedocs.io/en/master/user/advanced/#session-objects) functionality of the python requests module. Using a Session object will persist cookies across all requests.\n", 44 | "\n", 45 | "\n", 46 | "1. We start by creating a Session instance. \n", 47 | "2. Open(GET request) the login page using the session instance this will persist the response cookies in the session\n", 48 | "3. Create dictionary with required params to login\n", 49 | " * username/password: using os.environ.get to read the value from the \"Enviroment Variables\"\n", 50 | " * Set remember_me to true\n", 51 | " * _csrf: here we re-use the CSRF/XSRF token that was returned by the previous request \n", 52 | "4. Do the POST request with the data as [url params](https://requests.readthedocs.io/en/master/user/quickstart/#passing-parameters-in-urls)" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": null, 58 | "id": "intended-democracy", 59 | "metadata": {}, 60 | "outputs": [], 61 | "source": [ 62 | "s = requests.Session()\n", 63 | "s.get('https://profile.callofduty.com/cod/login')\n", 64 | "data = {'username': os.environ.get('COD_EMAIL'), \n", 65 | " 'password': os.environ.get('COD_PW'), \n", 66 | " 'remember_me': 'true', \n", 67 | " '_csrf': s.cookies['XSRF-TOKEN']}\n", 68 | "s.post('https://profile.callofduty.com/do_login?new_SiteId=cod', params=data)" 69 | ] 70 | }, 71 | { 72 | "cell_type": "markdown", 73 | "id": "elegant-cooperative", 74 | "metadata": {}, 75 | "source": [ 76 | "Test if the login worked by requesting private profile stats to see if we're properly authenticated." 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": null, 82 | "id": "compact-infection", 83 | "metadata": {}, 84 | "outputs": [], 85 | "source": [ 86 | "resp_profile = s.get('https://www.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/uno/uno/14688938695022220470/profile/type/warzone')\n", 87 | "resp_profile.json()" 88 | ] 89 | }, 90 | { 91 | "cell_type": "markdown", 92 | "id": "rural-modem", 93 | "metadata": {}, 94 | "source": [ 95 | "## Longer Version (without session)" 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "id": "younger-geology", 101 | "metadata": {}, 102 | "source": [ 103 | "We get the login page and save the XSRF-TOKEN that is returned by the response and can be found in the response object. CSRF/XSRF tokens are used to prevent CSRF attacks: https://en.wikipedia.org/wiki/Cross-site_request_forgery" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": null, 109 | "id": "exact-slovenia", 110 | "metadata": {}, 111 | "outputs": [], 112 | "source": [ 113 | "get_login = requests.get('https://profile.callofduty.com/cod/login')\n", 114 | "xsrf_token = get_login.cookies['XSRF-TOKEN']" 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "id": "creative-assurance", 120 | "metadata": {}, 121 | "source": [ 122 | "Now that we have the XSRF token we can login and get the SSO tokens en ATKN tokens to do requests to private endpoints.\n", 123 | "1. Create dictionary with required params to login\n", 124 | " * username/password: using os.environ.get to read the value from the \"Enviroment Variables\"\n", 125 | " * Set remember_me to true\n", 126 | " * _csrf: here we re-use the CSRF/XSRF token that was returned by the previous request\n", 127 | "2. Do the POST request with the data as url params AND also pass the cookies that you got from the previous request it will contain a cookie that has the XSRF-TOKEN.\n" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": null, 133 | "id": "dying-hungarian", 134 | "metadata": {}, 135 | "outputs": [], 136 | "source": [ 137 | "data = {\n", 138 | " 'username': os.environ.get('COD_EMAIL'), \n", 139 | " 'password': os.environ.get('COD_PW'), \n", 140 | " 'remember_me': 'true', \n", 141 | " '_csrf': xsrf_token\n", 142 | "}\n", 143 | "\n", 144 | "cookies = {\n", 145 | " 'XSRF-TOKEN': xsrf_token,\n", 146 | "}\n", 147 | "\n", 148 | "post_login = requests.post('https://profile.callofduty.com/do_login?new_SiteId=cod', params=data, cookies=get_login.cookies)" 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "id": "voluntary-pickup", 154 | "metadata": {}, 155 | "source": [ 156 | "Now we would expect the SSO tokens and ATKN to be in the response Cookies, unfortunately this is not case because in the response we are storing in \"post_login\" we've already been redirected twice and the post_login instance cookies won't contain the tokens." 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": null, 162 | "id": "racial-accommodation", 163 | "metadata": {}, 164 | "outputs": [], 165 | "source": [ 166 | "try: \n", 167 | " post_login.cookies['ACT_SSO_COOKIE']\n", 168 | " print(\"ACT_SSO_COOKIE found\")\n", 169 | "except KeyError:\n", 170 | " print(\"ACT_SSO_COOKIE not found\")" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "id": "lightweight-washer", 176 | "metadata": {}, 177 | "source": [ 178 | "If you check the history of the response, you'll see there have been two previous response objects with status_code 302(redirect), if you check the cookies of the first response you'll find the tokens that we need." 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": null, 184 | "id": "correct-cloud", 185 | "metadata": {}, 186 | "outputs": [], 187 | "source": [ 188 | "post_login.history" 189 | ] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "id": "considerable-affair", 194 | "metadata": {}, 195 | "source": [ 196 | "If we check the first Response instance at index zero of the list you'll see that it contains the tokens we need." 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": null, 202 | "id": "innocent-charleston", 203 | "metadata": {}, 204 | "outputs": [], 205 | "source": [ 206 | "try: \n", 207 | " post_login.history[0].cookies['ACT_SSO_COOKIE']\n", 208 | " print(\"ACT_SSO_COOKIE found\")\n", 209 | "except KeyError:\n", 210 | " print(\"ACT_SSO_COOKIE not found\")\n", 211 | "\n", 212 | "post_login.history[0].cookies" 213 | ] 214 | }, 215 | { 216 | "cell_type": "markdown", 217 | "id": "respected-baking", 218 | "metadata": {}, 219 | "source": [ 220 | "As we only need the tokens of first response we could disable redirection in the post request adding the parameter allow_redirects=False" 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": null, 226 | "id": "split-glenn", 227 | "metadata": {}, 228 | "outputs": [], 229 | "source": [ 230 | "post_login_wo_redirect = requests.post('https://profile.callofduty.com/do_login?new_SiteId=cod', params=data, cookies=get_login.cookies, allow_redirects=False)" 231 | ] 232 | }, 233 | { 234 | "cell_type": "markdown", 235 | "id": "outside-hometown", 236 | "metadata": {}, 237 | "source": [ 238 | "Test if the login worked by requesting private profile stats to see if we're properly authenticated. \n", 239 | "We pass the cookies that were returned by the first response instance of the \"do_login\" call. These cookies contain the ACT_SSO_COOKIE & atkn values that are required by callofduty to prove that our client is authenticated to make this API call.\n", 240 | "The cookies also contain a ACT_SSO_COOKIE_EXPIRY value that will indicate when the token will expirty and we'll have to renew it or authenticate again." 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "execution_count": null, 246 | "id": "former-player", 247 | "metadata": {}, 248 | "outputs": [], 249 | "source": [ 250 | "resp_profile = requests.get('https://www.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/uno/uno/14688938695022220470/profile/type/warzone', cookies=post_login_wo_redirect.cookies)\n", 251 | "resp_profile.json()" 252 | ] 253 | }, 254 | { 255 | "cell_type": "code", 256 | "execution_count": null, 257 | "id": "interior-public", 258 | "metadata": {}, 259 | "outputs": [], 260 | "source": [] 261 | } 262 | ], 263 | "metadata": { 264 | "kernelspec": { 265 | "display_name": "Python 3", 266 | "language": "python", 267 | "name": "python3" 268 | }, 269 | "language_info": { 270 | "codemirror_mode": { 271 | "name": "ipython", 272 | "version": 3 273 | }, 274 | "file_extension": ".py", 275 | "mimetype": "text/x-python", 276 | "name": "python", 277 | "nbconvert_exporter": "python", 278 | "pygments_lexer": "ipython3", 279 | "version": "3.8.2" 280 | } 281 | }, 282 | "nbformat": 4, 283 | "nbformat_minor": 5 284 | } 285 | -------------------------------------------------------------------------------- /friend-request.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "appreciated-banks", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "import requests\n", 11 | "import random\n", 12 | "import os" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": 2, 18 | "id": "rubber-center", 19 | "metadata": {}, 20 | "outputs": [ 21 | { 22 | "data": { 23 | "text/plain": [ 24 | "" 25 | ] 26 | }, 27 | "execution_count": 2, 28 | "metadata": {}, 29 | "output_type": "execute_result" 30 | } 31 | ], 32 | "source": [ 33 | "s = requests.Session()\n", 34 | "s.get('https://profile.callofduty.com/cod/login')\n", 35 | "data = {'username': os.environ.get('COD_EMAIL'), \n", 36 | " 'password': os.environ.get('COD_PW'), \n", 37 | " 'remember_me': 'true', \n", 38 | " '_csrf': s.cookies['XSRF-TOKEN']}\n", 39 | "s.post('https://profile.callofduty.com/do_login?new_SiteId=cod', params=data)" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": null, 45 | "id": "naked-genesis", 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 11, 53 | "id": "ceramic-butler", 54 | "metadata": {}, 55 | "outputs": [ 56 | { 57 | "data": { 58 | "text/plain": [ 59 | "{'status': 'success',\n", 60 | " 'data': {'title': 'mw',\n", 61 | " 'platform': 'psn',\n", 62 | " 'username': 'Hormigator1',\n", 63 | " 'type': 'wz',\n", 64 | " 'level': 200.0,\n", 65 | " 'maxLevel': 1.0,\n", 66 | " 'levelXpRemainder': 26683.0,\n", 67 | " 'levelXpGained': 16217.0,\n", 68 | " 'prestige': 15.0,\n", 69 | " 'prestigeId': 0.0,\n", 70 | " 'maxPrestige': 0.0,\n", 71 | " 'totalXp': 1325315.0,\n", 72 | " 'paragonRank': 0.0,\n", 73 | " 'paragonId': 0.0,\n", 74 | " 's': 1.0,\n", 75 | " 'p': 0.0,\n", 76 | " 'lifetime': {'all': {'properties': {'recordLongestWinStreak': 11.0,\n", 77 | " 'recordXpInAMatch': 58864.0,\n", 78 | " 'accuracy': 0.20601418614387512,\n", 79 | " 'losses': 824.0,\n", 80 | " 'totalGamesPlayed': 4445.0,\n", 81 | " 'score': 13052931.0,\n", 82 | " 'winLossRatio': 0.416262149810791,\n", 83 | " 'totalShots': 148582.0,\n", 84 | " 'bestScoreXp': 0.0,\n", 85 | " 'gamesPlayed': 4445.0,\n", 86 | " 'bestSquardKills': 0.0,\n", 87 | " 'bestSguardWave': 0.0,\n", 88 | " 'bestConfirmed': 54.0,\n", 89 | " 'deaths': 27965.0,\n", 90 | " 'wins': 343.0,\n", 91 | " 'bestSquardCrates': 0.0,\n", 92 | " 'kdRatio': 1.002145528793335,\n", 93 | " 'bestAssists': 30.0,\n", 94 | " 'bestFieldgoals': 0.0,\n", 95 | " 'bestScore': 13260.0,\n", 96 | " 'recordDeathsInAMatch': 81.0,\n", 97 | " 'scorePerGame': 2936.5424071991,\n", 98 | " 'bestSPM': 1237.0,\n", 99 | " 'bestKillChains': 0.0,\n", 100 | " 'recordKillsInAMatch': 80.0,\n", 101 | " 'suicides': 2115.0,\n", 102 | " 'wlRatio': 0.416262149810791,\n", 103 | " 'currentWinStreak': 2.0,\n", 104 | " 'bestMatchBonusXp': 0.0,\n", 105 | " 'bestMatchXp': 0.0,\n", 106 | " 'bestSguardWeaponLevel': 0.0,\n", 107 | " 'bestKD': 17.0,\n", 108 | " 'kills': 28025.0,\n", 109 | " 'bestKillsAsInfected': 0.0,\n", 110 | " 'bestReturns': 0.0,\n", 111 | " 'bestStabs': 0.0,\n", 112 | " 'bestKillsAsSurvivor': 0.0,\n", 113 | " 'timePlayedTotal': 363801.0,\n", 114 | " 'bestDestructions': 0.0,\n", 115 | " 'headshots': 5384.0,\n", 116 | " 'bestRescues': 0.0,\n", 117 | " 'assists': 3956.0,\n", 118 | " 'ties': 3.0,\n", 119 | " 'recordKillStreak': 14.0,\n", 120 | " 'bestPlants': 0.0,\n", 121 | " 'misses': 117972.0,\n", 122 | " 'bestDamage': 0.0,\n", 123 | " 'bestSetbacks': 0.0,\n", 124 | " 'bestTouchdowns': 0.0,\n", 125 | " 'scorePerMinute': 2152.7589533838554,\n", 126 | " 'bestDeaths': 81.0,\n", 127 | " 'bestMedalXp': 0.0,\n", 128 | " 'bestDefends': 29.0,\n", 129 | " 'bestSquardRevives': 0.0,\n", 130 | " 'bestKills': 80.0,\n", 131 | " 'bestDefuses': 0.0,\n", 132 | " 'bestCaptures': 13.0,\n", 133 | " 'hits': 30610.0,\n", 134 | " 'bestKillStreak': 14.0,\n", 135 | " 'bestDenied': 18.0}},\n", 136 | " 'mode': {'gun': {'properties': {'kills': 8.0,\n", 137 | " 'score': 883.0,\n", 138 | " 'timePlayed': 289.0,\n", 139 | " 'kdRatio': 0.5714285714285714,\n", 140 | " 'setBacks': 0.0,\n", 141 | " 'scorePerMinute': 183.32179930795849,\n", 142 | " 'stabs': 0.0,\n", 143 | " 'deaths': 14.0}},\n", 144 | " 'dom': {'properties': {'kills': 1182.0,\n", 145 | " 'score': 186590.0,\n", 146 | " 'timePlayed': 26678.0,\n", 147 | " 'kdRatio': 0.9874686716791979,\n", 148 | " 'captures': 269.0,\n", 149 | " 'defends': 339.0,\n", 150 | " 'scorePerMinute': 419.6491491116276,\n", 151 | " 'deaths': 1197.0}},\n", 152 | " 'war': {'properties': {'kills': 1158.0,\n", 153 | " 'score': 147720.0,\n", 154 | " 'timePlayed': 29981.0,\n", 155 | " 'kdRatio': 1.0394973070017954,\n", 156 | " 'assists': 207.0,\n", 157 | " 'scorePerMinute': 295.62723057936694,\n", 158 | " 'deaths': 1114.0}},\n", 159 | " 'hq': {'properties': {'kills': 168.0,\n", 160 | " 'score': 19450.0,\n", 161 | " 'timePlayed': 5927.0,\n", 162 | " 'kdRatio': 1.20863309352518,\n", 163 | " 'captures': 21.0,\n", 164 | " 'defends': 5.0,\n", 165 | " 'scorePerMinute': 196.8955626792644,\n", 166 | " 'deaths': 139.0}},\n", 167 | " 'hc_dom': {'properties': {'kills': 4340.0,\n", 168 | " 'score': 602645.0,\n", 169 | " 'timePlayed': 63627.0,\n", 170 | " 'kdRatio': 0.9890610756608933,\n", 171 | " 'captures': 614.0,\n", 172 | " 'defends': 1183.0,\n", 173 | " 'scorePerMinute': 568.2917629308313,\n", 174 | " 'deaths': 4388.0}},\n", 175 | " 'hc_conf': {'properties': {'kills': 2459.0,\n", 176 | " 'score': 332865.0,\n", 177 | " 'timePlayed': 40592.0,\n", 178 | " 'kdRatio': 0.9410639112131649,\n", 179 | " 'confirms': 923.0,\n", 180 | " 'scorePerMinute': 492.0156681119433,\n", 181 | " 'denies': 696.0,\n", 182 | " 'deaths': 2613.0}},\n", 183 | " 'koth': {'properties': {'kills': 1080.0,\n", 184 | " 'score': 139380.0,\n", 185 | " 'timePlayed': 20889.0,\n", 186 | " 'kdRatio': 0.9557522123893806,\n", 187 | " 'defends': 39.0,\n", 188 | " 'objTime': 843.0,\n", 189 | " 'scorePerMinute': 400.3446790176648,\n", 190 | " 'deaths': 1130.0}},\n", 191 | " 'conf': {'properties': {'kills': 47.0,\n", 192 | " 'score': 6700.0,\n", 193 | " 'timePlayed': 2285.0,\n", 194 | " 'kdRatio': 0.5340909090909091,\n", 195 | " 'confirms': 15.0,\n", 196 | " 'scorePerMinute': 175.92997811816193,\n", 197 | " 'denies': 11.0,\n", 198 | " 'deaths': 88.0}},\n", 199 | " 'hc_hq': {'properties': {'kills': 170.0,\n", 200 | " 'score': 18025.0,\n", 201 | " 'timePlayed': 4250.0,\n", 202 | " 'kdRatio': 1.0059171597633136,\n", 203 | " 'captures': 22.0,\n", 204 | " 'defends': 6.0,\n", 205 | " 'scorePerMinute': 254.47058823529414,\n", 206 | " 'deaths': 169.0}},\n", 207 | " 'arena': {'properties': {'kills': 40.0,\n", 208 | " 'score': 18425.0,\n", 209 | " 'timePlayed': 5579.0,\n", 210 | " 'damage': 4381.0,\n", 211 | " 'kdRatio': 1.0256410256410255,\n", 212 | " 'assists': 1.0,\n", 213 | " 'scorePerMinute': 198.15379100197168,\n", 214 | " 'deaths': 39.0}},\n", 215 | " 'br_dmz': {'properties': {'wins': 9.0,\n", 216 | " 'kills': 1936.0,\n", 217 | " 'kdRatio': 0.9448511469009273,\n", 218 | " 'downs': 2155.0,\n", 219 | " 'topTwentyFive': 9.0,\n", 220 | " 'topTen': 9.0,\n", 221 | " 'contracts': 1203.0,\n", 222 | " 'revives': 50.0,\n", 223 | " 'topFive': 9.0,\n", 224 | " 'score': 1081690.0,\n", 225 | " 'timePlayed': 338935.0,\n", 226 | " 'gamesPlayed': 319.0,\n", 227 | " 'tokens': 0.0,\n", 228 | " 'scorePerMinute': 191.48627317922313,\n", 229 | " 'cash': 12600.0,\n", 230 | " 'deaths': 2049.0}},\n", 231 | " 'br': {'properties': {'wins': 55.0,\n", 232 | " 'kills': 6607.0,\n", 233 | " 'kdRatio': 1.189593086064098,\n", 234 | " 'downs': 6515.0,\n", 235 | " 'topTwentyFive': 1581.0,\n", 236 | " 'topTen': 766.0,\n", 237 | " 'contracts': 2764.0,\n", 238 | " 'revives': 890.0,\n", 239 | " 'topFive': 397.0,\n", 240 | " 'score': 8465615.0,\n", 241 | " 'timePlayed': 2517965.0,\n", 242 | " 'gamesPlayed': 2262.0,\n", 243 | " 'tokens': 0.0,\n", 244 | " 'scorePerMinute': 201.72516297883408,\n", 245 | " 'cash': 0.0,\n", 246 | " 'deaths': 5554.0}},\n", 247 | " 'sd': {'properties': {'kills': 2.0,\n", 248 | " 'score': 900.0,\n", 249 | " 'timePlayed': 1241.0,\n", 250 | " 'kdRatio': 0.5,\n", 251 | " 'plants': 0.0,\n", 252 | " 'scorePerMinute': 43.5132957292506,\n", 253 | " 'defuses': 0.0,\n", 254 | " 'deaths': 4.0}},\n", 255 | " 'grnd': {'properties': {'kills': 113.0,\n", 256 | " 'score': 15430.0,\n", 257 | " 'timePlayed': 3517.0,\n", 258 | " 'kdRatio': 1.313953488372093,\n", 259 | " 'defends': 5.0,\n", 260 | " 'objTime': 246.0,\n", 261 | " 'scorePerMinute': 263.2357122547626,\n", 262 | " 'deaths': 86.0}},\n", 263 | " 'cyber': {'properties': {'kills': 0.0,\n", 264 | " 'score': 0.0,\n", 265 | " 'timePlayed': 0.0,\n", 266 | " 'kdRatio': 0.0,\n", 267 | " 'plants': 0.0,\n", 268 | " 'scorePerMinute': 0.0,\n", 269 | " 'revives': 0.0,\n", 270 | " 'deaths': 0.0}},\n", 271 | " 'hc_war': {'properties': {'kills': 2983.0,\n", 272 | " 'score': 354085.0,\n", 273 | " 'timePlayed': 45966.0,\n", 274 | " 'kdRatio': 0.9246745195288283,\n", 275 | " 'assists': 385.0,\n", 276 | " 'scorePerMinute': 462.19161989296435,\n", 277 | " 'deaths': 3226.0}},\n", 278 | " 'br_all': {'properties': {'wins': 64.0,\n", 279 | " 'kills': 8543.0,\n", 280 | " 'kdRatio': 1.123635407076154,\n", 281 | " 'downs': 8670.0,\n", 282 | " 'topTwentyFive': 1590.0,\n", 283 | " 'topTen': 775.0,\n", 284 | " 'contracts': 3967.0,\n", 285 | " 'revives': 940.0,\n", 286 | " 'topFive': 406.0,\n", 287 | " 'score': 9547305.0,\n", 288 | " 'timePlayed': 2856900.0,\n", 289 | " 'gamesPlayed': 2581.0,\n", 290 | " 'tokens': 0.0,\n", 291 | " 'scorePerMinute': 200.510448388113,\n", 292 | " 'cash': 12600.0,\n", 293 | " 'deaths': 7603.0}},\n", 294 | " 'hc_sd': {'properties': {'kills': 0.0,\n", 295 | " 'score': 0.0,\n", 296 | " 'timePlayed': 0.0,\n", 297 | " 'kdRatio': 0.0,\n", 298 | " 'plants': 0.0,\n", 299 | " 'scorePerMinute': 0.0,\n", 300 | " 'defuses': 0.0,\n", 301 | " 'deaths': 0.0}},\n", 302 | " 'arm': {'properties': {'kills': 185.0,\n", 303 | " 'score': 42880.0,\n", 304 | " 'timePlayed': 22358.0,\n", 305 | " 'kdRatio': 0.44047619047619047,\n", 306 | " 'captures': 15.0,\n", 307 | " 'defends': 11.0,\n", 308 | " 'scorePerMinute': 115.07290455318007,\n", 309 | " 'deaths': 420.0}},\n", 310 | " 'hc_cyber': {'properties': {'kills': 0.0,\n", 311 | " 'score': 0.0,\n", 312 | " 'timePlayed': 0.0,\n", 313 | " 'kdRatio': 0.0,\n", 314 | " 'plants': 0.0,\n", 315 | " 'scorePerMinute': 0.0,\n", 316 | " 'revives': 0.0,\n", 317 | " 'deaths': 0.0}},\n", 318 | " 'infect': {'properties': {'kills': 0.0,\n", 319 | " 'score': 0.0,\n", 320 | " 'infected': 0.0,\n", 321 | " 'timePlayed': 0.0,\n", 322 | " 'kdRatio': 0.0,\n", 323 | " 'scorePerMinute': 0.0,\n", 324 | " 'time': 0.0,\n", 325 | " 'deaths': 0.0}}},\n", 326 | " 'map': {},\n", 327 | " 'itemData': {'weapon_assault_rifle': {'iw8_ar_tango21': {'properties': {'hits': 1500.0,\n", 328 | " 'kills': 536.0,\n", 329 | " 'kdRatio': 0.9420035149384886,\n", 330 | " 'headshots': 94.0,\n", 331 | " 'accuracy': 0.17951172809956917,\n", 332 | " 'shots': 8356.0,\n", 333 | " 'deaths': 569.0}},\n", 334 | " 'iw8_ar_mike4': {'properties': {'hits': 1957.0,\n", 335 | " 'kills': 670.0,\n", 336 | " 'kdRatio': 0.950354609929078,\n", 337 | " 'headshots': 127.0,\n", 338 | " 'accuracy': 0.21505494505494505,\n", 339 | " 'shots': 9100.0,\n", 340 | " 'deaths': 705.0}},\n", 341 | " 'iw8_ar_valpha': {'properties': {'hits': 747.0,\n", 342 | " 'kills': 308.0,\n", 343 | " 'kdRatio': 1.1079136690647482,\n", 344 | " 'headshots': 52.0,\n", 345 | " 'accuracy': 0.180784123910939,\n", 346 | " 'shots': 4132.0,\n", 347 | " 'deaths': 278.0}},\n", 348 | " 'iw8_ar_falpha': {'properties': {'hits': 815.0,\n", 349 | " 'kills': 695.0,\n", 350 | " 'kdRatio': 0.9774964838255977,\n", 351 | " 'headshots': 131.0,\n", 352 | " 'accuracy': 0.16283716283716285,\n", 353 | " 'shots': 5005.0,\n", 354 | " 'deaths': 711.0}},\n", 355 | " 'iw8_ar_mcharlie': {'properties': {'hits': 2487.0,\n", 356 | " 'kills': 653.0,\n", 357 | " 'kdRatio': 1.007716049382716,\n", 358 | " 'headshots': 157.0,\n", 359 | " 'accuracy': 0.23776290630975144,\n", 360 | " 'shots': 10460.0,\n", 361 | " 'deaths': 648.0}},\n", 362 | " 'iw8_ar_akilo47': {'properties': {'hits': 1314.0,\n", 363 | " 'kills': 761.0,\n", 364 | " 'kdRatio': 1.0438957475994513,\n", 365 | " 'headshots': 123.0,\n", 366 | " 'accuracy': 0.1637995512341062,\n", 367 | " 'shots': 8022.0,\n", 368 | " 'deaths': 729.0}},\n", 369 | " 'iw8_ar_asierra12': {'properties': {'hits': 826.0,\n", 370 | " 'kills': 684.0,\n", 371 | " 'kdRatio': 1.0604651162790697,\n", 372 | " 'headshots': 119.0,\n", 373 | " 'accuracy': 0.19467358001414095,\n", 374 | " 'shots': 4243.0,\n", 375 | " 'deaths': 645.0}},\n", 376 | " 'iw8_ar_galima': {'properties': {'hits': 1454.0,\n", 377 | " 'kills': 651.0,\n", 378 | " 'kdRatio': 0.96875,\n", 379 | " 'headshots': 129.0,\n", 380 | " 'accuracy': 0.19809264305177113,\n", 381 | " 'shots': 7340.0,\n", 382 | " 'deaths': 672.0}},\n", 383 | " 'iw8_ar_sierra552': {'properties': {'hits': 4898.0,\n", 384 | " 'kills': 641.0,\n", 385 | " 'kdRatio': 1.346638655462185,\n", 386 | " 'headshots': 137.0,\n", 387 | " 'accuracy': 0.2861649918205188,\n", 388 | " 'shots': 17116.0,\n", 389 | " 'deaths': 476.0}},\n", 390 | " 'iw8_ar_falima': {'properties': {'hits': 932.0,\n", 391 | " 'kills': 680.0,\n", 392 | " 'kdRatio': 1.1314475873544094,\n", 393 | " 'headshots': 108.0,\n", 394 | " 'accuracy': 0.2515519568151147,\n", 395 | " 'shots': 3705.0,\n", 396 | " 'deaths': 601.0}},\n", 397 | " 'iw8_ar_anovember94': {'properties': {'hits': 1149.0,\n", 398 | " 'kills': 581.0,\n", 399 | " 'kdRatio': 1.0921052631578947,\n", 400 | " 'headshots': 89.0,\n", 401 | " 'accuracy': 0.1681791569086651,\n", 402 | " 'shots': 6832.0,\n", 403 | " 'deaths': 532.0}},\n", 404 | " 'iw8_ar_kilo433': {'properties': {'hits': 4512.0,\n", 405 | " 'kills': 777.0,\n", 406 | " 'kdRatio': 1.433579335793358,\n", 407 | " 'headshots': 109.0,\n", 408 | " 'accuracy': 0.2707795715057313,\n", 409 | " 'shots': 16663.0,\n", 410 | " 'deaths': 542.0}},\n", 411 | " 'iw8_ar_scharlie': {'properties': {'hits': 1012.0,\n", 412 | " 'kills': 779.0,\n", 413 | " 'kdRatio': 1.0774550484094052,\n", 414 | " 'headshots': 116.0,\n", 415 | " 'accuracy': 0.17167090754877015,\n", 416 | " 'shots': 5895.0,\n", 417 | " 'deaths': 723.0}}},\n", 418 | " 'weapon_shotgun': {'iw8_sh_mike26': {'properties': {'hits': 69.0,\n", 419 | " 'kills': 39.0,\n", 420 | " 'kdRatio': 39.0,\n", 421 | " 'headshots': 5.0,\n", 422 | " 'accuracy': 0.5307692307692308,\n", 423 | " 'shots': 130.0,\n", 424 | " 'deaths': 1.0}},\n", 425 | " 'iw8_sh_charlie725': {'properties': {'hits': 690.0,\n", 426 | " 'kills': 571.0,\n", 427 | " 'kdRatio': 0.926948051948052,\n", 428 | " 'headshots': 74.0,\n", 429 | " 'accuracy': 0.69,\n", 430 | " 'shots': 1000.0,\n", 431 | " 'deaths': 616.0}},\n", 432 | " 'iw8_sh_oscar12': {'properties': {'hits': 448.0,\n", 433 | " 'kills': 289.0,\n", 434 | " 'kdRatio': 0.9897260273972602,\n", 435 | " 'headshots': 35.0,\n", 436 | " 'accuracy': 0.43118383060635224,\n", 437 | " 'shots': 1039.0,\n", 438 | " 'deaths': 292.0}},\n", 439 | " 'iw8_sh_aalpha12': {'properties': {'hits': 182.0,\n", 440 | " 'kills': 101.0,\n", 441 | " 'kdRatio': 1.1477272727272727,\n", 442 | " 'headshots': 10.0,\n", 443 | " 'accuracy': 0.4354066985645933,\n", 444 | " 'shots': 418.0,\n", 445 | " 'deaths': 88.0}},\n", 446 | " 'iw8_sh_romeo870': {'properties': {'hits': 566.0,\n", 447 | " 'kills': 525.0,\n", 448 | " 'kdRatio': 1.0096153846153846,\n", 449 | " 'headshots': 58.0,\n", 450 | " 'accuracy': 0.5549019607843138,\n", 451 | " 'shots': 1020.0,\n", 452 | " 'deaths': 520.0}},\n", 453 | " 'iw8_sh_dpapa12': {'properties': {'hits': 572.0,\n", 454 | " 'kills': 537.0,\n", 455 | " 'kdRatio': 0.9210977701543739,\n", 456 | " 'headshots': 70.0,\n", 457 | " 'accuracy': 0.3864864864864865,\n", 458 | " 'shots': 1480.0,\n", 459 | " 'deaths': 583.0}}},\n", 460 | " 'weapon_marksman': {'iw8_sn_sbeta': {'properties': {'hits': 761.0,\n", 461 | " 'kills': 546.0,\n", 462 | " 'kdRatio': 0.914572864321608,\n", 463 | " 'headshots': 155.0,\n", 464 | " 'accuracy': 0.5066577896138482,\n", 465 | " 'shots': 1502.0,\n", 466 | " 'deaths': 597.0}},\n", 467 | " 'iw8_sn_crossbow': {'properties': {'hits': 57.0,\n", 468 | " 'kills': 99.0,\n", 469 | " 'kdRatio': 99.0,\n", 470 | " 'headshots': 21.0,\n", 471 | " 'accuracy': 0.17701863354037267,\n", 472 | " 'shots': 322.0,\n", 473 | " 'deaths': 0.0}},\n", 474 | " 'iw8_sn_romeo700': {'properties': {'hits': 260.0,\n", 475 | " 'kills': 262.0,\n", 476 | " 'kdRatio': 0.7043010752688172,\n", 477 | " 'headshots': 42.0,\n", 478 | " 'accuracy': 0.4529616724738676,\n", 479 | " 'shots': 574.0,\n", 480 | " 'deaths': 372.0}},\n", 481 | " 'iw8_sn_kilo98': {'properties': {'hits': 707.0,\n", 482 | " 'kills': 564.0,\n", 483 | " 'kdRatio': 1.0235934664246824,\n", 484 | " 'headshots': 198.0,\n", 485 | " 'accuracy': 0.517948717948718,\n", 486 | " 'shots': 1365.0,\n", 487 | " 'deaths': 551.0}},\n", 488 | " 'iw8_sn_mike14': {'properties': {'hits': 655.0,\n", 489 | " 'kills': 523.0,\n", 490 | " 'kdRatio': 0.8133748055987559,\n", 491 | " 'headshots': 78.0,\n", 492 | " 'accuracy': 0.2639000805801773,\n", 493 | " 'shots': 2482.0,\n", 494 | " 'deaths': 643.0}},\n", 495 | " 'iw8_sn_sksierra': {'properties': {'hits': 149.0,\n", 496 | " 'kills': 64.0,\n", 497 | " 'kdRatio': 2.909090909090909,\n", 498 | " 'headshots': 12.0,\n", 499 | " 'accuracy': 0.25689655172413794,\n", 500 | " 'shots': 580.0,\n", 501 | " 'deaths': 22.0}}},\n", 502 | " 'weapon_sniper': {'iw8_sn_alpha50': {'properties': {'hits': 1722.0,\n", 503 | " 'kills': 1441.0,\n", 504 | " 'kdRatio': 1.3555973659454374,\n", 505 | " 'headshots': 563.0,\n", 506 | " 'accuracy': 0.36123348017621143,\n", 507 | " 'shots': 4767.0,\n", 508 | " 'deaths': 1063.0}},\n", 509 | " 'iw8_sn_hdromeo': {'properties': {'hits': 346.0,\n", 510 | " 'kills': 328.0,\n", 511 | " 'kdRatio': 0.608534322820037,\n", 512 | " 'headshots': 74.0,\n", 513 | " 'accuracy': 0.39815880322209435,\n", 514 | " 'shots': 869.0,\n", 515 | " 'deaths': 539.0}},\n", 516 | " 'iw8_sn_delta': {'properties': {'hits': 353.0,\n", 517 | " 'kills': 367.0,\n", 518 | " 'kdRatio': 0.8378995433789954,\n", 519 | " 'headshots': 52.0,\n", 520 | " 'accuracy': 0.3115622241835834,\n", 521 | " 'shots': 1133.0,\n", 522 | " 'deaths': 438.0}},\n", 523 | " 'iw8_sn_xmike109': {'properties': {'hits': 24.0,\n", 524 | " 'kills': 14.0,\n", 525 | " 'kdRatio': 14.0,\n", 526 | " 'headshots': 2.0,\n", 527 | " 'accuracy': 0.20512820512820512,\n", 528 | " 'shots': 117.0,\n", 529 | " 'deaths': 0.0}}},\n", 530 | " 'tacticals': {'equip_gas_grenade': {'properties': {'extraStat1': 188.0,\n", 531 | " 'uses': 399.0}},\n", 532 | " 'equip_snapshot_grenade': {'properties': {'extraStat1': 202.0,\n", 533 | " 'uses': 239.0}},\n", 534 | " 'equip_decoy': {'properties': {'extraStat1': 1045.0, 'uses': 209.0}},\n", 535 | " 'equip_smoke': {'properties': {'extraStat1': 0.0, 'uses': 283.0}},\n", 536 | " 'equip_concussion': {'properties': {'extraStat1': 1696.0,\n", 537 | " 'uses': 2480.0}},\n", 538 | " 'equip_hb_sensor': {'properties': {'extraStat1': 0.0, 'uses': 7478.0}},\n", 539 | " 'equip_flash': {'properties': {'extraStat1': 523.0, 'uses': 935.0}},\n", 540 | " 'equip_adrenaline': {'properties': {'extraStat1': 191.0, 'uses': 11.0}}},\n", 541 | " 'lethals': {'equip_frag': {'properties': {'kills': 14.0, 'uses': 191.0}},\n", 542 | " 'equip_thermite': {'properties': {'kills': 442.0, 'uses': 1778.0}},\n", 543 | " 'equip_semtex': {'properties': {'kills': 44.0, 'uses': 534.0}},\n", 544 | " 'equip_claymore': {'properties': {'kills': 8.0, 'uses': 514.0}},\n", 545 | " 'equip_c4': {'properties': {'kills': 387.0, 'uses': 2049.0}},\n", 546 | " 'equip_at_mine': {'properties': {'kills': 20.0, 'uses': 624.0}},\n", 547 | " 'equip_throwing_knife': {'properties': {'kills': 26.0, 'uses': 83.0}},\n", 548 | " 'equip_molotov': {'properties': {'kills': 18.0, 'uses': 203.0}}},\n", 549 | " 'weapon_lmg': {'iw8_lm_kilo121': {'properties': {'hits': 269.0,\n", 550 | " 'kills': 41.0,\n", 551 | " 'kdRatio': 41.0,\n", 552 | " 'headshots': 11.0,\n", 553 | " 'accuracy': 0.13179813816756492,\n", 554 | " 'shots': 2041.0,\n", 555 | " 'deaths': 1.0}},\n", 556 | " 'iw8_lm_mkilo3': {'properties': {'hits': 217.0,\n", 557 | " 'kills': 34.0,\n", 558 | " 'kdRatio': 34.0,\n", 559 | " 'headshots': 4.0,\n", 560 | " 'accuracy': 0.14313984168865435,\n", 561 | " 'shots': 1516.0,\n", 562 | " 'deaths': 0.0}},\n", 563 | " 'iw8_lm_mgolf34': {'properties': {'hits': 476.0,\n", 564 | " 'kills': 137.0,\n", 565 | " 'kdRatio': 1.170940170940171,\n", 566 | " 'headshots': 16.0,\n", 567 | " 'accuracy': 0.1276824034334764,\n", 568 | " 'shots': 3728.0,\n", 569 | " 'deaths': 117.0}},\n", 570 | " 'iw8_lm_lima86': {'properties': {'hits': 536.0,\n", 571 | " 'kills': 167.0,\n", 572 | " 'kdRatio': 1.4649122807017543,\n", 573 | " 'headshots': 28.0,\n", 574 | " 'accuracy': 0.17783676177836763,\n", 575 | " 'shots': 3014.0,\n", 576 | " 'deaths': 114.0}},\n", 577 | " 'iw8_lm_pkilo': {'properties': {'hits': 583.0,\n", 578 | " 'kills': 212.0,\n", 579 | " 'kdRatio': 0.9098712446351931,\n", 580 | " 'headshots': 38.0,\n", 581 | " 'accuracy': 0.1570581896551724,\n", 582 | " 'shots': 3712.0,\n", 583 | " 'deaths': 233.0}},\n", 584 | " 'iw8_lm_sierrax': {'properties': {'hits': 142.0,\n", 585 | " 'kills': 30.0,\n", 586 | " 'kdRatio': 0.7142857142857143,\n", 587 | " 'headshots': 7.0,\n", 588 | " 'accuracy': 0.23745819397993312,\n", 589 | " 'shots': 598.0,\n", 590 | " 'deaths': 42.0}},\n", 591 | " 'iw8_lm_mgolf36': {'properties': {'hits': 138.0,\n", 592 | " 'kills': 25.0,\n", 593 | " 'kdRatio': 25.0,\n", 594 | " 'headshots': 1.0,\n", 595 | " 'accuracy': 0.17992177314211213,\n", 596 | " 'shots': 767.0,\n", 597 | " 'deaths': 0.0}}},\n", 598 | " 'weapon_launcher': {'iw8_la_gromeo': {'properties': {'hits': 168.0,\n", 599 | " 'kills': 196.0,\n", 600 | " 'kdRatio': 0.5648414985590778,\n", 601 | " 'headshots': 3.0,\n", 602 | " 'accuracy': 0.2048780487804878,\n", 603 | " 'shots': 820.0,\n", 604 | " 'deaths': 347.0}},\n", 605 | " 'iw8_la_rpapa7': {'properties': {'hits': 3.0,\n", 606 | " 'kills': 97.0,\n", 607 | " 'kdRatio': 1.1975308641975309,\n", 608 | " 'headshots': 0.0,\n", 609 | " 'accuracy': 0.016216216216216217,\n", 610 | " 'shots': 185.0,\n", 611 | " 'deaths': 81.0}},\n", 612 | " 'iw8_la_juliet': {'properties': {'hits': 0.0,\n", 613 | " 'kills': 6.0,\n", 614 | " 'kdRatio': 0.3,\n", 615 | " 'headshots': 0.0,\n", 616 | " 'accuracy': 0.0,\n", 617 | " 'shots': 33.0,\n", 618 | " 'deaths': 20.0}},\n", 619 | " 'iw8_la_kgolf': {'properties': {'hits': 70.0,\n", 620 | " 'kills': 108.0,\n", 621 | " 'kdRatio': 0.6033519553072626,\n", 622 | " 'headshots': 2.0,\n", 623 | " 'accuracy': 0.23333333333333334,\n", 624 | " 'shots': 300.0,\n", 625 | " 'deaths': 179.0}},\n", 626 | " 'iw8_la_mike32': {'properties': {'hits': 0.0,\n", 627 | " 'kills': 2.0,\n", 628 | " 'kdRatio': 2.0,\n", 629 | " 'headshots': 0.0,\n", 630 | " 'accuracy': 0.0,\n", 631 | " 'shots': 26.0,\n", 632 | " 'deaths': 0.0}}},\n", 633 | " 'supers': {'super_emp_drone': {'properties': {'kills': 0.0,\n", 634 | " 'misc1': 3.0,\n", 635 | " 'misc2': 0.0,\n", 636 | " 'uses': 11.0}},\n", 637 | " 'super_trophy': {'properties': {'kills': 2.0,\n", 638 | " 'misc1': 147.0,\n", 639 | " 'misc2': 0.0,\n", 640 | " 'uses': 593.0}},\n", 641 | " 'super_ammo_drop': {'properties': {'kills': 5.0,\n", 642 | " 'misc1': 2048.0,\n", 643 | " 'misc2': 0.0,\n", 644 | " 'uses': 433.0}},\n", 645 | " 'super_weapon_drop': {'properties': {'kills': 0.0,\n", 646 | " 'misc1': 1.0,\n", 647 | " 'misc2': 0.0,\n", 648 | " 'uses': 2.0}},\n", 649 | " 'super_fulton': {'properties': {'kills': 0.0,\n", 650 | " 'misc1': 0.0,\n", 651 | " 'misc2': 0.0,\n", 652 | " 'uses': 95.0}},\n", 653 | " 'super_armor_drop': {'properties': {'kills': 0.0,\n", 654 | " 'misc1': 0.0,\n", 655 | " 'misc2': 0.0,\n", 656 | " 'uses': 392.0}},\n", 657 | " 'super_select': {'properties': {'kills': 0.0,\n", 658 | " 'misc1': 0.0,\n", 659 | " 'misc2': 0.0,\n", 660 | " 'uses': 0.0}},\n", 661 | " 'super_tac_insert': {'properties': {'kills': 0.0,\n", 662 | " 'misc1': 405.0,\n", 663 | " 'misc2': 0.0,\n", 664 | " 'uses': 593.0}},\n", 665 | " 'super_recon_drone': {'properties': {'kills': 0.0,\n", 666 | " 'misc1': 119.0,\n", 667 | " 'misc2': 0.0,\n", 668 | " 'uses': 135.0}},\n", 669 | " 'super_deadsilence': {'properties': {'kills': 28.0,\n", 670 | " 'misc1': 3.0,\n", 671 | " 'misc2': 0.0,\n", 672 | " 'uses': 143.0}},\n", 673 | " 'super_supply_drop': {'properties': {'kills': 0.0,\n", 674 | " 'misc1': 0.0,\n", 675 | " 'misc2': 0.0,\n", 676 | " 'uses': 739.0}},\n", 677 | " 'super_tac_cover': {'properties': {'kills': 0.0,\n", 678 | " 'misc1': 65256.0,\n", 679 | " 'misc2': 0.0,\n", 680 | " 'uses': 161.0}},\n", 681 | " 'super_support_box': {'properties': {'kills': 173.0,\n", 682 | " 'misc1': 0.0,\n", 683 | " 'misc2': 0.0,\n", 684 | " 'uses': 458.0}}},\n", 685 | " 'weapon_pistol': {'iw8_pi_cpapa': {'properties': {'hits': 165.0,\n", 686 | " 'kills': 143.0,\n", 687 | " 'kdRatio': 0.8218390804597702,\n", 688 | " 'headshots': 35.0,\n", 689 | " 'accuracy': 0.35106382978723405,\n", 690 | " 'shots': 470.0,\n", 691 | " 'deaths': 174.0}},\n", 692 | " 'iw8_pi_mike9': {'properties': {'hits': 537.0,\n", 693 | " 'kills': 218.0,\n", 694 | " 'kdRatio': 1.2976190476190477,\n", 695 | " 'headshots': 56.0,\n", 696 | " 'accuracy': 0.2730045754956787,\n", 697 | " 'shots': 1967.0,\n", 698 | " 'deaths': 168.0}},\n", 699 | " 'iw8_pi_mike1911': {'properties': {'hits': 251.0,\n", 700 | " 'kills': 136.0,\n", 701 | " 'kdRatio': 1.1239669421487604,\n", 702 | " 'headshots': 20.0,\n", 703 | " 'accuracy': 0.3355614973262032,\n", 704 | " 'shots': 748.0,\n", 705 | " 'deaths': 121.0}},\n", 706 | " 'iw8_pi_golf21': {'properties': {'hits': 2171.0,\n", 707 | " 'kills': 155.0,\n", 708 | " 'kdRatio': 8.157894736842104,\n", 709 | " 'headshots': 29.0,\n", 710 | " 'accuracy': 0.24547715965626413,\n", 711 | " 'shots': 8844.0,\n", 712 | " 'deaths': 19.0}},\n", 713 | " 'iw8_pi_decho': {'properties': {'hits': 272.0,\n", 714 | " 'kills': 208.0,\n", 715 | " 'kdRatio': 0.9585253456221198,\n", 716 | " 'headshots': 31.0,\n", 717 | " 'accuracy': 0.25302325581395346,\n", 718 | " 'shots': 1075.0,\n", 719 | " 'deaths': 217.0}},\n", 720 | " 'iw8_pi_papa320': {'properties': {'hits': 520.0,\n", 721 | " 'kills': 168.0,\n", 722 | " 'kdRatio': 1.2537313432835822,\n", 723 | " 'headshots': 24.0,\n", 724 | " 'accuracy': 0.22540095361941917,\n", 725 | " 'shots': 2307.0,\n", 726 | " 'deaths': 134.0}}},\n", 727 | " 'weapon_other': {'iw8_me_riotshield': {'properties': {'hits': 0.0,\n", 728 | " 'kills': 25.0,\n", 729 | " 'kdRatio': 0.44642857142857145,\n", 730 | " 'headshots': 0.0,\n", 731 | " 'accuracy': 0.0,\n", 732 | " 'shots': 0.0,\n", 733 | " 'deaths': 56.0}}},\n", 734 | " 'weapon_smg': {'iw8_sm_mpapa7': {'properties': {'hits': 3666.0,\n", 735 | " 'kills': 657.0,\n", 736 | " 'kdRatio': 1.1465968586387434,\n", 737 | " 'headshots': 178.0,\n", 738 | " 'accuracy': 0.20971340312339112,\n", 739 | " 'shots': 17481.0,\n", 740 | " 'deaths': 573.0}},\n", 741 | " 'iw8_sm_augolf': {'properties': {'hits': 998.0,\n", 742 | " 'kills': 447.0,\n", 743 | " 'kdRatio': 1.2246575342465753,\n", 744 | " 'headshots': 92.0,\n", 745 | " 'accuracy': 0.1618028534370947,\n", 746 | " 'shots': 6168.0,\n", 747 | " 'deaths': 365.0}},\n", 748 | " 'iw8_sm_papa90': {'properties': {'hits': 1762.0,\n", 749 | " 'kills': 423.0,\n", 750 | " 'kdRatio': 0.990632318501171,\n", 751 | " 'headshots': 94.0,\n", 752 | " 'accuracy': 0.19369022754754314,\n", 753 | " 'shots': 9097.0,\n", 754 | " 'deaths': 427.0}},\n", 755 | " 'iw8_sm_charlie9': {'properties': {'hits': 13.0,\n", 756 | " 'kills': 2.0,\n", 757 | " 'kdRatio': 0.4,\n", 758 | " 'headshots': 0.0,\n", 759 | " 'accuracy': 0.23214285714285715,\n", 760 | " 'shots': 56.0,\n", 761 | " 'deaths': 5.0}},\n", 762 | " 'iw8_sm_mpapa5': {'properties': {'hits': 2525.0,\n", 763 | " 'kills': 450.0,\n", 764 | " 'kdRatio': 1.079136690647482,\n", 765 | " 'headshots': 85.0,\n", 766 | " 'accuracy': 0.2214523767760042,\n", 767 | " 'shots': 11402.0,\n", 768 | " 'deaths': 417.0}},\n", 769 | " 'iw8_sm_smgolf45': {'properties': {'hits': 170.0,\n", 770 | " 'kills': 35.0,\n", 771 | " 'kdRatio': 35.0,\n", 772 | " 'headshots': 5.0,\n", 773 | " 'accuracy': 0.26604068857589985,\n", 774 | " 'shots': 639.0,\n", 775 | " 'deaths': 1.0}},\n", 776 | " 'iw8_sm_beta': {'properties': {'hits': 1615.0,\n", 777 | " 'kills': 391.0,\n", 778 | " 'kdRatio': 1.0155844155844156,\n", 779 | " 'headshots': 88.0,\n", 780 | " 'accuracy': 0.21619812583668005,\n", 781 | " 'shots': 7470.0,\n", 782 | " 'deaths': 385.0}},\n", 783 | " 'iw8_sm_victor': {'properties': {'hits': 169.0,\n", 784 | " 'kills': 28.0,\n", 785 | " 'kdRatio': 2.8,\n", 786 | " 'headshots': 8.0,\n", 787 | " 'accuracy': 0.24780058651026393,\n", 788 | " 'shots': 682.0,\n", 789 | " 'deaths': 10.0}},\n", 790 | " 'iw8_sm_uzulu': {'properties': {'hits': 807.0,\n", 791 | " 'kills': 464.0,\n", 792 | " 'kdRatio': 0.8241563055062167,\n", 793 | " 'headshots': 91.0,\n", 794 | " 'accuracy': 0.15391951172992563,\n", 795 | " 'shots': 5243.0,\n", 796 | " 'deaths': 563.0}}},\n", 797 | " 'weapon_melee': {'iw8_me_akimboblunt': {'properties': {'hits': 0.0,\n", 798 | " 'kills': 0.0,\n", 799 | " 'kdRatio': 0.0,\n", 800 | " 'headshots': 0.0,\n", 801 | " 'accuracy': 0.0,\n", 802 | " 'shots': 0.0,\n", 803 | " 'deaths': 0.0}},\n", 804 | " 'iw8_me_akimboblades': {'properties': {'hits': 0.0,\n", 805 | " 'kills': 0.0,\n", 806 | " 'kdRatio': 0.0,\n", 807 | " 'headshots': 0.0,\n", 808 | " 'accuracy': 0.0,\n", 809 | " 'shots': 0.0,\n", 810 | " 'deaths': 0.0}},\n", 811 | " 'iw8_knife': {'properties': {'hits': 0.0,\n", 812 | " 'kills': 5.0,\n", 813 | " 'kdRatio': 0.2777777777777778,\n", 814 | " 'headshots': 0.0,\n", 815 | " 'accuracy': 0.0,\n", 816 | " 'shots': 0.0,\n", 817 | " 'deaths': 18.0}}}},\n", 818 | " 'scorestreakData': {'lethalScorestreakData': {'precision_airstrike': {'properties': {'extraStat1': 445.0,\n", 819 | " 'uses': 631.0,\n", 820 | " 'awardedCount': 305.0}},\n", 821 | " 'cruise_predator': {'properties': {'extraStat1': 67.0,\n", 822 | " 'uses': 52.0,\n", 823 | " 'awardedCount': 7.0}},\n", 824 | " 'manual_turret': {'properties': {'extraStat1': 0.0,\n", 825 | " 'uses': 48.0,\n", 826 | " 'awardedCount': 31.0}},\n", 827 | " 'white_phosphorus': {'properties': {'extraStat1': 15.0,\n", 828 | " 'uses': 2.0,\n", 829 | " 'awardedCount': 0.0}},\n", 830 | " 'hover_jet': {'properties': {'extraStat1': 108.0,\n", 831 | " 'uses': 29.0,\n", 832 | " 'awardedCount': 31.0}},\n", 833 | " 'chopper_gunner': {'properties': {'extraStat1': 45.0,\n", 834 | " 'uses': 7.0,\n", 835 | " 'awardedCount': 3.0}},\n", 836 | " 'gunship': {'properties': {'extraStat1': 15.0,\n", 837 | " 'uses': 2.0,\n", 838 | " 'awardedCount': 0.0}},\n", 839 | " 'sentry_gun': {'properties': {'extraStat1': 30.0,\n", 840 | " 'uses': 10.0,\n", 841 | " 'awardedCount': 0.0}},\n", 842 | " 'toma_strike': {'properties': {'extraStat1': 263.0,\n", 843 | " 'uses': 510.0,\n", 844 | " 'awardedCount': 158.0}},\n", 845 | " 'nuke': {'properties': {'extraStat1': 0.0,\n", 846 | " 'uses': 0.0,\n", 847 | " 'awardedCount': 0.0}},\n", 848 | " 'juggernaut': {'properties': {'extraStat1': 24.0,\n", 849 | " 'uses': 1.0,\n", 850 | " 'awardedCount': 0.0}},\n", 851 | " 'pac_sentry': {'properties': {'extraStat1': 200.0,\n", 852 | " 'uses': 51.0,\n", 853 | " 'awardedCount': 37.0}},\n", 854 | " 'chopper_support': {'properties': {'extraStat1': 13.0,\n", 855 | " 'uses': 2.0,\n", 856 | " 'awardedCount': 0.0}},\n", 857 | " 'bradley': {'properties': {'extraStat1': 0.0,\n", 858 | " 'uses': 0.0,\n", 859 | " 'awardedCount': 0.0}}},\n", 860 | " 'supportScorestreakData': {'airdrop': {'properties': {'extraStat1': 0.0,\n", 861 | " 'uses': 444.0,\n", 862 | " 'awardedCount': 937.0}},\n", 863 | " 'radar_drone_overwatch': {'properties': {'extraStat1': 0.0,\n", 864 | " 'uses': 53.0,\n", 865 | " 'awardedCount': 0.0}},\n", 866 | " 'scrambler_drone_guard': {'properties': {'extraStat1': 0.0,\n", 867 | " 'uses': 39.0,\n", 868 | " 'awardedCount': 0.0}},\n", 869 | " 'uav': {'properties': {'extraStat1': 352.0,\n", 870 | " 'uses': 1870.0,\n", 871 | " 'awardedCount': 19.0}},\n", 872 | " 'airdrop_multiple': {'properties': {'extraStat1': 0.0,\n", 873 | " 'uses': 0.0,\n", 874 | " 'awardedCount': 0.0}},\n", 875 | " 'directional_uav': {'properties': {'extraStat1': 27.0,\n", 876 | " 'uses': 71.0,\n", 877 | " 'awardedCount': 0.0}}}},\n", 878 | " 'accoladeData': {'properties': {'classChanges': 63.0,\n", 879 | " 'highestAvgAltitude': 46.0,\n", 880 | " 'killsFromBehind': 99.0,\n", 881 | " 'lmgDeaths': 76.0,\n", 882 | " 'riotShieldDamageAbsorbed': 35.0,\n", 883 | " 'flashbangHits': 50.0,\n", 884 | " 'meleeKills': 46.0,\n", 885 | " 'tagsLargestBank': 0.0,\n", 886 | " 'shotgunKills': 49.0,\n", 887 | " 'sniperDeaths': 102.0,\n", 888 | " 'timeProne': 37.0,\n", 889 | " 'killstreakWhitePhosphorousKillsAssists': 2.0,\n", 890 | " 'shortestLife': 116.0,\n", 891 | " 'deathsFromBehind': 116.0,\n", 892 | " 'higherRankedKills': 122.0,\n", 893 | " 'mostAssists': 62.0,\n", 894 | " 'leastKills': 108.0,\n", 895 | " 'tagsDenied': 11.0,\n", 896 | " 'killstreakWheelsonKills': 31.0,\n", 897 | " 'sniperHeadshots': 143.0,\n", 898 | " 'killstreakJuggernautKills': 1.0,\n", 899 | " 'smokesUsed': 13.0,\n", 900 | " 'avengerKills': 87.0,\n", 901 | " 'decoyHits': 2.0,\n", 902 | " 'killstreakCarePackageUsed': 0.0,\n", 903 | " 'molotovKills': 5.0,\n", 904 | " 'gasHits': 27.0,\n", 905 | " 'comebackKills': 123.0,\n", 906 | " 'lmgHeadshots': 16.0,\n", 907 | " 'smgDeaths': 105.0,\n", 908 | " 'carrierKills': 3.0,\n", 909 | " 'deployableCoverUsed': 45.0,\n", 910 | " 'thermiteKills': 102.0,\n", 911 | " 'arKills': 90.0,\n", 912 | " 'c4Kills': 0.0,\n", 913 | " 'suicides': 107.0,\n", 914 | " 'clutch': 0.0,\n", 915 | " 'survivorKills': 0.0,\n", 916 | " 'killstreakGunshipKills': 2.0,\n", 917 | " 'timeSpentAsPassenger': 4.0,\n", 918 | " 'returns': 0.0,\n", 919 | " 'smgHeadshots': 76.0,\n", 920 | " 'launcherDeaths': 63.0,\n", 921 | " 'oneShotOneKills': 166.0,\n", 922 | " 'ammoBoxUsed': 0.0,\n", 923 | " 'spawnSelectSquad': 1.0,\n", 924 | " 'weaponPickups': 122.0,\n", 925 | " 'pointBlankKills': 123.0,\n", 926 | " 'tagsCaptured': 3.0,\n", 927 | " 'killstreakGroundKills': 37.0,\n", 928 | " 'distanceTraveledInVehicle': 5.0,\n", 929 | " 'longestLife': 59.0,\n", 930 | " 'stunHits': 83.0,\n", 931 | " 'spawnSelectFlag': 1.0,\n", 932 | " 'shotgunHeadshots': 46.0,\n", 933 | " 'bombDefused': 0.0,\n", 934 | " 'snapshotHits': 3.0,\n", 935 | " 'noKillsWithDeath': 28.0,\n", 936 | " 'killstreakAUAVAssists': 3.0,\n", 937 | " 'killstreakPersonalUAVKills': 17.0,\n", 938 | " 'tacticalInsertionSpawns': 125.0,\n", 939 | " 'launcherKills': 20.0,\n", 940 | " 'spawnSelectVehicle': 0.0,\n", 941 | " 'mostKillsLeastDeaths': 21.0,\n", 942 | " 'mostKills': 101.0,\n", 943 | " 'defends': 24.0,\n", 944 | " 'timeSpentAsDriver': 6.0,\n", 945 | " 'bombDetonated': 0.0,\n", 946 | " 'arHeadshots': 102.0,\n", 947 | " 'timeOnPoint': 7.0,\n", 948 | " 'lmgKills': 28.0,\n", 949 | " 'killstreakUAVAssists': 5.0,\n", 950 | " 'carepackagesCaptured': 213.0,\n", 951 | " 'mostKillsLongestStreak': 53.0,\n", 952 | " 'killstreakCruiseMissileKills': 32.0,\n", 953 | " 'longestStreak': 109.0,\n", 954 | " 'destroyedKillstreaks': 59.0,\n", 955 | " 'hipfireKills': 99.0,\n", 956 | " 'stimDamageHealed': 0.0,\n", 957 | " 'skippedKillcams': 69.0,\n", 958 | " 'leastAssists': 433.0,\n", 959 | " 'mostMultikills': 100.0,\n", 960 | " 'highestRankedKills': 77.0,\n", 961 | " 'killstreakAirstrikeKills': 126.0,\n", 962 | " 'distanceTravelled': 55.0,\n", 963 | " 'killstreakKills': 122.0,\n", 964 | " 'semtexKills': 7.0,\n", 965 | " 'penetrationKills': 105.0,\n", 966 | " 'explosionsSurvived': 76.0,\n", 967 | " 'highestMultikill': 180.0,\n", 968 | " 'arDeaths': 103.0,\n", 969 | " 'longshotKills': 139.0,\n", 970 | " 'proximityMineKills': 1.0,\n", 971 | " 'tagsMegaBanked': 1.0,\n", 972 | " 'mostKillsMostHeadshots': 44.0,\n", 973 | " 'firstInfected': 0.0,\n", 974 | " 'killstreakCUAVAssists': 34.0,\n", 975 | " 'throwingKnifeKills': 0.0,\n", 976 | " 'executionKills': 4.0,\n", 977 | " 'lastSurvivor': 0.0,\n", 978 | " 'reconDroneMarks': 0.0,\n", 979 | " 'deadSilenceKills': 0.0,\n", 980 | " 'revengeKills': 102.0,\n", 981 | " 'infectedKills': 0.0,\n", 982 | " 'killEnemyTeam': 89.0,\n", 983 | " 'sniperKills': 156.0,\n", 984 | " 'killstreakCluserStrikeKills': 78.0,\n", 985 | " 'meleeDeaths': 72.0,\n", 986 | " 'timeWatchingKillcams': 39.0,\n", 987 | " 'killstreakTankKills': 0.0,\n", 988 | " 'noKillNoDeath': 23.0,\n", 989 | " 'shotgunDeaths': 62.0,\n", 990 | " 'killstreakChopperGunnerKills': 5.0,\n", 991 | " 'shotsFired': 14.0,\n", 992 | " 'stoppingPowerKills': 2.0,\n", 993 | " 'pistolPeaths': 116.0,\n", 994 | " 'killstreakShieldTurretKills': 0.0,\n", 995 | " 'timeCrouched': 64.0,\n", 996 | " 'noDeathsFromBehind': 906.0,\n", 997 | " 'bombPlanted': 0.0,\n", 998 | " 'setbacks': 0.0,\n", 999 | " 'smgKills': 71.0,\n", 1000 | " 'claymoreKills': 2.0,\n", 1001 | " 'kills10NoDeaths': 2.0,\n", 1002 | " 'pistolHeadshots': 15.0,\n", 1003 | " 'killstreakVTOLJetKills': 19.0,\n", 1004 | " 'headshots': 149.0,\n", 1005 | " 'mostDeaths': 119.0,\n", 1006 | " 'adsKills': 90.0,\n", 1007 | " 'empDroneHits': 0.0,\n", 1008 | " 'defenderKills': 126.0,\n", 1009 | " 'launcherHeadshots': 3.0,\n", 1010 | " 'timesSelectedAsSquadLeader': 0.0,\n", 1011 | " 'killstreakAirKills': 126.0,\n", 1012 | " 'assaults': 3.0,\n", 1013 | " 'fragKills': 4.0,\n", 1014 | " 'killstreakEmergencyAirdropUsed': 0.0,\n", 1015 | " 'captures': 30.0,\n", 1016 | " 'killstreakChopperSupportKills': 1.0,\n", 1017 | " 'spawnSelectBase': 5.0,\n", 1018 | " 'noKill10Deaths': 0.0,\n", 1019 | " 'leastDeaths': 122.0,\n", 1020 | " 'killstreakSentryGunKills': 7.0,\n", 1021 | " 'longestTimeSpentOnWeapon': 0.0,\n", 1022 | " 'lowerRankedKills': 88.0,\n", 1023 | " 'trophySystemHits': 28.0,\n", 1024 | " 'clutchRevives': 0.0,\n", 1025 | " 'lowestAvgAltitude': 68.0,\n", 1026 | " 'pickups': 3.0,\n", 1027 | " 'pistolKills': 23.0,\n", 1028 | " 'reloads': 75.0}}},\n", 1029 | " 'weekly': {'all': {'properties': {'kills': 174.0,\n", 1030 | " 'objectiveTeamWiped': 39.0,\n", 1031 | " 'objectiveLastStandKill': 123.0,\n", 1032 | " 'objectiveTagDenied': 6.0,\n", 1033 | " 'wallBangs': 0.0,\n", 1034 | " 'avgLifeTime': 536.1370558375635,\n", 1035 | " 'score': 151760.0,\n", 1036 | " 'headshots': 47.0,\n", 1037 | " 'assists': 37.0,\n", 1038 | " 'killsPerGame': 2.761904761904762,\n", 1039 | " 'scorePerMinute': 86.2117611414613,\n", 1040 | " 'distanceTraveled': 14264218.282999998,\n", 1041 | " 'deaths': 134.0,\n", 1042 | " 'objectiveManualFlareMissileRedirect': 1.0,\n", 1043 | " 'objectiveDestroyedEquipment': 3.0,\n", 1044 | " 'objectiveMunitionsBoxTeammateUsed': 13.0,\n", 1045 | " 'objectiveBrDownEnemyCircle4': 17.0,\n", 1046 | " 'objectiveBrDownEnemyCircle3': 19.0,\n", 1047 | " 'objectiveBrDownEnemyCircle2': 46.0,\n", 1048 | " 'objectiveTagCollected': 103.0,\n", 1049 | " 'kdRatio': 1.2985074626865671,\n", 1050 | " 'objectiveBrDownEnemyCircle1': 79.0,\n", 1051 | " 'objectiveBrMissionPickupTablet': 88.0,\n", 1052 | " 'objectiveReviver': 22.0,\n", 1053 | " 'objectiveBrKioskBuy': 42.0,\n", 1054 | " 'objectiveBrGametypeBodycountFinalKill': 35.0,\n", 1055 | " 'objectiveMedalScoreKillSsRadarDrone': 1.0,\n", 1056 | " 'gulagDeaths': 36.0,\n", 1057 | " 'objectiveBrDownEnemyCircle6': 6.0,\n", 1058 | " 'objectiveBrDownEnemyCircle5': 14.0,\n", 1059 | " 'timePlayed': 105619.0,\n", 1060 | " 'headshotPercentage': 0.27011494252873564,\n", 1061 | " 'executions': 0.0,\n", 1062 | " 'matchesPlayed': 63.0,\n", 1063 | " 'gulagKills': 12.0,\n", 1064 | " 'nearmisses': 0.0,\n", 1065 | " 'objectiveBrCacheOpen': 205.0,\n", 1066 | " 'objectivePerkMarkedTarget': 1.0,\n", 1067 | " 'objectiveTrophyDefense': 1.0,\n", 1068 | " 'damageDone': 76408.0,\n", 1069 | " 'damageTaken': 33597.0}},\n", 1070 | " 'mode': {'br_dmz_plndtrios': {'properties': {'kills': 8.0,\n", 1071 | " 'objectiveTeamWiped': 7.0,\n", 1072 | " 'objectiveLastStandKill': 1.0,\n", 1073 | " 'kdRatio': 1.1428571428571428,\n", 1074 | " 'scorePerGame': 3550.0,\n", 1075 | " 'wallBangs': 0.0,\n", 1076 | " 'avgLifeTime': 165.125,\n", 1077 | " 'score': 3550.0,\n", 1078 | " 'timePlayed': 1321.0,\n", 1079 | " 'headshotPercentage': 0.375,\n", 1080 | " 'headshots': 3.0,\n", 1081 | " 'executions': 0.0,\n", 1082 | " 'matchesPlayed': 1.0,\n", 1083 | " 'assists': 1.0,\n", 1084 | " 'nearmisses': 0.0,\n", 1085 | " 'objectiveBrCacheOpen': 1.0,\n", 1086 | " 'killsPerGame': 8.0,\n", 1087 | " 'scorePerMinute': 161.24148372445117,\n", 1088 | " 'distanceTraveled': 322984.0,\n", 1089 | " 'damageDone': 1754.0,\n", 1090 | " 'deaths': 7.0,\n", 1091 | " 'damageTaken': 914.0}},\n", 1092 | " 'br_rebirth_rbrthquad': {'properties': {'kills': 43.0,\n", 1093 | " 'objectiveTeamWiped': 5.0,\n", 1094 | " 'objectiveLastStandKill': 37.0,\n", 1095 | " 'wallBangs': 0.0,\n", 1096 | " 'avgLifeTime': 429.46774193548384,\n", 1097 | " 'score': 37775.0,\n", 1098 | " 'headshots': 8.0,\n", 1099 | " 'assists': 14.0,\n", 1100 | " 'killsPerGame': 2.0476190476190474,\n", 1101 | " 'scorePerMinute': 85.12036654523604,\n", 1102 | " 'distanceTraveled': 2024114.722,\n", 1103 | " 'deaths': 41.0,\n", 1104 | " 'objectiveDestroyedEquipment': 3.0,\n", 1105 | " 'objectiveMunitionsBoxTeammateUsed': 5.0,\n", 1106 | " 'objectiveBrDownEnemyCircle4': 2.0,\n", 1107 | " 'objectiveBrDownEnemyCircle3': 10.0,\n", 1108 | " 'objectiveBrDownEnemyCircle2': 10.0,\n", 1109 | " 'kdRatio': 1.048780487804878,\n", 1110 | " 'objectiveBrDownEnemyCircle1': 33.0,\n", 1111 | " 'objectiveBrMissionPickupTablet': 34.0,\n", 1112 | " 'objectiveReviver': 4.0,\n", 1113 | " 'scorePerGame': 1798.8095238095239,\n", 1114 | " 'objectiveBrKioskBuy': 14.0,\n", 1115 | " 'gulagDeaths': 0.0,\n", 1116 | " 'objectiveBrDownEnemyCircle6': 1.0,\n", 1117 | " 'objectiveBrDownEnemyCircle5': 1.0,\n", 1118 | " 'timePlayed': 26627.0,\n", 1119 | " 'headshotPercentage': 0.18604651162790697,\n", 1120 | " 'executions': 0.0,\n", 1121 | " 'matchesPlayed': 21.0,\n", 1122 | " 'gulagKills': 0.0,\n", 1123 | " 'nearmisses': 0.0,\n", 1124 | " 'objectiveBrCacheOpen': 50.0,\n", 1125 | " 'objectiveTrophyDefense': 1.0,\n", 1126 | " 'damageDone': 22332.0,\n", 1127 | " 'damageTaken': 11910.0}},\n", 1128 | " 'br_brtrios': {'properties': {'kills': 19.0,\n", 1129 | " 'objectiveTeamWiped': 1.0,\n", 1130 | " 'objectiveLastStandKill': 13.0,\n", 1131 | " 'wallBangs': 0.0,\n", 1132 | " 'avgLifeTime': 912.8928571428571,\n", 1133 | " 'score': 23275.0,\n", 1134 | " 'headshots': 7.0,\n", 1135 | " 'assists': 3.0,\n", 1136 | " 'killsPerGame': 1.9,\n", 1137 | " 'scorePerMinute': 54.634012753804626,\n", 1138 | " 'distanceTraveled': 4737181.19,\n", 1139 | " 'deaths': 18.0,\n", 1140 | " 'objectiveMunitionsBoxTeammateUsed': 2.0,\n", 1141 | " 'objectiveBrDownEnemyCircle4': 1.0,\n", 1142 | " 'objectiveBrDownEnemyCircle3': 3.0,\n", 1143 | " 'objectiveBrDownEnemyCircle2': 3.0,\n", 1144 | " 'kdRatio': 1.0555555555555556,\n", 1145 | " 'objectiveBrDownEnemyCircle1': 10.0,\n", 1146 | " 'objectiveBrMissionPickupTablet': 15.0,\n", 1147 | " 'objectiveReviver': 4.0,\n", 1148 | " 'scorePerGame': 2327.5,\n", 1149 | " 'objectiveBrKioskBuy': 8.0,\n", 1150 | " 'gulagDeaths': 3.0,\n", 1151 | " 'timePlayed': 25561.0,\n", 1152 | " 'headshotPercentage': 0.3684210526315789,\n", 1153 | " 'executions': 0.0,\n", 1154 | " 'matchesPlayed': 10.0,\n", 1155 | " 'gulagKills': 5.0,\n", 1156 | " 'nearmisses': 0.0,\n", 1157 | " 'objectiveBrCacheOpen': 49.0,\n", 1158 | " 'damageDone': 9028.0,\n", 1159 | " 'damageTaken': 4295.0}},\n", 1160 | " 'br_mini_rebirth_mini_royale_trios': {'properties': {'kills': 24.0,\n", 1161 | " 'objectiveTeamWiped': 5.0,\n", 1162 | " 'objectiveLastStandKill': 13.0,\n", 1163 | " 'wallBangs': 0.0,\n", 1164 | " 'avgLifeTime': 373.05263157894734,\n", 1165 | " 'score': 11225.0,\n", 1166 | " 'headshots': 4.0,\n", 1167 | " 'assists': 3.0,\n", 1168 | " 'killsPerGame': 1.7142857142857142,\n", 1169 | " 'scorePerMinute': 47.50987584650113,\n", 1170 | " 'distanceTraveled': 1120762.671,\n", 1171 | " 'deaths': 24.0,\n", 1172 | " 'objectiveBrDownEnemyCircle3': 1.0,\n", 1173 | " 'objectiveBrDownEnemyCircle2': 6.0,\n", 1174 | " 'kdRatio': 1.0,\n", 1175 | " 'objectiveBrDownEnemyCircle1': 15.0,\n", 1176 | " 'objectiveBrMissionPickupTablet': 5.0,\n", 1177 | " 'objectiveReviver': 4.0,\n", 1178 | " 'scorePerGame': 801.7857142857143,\n", 1179 | " 'gulagDeaths': 7.0,\n", 1180 | " 'timePlayed': 14176.0,\n", 1181 | " 'headshotPercentage': 0.16666666666666666,\n", 1182 | " 'executions': 0.0,\n", 1183 | " 'matchesPlayed': 14.0,\n", 1184 | " 'gulagKills': 5.0,\n", 1185 | " 'nearmisses': 0.0,\n", 1186 | " 'objectiveBrCacheOpen': 19.0,\n", 1187 | " 'damageDone': 8259.0,\n", 1188 | " 'damageTaken': 5497.0}},\n", 1189 | " 'br_bodycount_pwergrb': {'properties': {'kills': 75.0,\n", 1190 | " 'objectiveTeamWiped': 20.0,\n", 1191 | " 'objectiveLastStandKill': 57.0,\n", 1192 | " 'objectiveTagDenied': 6.0,\n", 1193 | " 'wallBangs': 0.0,\n", 1194 | " 'avgLifeTime': 591.4230769230769,\n", 1195 | " 'score': 67035.0,\n", 1196 | " 'headshots': 23.0,\n", 1197 | " 'assists': 16.0,\n", 1198 | " 'killsPerGame': 5.357142857142857,\n", 1199 | " 'scorePerMinute': 130.78298757885153,\n", 1200 | " 'distanceTraveled': 4523054.120000001,\n", 1201 | " 'deaths': 38.0,\n", 1202 | " 'objectiveManualFlareMissileRedirect': 1.0,\n", 1203 | " 'objectiveMunitionsBoxTeammateUsed': 4.0,\n", 1204 | " 'objectiveBrDownEnemyCircle4': 14.0,\n", 1205 | " 'objectiveBrDownEnemyCircle3': 5.0,\n", 1206 | " 'objectiveBrDownEnemyCircle2': 27.0,\n", 1207 | " 'objectiveTagCollected': 103.0,\n", 1208 | " 'kdRatio': 1.9736842105263157,\n", 1209 | " 'objectiveBrDownEnemyCircle1': 16.0,\n", 1210 | " 'objectiveBrMissionPickupTablet': 27.0,\n", 1211 | " 'objectiveReviver': 10.0,\n", 1212 | " 'scorePerGame': 4788.214285714285,\n", 1213 | " 'objectiveBrKioskBuy': 15.0,\n", 1214 | " 'objectiveBrGametypeBodycountFinalKill': 35.0,\n", 1215 | " 'objectiveMedalScoreKillSsRadarDrone': 1.0,\n", 1216 | " 'objectiveBrDownEnemyCircle6': 5.0,\n", 1217 | " 'gulagDeaths': 25.0,\n", 1218 | " 'objectiveBrDownEnemyCircle5': 13.0,\n", 1219 | " 'timePlayed': 30754.0,\n", 1220 | " 'headshotPercentage': 0.30666666666666664,\n", 1221 | " 'executions': 0.0,\n", 1222 | " 'matchesPlayed': 14.0,\n", 1223 | " 'gulagKills': 0.0,\n", 1224 | " 'nearmisses': 0.0,\n", 1225 | " 'objectiveBrCacheOpen': 67.0,\n", 1226 | " 'objectivePerkMarkedTarget': 1.0,\n", 1227 | " 'damageDone': 32488.0,\n", 1228 | " 'damageTaken': 10038.0}},\n", 1229 | " 'br_all': {'properties': {'kills': 174.0,\n", 1230 | " 'objectiveTeamWiped': 39.0,\n", 1231 | " 'objectiveLastStandKill': 123.0,\n", 1232 | " 'objectiveTagDenied': 6.0,\n", 1233 | " 'wallBangs': 0.0,\n", 1234 | " 'avgLifeTime': 536.1370558375635,\n", 1235 | " 'score': 151760.0,\n", 1236 | " 'headshots': 47.0,\n", 1237 | " 'assists': 37.0,\n", 1238 | " 'killsPerGame': 2.761904761904762,\n", 1239 | " 'scorePerMinute': 86.2117611414613,\n", 1240 | " 'distanceTraveled': 14264218.282999998,\n", 1241 | " 'deaths': 134.0,\n", 1242 | " 'objectiveManualFlareMissileRedirect': 1.0,\n", 1243 | " 'objectiveDestroyedEquipment': 3.0,\n", 1244 | " 'objectiveMunitionsBoxTeammateUsed': 13.0,\n", 1245 | " 'objectiveBrDownEnemyCircle4': 17.0,\n", 1246 | " 'objectiveBrDownEnemyCircle3': 19.0,\n", 1247 | " 'objectiveBrDownEnemyCircle2': 46.0,\n", 1248 | " 'objectiveTagCollected': 103.0,\n", 1249 | " 'kdRatio': 1.2985074626865671,\n", 1250 | " 'objectiveBrDownEnemyCircle1': 79.0,\n", 1251 | " 'objectiveBrMissionPickupTablet': 88.0,\n", 1252 | " 'objectiveReviver': 22.0,\n", 1253 | " 'objectiveBrKioskBuy': 42.0,\n", 1254 | " 'objectiveBrGametypeBodycountFinalKill': 35.0,\n", 1255 | " 'objectiveMedalScoreKillSsRadarDrone': 1.0,\n", 1256 | " 'gulagDeaths': 36.0,\n", 1257 | " 'objectiveBrDownEnemyCircle6': 6.0,\n", 1258 | " 'objectiveBrDownEnemyCircle5': 14.0,\n", 1259 | " 'timePlayed': 105619.0,\n", 1260 | " 'headshotPercentage': 0.27011494252873564,\n", 1261 | " 'executions': 0.0,\n", 1262 | " 'matchesPlayed': 63.0,\n", 1263 | " 'gulagKills': 12.0,\n", 1264 | " 'nearmisses': 0.0,\n", 1265 | " 'objectiveBrCacheOpen': 205.0,\n", 1266 | " 'objectivePerkMarkedTarget': 1.0,\n", 1267 | " 'objectiveTrophyDefense': 1.0,\n", 1268 | " 'damageDone': 76408.0,\n", 1269 | " 'damageTaken': 33597.0}},\n", 1270 | " 'br_brduos': {'properties': {'kills': 4.0,\n", 1271 | " 'objectiveTeamWiped': 1.0,\n", 1272 | " 'objectiveLastStandKill': 2.0,\n", 1273 | " 'wallBangs': 0.0,\n", 1274 | " 'avgLifeTime': 810.0,\n", 1275 | " 'score': 6850.0,\n", 1276 | " 'headshots': 2.0,\n", 1277 | " 'assists': 0.0,\n", 1278 | " 'killsPerGame': 2.0,\n", 1279 | " 'scorePerMinute': 84.5679012345679,\n", 1280 | " 'distanceTraveled': 1014448.2,\n", 1281 | " 'deaths': 4.0,\n", 1282 | " 'kdRatio': 1.0,\n", 1283 | " 'objectiveBrDownEnemyCircle1': 4.0,\n", 1284 | " 'objectiveBrMissionPickupTablet': 4.0,\n", 1285 | " 'scorePerGame': 3425.0,\n", 1286 | " 'objectiveBrKioskBuy': 4.0,\n", 1287 | " 'gulagDeaths': 1.0,\n", 1288 | " 'timePlayed': 4860.0,\n", 1289 | " 'headshotPercentage': 0.5,\n", 1290 | " 'executions': 0.0,\n", 1291 | " 'matchesPlayed': 2.0,\n", 1292 | " 'gulagKills': 1.0,\n", 1293 | " 'nearmisses': 0.0,\n", 1294 | " 'objectiveBrCacheOpen': 14.0,\n", 1295 | " 'damageDone': 1429.0,\n", 1296 | " 'damageTaken': 603.0}},\n", 1297 | " 'br_brquads': {'properties': {'kills': 1.0,\n", 1298 | " 'wallBangs': 0.0,\n", 1299 | " 'avgLifeTime': 773.3333333333334,\n", 1300 | " 'score': 2050.0,\n", 1301 | " 'headshots': 0.0,\n", 1302 | " 'assists': 0.0,\n", 1303 | " 'killsPerGame': 1.0,\n", 1304 | " 'scorePerMinute': 53.01724137931034,\n", 1305 | " 'distanceTraveled': 521673.38,\n", 1306 | " 'deaths': 2.0,\n", 1307 | " 'objectiveMunitionsBoxTeammateUsed': 2.0,\n", 1308 | " 'kdRatio': 0.5,\n", 1309 | " 'objectiveBrDownEnemyCircle1': 1.0,\n", 1310 | " 'objectiveBrMissionPickupTablet': 3.0,\n", 1311 | " 'scorePerGame': 2050.0,\n", 1312 | " 'objectiveBrKioskBuy': 1.0,\n", 1313 | " 'gulagDeaths': 0.0,\n", 1314 | " 'timePlayed': 2320.0,\n", 1315 | " 'headshotPercentage': 0.0,\n", 1316 | " 'executions': 0.0,\n", 1317 | " 'matchesPlayed': 1.0,\n", 1318 | " 'gulagKills': 1.0,\n", 1319 | " 'nearmisses': 0.0,\n", 1320 | " 'objectiveBrCacheOpen': 5.0,\n", 1321 | " 'damageDone': 1118.0,\n", 1322 | " 'damageTaken': 340.0}}},\n", 1323 | " 'map': {}},\n", 1324 | " 'engagement': None}}" 1325 | ] 1326 | }, 1327 | "execution_count": 11, 1328 | "metadata": {}, 1329 | "output_type": "execute_result" 1330 | } 1331 | ], 1332 | "source": [ 1333 | "wz_profile = s.get('https://my.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/psn/gamer/Hormigator1/profile/type/wz')\n", 1334 | "wz_profile.json()" 1335 | ] 1336 | }, 1337 | { 1338 | "cell_type": "code", 1339 | "execution_count": 6, 1340 | "id": "qualified-chancellor", 1341 | "metadata": {}, 1342 | "outputs": [], 1343 | "source": [ 1344 | "resp = s.post('https://my.callofduty.com/api/papi-client/codfriends/v1/invite/psn/gamer/Hormigator1')" 1345 | ] 1346 | }, 1347 | { 1348 | "cell_type": "code", 1349 | "execution_count": 7, 1350 | "id": "fourth-affairs", 1351 | "metadata": {}, 1352 | "outputs": [ 1353 | { 1354 | "data": { 1355 | "text/plain": [ 1356 | "" 1357 | ] 1358 | }, 1359 | "execution_count": 7, 1360 | "metadata": {}, 1361 | "output_type": "execute_result" 1362 | } 1363 | ], 1364 | "source": [ 1365 | "resp" 1366 | ] 1367 | }, 1368 | { 1369 | "cell_type": "code", 1370 | "execution_count": 8, 1371 | "id": "spiritual-boxing", 1372 | "metadata": {}, 1373 | "outputs": [ 1374 | { 1375 | "data": { 1376 | "text/plain": [ 1377 | "{'status': 'error',\n", 1378 | " 'data': {'type': 'com.activision.mt.common.stdtools.exceptions.NoStackTraceException',\n", 1379 | " 'message': 'Not permitted: not authenticated'}}" 1380 | ] 1381 | }, 1382 | "execution_count": 8, 1383 | "metadata": {}, 1384 | "output_type": "execute_result" 1385 | } 1386 | ], 1387 | "source": [ 1388 | "resp.json()" 1389 | ] 1390 | }, 1391 | { 1392 | "cell_type": "code", 1393 | "execution_count": null, 1394 | "id": "advisory-technique", 1395 | "metadata": {}, 1396 | "outputs": [], 1397 | "source": [] 1398 | } 1399 | ], 1400 | "metadata": { 1401 | "kernelspec": { 1402 | "display_name": "Python 3", 1403 | "language": "python", 1404 | "name": "python3" 1405 | }, 1406 | "language_info": { 1407 | "codemirror_mode": { 1408 | "name": "ipython", 1409 | "version": 3 1410 | }, 1411 | "file_extension": ".py", 1412 | "mimetype": "text/x-python", 1413 | "name": "python", 1414 | "nbconvert_exporter": "python", 1415 | "pygments_lexer": "ipython3", 1416 | "version": "3.8.2" 1417 | } 1418 | }, 1419 | "nbformat": 4, 1420 | "nbformat_minor": 5 1421 | } 1422 | -------------------------------------------------------------------------------- /lobby_kd.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Warzone Lobby Stats" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import requests\n", 17 | "import urllib.parse\n", 18 | "import random\n", 19 | "import os\n", 20 | "import pandas as pd\n", 21 | "import time\n", 22 | "import math\n", 23 | "import numpy as np\n", 24 | "import matplotlib.pyplot as plt\n", 25 | "%matplotlib inline" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | "Authentication: See the other two notebooks and videos on authentication." 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": null, 38 | "metadata": {}, 39 | "outputs": [], 40 | "source": [ 41 | "s = requests.Session()\n", 42 | "s.get('https://profile.callofduty.com/cod/login')\n", 43 | "data = {'username': os.environ.get('COD_EMAIL'), \n", 44 | " 'password': os.environ.get('COD_PW'), \n", 45 | " 'remember_me': 'true', \n", 46 | " '_csrf': s.cookies['XSRF-TOKEN']}\n", 47 | "s.post('https://profile.callofduty.com/do_login?new_SiteId=cod', params=data)" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": null, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "match_id = \"3726192899756849207\"\n", 64 | "team_mates = {\"Vio\": \"14688938695022220470\", \"Bublous\": \"1860799185863297602\"}\n", 65 | "#, \"Uncarriable\": '5291500827578550226'\n", 66 | "#team_mates = {\"Huskerrs\": \"11946786255256953231\", \"Symfuhny\": \"4864369508081987227\", \"ZLaner\": \"5499179043424889056\"}\n", 67 | "#team_mates = {\"BookaShade\": \"16503230311151154188\"}\n", 68 | "#team_mates = {\"Huskerrs\": \"11946786255256953231\", \"ZLaner\": \"5499179043424889056\", \"OakBoi\": \"1506652682349281517\", \"AydaN\": \"6466570850733519449\"}\n", 69 | "#team_mates = {\"ZLaner\": \"5499179043424889056\", \"Destroy\": \"13121215955392487462\", \"Trash_Fue\": \"9516497865377061135\", \"SuperEvan\": \"3099898901879856705\"}" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "In january after some outcry about sbmmwarzone.com Activision decided to put all COD Profiles privacy on private. What this means is that getting a users profile data using their \"uno\" is not possible anymore. This was an easy way to calculate the average lobby kd because in the match endpoint all the players uno's were returned. Now even after a user sets it's profile to public you won't be able to get info about this user, only when he/she is your friend it's still possible." 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "Get data from a match/lobby:" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": null, 89 | "metadata": {}, 90 | "outputs": [], 91 | "source": [ 92 | "lobby_data = s.get('https://my.callofduty.com/api/papi-client/crm/cod/v2/title/mw/platform/battle/fullMatch/wz/' + match_id + '/it')" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": null, 98 | "metadata": {}, 99 | "outputs": [], 100 | "source": [ 101 | "lobby_data.json()['data']" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": null, 107 | "metadata": {}, 108 | "outputs": [], 109 | "source": [ 110 | "lobby_data.json()['data']['allPlayers'][0]" 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": null, 116 | "metadata": {}, 117 | "outputs": [], 118 | "source": [ 119 | "#username = urllib.parse.quote(\"Weixo En Nike\")\n", 120 | "username = urllib.parse.quote(\"Viioozz\")\n", 121 | "username" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": null, 127 | "metadata": {}, 128 | "outputs": [], 129 | "source": [ 130 | "search_resp = s.get(f'https://my.callofduty.com/api/papi-client/crm/cod/v2/platform/uno/username/{ username }/search')\n", 131 | "search_resp.json()" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": null, 137 | "metadata": {}, 138 | "outputs": [], 139 | "source": [] 140 | }, 141 | { 142 | "cell_type": "code", 143 | "execution_count": null, 144 | "metadata": {}, 145 | "outputs": [], 146 | "source": [ 147 | "lobby_players = lobby_data.json()['data']['allPlayers']\n", 148 | "lobby_players_df = pd.DataFrame.from_records(lobby_players)\n", 149 | "lobby_players_df.info()" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": null, 155 | "metadata": {}, 156 | "outputs": [], 157 | "source": [ 158 | "lobby_players_df['playerStats']" 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "execution_count": null, 164 | "metadata": {}, 165 | "outputs": [], 166 | "source": [ 167 | "lobby_players_df = pd.DataFrame.from_records(lobby_players_df['playerStats'])\n", 168 | "lobby_players_df" 169 | ] 170 | }, 171 | { 172 | "cell_type": "code", 173 | "execution_count": null, 174 | "metadata": {}, 175 | "outputs": [], 176 | "source": [ 177 | "lobby_players_df.info()" 178 | ] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "execution_count": null, 183 | "metadata": {}, 184 | "outputs": [], 185 | "source": [ 186 | "lobby_players_df.describe()" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": null, 192 | "metadata": {}, 193 | "outputs": [], 194 | "source": [ 195 | "resp = s.get('https://www.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/uno/uno/' + str(lobby_players[43]['player']['uno']) + '/profile/type/warzone')" 196 | ] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "execution_count": null, 201 | "metadata": { 202 | "scrolled": true 203 | }, 204 | "outputs": [], 205 | "source": [ 206 | "resp.json()" 207 | ] 208 | }, 209 | { 210 | "cell_type": "code", 211 | "execution_count": null, 212 | "metadata": {}, 213 | "outputs": [], 214 | "source": [ 215 | "kds = []\n", 216 | "lobby_players_full = []\n", 217 | "team = \"\"\n", 218 | "teamPlacement = \"\"\n", 219 | "team_stats = {}\n", 220 | "for player in lobby_players:\n", 221 | " time.sleep(0.2)\n", 222 | " if player['player']['uno'] in team_mates.values():\n", 223 | " team = player['player']['team']\n", 224 | " team_placement = player['playerStats']['teamPlacement']\n", 225 | " team_stats[player['player']['username']] = [player['playerStats']['kills']]\n", 226 | " resp = requests.get('https://www.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/uno/uno/' + str(player['player']['uno']) + '/profile/type/warzone', headers=headers, cookies=resp_login.cookies)\n", 227 | "# try resp.json()['data'].get('message', ) == \"Not permitted: not allowed\":\n", 228 | "# kds.append('NA')\n", 229 | "# catch:\n", 230 | " kds.append(resp.json().get('data', {}).get('lifetime', {}).get('mode', {}).get('br', {}).get('properties', {}).get('kdRatio'))\n", 231 | " lobby_players_full.append(resp.json()['data'])\n", 232 | "kds" 233 | ] 234 | }, 235 | { 236 | "cell_type": "code", 237 | "execution_count": null, 238 | "metadata": {}, 239 | "outputs": [], 240 | "source": [ 241 | "len(kds)" 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": null, 247 | "metadata": {}, 248 | "outputs": [], 249 | "source": [ 250 | "plt.hist(kds, density=True, bins=50)\n", 251 | "plt.xlabel(\"KD\")\n", 252 | "plt.ylabel(\"#Players\")" 253 | ] 254 | }, 255 | { 256 | "cell_type": "code", 257 | "execution_count": null, 258 | "metadata": {}, 259 | "outputs": [], 260 | "source": [ 261 | "avg = round(sum(kds)/len(kds), 2)\n", 262 | "math.floor(len(kds)/2)\n", 263 | "median = round(sorted(kds)[math.floor(len(kds)/2)], 2)\n", 264 | "kd_min = round(min(kds), 2)\n", 265 | "kd_max = round(max(kds), 2)\n", 266 | "top_ten = [round(kd, 2) for kd in sorted(kds)[math.floor(len(kds) * (80/100)):len(kds)]]\n", 267 | "print(\"Game ID: \" + match_id)\n", 268 | "print(\"Team Placement: \" + str(team_placement))\n", 269 | "print(\"Team Kills\")\n", 270 | "print(team_stats)\n", 271 | "print(\"Lobby Stats\")\n", 272 | "print(\"Average KD: \" + str(avg))\n", 273 | "print(\"Median KD: \" + str(median))\n", 274 | "print(\"Worst KD: \" + str(kd_min))\n", 275 | "print(\"Best KD:\" + str(kd_max))\n", 276 | "print(\"Top 20% KD: \" + str([x for x in top_ten]))\n" 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": null, 282 | "metadata": {}, 283 | "outputs": [], 284 | "source": [ 285 | "sorted_kds = sorted(kds)" 286 | ] 287 | }, 288 | { 289 | "cell_type": "code", 290 | "execution_count": null, 291 | "metadata": {}, 292 | "outputs": [], 293 | "source": [ 294 | "sorted_kds = sorted_kds[:-4]\n", 295 | "adj_avg = round(sum(sorted_kds)/len(sorted_kds), 2)\n", 296 | "print(sorted_kds[-1])\n", 297 | "print(len(sorted_kds))\n", 298 | "print(adj_avg)" 299 | ] 300 | }, 301 | { 302 | "cell_type": "code", 303 | "execution_count": null, 304 | "metadata": {}, 305 | "outputs": [], 306 | "source": [ 307 | "max(kds)" 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": null, 313 | "metadata": {}, 314 | "outputs": [], 315 | "source": [ 316 | "min(kds)" 317 | ] 318 | }, 319 | { 320 | "cell_type": "code", 321 | "execution_count": null, 322 | "metadata": {}, 323 | "outputs": [], 324 | "source": [] 325 | }, 326 | { 327 | "cell_type": "code", 328 | "execution_count": null, 329 | "metadata": {}, 330 | "outputs": [], 331 | "source": [ 332 | "np.var(kds)" 333 | ] 334 | }, 335 | { 336 | "cell_type": "code", 337 | "execution_count": null, 338 | "metadata": {}, 339 | "outputs": [], 340 | "source": [ 341 | "resp_profile = requests.get('https://www.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/uno/uno/12035878875057403705/profile/type/warzone', headers=headers, cookies=resp_login.cookies)\n", 342 | "resp_profile.json()" 343 | ] 344 | }, 345 | { 346 | "cell_type": "code", 347 | "execution_count": null, 348 | "metadata": {}, 349 | "outputs": [], 350 | "source": [ 351 | "resp_profile_pub = requests.get('https://www.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/uno/uno/14688938695022220470/profile/type/warzone', headers=headers, cookies=resp_login.cookies)\n", 352 | "resp_profile_pub.json()" 353 | ] 354 | }, 355 | { 356 | "cell_type": "markdown", 357 | "metadata": {}, 358 | "source": [] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "execution_count": null, 363 | "metadata": {}, 364 | "outputs": [], 365 | "source": [ 366 | "resp_profile_pub.json()['data']['lifetime']['mode']['br']['properties']['kdRatio']" 367 | ] 368 | }, 369 | { 370 | "cell_type": "code", 371 | "execution_count": null, 372 | "metadata": {}, 373 | "outputs": [], 374 | "source": [ 375 | "'https://my.callofduty.com/api/papi-client/crm/cod/v2/title/mw/platform/uno/uno/4066176156082092197/matches/wz/start/0/end/0/details' \\\n", 376 | "--header 'Cookie: ACT_SSO_COOKIE=Set by test scripts; ACT_SSO_COOKIE_EXPIRY=1591153892430; atkn=Set by test scripts;'" 377 | ] 378 | }, 379 | { 380 | "cell_type": "code", 381 | "execution_count": null, 382 | "metadata": {}, 383 | "outputs": [], 384 | "source": [ 385 | "resp_profile = requests.get('https://www.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/psn/gamer/Viioozz/profile/type/warzone', headers=headers, cookies=resp_login.cookies)\n", 386 | "resp_profile.json()" 387 | ] 388 | }, 389 | { 390 | "cell_type": "code", 391 | "execution_count": null, 392 | "metadata": {}, 393 | "outputs": [], 394 | "source": [] 395 | } 396 | ], 397 | "metadata": { 398 | "kernelspec": { 399 | "display_name": "Python 3", 400 | "language": "python", 401 | "name": "python3" 402 | }, 403 | "language_info": { 404 | "codemirror_mode": { 405 | "name": "ipython", 406 | "version": 3 407 | }, 408 | "file_extension": ".py", 409 | "mimetype": "text/x-python", 410 | "name": "python", 411 | "nbconvert_exporter": "python", 412 | "pygments_lexer": "ipython3", 413 | "version": "3.8.2" 414 | } 415 | }, 416 | "nbformat": 4, 417 | "nbformat_minor": 4 418 | } 419 | -------------------------------------------------------------------------------- /match-history.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import requests\n", 10 | "import random\n", 11 | "import time\n", 12 | "import os\n", 13 | "import urllib.parse\n", 14 | "import pandas as pd\n", 15 | "from datetime import datetime\n", 16 | "pd.set_option('display.max_rows', 1000)" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": null, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "s = requests.Session()\n", 26 | "s.get('https://profile.callofduty.com/cod/login')\n", 27 | "data = {'username': os.environ.get('COD_EMAIL'), \n", 28 | " 'password': os.environ.get('COD_PW'), \n", 29 | " 'remember_me': 'true', \n", 30 | " '_csrf': s.cookies['XSRF-TOKEN']}\n", 31 | "s.post('https://profile.callofduty.com/do_login?new_SiteId=cod', params=data)" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "The matches endpoint is made up of different parts \n", 39 | "https://my.callofduty.com/api/papi-client/crm/cod/:version/title/:game/platform/:platform/gamer/:username/matches/:mode/start/:start/end/:end/details\n", 40 | "\n", 41 | "### Version\n", 42 | "API Version - Mostly v2 should work for Warzone.\n", 43 | "\n", 44 | "### game\n", 45 | "Game - \"mw\" for Modern Warfare, \"wwii\" for WWII, \"bo4\" for Black Ops 4\n", 46 | "\n", 47 | "### platform\n", 48 | "Platform associated with username - \"uno\" for Activision, \"battle\" for Battle.net, psn for Playstation, xbl for XBOX Live \"steam\" for WWII\n", 49 | "\n", 50 | "### username\n", 51 | "URI encoded string of the platform-specific username (eg: Viioozz for my psn)\n", 52 | "\n", 53 | "### mode\n", 54 | "Game Mode - \"wz\" for Warzone or \"mp\" for Multiplayer\n", 55 | "\n", 56 | "### start\n", 57 | "UNIX Timestamp\n", 58 | "\n", 59 | "Can remain at 0, or unless you want only the games between certain timeframes, can be interesting for killrace like tournamements where only the games during a certain time window count. Defaults to 0.\n", 60 | "\n", 61 | "### end\n", 62 | "UNIX Timestamp in milliseconds, defaults to 0\n" 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": {}, 68 | "source": [ 69 | "Let's call the api without providing timestamps:" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": null, 75 | "metadata": {}, 76 | "outputs": [], 77 | "source": [ 78 | "latest_matches_response = s.get('https://www.callofduty.com/api/papi-client/crm/cod/v2/title/mw/platform/xbl/gamer/coltie119/matches/wz/start/0/end/0/')\n", 79 | "latest_matches_response.json()" 80 | ] 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "metadata": {}, 85 | "source": [ 86 | "You'll see that you get a summary of the latest 20 games by default. If you want the details of every game you have to add '/details' to the endpoint." 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": null, 92 | "metadata": { 93 | "scrolled": false 94 | }, 95 | "outputs": [], 96 | "source": [ 97 | "latest_matches_response = s.get('https://www.callofduty.com/api/papi-client/crm/cod/v2/title/mw/platform/psn/gamer/Viioozz/matches/wz/start/0/end/0/details')\n", 98 | "latest_matches_response.json()" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "## URL Encode\n", 106 | "\n", 107 | "If you want to use other platforms like battle.net, keep in mind you'll have to url encode the username if they contain a hash symbol for example or other 'special' characters." 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": null, 113 | "metadata": {}, 114 | "outputs": [], 115 | "source": [ 116 | "username = 'Viöo$'\n", 117 | "urllib.parse.quote(nickname)" 118 | ] 119 | }, 120 | { 121 | "cell_type": "code", 122 | "execution_count": null, 123 | "metadata": {}, 124 | "outputs": [], 125 | "source": [ 126 | "username = 'Vioo#21794'\n", 127 | "urllib.parse.quote(nickname)" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": null, 133 | "metadata": {}, 134 | "outputs": [], 135 | "source": [ 136 | "s.get('https://www.callofduty.com/api/papi-client/crm/cod/v2/title/mw/platform/battle/gamer/{username}/matches/wz/start/0/end/0')" 137 | ] 138 | }, 139 | { 140 | "cell_type": "markdown", 141 | "metadata": {}, 142 | "source": [ 143 | "## UNIX Timestamps\n", 144 | "\n", 145 | "Unix time is a system for describing a point in time. It is the number of seconds that have elapsed since the Unix epoch, minus leap seconds; the Unix epoch is 00:00:00 UTC on 1 January 1970. It's a way of encoding time in a numeric way.\n", 146 | "\n", 147 | "Let's get the current time and use it to call the API.\n", 148 | "\n", 149 | "! Keep in mind, for the api we need MILLISECONDS, so we multiply by 1000." 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": null, 155 | "metadata": {}, 156 | "outputs": [], 157 | "source": [ 158 | "current_ts = int(time.time() * 1000)\n", 159 | "current_ts" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": null, 165 | "metadata": {}, 166 | "outputs": [], 167 | "source": [ 168 | "resp_matches = s.get(f'https://www.callofduty.com/api/papi-client/crm/cod/v2/title/mw/platform/psn/gamer/Viioozz/matches/wz/start/0/end/{current_ts}/details?limit=20')" 169 | ] 170 | }, 171 | { 172 | "cell_type": "code", 173 | "execution_count": null, 174 | "metadata": {}, 175 | "outputs": [], 176 | "source": [ 177 | "matches = resp_matches.json()['data']['matches']" 178 | ] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "execution_count": null, 183 | "metadata": {}, 184 | "outputs": [], 185 | "source": [ 186 | "len(matches)" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": null, 192 | "metadata": {}, 193 | "outputs": [], 194 | "source": [ 195 | "matches" 196 | ] 197 | }, 198 | { 199 | "cell_type": "markdown", 200 | "metadata": { 201 | "scrolled": true 202 | }, 203 | "source": [ 204 | "## Entire Match History\n", 205 | "\n", 206 | "How to pull all your matches as we only have 20 in one response. The way I solved this is to write a while loop that goes through my match history and stops when less than 20 matches are in a response meaning we are pulling in the last batch. \n", 207 | "For every subsequent call I use the timestamp of the latest game in the response as the 'end' parameter, so then I get all 20 matches before that last game." 208 | ] 209 | }, 210 | { 211 | "cell_type": "code", 212 | "execution_count": null, 213 | "metadata": {}, 214 | "outputs": [], 215 | "source": [ 216 | "tsLastGame = '0'\n", 217 | "matchesFound = True\n", 218 | "matches = []\n", 219 | "while matchesFound:\n", 220 | " resp_matches = s.get('https://www.callofduty.com/api/papi-client/crm/cod/v2/title/mw/platform/battle/gamer/Vioo%2321794/matches/wz/start/0/end/' + str(tsLastGame) + '000/details?limit=20')\n", 221 | " if len(resp_matches.json()['data']['matches']) == 20:\n", 222 | " new_matches = resp_matches.json()['data']['matches']\n", 223 | " tsLastGame = new_matches[-1]['utcStartSeconds']\n", 224 | " matches += new_matches\n", 225 | " else:\n", 226 | " matchesFound = False\n", 227 | " time.sleep(0.2)\n", 228 | " \n", 229 | "len(matches)" 230 | ] 231 | }, 232 | { 233 | "cell_type": "markdown", 234 | "metadata": {}, 235 | "source": [ 236 | "## Match Modes" 237 | ] 238 | }, 239 | { 240 | "cell_type": "markdown", 241 | "metadata": {}, 242 | "source": [ 243 | "## Calculate best games using Pandas DataFrames" 244 | ] 245 | }, 246 | { 247 | "cell_type": "code", 248 | "execution_count": null, 249 | "metadata": {}, 250 | "outputs": [], 251 | "source": [ 252 | "df_matches = pd.DataFrame(matches)\n", 253 | "df_matches = df_matches[~df_matches['mode'].str.contains('dmz')]\n", 254 | "len(df_matches)\n", 255 | "df_matches = pd.concat([df_matches.drop(['playerStats'], axis=1), df_matches['playerStats'].apply(pd.Series)], axis=1)\n", 256 | "df_matches.sort_values(by=['kills', 'damageDone'], ascending=False, inplace=True)\n", 257 | "csv_top = df_matches[['kills', 'deaths', 'gulagKills', 'gulagDeaths', 'damageDone', 'damageTaken', 'mode', 'teamPlacement']]\n", 258 | "csv_top.to_csv(\"./top.csv\")" 259 | ] 260 | }, 261 | { 262 | "cell_type": "code", 263 | "execution_count": null, 264 | "metadata": {}, 265 | "outputs": [], 266 | "source": [ 267 | "print(df_matches['kills'].sum())\n", 268 | "print(df_matches['deaths'].sum())\n", 269 | "print(df_matches['gulagDeaths'].sum())\n", 270 | "#print(df_matches[df_matches['gulagDeaths'] > 1].count())\n", 271 | "df_matches['kills'].sum()/df_matches['deaths'].sum()" 272 | ] 273 | }, 274 | { 275 | "cell_type": "code", 276 | "execution_count": null, 277 | "metadata": {}, 278 | "outputs": [], 279 | "source": [ 280 | "df_matches['gulagKills'].sum()" 281 | ] 282 | }, 283 | { 284 | "cell_type": "code", 285 | "execution_count": null, 286 | "metadata": {}, 287 | "outputs": [], 288 | "source": [ 289 | "df_matches[df_matches['gulagKills'] >= 1]['kills']" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": null, 295 | "metadata": {}, 296 | "outputs": [], 297 | "source": [ 298 | "df_matches.groupby(['mode']).count().sort_values('mode')" 299 | ] 300 | }, 301 | { 302 | "cell_type": "code", 303 | "execution_count": null, 304 | "metadata": {}, 305 | "outputs": [], 306 | "source": [ 307 | "print(matches[-1])" 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": null, 313 | "metadata": {}, 314 | "outputs": [], 315 | "source": [ 316 | "matchIds = []\n", 317 | "for match in matches:\n", 318 | " matchIds.append(match['rankedTeams'])\n", 319 | "print(len(set(matchIds)))" 320 | ] 321 | }, 322 | { 323 | "cell_type": "code", 324 | "execution_count": null, 325 | "metadata": {}, 326 | "outputs": [], 327 | "source": [ 328 | "matchModes = []\n", 329 | "for match in matches:\n", 330 | " matchModes.append(match['gameType'])\n", 331 | "print(len(matchModes))\n", 332 | "modes = set(matchModes)\n", 333 | "print(modes)" 334 | ] 335 | }, 336 | { 337 | "cell_type": "code", 338 | "execution_count": null, 339 | "metadata": {}, 340 | "outputs": [], 341 | "source": [ 342 | "for match in matches:\n", 343 | " if match['mode'] == \"brtdm_113\":\n", 344 | " print(match['playerStats']['gulagDeaths'])" 345 | ] 346 | }, 347 | { 348 | "cell_type": "code", 349 | "execution_count": null, 350 | "metadata": {}, 351 | "outputs": [], 352 | "source": [ 353 | "totalWZMatches = 0\n", 354 | "totalGulags = 0\n", 355 | "totalGulagKills = 0\n", 356 | "totalGulagDeaths = 0\n", 357 | "totalKills = 0\n", 358 | "totalDeaths = 0\n", 359 | "for match in matches:\n", 360 | " gulagKills = match['playerStats'].get('gulagKills', 0.0)\n", 361 | " gulagDeaths = match['playerStats'].get('gulagDeaths', 0.0)\n", 362 | " print(gulagDeaths)\n", 363 | " if match['mode'] not in [\"br_dmz_plnbld\", \"brtdm_113\", \"br_dmz_104\", \"br_dmz_38\", \"br_dmz_85\"]:\n", 364 | " print(str(match['playerStats']['kills']) + \"/\" + str(match['playerStats']['deaths']))\n", 365 | " if gulagKills != 0.0 or gulagDeaths != 0.0:\n", 366 | " totalGulags += 1\n", 367 | " if gulagKills >= 1.0:\n", 368 | " totalGulagKills += 1\n", 369 | " print(\"Gulag Won!\")\n", 370 | " if gulagDeaths >= 1.0:\n", 371 | " totalGulagDeaths += 1\n", 372 | " print(\"Gulag Lost!\")\n", 373 | " totalWZMatches += 1\n", 374 | " totalKills += match['playerStats']['kills']\n", 375 | " totalDeaths += match['playerStats']['deaths']\n", 376 | "print(totalWZMatches)\n", 377 | "print(totalGulags)\n", 378 | "print(totalGulagKills)\n", 379 | "print(totalGulagDeaths)\n", 380 | "print(totalKills)\n", 381 | "print(totalDeaths)\n", 382 | " " 383 | ] 384 | }, 385 | { 386 | "cell_type": "code", 387 | "execution_count": null, 388 | "metadata": {}, 389 | "outputs": [], 390 | "source": [ 391 | "727/800" 392 | ] 393 | }, 394 | { 395 | "cell_type": "code", 396 | "execution_count": null, 397 | "metadata": {}, 398 | "outputs": [], 399 | "source": [ 400 | "date_start = datetime(2000,1,1,0,0)\n", 401 | "date_start = int(time.mktime(date_start.timetuple()))\n", 402 | "date_start" 403 | ] 404 | }, 405 | { 406 | "cell_type": "code", 407 | "execution_count": null, 408 | "metadata": {}, 409 | "outputs": [], 410 | "source": [] 411 | } 412 | ], 413 | "metadata": { 414 | "kernelspec": { 415 | "display_name": "Python 3", 416 | "language": "python", 417 | "name": "python3" 418 | }, 419 | "language_info": { 420 | "codemirror_mode": { 421 | "name": "ipython", 422 | "version": 3 423 | }, 424 | "file_extension": ".py", 425 | "mimetype": "text/x-python", 426 | "name": "python", 427 | "nbconvert_exporter": "python", 428 | "pygments_lexer": "ipython3", 429 | "version": "3.8.2" 430 | } 431 | }, 432 | "nbformat": 4, 433 | "nbformat_minor": 4 434 | } 435 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # COD API HOW TO 2 | 3 | COD API Docs built by the community: https://documenter.getpostman.com/view/5519582/SzzgAefq 4 | ## Run it with jupyter installed globally 5 | 6 | ````shell 7 | pip install -r requirements.txt 8 | ```` 9 | 10 | ````bash 11 | jupyter notebook . 12 | ```` 13 | 14 | ## Run it with jupyter in a virtualenv 15 | 16 | If you don't want to install jupyter globally and/or want to play around with different versions of python modules you can either run in a virtual python environment or with docker. 17 | This gives you more flexibility to try and test different versions for different projects. 18 | 19 | For this I use pyenv. 20 | https://realpython.com/intro-to-pyenv/ 21 | https://github.com/pyenv/pyenv 22 | 23 | Create a new virtual environment specifically for this project, choose a python version and give it a name. For example I'll be using python 3.8.2 with the name "cod_api". 24 | 25 | ````bash 26 | pyenv virtualenv 3.8.2 cod_api 27 | ```` 28 | 29 | ````bash 30 | pyenv local cod_api 31 | ```` 32 | 33 | ````bash 34 | pip install -r requirements.txt 35 | ```` 36 | 37 | ## Run locally with docker -------------------------------------------------------------------------------- /recaptcha-sso-token.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "absolute-malta", 6 | "metadata": {}, 7 | "source": [] 8 | }, 9 | { 10 | "cell_type": "code", 11 | "execution_count": null, 12 | "id": "organized-budapest", 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import os\n", 17 | "import requests" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": null, 23 | "id": "domestic-drinking", 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "sso_token = os.environ.get('SSO_TOKEN')\n", 28 | "cookies={\"ACT_SSO_COOKIE\": sso_token}" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": null, 34 | "id": "tight-charm", 35 | "metadata": {}, 36 | "outputs": [], 37 | "source": [] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "id": "dated-douglas", 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "resp_profile = requests.get('https://www.callofduty.com/api/papi-client/crm/cod/v2/title/mw/platform/xbl/gamer/coltie119/matches/wz/start/0/end/0/details', cookies=cookies)\n", 47 | "uno = resp_profile.json()['data']['matches'][0]['player']['uno']" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "id": "perfect-deadline", 54 | "metadata": {}, 55 | "outputs": [], 56 | "source": [ 57 | "print(uno)" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": null, 63 | "id": "reported-formula", 64 | "metadata": {}, 65 | "outputs": [], 66 | "source": [ 67 | "uno_profile = requests.get(f'https://www.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/uno/uno/{uno}/profile/type/warzone', cookies=cookies)" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": null, 73 | "id": "shaped-harmony", 74 | "metadata": {}, 75 | "outputs": [], 76 | "source": [ 77 | "uno_profile.json()" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": null, 83 | "id": "virtual-alias", 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [ 87 | "uno_matches = requests.get(f'https://www.callofduty.com/api/papi-client/crm/cod/v2/title/mw/platform/uno/uno/{uno}/matches/wz/start/0/end/0/', cookies=cookies)" 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": null, 93 | "id": "running-stretch", 94 | "metadata": {}, 95 | "outputs": [], 96 | "source": [ 97 | "uno_matches.json()" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": null, 103 | "id": "capital-valve", 104 | "metadata": {}, 105 | "outputs": [], 106 | "source": [ 107 | "uno_matches = requests.get(f'https://www.callofduty.com/api/papi-client/crm/cod/v2/title/mw/platform/uno/uno/{uno}/matches/wz/start/0/end/0/', cookies=cookies)" 108 | ] 109 | } 110 | ], 111 | "metadata": { 112 | "kernelspec": { 113 | "display_name": "Python 3", 114 | "language": "python", 115 | "name": "python3" 116 | }, 117 | "language_info": { 118 | "codemirror_mode": { 119 | "name": "ipython", 120 | "version": 3 121 | }, 122 | "file_extension": ".py", 123 | "mimetype": "text/x-python", 124 | "name": "python", 125 | "nbconvert_exporter": "python", 126 | "pygments_lexer": "ipython3", 127 | "version": "3.8.2" 128 | } 129 | }, 130 | "nbformat": 4, 131 | "nbformat_minor": 5 132 | } 133 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | jupyter 2 | requests 3 | numpy 4 | matplotlib 5 | --------------------------------------------------------------------------------