For /v1, I used to have a single class per item type to hold type-specific item details.
Statically typed languages like C# do not allow “item.details” objects to take on different types according to the value of “item.type”.
For /v2, I need to rethink my design so that every possible item detail fits into a single class hierarchy.
Is anyone trying to do the same thing? Did you run into any problems with things like duplicate property names meaning different things for different item types?
edit
Does anyone use JSON schema validation? Is there a way to generate an aggregate schema from a number of different json documents? It would be interesting to see a tool that loops through all 38k items, then outputs a complete schema that describes all possible objects and properties.
(edited by StevenL.3761)
The error code is useful to determine which parameter was invalid.
10 = invalid identifier
90 = invalid language
You could then use that information to do things like display localized error information, which is useful because error responses are always in English regardless of the given ‘lang’ parameter.
What? Sure it’s a lot more ugly and verbose than “Ticker”:“IBM”, but if you want to go with XML then you have to go all the way man.
V2, now featuring maximum code reuse (by reusing the existing XSI namespace):
<Ticker xsi:type="json:string">IBM</Ticker>
(edited by StevenL.3761)
That looks pretty bad for an IBM product. I mean, “name” attributes to represent the name of the tag? Really?
It would have made more sense if they did this instead:
<Ticker json:type="string">IBM</Ticker>
Maybe I should work for IBM.
Forget about /v1, show us the numbers for /v2/items. The new APIs seem fast enough to not require asynchronous code, but I’m curious to see how far it can be pushed.
I’m PRETTY sure this looks wrong: https://api.guildwars2.com/v2/items/21092
Shouldn’t that ‘upgrade_component’ property instead be a ‘details’ property?
It’s so fast. :O
Seems like a number of other bugs were fixed as well. Nice work!
(edited by StevenL.3761)
How many requests out of 1000 does it send and post-process at a time? Would you be able to queue up all 1000 requests at the same time, then handle each one as it completes?
My understanding is that the total duration should approach the sum of (the time it takes to queue all requests) plus (the time of the slowest HTTP query). How does it still take over a minute? (honest question)
(edited by StevenL.3761)
I’m a little paranoid about the build number changing while I’m updating my database. My workflow now is to get the build number, then retrieve a batch of items, then verify that the build number hasn’t changed. Only if the build hasn’t changed can I be sure that each item was assigned the correct build identifier. If it did change, I have to discard that batch.
I could be mistaken, but doesn’t that refer to its chance of spawning? Meaning that the event start time is fixed, but it may or may not start depending on a roll of the dice.
Feature request: could you add a response header ‘X-Build’ that represents the current game build number?
Aren’t the dry top events on a fixed schedule though? I saw someone post a time table on reddit a while ago.
Don’t worry about how long it takes to populate a database. You only have to do it once for the lifetime of the installation.
Wrong. Do you know how often even the names of items change? There’s some more languages than just english. Also, if you want to offer an extended search, you need to run an updater after every new build. There’s a reason why so many people asking for a list of changed item ids for each patch.
While the updater is updating the database, the search engine can still use the (partially) outdated data. The real problem is that right after installing the app, the updater hasn’t had a chance to bring the database up to date. So any given search would return 0 results until enough time has elapsed to populate the database.
Don’t worry about how long it takes to populate a database. You only have to do it once for the lifetime of the installation.
Lazy solution: create a database table with just 4 columns:
- item_id
- build_id
- language
- name
Then, create a background service that periodically checks for new item identifiers, and also keeps existing items up-to-date based on their build_id. The end result is a searchable index of items that is updated regularly.
You can decide to add additional columns based on how complicated your search engine should be: item_rarity, level, description (…).
For everything that isn’t going to be used by your search engine, do use the item_details.json API.
It looks to me as if these items are not supposed to be listed on the trading post. I converted some of the identifiers to chat links and pasted them in-game to see what item they correspond to. Items include things like “Cinematic Weapon Sword Charr”.
[&AgGOIwAA]
[&AgGjPQAA]
[&AgFhSQAA]
[&AgEoSgAA]
[&AgFLWgAA]
[&AgFPWgAA]
[&AgFgYQAA]
[&AgF1YQAA]
[&AgF/ZAAA]
[&AgGQZAAA]
[&AgGSZAAA]
[&AgGVZAAA]
[&AgGXZAAA]
[&AgFKcgAA]
[&AgEAdQAA]
[&AgEIdQAA]
[&AgEMdQAA]
[&AgEWdQAA]
[&AgGJeQAA]
[&AgGQeQAA]
[&AgGUeQAA]
[&AgGXeQAA]
[&AgGaeQAA]
[&AgGbeQAA]
[&AgGceQAA]
[&AgGdeQAA]
[&AgGfeQAA]
[&AgGgeQAA]
[&AgGheQAA]
[&AgGjeQAA]
[&AgGkeQAA]
[&AgGoeQAA]
[&AgGpeQAA]
[&AgG/eQAA]
[&AgHAeQAA]
[&AgHBeQAA]
[&AgHHeQAA]
[&AgHKeQAA]
[&AgECfgAA]
[&AgE1jgAA]
[&AgE3jgAA]
(edited by StevenL.3761)
Oooh I had no idea that nodejs works with IIS.
/commerce/listings only returns identifiers for items that are currently listed on the trading post. That explains why there are well over 15000 identifiers missing from the listing service.
What it doesn’t expain is why there are item identifiers in the listing service that are not in the items.json service?!
example:
https://api.guildwars2.com/v2/commerce/listings/9102
https://api.guildwars2.com/v1/item_details.json?item_id=9102
edit
Mystery solved. You can place bids for that item on the trading post, but nobody actually has it. Only discovered items appear in the items service.
(edited by StevenL.3761)
/prices is more useful for viewing by humans. You have to consider that people have a reading speed of just a few bytes per second (at 1 byte per character for UTF-8 encoded text). So live data is no longer live data by the time they reach the bottom of the page.
Is the public API written in .NET? You might be able to get better performance if you use Task.WhenAny() to process requests as soon as they complete. Waiting for all requests to complete before handling their response means wasted CPU time. Client applications will benefit as well if they support streaming JSON while it is still being created.
(edited by StevenL.3761)
I’ve always wanted to know why an item’s combat attributes is a collection instead of an object. Don’t you store each attribute as a separate table column?
Can items have multiple inherent attributes of the same type? Even if so, why not add them together?
To clarify, this would make more sense to me:
"attributes": {
"Power": 33,
"Precision" : 33,
"Toughness" : 33,
"Vitality : 33,
"Healing" : 33,
"ConditionDamage" : 33,
"CritDamage" : 33
}
(edited by StevenL.3761)
Will the json schema for item details change at all? Or will it be the same as v1, but with added support for bulk requests and pagination?
You can still use v1 for now. The data that v2 will return should be the same. Only the response format will be different. Consider converting incoming response data to custom class layouts that are reusable for v2 when that becomes available.
I found the quaggan API very useful for testing different API options. My code had full support for /v2 request syntax by the time that the commerce services were enabled. I’m a happy Quaggan.
(edited by StevenL.3761)
I’ll put in multiple layers of settings. From high to low priority : user defined language -> Local.dat language (if file is present and in a known format) -> system language (if supported) -> default language (English).
Still need to figure out the format first. It’s more complicated than I thought at first.
(edited by StevenL.3761)
So: i’d say you can’t without violating the EULA. Since GW2 doesn’t store the settings in the windows registry but most likely in the /appdata/roaming/Guild Wars 2/Local.dat. So you’d have to find the setting in there or might hook into the game to find out. (But i guess you know that anyway)
Actually I didn’t know that, but I’ll look into it. If Local.dat is really where the language setting is stored, I should be able to find it by checking which bytes change when I change my language setting.
edit : thanks, it worked.
(edited by StevenL.3761)
So that brings me back to my original question: can I detect the user’s in-game language setting somehow? That way, they can set my app’s language by changing their in-game language. And it will always be a valid value.
Why shouldn’t I detect the system language in order to provide a better user experience?
(zh is a valid language code for v2, but not v1.)
It does make sense. Observe the differences between the response data for all of these:
https://api.guildwars2.com/v1/event_names.json
https://api.guildwars2.com/v1/event_names.json?lang=en
https://api.guildwars2.com/v1/event_names.json?lang=de
https://api.guildwars2.com/v1/event_names.json?lang=ru
https://api.guildwars2.com/v1/event_names.json?lang=zh
Responses: en → en → de → en → error
There is no way to accurately determine which language is actually returned (other than analyzing the value of the “name” property using some advanced language detection algorithm).
The only solution for now is to limit allowed values to values that are known to work. Which brings us back to the original problem: the system language might not be supported.
(edited by StevenL.3761)
Is there a way to figure out the user’s in-game “Text Language” setting somehow? I’m afraid to go by the current system’s settings, because those include unsupported languages.
If the answer is no, could a dev please update /v1 to include Content-Language headers in the response? The API data defaults to English when the value of the “lang” parameter is invalid. That’s fine, but it should be reflected in the response when it happens.
My best guess is that listings are (lazily) loaded in parallel, so the order would be undefined. For practical purposes, that means that the list goes from listings with few offers to listings with lots of offers.
No idea if that’s how it really works.
(edited by StevenL.3761)
Pat, is it just you maintaining the public API now?
@MentalFS
I think you can get better performance if you run multiple queries (for 200 ids each) in parallel. The ids=all would take too long to complete for a client application to just sit there and wait for the data to return.
“id list too long; this endpoint is limited to 200 ids at once”
Looks okay to me.
I just checked again, and I still don’t receive the X-Result-Count or X-Result-Total headers.
Request
/v2/commerce/listings?page=1
Response headers
Content-Type: application/json; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
X-Content-Type-Options: nosniff
Link: </v2/commerce/listings?page=0>; rel=previous, </v2/commerce/listings?page=2>; rel=next, </v2/commerce/listings?page=1>; rel=self, </v2/commerce/listings?page=0>; rel=first, </v2/commerce/listings?page=442>; rel=last
X-Page-Total: 443
X-Page-Size: 50
Access-Control-Allow-Origin: *
Date: Fri, 12 Sep 2014 23:52:07 GMT
Content-Length: 22090
Hey guys
I published version 0.9.9.0 of GW2.NET on the Codeplex project page.
This release adds support for all /v2/commerce services.
https://gw2dotnet.codeplex.com/
Enjoy!
Still broken for me. :/ Does it take some time for API changes to roll out for everyone?
Yes! YES! Thanks.
So I guess I’ll implement an artificial limit of 200 identifiers in my code. Otherwise, I get problems where the API crashes and returns plain html when the URL becomes too big.
The same limit does not apply to “ids” requests. I can request over 200 identifiers just fine. So it seems that there is no limit. Strange…
/v2/commerce/listings returns literal “null” strings when a bulk request specifies non-existent or account-bound item identifiers.
https://api.guildwars2.com/v2/commerce/listings?ids=-2,-3,6,24
You might have to refresh the page a couple of times to see it.
I tried two different serialization engines, and both fail to correctly recognize these values as null.
Not all /v2 endpoints support the “ids=all” identifier, but there doesn’t seem to actually be a limit on the number of identifiers that you are allowed to request in a single HTTP GET? I’ve noticed that it does break when the URL reaches some length. I’m not sure what’s up with that.
Yeah but why does it not accept parameters? Nothing in the documentation (the official pages or the pages written by Poke) explains the why.
In fact, the official page explicitly states that it should work.
All APIs offer bulk expansion.
(edited by StevenL.3761)
Hmmm… I would expect to be able to do this:
/v2/commerce/exchange?ids=coins
/v2/commerce/exchange?ids=gems
/v2/commerce/exchange?ids=all
Can’t think of why this doesn’t work.
Thanks Stephane. Don’t stop there! We want those other APIs too.
Interesting. Could that be intended? The actual count depends on how players interact with the game, so I wouldn’t be surprised.
At least there is some communication now. What bothers me more is that they demonstrated the /v2/quaggans endpoint, but never even mentioned the /v2/commerce endpoints. If /v2/commerce were ready, wouldn’t they have told us that on the live stream when that one person asked about the APIs?
http://www.twitch.tv/guildwars2/b/565458903
Skip to 32:00 where they talk about the APIs.
Sorry, I thought that was what you were getting at. Can’t wait for the news post to find out.
Trading Post 2.0 will use /v2/commerce APIs? I’m sceptical, but I hope you’re right.