1 module pubg.match;
2 
3 import std.stdio:writeln;
4 import std.file: write;
5 import pubg.request;
6 import std.json;
7 import std.conv: parse;
8 
9 class MatchAttributes
10 {
11 public:
12     this(JSONValue json)
13     {
14         this.json = json;
15     }
16     string getCreationDate()
17     {
18         return this.json["createdAt"].str;
19     }
20     int getDuration()
21     {
22         return cast(int)this.json["duration"].integer;
23     }
24     string getGameMode()
25     {
26         return this.json["gameMode"].str;
27     }
28     string getMapName()
29     {
30         return this.json["mapName"].str;
31     }
32     string getShardId()
33     {
34         return this.json["shardId"].str;
35     }
36     string getTitleId()
37     {
38         return this.json["titleId"].str;
39     }
40 private:
41     JSONValue json;
42 }
43 
44 class MatchAssets
45 {
46 public:
47     this(JSONValue json)
48     {
49         this.json = json;
50     }
51     string getId()
52     {
53         return this.json["data"].array[0]["id"].str;
54     }
55 private:
56     JSONValue json;
57 }
58 
59 class MatchRosters
60 {
61 public:
62     this(JSONValue json)
63     {
64         this.json = json;
65     }
66     string[] getRosterIds()
67     {
68         auto data = this.json["data"].array;
69         string[] ret;
70         foreach (j; data)
71         {
72             if (j["type"].str == "roster")
73                 ret ~= j["id"].str;
74         }
75         return ret;
76     }
77 private:
78     JSONValue json;
79 }
80 
81 class MatchRelationships
82 {
83 public:
84     this(JSONValue json)
85     {
86         this.json = json;
87     }
88     MatchAssets getAssets()
89     {
90         return new MatchAssets(this.json["assets"]);
91     }
92     MatchRosters getRosters()
93     {
94         return new MatchRosters(this.json["rosters"]);
95     }
96 private:
97     JSONValue json;
98 }
99 
100 class MatchLinks
101 {
102 public:
103     this(JSONValue json)
104     {
105         this.json = json;
106     }
107     string getSchema()
108     {
109         return this.json["schema"].str;
110     }
111     string getSelf()
112     {
113         return this.json["self"].str;
114     }
115 private:
116     JSONValue json;
117 }
118 
119 class MatchData
120 {
121 public:
122     this(JSONValue json)
123     {
124         this.json = json;
125     }
126     MatchAttributes getAttributes()
127     {
128         return new MatchAttributes(this.json["attributes"]);
129     }
130     MatchRelationships getRelationships()
131     {
132         return new MatchRelationships(this.json["relationships"]);
133     }
134     string getType()
135     {
136         return this.json["type"].str;
137     }
138     string getId()
139     {
140         return this.json["id"].str;
141     }
142 private:
143     JSONValue json;
144 }
145 
146 class MatchParticipant
147 {
148 public:
149     this(JSONValue json)
150     {
151         this.json = json;
152     }
153     string getActor()
154     {
155         return this.json["actor"].str;
156     }
157     string getShardId()
158     {
159         return this.json["shardId"].str;
160     }
161     int getDBNOs()
162     {
163         return cast(int)this.json["attributes"]["stats"]["DBNOs"].integer;
164     }
165     int getAssists()
166     {
167         return cast(int)this.json["attributes"]["stats"]["assists"].integer;
168     }
169     int getBoosts()
170     {
171         return cast(int)this.json["attributes"]["stats"]["boosts"].integer;
172     }
173     int getDamageDealt()
174     {
175         return cast(int)this.json["attributes"]["stats"]["damageDealt"].integer;
176     }
177     string getDeathType()
178     {
179         return this.json["attributes"]["stats"]["deathType"].str;
180     }
181     int getHeadshotKills()
182     {
183         return cast(int)this.json["attributes"]["stats"]["headShotKills"].integer;
184     }
185     int getHeals()
186     {
187         return cast(int)this.json["attributes"]["stats"]["heals"].integer;
188     }
189     int getKillPlace()
190     {
191         return cast(int)this.json["attributes"]["stats"]["killPlace"].integer;
192     }
193     int getKillPoints()
194     {
195         return cast(int)this.json["attributes"]["stats"]["killPoints"].integer;
196     }
197     float getKillPointsDelta()
198     {
199         return cast(float)this.json["attributes"]["stats"]["killPointsDelta"].floating;
200     }
201     int getKillStreaks()
202     {
203         return cast(int)this.json["attributes"]["stats"]["killPoints"].integer;
204     }
205     int getKills()
206     {
207         return cast(int)this.json["attributes"]["stats"]["kills"].integer;
208     }
209     int getLastKillPoints()
210     {
211         return cast(int)this.json["attributes"]["stats"]["lastKillPoints"].integer;
212     }
213     int getLastWinPoints()
214     {
215         return cast(int)this.json["attributes"]["stats"]["lastWinPoints"].integer;
216     }
217     int getLongestKill()
218     {
219         return cast(int)this.json["attributes"]["stats"]["longestKill"].integer;
220     }
221     int getMostDamage()
222     {
223         return cast(int)this.json["attributes"]["stats"]["longestKill"].integer;
224     }
225     string getName()
226     {
227         return this.json["attributes"]["stats"]["name"].str;
228     }
229     string getPlayerId()
230     {
231         return this.json["attributes"]["stats"]["playerId"].str;
232     }
233     int getRevives()
234     {
235         return cast(int)this.json["attributes"]["stats"]["revives"].integer;
236     }
237     int getRideDistance()
238     {
239         return cast(int)this.json["attributes"]["stats"]["rideDistance"].integer;
240     }
241     int getRoadKills()
242     {
243         return cast(int)this.json["attributes"]["stats"]["roadKills"].integer;
244     }
245     int getTeamKills()
246     {
247         return cast(int)this.json["attributes"]["stats"]["teamKills"].integer;
248     }
249     int getTimeSurvived()
250     {
251         return cast(int)this.json["attributes"]["stats"]["timeSurvived"].integer;
252     }
253     int getVehicleDestroys()
254     {
255         return cast(int)this.json["attributes"]["stats"]["vehicleDestroys"].integer;
256     }
257     float getWalkDistance()
258     {
259         return cast(float)this.json["attributes"]["stats"]["walkDistance"].floating;
260     }
261     int getWeaponsAcquired()
262     {
263         return cast(int)this.json["attributes"]["stats"]["weaponsAcquired"].integer;
264     }
265     int getWinPlace()
266     {
267         return cast(int)this.json["attributes"]["stats"]["winPlace"].integer;
268     }
269     int getWinPoints()
270     {
271         return cast(int)this.json["attributes"]["stats"]["winPoints"].integer;
272     }
273     float getWinPointsDelta()
274     {
275         return cast(float)this.json["attributes"]["stats"]["winPointsDelta"].floating;
276     }
277     override int opCmp(Object other)
278     {
279         if (other is null || this is null)
280             return 0;
281         if (this.getKills() == (cast(MatchParticipant)other).getKills())
282             return 0;
283         return this.getKills() -(cast(MatchParticipant)other).getKills();
284     }
285 private:
286     JSONValue json;
287 }
288 
289 class MatchRoster
290 {
291 public:
292     this(JSONValue json)
293     {
294         this.json = json;
295     }
296     string getShardId()
297     {
298         return this.json["attributes"]["shardId"].str;
299     }
300     int getRank()
301     {
302         return cast(int)this.json["attributes"]["stats"]["rank"].integer;
303     }
304     int getTeamId()
305     {
306         return cast(int)this.json["attributes"]["stats"]["teamId"].integer;
307     }
308     string getId()
309     {
310         return this.json["id"].str;
311     }
312     bool getWon()
313     {
314         auto s = this.json["attributes"]["won"].str;
315         return parse!bool(s);
316     }
317     string[] getParticipantIds()
318     {
319         string[] ret;
320         foreach (j; this.json["relationships"]["participants"]["data"].array)
321         {
322             if (j["type"].str == "participant")
323                 ret ~= j["id"].str;
324         }
325         return ret;
326     }
327 private:
328     JSONValue json;
329 }
330 
331 class MatchIncluded
332 {
333 public:
334     this(JSONValue json)
335     {
336         this.json = json;
337     }
338     MatchParticipant[] getParticipants()
339     {
340         MatchParticipant[] stats;
341         auto data = this.json.array;
342         foreach(j; data)
343         {
344             if (j["type"].str == "participant")
345             {
346                 stats ~= new MatchParticipant(j);
347             }
348         }
349         return stats;
350     }
351     MatchRoster[] getRosters()
352     {
353         MatchRoster[] rosters;
354         auto data = this.json.array;
355         foreach(j; data)
356         {
357             if (j["type"].str == "roster")
358             {
359                 rosters ~= new MatchRoster(j);
360             }
361         }
362         return rosters;
363     }
364 private:
365     JSONValue json;
366 }
367 
368 class Match
369 {
370 public:
371     this(char[] content)
372     {
373         this.json = parseJSON(cast(string)content);
374         //auto data = this.json["included"];
375         //writeln(this.json.toPrettyString());
376         //write("test.json", this.json.toPrettyString());
377     }
378     this(JSONValue json)
379     {
380         this.json = json;
381     }
382     MatchData getData()
383     {
384         return new MatchData(this.json["data"]);
385     }
386     MatchIncluded getIncluded()
387     {
388         return new MatchIncluded(this.json["included"]);
389     }
390 private:
391     JSONValue json;
392 }
393 
394 class MatchRequest : ObjectRequest
395 {
396 public:
397     this(string region)
398     {
399         super("https://api.playbattlegrounds.com/shards/" ~ region ~ "/");
400     }
401     Match getMatch(string matchID)
402     {
403         return new Match(this.request("matches/" ~ matchID));
404     }
405 }