From ec09b7d66fb4a939c0f8cc450a8c343e78cba606 Mon Sep 17 00:00:00 2001 From: redbeardy Date: Thu, 7 Oct 2021 01:26:05 -0500 Subject: [PATCH 1/3] Add ranked stats support --- src/pubg_clj/api.clj | 18 ++++++++++++++++ src/pubg_clj/api/parsers.clj | 41 +++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/pubg_clj/api.clj b/src/pubg_clj/api.clj index a275294..8807c58 100644 --- a/src/pubg_clj/api.clj +++ b/src/pubg_clj/api.clj @@ -91,6 +91,9 @@ (defn- season-stats-endpoint [player-id season-id] (str "players/" player-id "/seasons/" season-id)) +(defn- season-ranked-stats-endpoint + [player-id season-id] + (str "players/" player-id "/seasons/" season-id "/ranked")) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Status @@ -271,3 +274,18 @@ :endpoint (season-stats-endpoint id season-id)}) :body p/player-season-stats-parse))) + +(defn fetch-player-season-ranked-stats + "Fetches the ranked season stats for a given player and season. The + region is required for PS4, Xbox, and for stats of PC players prior + to and including division.bro.official.2018-09. It is probably best + to always include the region, as the API will respond with stats for + EVERY region in the cases where it is depracated." + [player season-id & [region]] + (let [{:keys [pubg.player/id pubg/shard-id]} player] + (->> (pubg-fetch + {:platform shard-id, + :region (or region ""), + :endpoint (season-ranked-stats-endpoint id season-id)}) + :body + p/player-season-ranked-stats-parse))) diff --git a/src/pubg_clj/api/parsers.clj b/src/pubg_clj/api/parsers.clj index 0b5a7da..b37084d 100644 --- a/src/pubg_clj/api/parsers.clj +++ b/src/pubg_clj/api/parsers.clj @@ -174,6 +174,39 @@ :pubg.season.stats/wins {:from [:wins]} }) +(defparser season-ranked-stats-parse + {:pubg/game-mode {:from [:game-mode]}, + :pubg.season.stats/kills {:from [:kills]}, + :pubg.season.stats/kill-streak {:from [:kill-streak]}, + :pubg.season.stats/boosts {:from [:boosts]}, + :pubg.season.stats/team-kills {:from [:team-kills]}, + :pubg.season.stats/revives {:from [:revives]}, + :pubg.season.stats/assists {:from [:assists]}, + :pubg.season.stats/kdr {:from [:kdr]}, + :pubg.season.stats/revive-ratio {:from [:revive-ratio]}, + :pubg.season.stats/avg-rank {:from [:avg-rank]}, + :pubg.season.stats/deaths {:from [:deaths]}, + :pubg.season.stats/damage-dealt {:from [:damage-dealt]}, + :pubg.season.stats/weapons-acquired {:from [:weapons-acquired]}, + :pubg.season.stats/heals {:from [:heals]}, + :pubg.season.stats/play-time {:from [:play-time]}, + :pubg.season.stats/top-10-ratio {:from [:top-10-ratio]}, + :pubg.season.stats/kda {:from [:kda]}, + :pubg.season.stats/headshot-kill-ratio {:from [:headshot-kill-ratio]}, + :pubg.season.stats/current-rank-point {:from [:current-rank-point]}, + :pubg.season.stats/dbnos {:from [:d-bn-os]}, + :pubg.season.stats/best-tier {:from [:best-tier :tier]}, + :pubg.season.stats/avg-survival-time {:from [:avg-survival-time]}, + :pubg.season.stats/round-most-kills {:from [:round-most-kills]}, + :pubg.season.stats/headshot-kills {:from [:headshot-kills]}, + :pubg.season.stats/current-tier {:from [:current-tier :tier]}, + :pubg.season.stats/current-sub-tier {:from [:current-tier :sub-tier]}, + :pubg.season.stats/best-rank-point {:from [:best-rank-point]}, + :pubg.season.stats/longest-kill {:from [:longest-kill]}, + :pubg.season.stats/wins {:from [:wins]}, + :pubg.season.stats/win-ratio {:from [:win-ratio]}, + :pubg.season.stats/rounds-played {:from [:rounds-played]}}) + (defn- pack-game-mode-stats [[game-mode-key stats-map]] (assoc stats-map :game-mode (name game-mode-key))) @@ -184,6 +217,13 @@ :using #(let [stats (map pack-game-mode-stats %)] (mapv season-stats-parse stats))}}) +(defparser + player-season-ranked-stats-parse + {:pubg.player/id {:from [:data :relationships :player :data :id]}, + :pubg.player/season-stats {:from [:data :attributes :game-mode-stats], + :using #(let [stats (map pack-game-mode-stats %)] + (mapv season-ranked-stats-parse stats))}}) + (defparser telemetry-common-parse {:pubg.match.telemetry.common/is-game {:from [:is-game]}}) @@ -366,4 +406,3 @@ maybe-discard (fn [x] (if (map? x) (discard-nil-vals x) x))] (walk/postwalk maybe-discard evts))}}) - From 3b7e9f15740224d423f2a8661f8a9a62a81df161 Mon Sep 17 00:00:00 2001 From: redbeardy Date: Thu, 7 Oct 2021 09:46:24 -0500 Subject: [PATCH 2/3] Implement ranked stats parsing. First pass. `api-url` is currently modified to temporarily test without other intrusive changes to calling conventions. Issue #2 describes what the main issue seems to be, but fixing this is out of scope of the current goal. --- src/pubg_clj/api.clj | 2 +- src/pubg_clj/api/parsers.clj | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pubg_clj/api.clj b/src/pubg_clj/api.clj index 8807c58..dca7099 100644 --- a/src/pubg_clj/api.clj +++ b/src/pubg_clj/api.clj @@ -30,7 +30,7 @@ (cond-> "https://api.pubg.com/" (or platform region) (concat "shards/") platform (concat platform) - region (concat "-" region) + ;; region (concat "-" region) endpoint (concat "/" endpoint) true str/join)) diff --git a/src/pubg_clj/api/parsers.clj b/src/pubg_clj/api/parsers.clj index b37084d..b458552 100644 --- a/src/pubg_clj/api/parsers.clj +++ b/src/pubg_clj/api/parsers.clj @@ -219,8 +219,8 @@ (defparser player-season-ranked-stats-parse - {:pubg.player/id {:from [:data :relationships :player :data :id]}, - :pubg.player/season-stats {:from [:data :attributes :game-mode-stats], + {:pubg.player/id {:from [:data :relationships :player :data :id]}, + :pubg.player/season-ranked-stats {:from [:data :attributes :ranked-game-mode-stats] :using #(let [stats (map pack-game-mode-stats %)] (mapv season-ranked-stats-parse stats))}}) From c8a05e1655ce1ca7f5a20b65ce0d706d7ea16884 Mon Sep 17 00:00:00 2001 From: redbeardy Date: Sun, 10 Oct 2021 17:51:03 -0500 Subject: [PATCH 3/3] Paramaterize platform shard Platform and region are incompatible parameters now. API expects either a platform, or combined platform-region, as a shard route. Some endpoints expect a platform, others expect a platform-region. --- src/pubg_clj/api.clj | 83 +++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/src/pubg_clj/api.clj b/src/pubg_clj/api.clj index dca7099..c26f20c 100644 --- a/src/pubg_clj/api.clj +++ b/src/pubg_clj/api.clj @@ -23,15 +23,13 @@ ~@body)) (defn- api-url - "Constructs a valid PubG API URL given a platform, region, and endpoint. region - is optional. Query parameters are not included, and should be added by the - HTTP client mechanism." - [{:keys [platform region endpoint]}] + "Constructs a valid PubG API URL given a platform or platform-region, + and endpoint. region is optional. Query parameters are not included, + and should be added by the HTTP client mechanism." + [{:keys [platform-region endpoint]}] (cond-> "https://api.pubg.com/" - (or platform region) (concat "shards/") - platform (concat platform) - ;; region (concat "-" region) - endpoint (concat "/" endpoint) + platform-region (concat "shards/" platform-region) + endpoint (concat "/" endpoint) true str/join)) (defn- parse-response-body @@ -41,11 +39,12 @@ (update resp :body #(json/parse-string % ->kebab-case-keyword))) (defn pubg-fetch - "Makes a request to the PubG API using the given api-key, platform, - region (optional), endpoint and query parameters (qparams). Platform, region - and endpoint are all used to construct the final URL, but this can be - overidden using the url key. Returns the response map." - [{:keys [api-key platform region endpoint qparams url] :as opts}] + "Makes a request to the PubG API using the given api-key, platform or + platform-region, endpoint and query parameters (qparams). + platform(-region) and endpoint are used to construct the final URL, + but this can be overidden using the url key. Returns the response + map." + [{:keys [api-key platform-region endpoint qparams url] :as opts}] (let [api-key (or api-key *api-key*) url (or url (api-url opts)) resp (http/get url @@ -55,12 +54,13 @@ (parse-response-body resp))) (defn pubg-fetch-async - "Asynchronously makes a request to the PubG API using the given api-key, platform, - region (optional), endpoint and query parameters (qparams). Platform, region - and endpoint are all used to construct the final URL, but this can be - overidden with the url key. Passes the response map to succ upon success, or - exception data to err upon failure." - [{:keys [api-key platform region endpoint qparams url] :as opts} succ err] + "Asynchronously makes a request to the PubG API using the given + api-key, platform or platform-region, endpoint and query + parameters (qparams). platform(-region) and endpoint are used to + construct the final URL, but this can be overidden with the url key. + Passes the response map to succ upon success, or exception data to + err upon failure." + [{:keys [api-key platform-region endpoint qparams url] :as opts} succ err] (let [api-key (or api-key *api-key*)] (let [url (or url (api-url opts))] (http/get url {:accept "application/vnd.api+json" @@ -118,7 +118,7 @@ "Internal implementation of player fetching given a filter query parameter key, platform, and player identifier(s) (name or ID). " [filter-key platform pident] - (->> (pubg-fetch {:platform platform + (->> (pubg-fetch {:platform-region platform :endpoint (player-endpoint) :qparams {filter-key pident}}) :body @@ -157,7 +157,7 @@ (defn fetch-match "Retrieves a match by its ID on the given platform." [platform match-id] - (->> (pubg-fetch {:platform platform + (->> (pubg-fetch {:platform-region platform :endpoint (match-endpoint match-id)}) :body p/match-parse)) @@ -173,7 +173,7 @@ (wrap-err [f] (fn [e] (f (merge e {::match-id match-id}))))] - (pubg-fetch-async {:platform platform + (pubg-fetch-async {:platform-region platform :endpoint (match-endpoint match-id)} (wrap-succ succ) (wrap-err err)))) @@ -200,9 +200,8 @@ (defn fetch-match-samples "Fetches n random matches for the given platform and region in parallel." - [n platform region] - (let [match-samples (->> (pubg-fetch {:platform platform - :region region + [n platform] + (let [match-samples (->> (pubg-fetch {:platform-region platform :endpoint (match-samples-endpoint)}) :body :data :relationships :matches :data (map :id))] @@ -213,10 +212,10 @@ accepts an err callback that will be passed exception data for every match that fails to load. Exception data will contain ::pubg/match-id for reference." - [player & [err]] - (let [{:keys [pubg.player/matches pubg/shard-id]} player - match-ids (map :pubg.match/id matches)] - (batch-get-matches shard-id match-ids err))) + [player platform & [err]] + (let [{:keys [pubg.player/matches]} player + match-ids (map :pubg.match/id matches)] + (batch-get-matches platform match-ids err))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Telemetry @@ -236,8 +235,8 @@ (defn fetch-leaderboard "Retrieves the leaderboard for the given platform and game mode. Currently leaderboards are only available on PC." - [platform game-mode] - (->> (pubg-fetch {:platform platform + [platform-region game-mode] + (->> (pubg-fetch {:platform-region platform-region :endpoint (leaderboard-endpoint game-mode)}) :body p/leaderboard-parse)) @@ -247,8 +246,8 @@ (defn fetch-seasons "Fetches a list of available seasons for the given platform." - [platform] - (->> (pubg-fetch {:platform platform + [platform-region] + (->> (pubg-fetch {:platform-region platform-region :endpoint (seasons-endpoint)}) :body :data @@ -256,8 +255,8 @@ (defn fetch-current-season "Fetches the season that is currently in progress for the given platform." - [platform] - (->> (fetch-seasons platform) + [platform-region] + (->> (fetch-seasons platform-region) (filter :pubg.season/is-current?) first)) @@ -267,10 +266,9 @@ division.bro.official.2018-09. It is probably best to always include the region, as the API will respond with stats for EVERY region in the cases where it is depracated." - [player season-id & [region]] - (let [{:keys [pubg.player/id pubg/shard-id]} player] - (->> (pubg-fetch {:platform shard-id - :region (or region "") + [platform-region player season-id] + (let [{:keys [pubg.player/id]} player] + (->> (pubg-fetch {:platform-region platform-region :endpoint (season-stats-endpoint id season-id)}) :body p/player-season-stats-parse))) @@ -281,11 +279,10 @@ to and including division.bro.official.2018-09. It is probably best to always include the region, as the API will respond with stats for EVERY region in the cases where it is depracated." - [player season-id & [region]] - (let [{:keys [pubg.player/id pubg/shard-id]} player] + [platform-region player season-id] + (let [{:keys [pubg.player/id]} player] (->> (pubg-fetch - {:platform shard-id, - :region (or region ""), + {:platform-region platform-region, :endpoint (season-ranked-stats-endpoint id season-id)}) :body p/player-season-ranked-stats-parse)))