/PubgRecords-server

A GraphQL proxy between the PUBG API and the PubgRecords Apps

Primary LanguageJavaScriptGNU General Public License v3.0GPL-3.0

pubgrecords.com GraphQL server

All Contributors Heroku PRs Welcome

This server is currently deployed on heroku and serves as a proxy between the PUBG API and both Pubg Records Apps:

Web App: PubgRecords.com

Table of Contents

Run locally 💻

Install dependencies

yarn install

Rename .env.example to .env and include your own API Key that you can get from here.

Run the dev server

yarn dev

Go to http://localhost:3001/

Test using the GraphQL interface

  • Locally 💻 :

After starting the server, go to http://localhost:3001/api/graphql to launch it.

  • Online 🌏 :

Go to https://pubgrecords-graphql.herokuapp.com/api/graphql

Query examples

Player ID

Query:

query {
  playerId(region: "steam", playerName: "JadT26")
}

Result:

{
  "data": {
    "playerId": "account.c04b3561ec5442c9bb52433648482b65"
  }
}

All match IDs for a given player

Query:

query {
  playerGames(region: "steam", playerName: "JadT26") {
    id
  }
}

Result:

{
  "data": {
    "playerGames": [
      {
        "id": "a3f7f354-bab0-4b54-9a3f-3ba5f0bc0cdb"
      },
      {
        "id": "a3d0171b-0288-4e59-be08-2414eb1ebc31"
      },
      {
        "id": "22a67e10-30e6-4fcd-b902-9759015c0dcc"
      },
      ...
    ]
  }
}

Match Details for 1 or more matches

Query:

query {
  matchesInfo(
    region: "steam"
    playerId: "account.c04b3561ec5442c9bb52433648482b65"
    matchesId: "a3d0171b-0288-4e59-be08-2414eb1ebc31"
    // matchesId: ["a3d0171b-0288-4e59-be08-2414eb1ebc31", "22a67e10-30e6-4fcd-b902-9759015c0dcc", "4780ad2f-6d93-4a8b-b4da-efe5c0db2fda"]
  ) {
    playersInfo {
      assists
      damage
      DBNOs
      headshotKills
      heals
      killPlace
      kills
      longestKill
      name
      playerId
      rank
      revives
      rideDistance (meters)
      roadKills
      swimDistance (meters)
      teamKills
      timeSurvived (minutes)
      vehiclesDestroyed
      walkDistance (meters)
    }
    generalInfo {
      date (YYYY-MM-DD)
      gameMode
      mapName
      matchDuration (minutes)
      participants
      team
      teams
      telemetryUrl
      time (HH:MM:SS)
      userRank
    }
  }
}

Result (of a single match):

{
  "data": {
    "matchesInfo": [
      {
        "playersInfo": [
          {
            "assists": 0,
            "damage": 335,
            "DBNOs": 0,
            "headshotKills": 0,
            "heals": 12,
            "killPlace": 23,
            "kills": 1,
            "longestKill": 28,
            "name": "JadT26",
            "playerId": "account.c04b3561ec5442c9bb52433648482b65",
            "rank": 9,
            "revives": 1,
            "rideDistance": 2048,
            "roadKills": 0,
            "swimDistance": 0,
            "teamKills": 0,
            "timeSurvived": 24,
            "vehiclesDestroyed": 1,
            "walkDistance": 3341
          },
          {
            "assists": 1,
            "damage": 99,
            "DBNOs": 1,
            "headshotKills": 1,
            "heals": 11,
            "killPlace": 24,
            "kills": 1,
            "longestKill": 32,
            "name": "sguss",
            "playerId": "account.c04b3561ec5442c9bb52433648482b65",
            "rank": 9,
            "revives": 1,
            "rideDistance": 2035,
            "roadKills": 0,
            "swimDistance": 0,
            "teamKills": 0,
            "timeSurvived": 24,
            "vehiclesDestroyed": 0,
            "walkDistance": 3654
          }
        ],
        "generalInfo": {
          "date": "2018-09-17",
          "gameMode": "duo-fpp",
          "mapName": "Erangel_Main",
          "matchDuration": 31,
          "participants": 87,
          "team": ["JadT26", "sguss"],
          "teams": 44,
          "telemetryUrl": "https://telemetry-cdn.playbattlegrounds.com/bluehole-pubg/pc-eu/2019/03/23/14/11/8a691612-4d75-11e9-ad4d-0a586463690a-telemetry.json",
          "time": "20:35:47",
          "userRank": 9
        }
      }
    ]
  }
}

Seasonal stats for a given player

Query:

query {
  getSeasonStats(
    region: "steam"
    playerId: "account.c04b3561ec5442c9bb52433648482b65"
    season: "division.bro.official.2018-08"
  ) {
    assists
    damage
    deaths
    drivingDistance (meters)
    heals
    kdRatio
    kills
    longestGame (minutes)
    longestKill (meters)
    mostKills
    revives
    rounds
    runningDistance (meters)
    suicides
    teamKills
    timePlayed (minutes)
    top10s
    vehiclesDestroyed
    wins
  }
}

Result:

{
  "data": {
    "getSeasonStats": {
      "assists": 22,
      "damage": 7675,
      "deaths": 69,
      "drivingDistance": 16212,
      "heals": 169,
      "kdRatio": 0.65,
      "kills": 45,
      "longestGame": 26,
      "longestKill": 226.07,
      "mostKills": 5,
      "revives": 14,
      "rounds": 69,
      "runningDistance": 54739,
      "suicides": 0,
      "teamKills": 1,
      "timePlayed": 578,
      "top10s": 16,
      "vehiclesDestroyed": 0,
      "wins": 1
    }
  }
}

Lifetime stats for a given player

Query:

query {
  getLifetimeStats(
    region: "steam"
    playerId: "account.c04b3561ec5442c9bb52433648482b65"
  ) {
    assists
    damage
    dBNOs
    deaths
    drivingDistance (meters)
    headshotKills
    heals
    kdRatio
    kills
    longestGame (minutes)
    longestKill (meters)
    revives
    roadKills
    roundMostKills
    rounds
    runningDistance (meters)
    suicides
    swimDistance (meters)
    teamKills
    timePlayed (minutes)
    top10s
    vehiclesDestroyed
    weaponsAcquired
    wins
  }
}

Result:

{
  "data": {
    "getLifetimeStats": {
      "assists": 98,
      "damage": 39734,
      "dBNOs": 205,
      "deaths": 507,
      "drivingDistance": 314073,
      "headshotKills": 62,
      "heals": 980,
      "kdRatio": 0.49,
      "kills": 246,
      "longestGame": 31,
      "longestKill": 413.64,
      "revives": 109,
      "roadKills": 2,
      "roundMostKills": 6,
      "rounds": 512,
      "runningDistance": 354559,
      "suicides": 11,
      "swimDistance": 1935,
      "teamKills": 15,
      "timePlayed": 4453,
      "top10s": 73,
      "vehiclesDestroyed": 0,
      "weaponsAcquired": 1377,
      "wins": 6
    }
  }
}

Weapon Mastery for a given player

Query:

query {
  weaponMastery(
    region: "steam"
    playerId: "account.c04b3561ec5442c9bb52433648482b65"
  ) {
    name
    stats {
      damage
      defeats
      headshots
      kills
      knocks
      levelCurrent
      longRangeKills
      longestKill
      roundMostDamage
      roundMostDefeats
      roundMostHeadshots
      roundMostKills
      roundMostKnocks
      tierCurrent
      xpTotal
    }
    medals {
      count
      medalId
    }
  }
}

Result:

{
  "data": {
    "weaponMastery": [
      {
        "name": "Item_Weapon_AK47_C",
        "stats": {
          "damage": 2353.9,
          "defeats": 19,
          "headshots": 14,
          "kills": 12,
          "knocks": 14,
          "levelCurrent": 10,
          "longRangeKills": 0,
          "longestKill": 50.36,
          "roundMostDamage": 407.51,
          "roundMostDefeats": 3,
          "roundMostHeadshots": 3,
          "roundMostKills": 2,
          "roundMostKnocks": 3,
          "tierCurrent": 2,
          "xpTotal": 50790
        },
        "medals": [
          {
            "count": 6,
            "medalId": "MedalDeadeye"
          },
          {
            "count": 5,
            "medalId": "MedalAssassin"
          },
          {
            "count": 2,
            "medalId": "MedalPunisher"
          }
        ]
      },
      {
        "name": "Item_Weapon_AUG_C",
        "stats": {
          "damage": 283.33,
          "defeats": 1,
          "headshots": 1,
          "kills": 0,
          "knocks": 1,
          "levelCurrent": 2,
          "longRangeKills": 0,
          "longestKill": 28.1,
          "roundMostDamage": 151.72,
          "roundMostDefeats": 1,
          "roundMostHeadshots": 1,
          "roundMostKills": 0,
          "roundMostKnocks": 1,
          "tierCurrent": 1,
          "xpTotal": 6142
        },
        "medals": [
          {
            "count": 1,
            "medalId": "MedalDeadeye"
          }
        ]
      },
      ...
      ...
    ]
  }
}

Leaderboards

Query:

query {
  leaderboards(
    gameMode: "solo"
    #gameMode: "solo-fpp"
    count: 50
    season: "division.bro.official.pc-2018-06"
  ) {
    id
    name
    rank
    stats {
      averageDamage
      averageRank
      games
      killDeathRatio
      kills
      rankPoints
      winRatio (%)
      wins
    }
  }
}

Results are ordered by player rank

{
  "data": {
    "leaderboards": [
      {
        "name": "HuYaTV-17044129",
        "rank": 1,
        "id": "account.829af3612d4c4bed8d82a93a176eb7a6",
        "stats": {
          "rankPoints": 7508,
          "wins": 685,
          "games": 2637,
          "winRatio": 25.98,
          "averageDamage": 367,
          "kills": 8609,
          "killDeathRatio": 4.17,
          "averageRank": 12.99
        }
      },
      {
        "name": "XiGua-520820_Xg",
        "rank": 2,
        "id": "account.18455fef7f114facb739bd23ad370e29",
        "stats": {
          "rankPoints": 7505,
          "wins": 557,
          "games": 2822,
          "winRatio": 19.74,
          "averageDamage": 314,
          "kills": 7371,
          "killDeathRatio": 3.16,
          "averageRank": 12.81
        }
      },
      ...

Telemetry data 🎉

Coordinates

The coordinates represent the player's movement from the moment the player lands until his death (or victory). The query requires a telemetry url and a username of a participant of this match. The scale parameter is optional and you can use it to return the coordinated scaled to your preference.

Scale Example

Erangel is 816000 x 816000 and I want to scale the coordinates to be translated on a 408x408 px canvas. To achieve this, I add a scale parameter to the query and give it a value of 2000.

Scales to fit a 408x408 px canvas:

{
  Erangel: 2000,
  Miramar: 2000,
  Sanhok: 1000,
  Vikendi: 1500,
  Karakin: 500
}

Player or Team

query {
  telemetry(
    # Replace the url with your telemetry URL
    url: "https://telemetry-cdn.playbattlegrounds.com/bluehole-pubg/steam/2020-telemetry.json"
    users: "JadT26"
    # users: ["JadT26", "sguss"]
    scale: 2000
  ) {
    playerCoords {
      Id
      Coords {
        x
        y
        z
      }
    }
  }
}

Response of a single player:

{
  "data": {
    "telemetry": {
      "playerCoords": [
        {
          "Id": "JadT26",
          "Coords": [
            {
              "x": 215,
              "y": 333,
              "z": 1255
            },
            {
              "x": 215,
              "y": 333,
              "z": 1255
            },
          ...

Safety, Red, and Black Zones

query {
  telemetry(
    # Replace the url with your telemetry URL
    url: "https://telemetry-cdn.playbattlegrounds.com/bluehole-pubg/pc-eu/telemetry.json"
    users: "JadT26"
    # users: ["JadT26", "sguss"]
    scale: 500
  ) {
    safetyZoneCoords {
      x
      y
      radius
    }
    redZoneCoords {
      x
      y
      radius
    }
    blackZoneCoords {
      x
      y
      radius
    }
  }
}

Response:

{
  "data": {
    "telemetry": {
      "safetyZoneCoords": [
        {
          "x": 234.6998125,
          "y": 277.33684375,
          "radius": 145.609578125
        },
        {
          "x": 224.94015625,
          "y": 289.24596875,
          "radius": 101.926703125
        },
        ...
      "redZoneCoords": [
        {
          "x": 234.6998125,
          "y": 277.33684375,
          "radius": 145.609578125
        },
        {
          "x": 224.94015625,
          "y": 289.24596875,
          "radius": 101.926703125
        },
        ...
      "blackZoneCoords": [
        {
          "x": 124.6998125,
          "y": 277.33684375,
          "radius": 15
        },
        {
          "x": 224.94015625,
          "y": 289.24596875,
          "radius": 15
        },
        ...

Contributors


Jad Termsani

💻 📖

Serge Kamel

💻 📖

This project follows the all-contributors specification. Contributions of any kind welcome!