diff --git a/lib/api/community/leaderboard.ml b/lib/api/community/leaderboard.ml index 4441f46..5bb6b88 100644 --- a/lib/api/community/leaderboard.ml +++ b/lib/api/community/leaderboard.ml @@ -26,3 +26,33 @@ let get_avatar ?(profile_ids = []) game domain send = Lwt.return @@ Some model | None -> Lwt.return None) ;; + +let get_leaderboard_2 + ?(sortby = Models.Stub.Leaderboard_sorting.ByRating) + ?(platform = "PC_STEAM") + ?(leaderboard_id = 3) + ?(start = 0) + ?(count = 100) + game + domain + send + = + let base_url = Uri.make ~scheme:"https" ~host:domain ~path:"/community/leaderboard/getLeaderboard2" () in + let url = + Uri.with_query' + base_url + [ "title", Data.Game.to_str game + ; "sortBy", string_of_int @@ Models.Stub.Leaderboard_sorting.to_int sortby + ; "platform", platform + ; "leaderboard_id", string_of_int leaderboard_id + ; "start", string_of_int start + ; "count", string_of_int count + ] + in + let* json = send url in + match json with + | Some j -> + let model = Models.Response.Community.Leaderboard2.from_json j in + Lwt.return @@ Some model + | None -> Lwt.return None +;; diff --git a/lib/models/response/community/leaderboard2.ml b/lib/models/response/community/leaderboard2.ml new file mode 100644 index 0000000..2c8f886 --- /dev/null +++ b/lib/models/response/community/leaderboard2.ml @@ -0,0 +1,24 @@ +type t = + { result : Stub.Response.t + ; stat_groups : Stub.Stat_group.t list + ; leaderboard_stats : Stub.Leaderboard_stat.t list + ; rank_total : int + } + +let to_json l = + `Assoc + [ "result", Stub.Response.to_json l.result + ; "statGroups", `List (List.map Stub.Stat_group.to_json l.stat_groups) + ; "leaderboardStats", `List (List.map Stub.Leaderboard_stat.to_json l.leaderboard_stats) + ; "rankTotal", `Int l.rank_total + ] +;; + +let from_json json = + let open Yojson.Basic.Util in + { result = json |> member "result" |> Stub.Response.from_json + ; stat_groups = json |> member "statGroups" |> to_list |> List.map Stub.Stat_group.from_json + ; leaderboard_stats = json |> member "leaderboardStats" |> to_list |> List.map Stub.Leaderboard_stat.from_json + ; rank_total = json |> member "rankTotal" |> to_int + } +;; diff --git a/lib/models/stub/leaderboard_sorting.ml b/lib/models/stub/leaderboard_sorting.ml new file mode 100644 index 0000000..ed024f8 --- /dev/null +++ b/lib/models/stub/leaderboard_sorting.ml @@ -0,0 +1,12 @@ +type t = + | NumberOfWins + | ByRating + +let from_int i = + match i with + | 0 -> NumberOfWins + | 1 -> ByRating + | _ -> failwith (Printf.sprintf "Invalid join policy integer: %d" i) +;; + +let to_int = function NumberOfWins -> 0 | ByRating -> 1 diff --git a/lib/models/stub/leaderboard_stat.ml b/lib/models/stub/leaderboard_stat.ml new file mode 100644 index 0000000..706090b --- /dev/null +++ b/lib/models/stub/leaderboard_stat.ml @@ -0,0 +1,63 @@ +type t = + { statgroup_id : int + ; leaderboard_id : int + ; wins : int + ; losses : int + ; streak : int + ; disputes : int + ; drops : int + ; rank : int + ; ranktotal : int + ; ranklevel : int + ; rating : int + ; regionrank : int + ; regionranktotal : int + ; lastmatchdate : int + ; highestrank : int + ; highestranklevel : int + ; highestrating : int + } + +let to_json sg = + `Assoc + [ "statgroup_id", `Int sg.statgroup_id + ; "leaderboard_id", `Int sg.leaderboard_id + ; "wins", `Int sg.wins + ; "losses", `Int sg.losses + ; "streak", `Int sg.streak + ; "disputes", `Int sg.disputes + ; "drops", `Int sg.drops + ; "rank", `Int sg.rank + ; "ranktotal", `Int sg.ranktotal + ; "ranklevel", `Int sg.ranklevel + ; "rating", `Int sg.rating + ; "regionrank", `Int sg.regionrank + ; "regionranktotal", `Int sg.regionranktotal + ; "lastmatchdate", `Int sg.lastmatchdate + ; "highestrank", `Int sg.highestrank + ; "highestranklevel", `Int sg.highestranklevel + ; "highestrating", `Int sg.highestrating + ] +;; + +let from_json json = + let open Yojson.Basic.Util in + { statgroup_id = json |> member "statgroup_id" |> to_int + ; leaderboard_id = json |> member "leaderboard_id" |> to_int + ; wins = json |> member "wins" |> to_int + ; losses = json |> member "losses" |> to_int + ; streak = json |> member "streak" |> to_int + ; disputes = json |> member "disputes" |> to_int + ; drops = json |> member "drops" |> to_int + ; rank = json |> member "rank" |> to_int + ; ranktotal = json |> member "ranktotal" |> to_int + ; ranklevel = json |> member "ranklevel" |> to_int + ; rating = json |> member "rating" |> to_int + ; regionrank = json |> member "regionrank" |> to_int + ; regionranktotal = json |> member "regionranktotal" |> to_int + ; lastmatchdate = json |> member "lastmatchdate" |> to_int + ; highestrank = json |> member "highestrank" |> to_int + ; highestranklevel = json |> member "highestranklevel" |> to_int + ; highestrating = json |> member "highestrating" |> to_int + } +;; diff --git a/lib/models/stub/stat_group.ml b/lib/models/stub/stat_group.ml new file mode 100644 index 0000000..c40155d --- /dev/null +++ b/lib/models/stub/stat_group.ml @@ -0,0 +1,24 @@ +type t = + { id : int + ; name : string + ; type_ : int + ; members : Avatar.t list + } + +let to_json s = + `Assoc + [ "id", `Int s.id + ; "name", `String s.name + ; "type", `Int s.type_ + ; "members", `List (List.map Avatar.to_json s.members) + ] +;; + +let from_json json = + let open Yojson.Basic.Util in + { id = json |> member "id" |> to_int + ; name = json |> member "name" |> to_string + ; type_ = json |> member "type" |> to_int + ; members = json |> member "members" |> to_list |> List.map Avatar.from_json + } +;; diff --git a/tests/res/getLeaderBoard2.json b/tests/res/getLeaderBoard2.json new file mode 100644 index 0000000..c94037b --- /dev/null +++ b/tests/res/getLeaderBoard2.json @@ -0,0 +1,497 @@ +{ + "result": { + "code": 0, + "message": "SUCCESS" + }, + "statGroups": [ + { + "id": 1178783, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 1389164, + "name": "/steam/76561198240662592", + "alias": "The Illusionist", + "personal_statgroup_id": 1178783, + "xp": 4649, + "level": 2, + "leaderboardregion_id": 0, + "country": "sk" + } + ] + }, + { + "id": 4961990, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 6440047, + "name": "/steam/76561198067238361", + "alias": "Blackheart", + "personal_statgroup_id": 4961990, + "xp": 2080, + "level": 2, + "leaderboardregion_id": 0, + "country": "de" + } + ] + }, + { + "id": 3381111, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 4012008, + "name": "/steam/76561198294644972", + "alias": "chaos_2_win", + "personal_statgroup_id": 3381111, + "xp": 4624, + "level": 2, + "leaderboardregion_id": 0, + "country": "de" + } + ] + }, + { + "id": 6138669, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 10921131, + "name": "/steam/76561199383684361", + "alias": "modern clix", + "personal_statgroup_id": 6138669, + "xp": 1256, + "level": 1, + "leaderboardregion_id": 4, + "country": "ar" + } + ] + }, + { + "id": 9406284, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 15391105, + "name": "/steam/76561199516701491", + "alias": "momo", + "personal_statgroup_id": 9406284, + "xp": 160, + "level": 1, + "leaderboardregion_id": 3, + "country": "us" + } + ] + }, + { + "id": 392817, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 541127, + "name": "/steam/76561198084061002", + "alias": "RmcooTheHater_", + "personal_statgroup_id": 392817, + "xp": 2426, + "level": 2, + "leaderboardregion_id": 0, + "country": "lt" + } + ] + }, + { + "id": 487079, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 628503, + "name": "/steam/76561198036586732", + "alias": "Valas", + "personal_statgroup_id": 487079, + "xp": 7210, + "level": 3, + "leaderboardregion_id": 0, + "country": "fi" + } + ] + }, + { + "id": 5566952, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 9555704, + "name": "/steam/76561199242460562", + "alias": "Ganji", + "personal_statgroup_id": 5566952, + "xp": 5043, + "level": 2, + "leaderboardregion_id": 0, + "country": "de" + } + ] + }, + { + "id": 39756, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 239238, + "name": "/steam/76561198113285862", + "alias": "Fedex", + "personal_statgroup_id": 39756, + "xp": 2672, + "level": 2, + "leaderboardregion_id": 4, + "country": "ar" + } + ] + }, + { + "id": 53707, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 250103, + "name": "/steam/76561198061054857", + "alias": "_Hallis", + "personal_statgroup_id": 53707, + "xp": 3129, + "level": 2, + "leaderboardregion_id": 0, + "country": "gb" + } + ] + }, + { + "id": 1410821, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 1629889, + "name": "/steam/76561198354278976", + "alias": "[KGB] Alive", + "personal_statgroup_id": 1410821, + "xp": 4219, + "level": 2, + "leaderboardregion_id": 4, + "country": "br" + } + ] + }, + { + "id": 61573, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 256338, + "name": "/steam/76561198007187809", + "alias": "Running", + "personal_statgroup_id": 61573, + "xp": 5491, + "level": 2, + "leaderboardregion_id": 0, + "country": "de" + } + ] + }, + { + "id": 4317687, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 5416282, + "name": "/steam/76561199159318317", + "alias": "Smurf_zZ", + "personal_statgroup_id": 4317687, + "xp": 1057, + "level": 1, + "leaderboardregion_id": 4, + "country": "ar" + } + ] + }, + { + "id": 5687009, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 9873875, + "name": "/steam/76561199260891276", + "alias": "抖音 肥龙", + "personal_statgroup_id": 5687009, + "xp": 752, + "level": 1, + "leaderboardregion_id": 2, + "country": "cn" + } + ] + }, + { + "id": 6131004, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 10892656, + "name": "/steam/76561199383015281", + "alias": "loner", + "personal_statgroup_id": 6131004, + "xp": 1108, + "level": 1, + "leaderboardregion_id": 0, + "country": "ru" + } + ] + }, + { + "id": 1056456, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 1252385, + "name": "/steam/76561199014766072", + "alias": "Carpincho", + "personal_statgroup_id": 1056456, + "xp": 1562, + "level": 1, + "leaderboardregion_id": 4, + "country": "ar" + } + ] + }, + { + "id": 427697, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 573282, + "name": "/steam/76561198411901312", + "alias": "LACA | Terz", + "personal_statgroup_id": 427697, + "xp": 5579, + "level": 3, + "leaderboardregion_id": 0, + "country": "de" + } + ] + }, + { + "id": 619706, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 757886, + "name": "/steam/76561198112235172", + "alias": "VN_DarK_KnighT_", + "personal_statgroup_id": 619706, + "xp": 2534, + "level": 2, + "leaderboardregion_id": 3, + "country": "mx" + } + ] + }, + { + "id": 3465945, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 4132074, + "name": "/steam/76561199071416069", + "alias": "TRM", + "personal_statgroup_id": 3465945, + "xp": 3742, + "level": 2, + "leaderboardregion_id": 0, + "country": "ch" + } + ] + }, + { + "id": 796646, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 945852, + "name": "/steam/76561198075555979", + "alias": "Lucky_zZ", + "personal_statgroup_id": 796646, + "xp": 2504, + "level": 2, + "leaderboardregion_id": 4, + "country": "ar" + } + ] + }, + { + "id": 3010544, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 3320450, + "name": "/steam/76561199086370769", + "alias": "Ciskhan", + "personal_statgroup_id": 3010544, + "xp": 1188, + "level": 1, + "leaderboardregion_id": 0, + "country": "fr" + } + ] + }, + { + "id": 3318781, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 3884287, + "name": "/steam/76561199101842491", + "alias": "DaddySt4rk", + "personal_statgroup_id": 3318781, + "xp": 1562, + "level": 1, + "leaderboardregion_id": 4, + "country": "br" + } + ] + }, + { + "id": 2185744, + "name": "", + "type": 1, + "members": [ + { + "profile_id": 2444511, + "name": "/steam/76561199050196526", + "alias": "Gabi", + "personal_statgroup_id": 2185744, + "xp": 6116, + "level": 3, + "leaderboardregion_id": 4, + "country": "br" + } + ] + } + ], + "leaderboardStats": [ + { + "statgroup_id": 527797, + "leaderboard_id": 3, + "wins": 1902, + "losses": 1085, + "streak": 8, + "disputes": 0, + "drops": 12, + "rank": 1, + "ranktotal": 46501, + "ranklevel": 1, + "rating": 2802, + "regionrank": -1, + "regionranktotal": -1, + "lastmatchdate": 1712577123, + "highestrank": 1, + "highestranklevel": 1, + "highestrating": 2802 + }, + { + "statgroup_id": 297, + "leaderboard_id": 3, + "wins": 3053, + "losses": 1246, + "streak": 1, + "disputes": 0, + "drops": 34, + "rank": 2, + "ranktotal": 46501, + "ranklevel": 1, + "rating": 2763, + "regionrank": -1, + "regionranktotal": -1, + "lastmatchdate": 1712593321, + "highestrank": 1, + "highestranklevel": 1, + "highestrating": 2919 + }, + { + "statgroup_id": 273, + "leaderboard_id": 3, + "wins": 2042, + "losses": 1165, + "streak": -4, + "disputes": 0, + "drops": 24, + "rank": 3, + "ranktotal": 46501, + "ranklevel": 1, + "rating": 2733, + "regionrank": -1, + "regionranktotal": -1, + "lastmatchdate": 1712252663, + "highestrank": 1, + "highestranklevel": 1, + "highestrating": 2839 + }, + { + "statgroup_id": 1137, + "leaderboard_id": 3, + "wins": 1457, + "losses": 628, + "streak": 4, + "disputes": 0, + "drops": 9, + "rank": 4, + "ranktotal": 46501, + "ranklevel": 1, + "rating": 2714, + "regionrank": -1, + "regionranktotal": -1, + "lastmatchdate": 1712548529, + "highestrank": 3, + "highestranklevel": 1, + "highestrating": 2752 + }, + { + "statgroup_id": 173507, + "leaderboard_id": 3, + "wins": 2553, + "losses": 1143, + "streak": 13, + "disputes": 0, + "drops": 48, + "rank": 5, + "ranktotal": 46501, + "ranklevel": 1, + "rating": 2692, + "regionrank": -1, + "regionranktotal": -1, + "lastmatchdate": 1712550125, + "highestrank": 1, + "highestranklevel": 1, + "highestrating": 2797 + } + ], + "rankTotal": 46501 +} diff --git a/tests/test.ml b/tests/test.ml index c638a1f..e79b7b4 100644 --- a/tests/test.ml +++ b/tests/test.ml @@ -17,6 +17,10 @@ let () = Test_cases.Api.test_get_community_events ()) ; Alcotest_lwt.test_case "/community/leaderboard/GetAvailableLeaderboards" `Quick (fun _ () -> Test_cases.Api.test_get_leaderboards ()) + ; Alcotest_lwt.test_case "/community/leaderboard/GetAvatarStatForProfile" `Quick (fun _ () -> + Test_cases.Api.test_get_avatar_stat ()) + ; Alcotest_lwt.test_case "/community/leaderboard/getLeaderBoard2.json" `Quick (fun _ () -> + Test_cases.Api.test_get_leaderboard2 ()) ; Alcotest_lwt.test_case "invalid json" `Quick (fun _ () -> Test_cases.Api.test_invalid ()) ] ) ; ( "query" diff --git a/tests/test_cases/api.ml b/tests/test_cases/api.ml index e58c35a..f37f7a7 100644 --- a/tests/test_cases/api.ml +++ b/tests/test_cases/api.ml @@ -93,6 +93,16 @@ let test_get_avatar_stat () = | None -> Lwt.fail_with "Expected Some but got None" ;; +let test_get_leaderboard2 () = + let requester = Mock.Json_file.create_requester "getLeaderBoard2.json" in + let client = Client.create "aoe-api.worldsedgelink.com" Data.Game.Age2 in + let endpoint = Api.Community.Leaderboard.get_leaderboard_2 in + Client.get endpoint client ~requester + >>= function + | Some r -> Lwt.return @@ Alcotest.(check int) "Id [0] was correct" 1178783 (List.nth r.stat_groups 0).id + | None -> Lwt.fail_with "Expected Some but got None" +;; + let test_invalid () = let endpoints = [ Api.Community.News.get ] in Lwt_list.iter_s (fun endpoint -> Util.request_with_file_throw endpoint) endpoints