Closed Backxtar closed 1 year ago
Hello,
Thank you 😄 It's a good suggestion, I think I'll do the following :
health
, armor
and shields
in the /heroes/{hero_key}
endpoint. The data will come from a CSV file in the project, like maps. It should be easy to update for anybody in a PR (can be useful if I'm not available when there is an update). I'll add some information in order to guide those who would want to update it./heroes
endpoint, with a specific GET attribute (i'll share it in the dedicated PR).I'll keep you updated here 😉
yeah i really like it :) Here is a video from the app ill programming right now :) - will be available for iOS and Android. Link
Btw the video + thumbnail would be very nice :) - i would say the webm version is better than the mp4
Oh very nice app you have here, can't wait to try it ! When you'll publish it (and/or the source code), don't hesitate to share the link with me, I'll gladly add your project in the README if you're OK with it (🚀 Community projects section)
ye the code wont be official but its free 4 all :) so remeber herodata (health shield etc)
thumbnails and videos for the skills (from the offical website :) i can give you the links :))
Health, armor and shields are OK (dev in progress), and i'll take a look for the thumbnails and videos for the skills, I should be able to retrieve them directly, I'll keep you updated ;)
Ah nice :) so ill keep working on the profile / stats page and do the heroes / maps etc later :)
Btw: here is a screen of the profile page :) http://i.epvpimg.com/K0nNcab.png
I made the update about heroes HP and abilities videos in the last release : https://github.com/TeKrop/overfast-api/releases/tag/v2.15.0
You'll find the new data in hitpoints
and abilities[].video
fields, I'll let you check the updated documentation and an example with Ana :
I'll let this issue opened while I'll be working on exposing more data in the general /heroes
endpoint as discussed earlier 👍
Nice! There is one more thing i have to add. At the player stats summary for the heroes -> can u add a hero key for filtering the list? Cant filter the list for a specific hero because you dont have any unique key :)
i mean like this
"heroes": {
"ana": {
"key": "ana", <- this line is missing
"games_played": 37,
"time_played": 18032,
"winrate": 48.65,
"kda": 1.63,
"total": {
"eliminations": 206,
"assists": 142,
"deaths": 214,
"damage": 98563,
"healing": 190320
},
"average": {
"eliminations": 6.85,
"assists": 4.72,
"deaths": 7.12,
"damage": 3279.6,
"healing": 6332.74
}
}
}
Otherwise you cant filter the list for hero-data because you cant filter for any attribute specific for that hero :)
Also which timeformat is that: "time_played": 172937
?
At the player stats summary for the heroes -> can u add a hero key for filtering the list? Cant filter the list for a specific hero because you dont have any unique key :)
I don't understand your issue here 🤔 You should be able to use the key referencing the object in your code ("ana": {...}
), without me needing to add a key
in the object, I would find it superfluous 😅 Maybe I'm missing a point, don't hesitate to give me more precision if you think this is the case 👍
Also which timeformat is that: "time_played": 172937 ?
As stated in the introduction on the main documentation page, it's in seconds 😉
First of all can you create an endpoint where you can fetch all hero specific data with 1 api call? Atm i need to loop threw each hero to get the complete data. E.g. heroes/ana -> then heroes/ashe etc.
Finally, regarding this main topic, I'm starting to wonder if this is really necessary 🤔
Don't hesitate to give me some details and arguments, I will be happy to discuss about it 😄
my current status: https://streamable.com/dpbfl7
and no i cant search for the "key" because:
class Heroes {
DataBlueprint? ana;
DataBlueprint? ashe;
DataBlueprint? baptiste;
DataBlueprint? bastion;
DataBlueprint? brigitte;
DataBlueprint? cassidy;
DataBlueprint? dva;
DataBlueprint? doomfist;
DataBlueprint? echo;
DataBlueprint? lifeweaver; // <- This data is missing in stats summary
DataBlueprint? genji;
DataBlueprint? hanzo;
DataBlueprint? junkerQueen;
DataBlueprint? junkrat;
DataBlueprint? kiriko;
DataBlueprint? lucio;
DataBlueprint? mei;
DataBlueprint? mercy;
DataBlueprint? moira;
DataBlueprint? orisa;
DataBlueprint? pharah;
DataBlueprint? ramattra;
DataBlueprint? reaper;
DataBlueprint? reinhardt;
DataBlueprint? roadhog;
DataBlueprint? sigma;
DataBlueprint? soldier76;
DataBlueprint? sojourn;
DataBlueprint? sombra;
DataBlueprint? symmetra;
DataBlueprint? torbjorn;
DataBlueprint? tracer;
DataBlueprint? widowmaker;
DataBlueprint? winston;
DataBlueprint? wreckingBall;
DataBlueprint? zarya;
DataBlueprint? zenyatta;
}
They have all the same structure, i cant check for variable names :). I can check for null, but i need the key inside to get a reference to the heroes avatar etc from my other list :)
Btw. the lifeweaver stats are missing :)
Ah and no its not that terrible to make x calls to the api. i mean i fetch them async :) and without loading time i dont need a loading-screen 👯 . You dont need to make an extra endpoint for that :)
They have all the same structure, i cant check for variable names :). I can check for null, but i need the key inside to get a reference to the heroes avatar etc from my other list :)
Hmm 🤔 Why can't you check by variable name ? Isn't there another way for you to retrieve the JSON from the API and store the information ? Can't you just loop over the keys/properties + values ? 🤔
Also, I can see you have some values which are different from the ones exposed by the API, junkerQueen
instead of junker-queen
, soldier76
instead of soldier-76
, does it mean that you're defining the name somewhere, or is there some sort of conversion ? I don't know the language/framework you're using, but it seems weird that you don't have a way to use keys/properties from an object 😅 I find it superfluous to put it both as an object "key", and in the "key" property along with the statistics values 😅
Btw. the lifeweaver stats are missing :)
It means you didn't play Lifeweaver in QP or Ranked this season. If you have no stat on a specific hero, it's not here at all, that's why it's not displayed as required
in the documentation
Ah and no its not that terrible to make x calls to the api. i mean i fetch them async :) and without loading time i dont need a loading-screen 👯 . You dont need to make an extra endpoint for that :)
OK, thank you for your feedback, if it's working fine i'll not make an extra endpoint there, don't hesitate to tell me if you encounter any issue with the existing ones :)
Nah i cant filter for variable names (Got a list of off and need to loop threw it) - so i need to check data with a machting key (profilepic from herodata - ranked stats from other list | key: ana - ana for e.g.)
Also the webm format was not a good idea - mp4 is a better format but apple does not support webm yet 🤯
I mean something like
{
"name": "Ana", <-- name.toLowerCase() = key
"description": "One of the founding members of Overwatch, Ana uses her skills and expertise to defend her home and the people she cares for.",
"portrait": ["https://d15f34w2p8l1cc.cloudfront.net/overwatch/3429c394716364bbef802180e9763d04812757c205e1b4568bc321772096ed86.png"](https://d15f34w2p8l1cc.cloudfront.net/overwatch/3429c394716364bbef802180e9763d04812757c205e1b4568bc321772096ed86.png),
"role": "support",
"location": "Cairo, Egypt",
"hitpoints": {
"health": 200,
"shields": 0,
"armor": 0,
"total": 200
},
...
}
and in the ranked hero stats
"heroes": {
"ana": {
"key": "ana", <-- This key
"games_played": 56,
"time_played": 26889,
"winrate": 46.43,
"kda": 2.72,
"total": {
"eliminations": 435,
"assists": 282,
"deaths": 264,
"damage": 152088,
"healing": 354998
},
"average": {
"eliminations": 9.71,
"assists": 6.29,
"deaths": 5.89,
"damage": 3393.69,
"healing": 7921.41
}
},
...
}
Nah i cant filter for variable names (Got a list of off and need to loop threw it) - so i need to check data with a machting key (profilepic from herodata - ranked stats from other list | key: ana - ana for e.g.)
Add herokey to ranked stats
Also the webm format was not a good idea - mp4 is a better format but apple does not support webm yet 🤯
Use mp4 instead of webm (only Android supports webm atm.)
Some herodata is wrong
Wrecking-Ball has 700 hp (shield + armor)
Can you provide these two changes? :3 - i mean the wrecking ball is maybe just not updated yet on the page you getting the data from :)
With the mp4 video the heroes page is finished then :)
Also, I can see you have some values which are different from the ones exposed by the API, junkerQueen instead of junker-queen, soldier76 instead of soldier-76, does it mean that you're defining the name somewhere, or is there some sort of conversion ? I don't know the language/framework you're using, but it seems weird that you don't have a way to use keys/properties from an object 😅 I find it superfluous to put it both as an object "key", and in the "key" property along with the statistics values 😅
These are not the strings i get from the api, i convert the json to an array of objects :) - and objects cant be named with special letters. The values have just names :) but thats the problem :) i cant filter the list by object names, i only can loop threw it and check for a specific key :)
These are not the strings i get from the api, i convert the json to an array of objects :) - and objects cant be named with special letters. The values have just names :) but thats the problem :) i cant filter the list by object names, i only can loop threw it and check for a specific key :)
Hmm if you're doing some kind of conversion, you may have a solution : while doing the conversion from JSON ({"junker-queen": {...}}
) to an object named junkerQueen
, can't you add the "junker-queen" key into the object ? Or even before doing the conversion ?
Or if you're looking for a way to loop over attributes of an object in Swift (I guess you're using this language for Apple's ecosystem), here is an example of discussion on Stack Overflow which may help you : https://stackoverflow.com/questions/25463146/iterate-over-object-class-attributes-in-swift
You'll just have to add the property while looping over DataBlueprint list 🤔
Sorry for insisting on this, but as it's very simple to do it in other common languages I know (Python, JS, PHP, etc.), I don't understand why it wouldn't be possible with Swift which is quite a popular language, and I would be very surprised 😅 Also, I wouldn't want you to be blocked one day if you have to deal with another API for another project with a similar problematic, and the developer can't be reached as easily and/or the API is handled by a private company which will not do any change easily 🙈 So I'm trying to find solutions with you, as we're talking about data which is already in the returned response 😅
Also the webm format was not a good idea - mp4 is a better format but apple does not support webm yet 🤯
Ah 🙈 I updated the API with both formats, API users will be able to chose the one they prefer 😉
Wrecking-Ball has 700 hp (shield + armor)
You're right, thank you for the feedback, I just fixed it 👍 In fact the data is located in the project directly, I don't have an external source on which I can get this data easily 😅 You can find it here : https://github.com/TeKrop/overfast-api/blob/main/app/data/heroes_stats.csv
Hmm if you're doing some kind of conversion, you may have a solution : while doing the conversion from JSON ({"junker-queen": {...}}) to an object named junkerQueen, can't you add the "junker-queen" key into the object ? Or even before doing the conversion ? Or if you're looking for a way to loop over attributes of an object in Swift (I guess you're using this language for Apple's ecosystem), here is an example of discussion on Stack Overflow which may help you : https://stackoverflow.com/questions/25463146/iterate-over-object-class-attributes-in-swift You'll just have to add the property while looping over DataBlueprint list 🤔
Please just add the herokey to the herostats :) its really way easier to loop threw it. Otherwise i have this ugly function in there. Also can u convert the heroes section to a list? Would be way easier for all to convert it. Otherwise they have to do a list manually. The list is really important for an app. I need to build the pages dynamically. otherwise i have to set a fixed number of heros because i cant loop threw an object. Without a list i have to check every hero / 37 heroes ^^. Thats not smart.
class OWPlayerStats {
DataBlueprint? general;
Roles? roles;
Heroes? _heroes;
List<DataBlueprint> heroes = List<DataBlueprint>.empty(growable: true);
OWPlayerStats({this.general, this.roles});
OWPlayerStats.fromJson(Map<String, dynamic> json) {
general = json['general'] != null
? DataBlueprint.fromJson(json['general'])
: null;
roles = json['roles'] != null ? Roles.fromJson(json['roles']) : null;
_heroes = json['heroes'] != null ? Heroes.fromJson(json['heroes']) : null;
_loopHeroes();
_heroes = null;
}
void _loopHeroes() {
_addHeroToList(_heroes!.ana);
_addHeroToList(_heroes!.ashe);
_addHeroToList(_heroes!.baptiste);
_addHeroToList(_heroes!.bastion);
_addHeroToList(_heroes!.brigitte);
_addHeroToList(_heroes!.cassidy);
_addHeroToList(_heroes!.doomfist);
_addHeroToList(_heroes!.dva);
_addHeroToList(_heroes!.echo);
_addHeroToList(_heroes!.genji);
_addHeroToList(_heroes!.hanzo);
_addHeroToList(_heroes!.junkerQueen);
_addHeroToList(_heroes!.junkrat);
_addHeroToList(_heroes!.kiriko);
_addHeroToList(_heroes!.lifeweaver);
_addHeroToList(_heroes!.lucio);
_addHeroToList(_heroes!.mei);
_addHeroToList(_heroes!.mercy);
_addHeroToList(_heroes!.moira);
_addHeroToList(_heroes!.orisa);
_addHeroToList(_heroes!.pharah);
_addHeroToList(_heroes!.ramattra);
_addHeroToList(_heroes!.reaper);
_addHeroToList(_heroes!.reinhardt);
_addHeroToList(_heroes!.roadhog);
_addHeroToList(_heroes!.sigma);
_addHeroToList(_heroes!.sojourn);
_addHeroToList(_heroes!.soldier76);
_addHeroToList(_heroes!.sombra);
_addHeroToList(_heroes!.symmetra);
_addHeroToList(_heroes!.torbjorn);
_addHeroToList(_heroes!.tracer);
_addHeroToList(_heroes!.widowmaker);
_addHeroToList(_heroes!.winston);
_addHeroToList(_heroes!.wreckingBall);
_addHeroToList(_heroes!.zarya);
_addHeroToList(_heroes!.zenyatta);
}
void _addHeroToList(DataBlueprint? hero) {
if (hero != null) heroes.add(hero);
}
}
Json like this:
"heroes": [
{
"key": "ana",
"games_played": 57,
"time_played": 27369,
"winrate": 47.37,
"kda": 2.77,
"total": {
"eliminations": 459,
"assists": 290,
"deaths": 270,
"damage": 156057,
"healing": 357333
},
"average": {
"eliminations": 10.06,
"assists": 6.36,
"deaths": 5.92,
"damage": 3421.18,
"healing": 7833.67
}
},
{
...
}
]
Btw thumbnails and videos work like a charm :) Watch: https://streamable.com/9sy2on
In order to meet your needs :
key
in the object at the same level of games_played
, etc.I was curious and asked ChatGPT to give me a hand in order to convert the input provided by the API into the one you're expecting, and it answered to me this piece of Swift code which seems to be working (tested with Replit, an online IDE) :
import Foundation
let json = """
{
"heroes": {
"ana": {
"games_played": 1219,
"time_played": 570188,
"winrate": 46.92,
"kda": 2.42,
"total": {
"eliminations": 9622,
"assists": 7273,
"deaths": 6972,
"damage": 3341466,
"healing": 6460895
},
"average": {
"eliminations": 10.13,
"assists": 7.65,
"deaths": 7.34,
"damage": 3516.17,
"healing": 6798.7
}
},
"ashe": {
"games_played": 2,
"time_played": 950,
"winrate": 50.0,
"kda": 2.29,
"total": {
"eliminations": 32,
"assists": 0,
"deaths": 14,
"damage": 13873,
"healing": 0
},
"average": {
"eliminations": 20.21,
"assists": 0.0,
"deaths": 8.84,
"damage": 8761.89,
"healing": 0.0
}
}
}
}
"""
if let data = json.data(using: .utf8),
let jsonObj = try? JSONSerialization.jsonObject(with: data),
let heroes = (jsonObj as? [String: Any])?["heroes"] as? [String: Any] {
let heroList = heroes.map { (key, value) -> [String: Any] in
var hero = value as? [String: Any] ?? [:]
hero["key"] = key
return hero
}
let outputJSON: [String: Any] = ["heroes": heroList]
if let outputData = try? JSONSerialization.data(withJSONObject: outputJSON),
let outputString = String(data: outputData, encoding: .utf8) {
print(outputString)
}
}
I don't have any knowledge in Swift, so I guess there are cleaner ways to do the job, but at least it's working and you're not limited with the "ugly function" you have in your code. And it will work even if new heroes are coming into the API in the future :) Don't hesitate to tell me if it's working well for you on your dev environment ^^
Btw thumbnails and videos work like a charm :) Watch: https://streamable.com/9sy2on
Ooh very nice result you have here, good job 😄
In order to meet your needs :
- having the
key
in the object at the same level ofgames_played
, etc.- having a list instead of an object with hero keys
Yes and Yes (Having a list for the hero stats would make life way easier because you dont have allways the same amount on heroes you are playing) :)
I was curious and asked ChatGPT to give me a hand in order to convert the input provided by the API into the one you're expecting, and it answered to me this piece of Swift code which seems to be working (tested with Replit, an online IDE) :
I don't have any knowledge in Swift, so I guess there are cleaner ways to do the job, but at least it's working and you're not limited with the "ugly function" you have in your code. And it will work even if new heroes are coming into the API in the future :) Don't hesitate to tell me if it's working well for you on your dev environment ^^
Im not using swift :D im using dart and flutter for the app :) - because its cross plattform. Android and iOS.
Yes and Yes (Having a list for the hero stats would make life way easier because you dont have allways the same amount on heroes you are playing) :)
I guess this is more convenient in your case, but I'm not sure it always will for everyone. I had the choice when creating this endpoint, and I chose the other way. I know some people are already using this endpoint when looking at access logs, and no one told me it was not handy and that I should switch to a list 😅 I'm always trying to give the data in the most exploitable way, and then it's the responsability of the app/website developer to use the API as it's exposed and adapt : as long as all the needed data is here, I assume I've done my part 🤔
Im not using swift :D im using dart and flutter for the app :) - because its cross plattform. Android and iOS.
Ah I didn't know 🙈 Cross platform dev is a good choice 👍 Well then, I asked the same thing in Dart to ChatGPT and tested with Replit, here is a working piece of code which seems to be clean enough and will do the job 😉 You just have to add the dart:convert
dependency in your project if it's not already done.
import 'dart:convert';
void main() {
String jsonString = '''
{
"heroes": {
"ana": {
"games_played": 1219,
"time_played": 570188,
"winrate": 46.92,
"kda": 2.42,
"total": {
"eliminations": 9622,
"assists": 7273,
"deaths": 6972,
"damage": 3341466,
"healing": 6460895
},
"average": {
"eliminations": 10.13,
"assists": 7.65,
"deaths": 7.34,
"damage": 3516.17,
"healing": 6798.7
}
},
"ashe": {
"games_played": 2,
"time_played": 950,
"winrate": 50.0,
"kda": 2.29,
"total": {
"eliminations": 32,
"assists": 0,
"deaths": 14,
"damage": 13873,
"healing": 0
},
"average": {
"eliminations": 20.21,
"assists": 0.0,
"deaths": 8.84,
"damage": 8761.89,
"healing": 0.0
}
}
}
}
''';
Map<String, dynamic> jsonMap = json.decode(jsonString);
List<Map<String, dynamic>> heroesList = [];
jsonMap['heroes'].forEach((key, value) {
value['key'] = key;
heroesList.add(value);
});
Map<String, List<Map<String, dynamic>>> result = {'heroes': heroesList};
String resultString = json.encode(result);
print(resultString);
}
In general, as long as it's free, don't hesitate to use ChatGPT or equivalent AI tools to help you when you're blocked with some issues in your code for your personal projects, or when you're learning things related to a programming language. It's very powerful to have a start with a new language or even to have some leads on solving a problem. I shared with you some pieces of Swift and Dart codes, which took me no more than 5 min, even if I never learned how to use these languages 😅
Ahh thanks to you i got a solution :)
class OWPlayerStats {
DataBlueprint? general;
Roles? roles;
List<DataBlueprint>? heroes;
OWPlayerStats({this.general, this.roles, this.heroes});
OWPlayerStats.fromJson(Map<String, dynamic> json) {
general = json['general'] != null
? DataBlueprint.fromJson(json['general'])
: null;
roles = json['roles'] != null ? Roles.fromJson(json['roles']) : null;
heroes = json['heroes'] != null ? _getHeroes(json['heroes']) : null;
}
List<DataBlueprint> _getHeroes(Map<String, dynamic> json) {
List<DataBlueprint> heroes = List<DataBlueprint>.empty(growable: true);
json.forEach((key, value) {
DataBlueprint hero = DataBlueprint.fromJson(value);
hero.key = key;
heroes.add(hero);
});
return heroes;
}
}
Now its a dynamic list of my object :)
The key
is exactly the key from the heroes api endpoint?
Ahh thanks to you i got a solution :) Now its a dynamic list of my object :)
Nice solution you have there, you're welcome 😉 Sorry again for insisting on this, in the end we came up with a solution, and if some day you encounter a similar issue with another API, you'll know how to handle it 😄
The
key
is exactly the key from the heroes api endpoint ?
Yes exactly ! I'm using the same enumeration all across my code and the exposed endpoints 😉
Can I consider this issue as solved then ? I think that if you find out another issue anywhere else, it will be better to open a new issue rather than continuing comments here 🙈
Ye all good right now 👍
First of all - really nice api!
But can you provide some more informations about the heroes? First of all can you create an endpoint where you can fetch all hero specific data with 1 api call? Atm i need to loop threw each hero to get the complete data. E.g. heroes/ana -> then heroes/ashe etc.
Maybe an endpoint heroes/all would be nice.
I have created an external json with some more informations needed for the heroes. Would be really nice if this can be integraded into the normal heroes/all - heroes/ana request