`Choice` structure reform
fergcb opened this issue Β· 106 comments
Summary
There are a number of issues with the Choice structure that keep cropping up: nested Choices, arrays of mixed types, no way to easily describe or deserialize the structure... This issue aggregates those problems and proposes a reformed Choice structure that aims to solve them.
The details of the existing problems and proposed solutions are explained below. I've also described the final proposed structure in TypeScript syntax for reference (this is not intended to be official documentation), and provided an example of the structure in the form of the Fighter's starting_equipment_options
array. Both can be found in this gist: https://gist.github.com/fergcb/a02760c460def3904358cbdfea9312c6
With the community's approval I'll be more than happy to take up the task of implementing the proposal, as well as producing the user-facing documentation.
Details
Consistency
The biggest issue being addressed is consistency. A lot of data consumers don't like arrays with items of mixed types (#274), and there are a variety of structures that can appear in different places without any straightforward way of identifying them.
The proposal uses an inheritance pattern to give all items in an array a common type, for easy deserialization. For example, in the from
array of a Choice, there could be nested choices, arrays of items that must each be resolved separately, or a "terminal", single item. Currently these are given in their raw forms; the from
array could contain Choice objects, JSON arrays, or single objects.
To solve this, every item in the array will now be an object with an option_type
attribute of either choice
, multiple
or single
, which indicates the structure of the underlying data. The same pattern is used to identify whether the Choice is between an array, as described above, or a ResourceList. See the JSON snippet in the gist for examples.
Descriptions
Another issue with the current Choice structure is that it can be hard to explain to a human user what they're actually choosing between (#355). While it is easy to list the options available, and the type
attribute of a choice provides some information, a consumer has no way of indicating where the choices are coming from, or what they are. For example type
may indicate that a "proficiency"
is being chosen, so an application could easily render something like "Choose one proficiency:", but the underlying choice in the SRD is actually "one type of artisan's tools or one musical instrument"
To solve this, the proposal adds an optional desc
string for Choices, so that consumers don't have to write any funky algorithms to tell a human user what they're choosing from. The string should include the text from the SRD that describes what needs to be chosen, e.g. "a wooden shield or any simple weapon", "one type of artisan's tools or one musical instrument", "a martial weapon and a shield or two martial weapons", etc.
Amendments
- The
type
attributes of Option and OptionSet objects have been renamed tooption_type
andoption_set_type
respectively, to more easily distinguish the difference between the structures from the programmer's perspective. - The
array
value of theoption_type
attribute has been changed tomultiple
, to help indicate that all of the items in the JSON array come with that option. Theresource_list
value of theoption_set_type
has been changed toresource_list_url
to better indicate the structure of the data: it is a string holding a URL that resolves to a ResourceList, not an actual ResourceList in its own right.- The
resource_list
OptionSet now holds the ResourceList's URL underresource_list_url
, rather than justurl
. - The EquipmentCategoryOptionSet type has been added to support equipment categories properly (which have a structure distinct from ResourceLists). EquipmentCategories are now linked with an APIReference.
- The
single
Option type has been split intoreference
andaction
. Thereference
type is identical to the previoussingle
type, corresponding to a counted APIReference. Theaction
type is intended for use within "Multiattack" actions, referring to actions, by name, within the same Monster document. An example based on the "Captain" has been added to the Gist. - The
array
option_set_type
has been renamed tooptions_array
, to make it clear what the array contains.
Final Spec
This section describes the state of the proposal after the discussed amendments, to aid with the implementation:
Choice
The Choice structure describes a decision that must be made by a player during character creation or gameplay. It has four attributes:
desc
(string, optional): A description of the choice to be made in human-friendly and (where possible) SRD text.choose
(number): The number of options that must be chosen. The same option can be chosen more than once.type
(string): A string indicating the type of object that will be chosen.from
(object): An object containing the options to choose from. This may take one of a number of forms as described below.
OptionSet
The OptionSet structure provides the options to be chosen from, or sufficient data to fetch and interpret the options. All OptionSets have an option_set_type
attribute that indicates the structure of the object that contains the options. The possible values are options_array
, equipment_category
and reference_list
. Other attributes on the OptionSet depend on the value of this attribute.
options_array
options
(array): An array of Option objects. Each item in the array represents an option that can be chosen.
equipment_category
equipment_category
(APIReference): A reference to an EquipmentCategory. Each item in the EquipmentCategory'sequipment
array represents one option that can be chosen.
resource_list
resource_list_url
(string): A reference (by URL) to a collection in the database. The URL may include query parameters. Each item in the resulting ResourceList'sresults
array represents one option that can be chosen.
Option
When the options are given in an options_array
, each item in the array inherits from the Option structure. All Options have an option_type
attribute that indicates the structure of the option. The possible values are reference
, action
, multiple
and choice
. The value of this attribute indicates how the option should be handled, and each type has different attributes.
reference
- A terminal option. Contains a reference to a Document that can be added to the list of options chosen.item
(APIReference): A reference to the chosen item.
action
- A terminal option. Contains information describing an action, for use within Multiattack actions.action_name
(string): The name of the action, according to itsname
attribute.count
(number): The number of times this action can be repeated if this option is chosen.type
(string ="melee" | "ranged"
, optional): For attack actions that can be either melee or ranged (e.g. for thrown weapons).
multiple
- When this option is chosen, all of its child options are chosen, and must be resolved the same way as a normal option.items
(array): An array of Option objects. All of them must be taken if the option is chosen.
choice
- A nested choice. If this option is chosen, the Choice structure contained within must be resolved like a normal Choice structure, and the results are the chosen options.choice
(Choice): The Choice to resolve.
I already said this on discord but am saying it again for github users..
I approve of the structure. My main concern is how we would document this. I am sure it can be done properly it's just something we will have to be careful with.
Additionally I think it would be best to have more specific type names in the data. The type
field for OptionSets could be named option_set_type
and the type
field for Option could be named option_type
. I think the actual values for these fields are named sufficiently.
Good luck.
Additionally now that I'm thinking about it, it could also be good to use a regular APIReference as an Option as well. It seems odd to have certain things (like spells, sub-features and sub-traits) to be counted, even if it's just 1. Perhaps this isn't needed though.
Additionally I think it would be best to have more specific type names in the data. The type field for OptionSets could be named option_set_type and the type field for Option could be named option_type. I think the actual values for these fields are named sufficiently.
I can see this being beneficial. If others agree I'd be happy to go with this.
now that I'm thinking about it, it could also be good to use a regular APIReference as an Option as well. It seems odd to have certain things (like spells, sub-features and sub-traits) to be counted, even if it's just 1. Perhaps this isn't needed though.
I had thought about this, and cut it out in an effort to simplify a little, with the justification that a count of 1 does the trick, but that is quite StartingEquipment-centric thinking from me. There are other places that do require counts, like actions (esp. Multiattack actions), but those that don't probably outweigh them.
Requiring count
across the board works, but might not be as intuitive. Introducing an uncounted APIReference would also work, might be more intuitive, but would increase complexity. I'm interested to know what others have to say about this.
Globally, I like this structure, especially the desc
suggestion, but I believe names should be better.
Option
type Option = {
type: 'single' | 'array' | 'choice'
prerequisites?: Prerequisite[]
} & (SingleOption | ArrayOption | ChoiceOption)
I don't like the word array
: it's too JSON-y and not data enough. In regards to data, I believe the term list
is preferred. When it comes to a choice between choice
, array
and single
, it's very weird to use array
here. Can we use choice
, multiple
, single
, or maybe one_of
, all_of
, one
? I'm not a native English speaker but to my ear as a developer for so many years, this sounds very strange. So maybe other words can be preferred. Any suggestion?
OptionSet
type OptionSet = {
type: 'resource_list' | 'array'
} & (ResourceListOptionSet | ArrayOptionSet)
This really requires improvement:
- the
resource_list
is not a list of resource: it's a reference to a resource list. Can we just usereference
instead ofresource_list
? This way it's clear that we must go to some other place to lookup the data. Currently, as a reader of the JSON, I'd nearly expect that it's filled with the actual value. I really mean reader of the JSON, not a reader of the.ts
: the.ts
should be there to explain the JSON, not to enforce it. - Also the
array
here makes little sense as seen here. I suggest we use the nameoptions
instead ofarray
.
Ok, I understand that some people will invalidate my first point with my second or vice-versa, but the point here is to be self-contained relevancy. And OptionSet
can actually contain a reference to options, or options themselves. Hence my suggestion.
Yes, I know, naming is hard. Sorry...
I don't like the word array: it's too JSON-y
The whole point of the attribute is to describe the structure of the underlying data. That data is a JSON array; hence, the use of JSON terminology.
Certainly choice
, multiple
, single
is far better than one_of
, all_of
, one
, as it much closer to describing the actual structures here. For example, one_of
implies an array of options, one of which must be selected, when in actual fact, it corresponds to a Choice object. Once again, I am interested to hear what others have to say on this.
the resource_list is not a list of resource: it's a reference to a resource list. Can we just use reference instead of resource_list?
I would be happy to use resource_list_reference
, or similar. As you're correct, it's not a ResourceList, but a reference to one. I feel reference
alone is too vague.
the .ts should be there to explain the JSON, not to enforce it.
The entire purpose of TS types is to enforce the type, or structure, of data at compile time. While it may help explain the structure for those who understand the syntax, it is chiefly here to allow the schema to be enforced while it is being implemented.
the array here makes little sense as seen here. I suggest we use the name options instead of array.
The solution to this is not to give the attribute a value of options
. That does not describe the structure of the data. The from
attribute of the Choice structure contains the options. The type
attribute of the OptionSet structure indicates the format in which those options are presented: Either a ResourceList, or a JSON Array.
I believe Wyzards' suggestion of naming the attributes option_set_type
and option_type
is a far stronger suggestion, as it actually corresponds to the purpose of the attributes, rather than trying to give them a different, less useful purpose altogether.
ETA: as I have mentioned in previous discussions, the value of the type
attribute IS NOT a name. Treating it as one is counter-productive.
The whole point of the attribute is to describe the structure of the underlying data. That data is a JSON array; hence, the use of JSON terminology.
No, we can't just go around and name everything array
. If I have a list of bikes in a structure and I name that list of bikes list
, my reviewer will reject my code telling me to call it bikes
or similar. An array is a good structure, but array
is a bad name for something that uses that structure. I don't really care if it's the one_of
and friends that's selected or multiple
, but array
has to leave, here.
The entire purpose of TS types is to enforce the type, or structure, of data at compile time. While it may help explain the structure for those who understand the syntax, it is chiefly here to allow the schema to be enforced while it is being implemented.
I understand why TS is here, but I don't work in JavaScript and friends. I work in different languages such as Java and Python, and if at some point in time, TypeScript goes against JSON and creates its own TSON (for instance), your stance means that you'll think about follow it, making the data secondary to the structure rather than primary as it (still) currently is. I must say that if the data is not in pure JSON, I'm out, forking the data of this project.
So yes, it's important to understand that JSON is king, and TS is only here to support it.
The solution to this is not to give the attribute a value of
options
. That does not describe the structure of the data.
It's not about describing the structure of the data: it's about describing the data. array
is a bad name and I'll reject it. I'm fine with you not liking options
, but let's find something else that is not options
or array
in that case. We can try going with option_set_type
and option_type
, as you mention: I'm fine with testing it at the very least.
It's not about describing the structure of the data: it's about describing the data.
This is were we disagree. As I keep saying, the type
attribute only describes the structure of the data. That's it.
Please stop getting hung up on the TS thing. It will not be included in the project anywhere. It is only used by me to validate the data as it is being entered. I only included it for people who do understand it, in the hope it may assist the explanation. You don't even have to lay eyes on it if you don't want to.
I feel like almost all of your comments stem from a fundamental misunderstanding of the issues and the proposed solutions, and I don't know how I can explain them in ways other than those I already have. I'm going to reserve further comment until others have had a chance to take a look at the proposal and the discussion, in the hope that different perspectives can shed some light on this blip in communication.
I do understand your proposals. Structurally your suggestion is excellent. I really like it. Please just try to read the JSON you wrote (lines 61-72):
{
"desc": "(a) a martial weapon and a shield or (b) two martial weapons",
"type": "equipment",
"choose": 1,
"from": {
"type": "array",
"options": [
{
"type": "array",
"items": [
{
"type": "choice",
What I read is: "my type is array
, but I'm offering options
as field".
Then the very next object reads "my type is array
, but I'm offering items
as field".
So because you prefer to describe the structure of the data and not the data itself, there is a huge confusion here: at some point an object that says it's an array
contains options
and at some other time, another object that says it's an array
contains items
. How is that not confusing? This is what I have an issue with.
All the rest is fine by me, and I mean all.
I don't like the word array: it's too JSON-y
The whole point of the attribute is to describe the structure of the underlying data. That data is a JSON array; hence, the use of JSON terminology.
Certainly
choice
,multiple
,single
is far better thanone_of
,all_of
,one
, as it much closer to describing the actual structures here. For example,one_of
implies an array of options, one of which must be selected, when in actual fact, it corresponds to a Choice object. Once again, I am interested to hear what others have to say on this.the resource_list is not a list of resource: it's a reference to a resource list. Can we just use reference instead of resource_list?
I would be happy to use
resource_list_reference
, or similar. As you're correct, it's not a ResourceList, but a reference to one. I feelreference
alone is too vague.the .ts should be there to explain the JSON, not to enforce it.
The entire purpose of TS types is to enforce the type, or structure, of data at compile time. While it may help explain the structure for those who understand the syntax, it is chiefly here to allow the schema to be enforced while it is being implemented.
the array here makes little sense as seen here. I suggest we use the name options instead of array.
The solution to this is not to give the attribute a value of
options
. That does not describe the structure of the data. Thefrom
attribute of the Choice structure contains the options. Thetype
attribute of the OptionSet structure indicates the format in which those options are presented: Either a ResourceList, or a JSON Array.I believe Wyzards' suggestion of naming the attributes
option_set_type
andoption_type
is a far stronger suggestion, as it actually corresponds to the purpose of the attributes, rather than trying to give them a different, less useful purpose altogether.ETA: as I have mentioned in previous discussions, the value of the
type
attribute IS NOT a name. Treating it as one is counter-productive.
I think the choice
, multiple
, single
name scheme is best. Also how about resource_list_url
for the resource list url lol... I agree that reference
would be too ambiguous.
Also I agree with what ferg is saying about the array naming. The type field is describing the literal type structure of the choice, so array and resource list seems most fitting since it's not actually describing the content of the optionset itself. The type field exists here to distinguish from the two OptionSets type and tells the consumer how to handle them. It isn't indicating what type of data is stored within the choice. When it comes down to it I'm not too hung up on whether array is renamed to options or not, I think either is properly indicative of what is stored within it.
If the type field were meant to describe the type of CONTENTS, then I would agree with @ogregoire but as far as I can tell that is not the case.
Was just taking a look again at the gist and noticed that your schema for Option has an attribute called prerequisites
. It's clear to me what the purpose of this could be, but could you provide an example that makes use of it within the SRD?
Was just taking a look again at the gist and noticed that your schema for Option has an attribute called
prerequisites
. It's clear to me what the purpose of this could be, but could you provide an example that makes use of it within the SRD?
Cleric gets "(a) a mace or (b) a Warhammer (if proficient)".
You can see how this is represented in the API currently using the prerequisites
attribute:
Was just taking a look again at the gist and noticed that your schema for Option has an attribute called
prerequisites
. It's clear to me what the purpose of this could be, but could you provide an example that makes use of it within the SRD?Cleric gets "(a) a mace or (b) a Warhammer (if proficient)".
You can see how this is represented in the API currently using the
prerequisites
attribute:
I see, thanks. That makes sense.
Now I'm just waiting for these changes to be implemented lol, I've already inserted the data structure into my own code since it's sort of all encompassing.
Now I'm just waiting for these changes to be implemented
As soon as I have agreement from the maintainers, I'll get to work.
Haha. I feel reasonably called out and I definitely deserve it. @fergcb I have no plans tonight after work so I'll dedicate it to this.
I agree with @Wyzards that type
as a field name feels a bit overloaded and it has a different meaning depending on where in the structure you are. This could become quite confusing.
I agree with @ogregoire that OptionSet should probably not use the term resource_list
. Perhaps api_reference
instead of reference
? That seems a little less vague. I kind of feel like resource_list_url
isn't quite right either. And makes sense to use our ApiReference structure that we already have?
I also like choice
, multiple
, single
as the options. I think that's a bit clearer.
@fergcb If it's not too much of a bother, can you update that gist with the changes we've agreed on so far? Just so it's easier to track where we are now that we've agreed on some things?
I also feel like the overloading of our usage of the type
field might have been causing some confusion in the discussion.
That being said, just a friendly remind to try and keep discussions friendly and civil. We're all doing this for fun. Or at least... I'm doing this for fun.
That being said, just a friendly remind to try and keep discussions friendly and civil. We're all doing this for fun. Or at least... I'm doing this for fun.
This API is for blood, and blood only. No fun.
@fergcb If it's not too much of a bother, can you update that gist with the changes we've agreed on so far? Just so it's easier to track where we are now that we've agreed on some things?
In all seriousness though, what you said here would be great and make discussing this a lot more clear.
This API is for blood, and blood only. No fun.
Blood for the blood god. Skulls for the skull throne.
OptionSet should probably not use the term resource_list. Perhaps api_reference instead of reference? That seems a little less vague. I kind of feel like resource_list_url isn't quite right either. And makes sense to use our ApiReference structure that we already have?
@bagelbits the data corresponding to the type resource_list
isn't an APIReference, and it can't be represented that way.
We already have the ResourceList structure, and that's that the URL links to. A ResourceList doesn't have an index or a name, just a URL.
I'm fine with all the other changes though :)
Okay! Then resource_list_url
probably makes sense.
The gist has been updated to reflect the following suggested amendments:
- The
type
attributes of Option and OptionSet objects have been renamed tooption_type
andoption_set_type
respectively, to more easily distinguish the difference between the structures from the programmer's perspective. - The
array
value of theoption_type
attribute has been changed tomultiple
, to help indicate that all of the items in the JSON array come with that option. - The
resource_list
value of theoption_set_type
has been changed toresource_list_url
to better indicate the structure of the data: it is a string holding a URL that resolves to a ResourceList, not an actual ResourceList in its own right.
That seems a little less vague. I kind of feel like
resource_list_url
isn't quite right either.
When I suggested resource_list_url
I was referring to the attribute that stored the resource list url, not the name for the OptionSet type.
In that respect I thought the names array
and resource_list
were sufficiently descriptive. Now that my suggestion has been implemented in the wrong place its less accurate. @fergcb
When I suggested
resource_list_url
I was referring to the attribute that stored the resource list url, not the name for the OptionSet type.
@Wyzards this change was based more on @bagelbits suggestion later in the thread. I think changing the value of the option_set_type
makes the most sense, because it's describing the structure of the data within, and the data is a URL, not a ResourceList. The url
attribute could be renamed as well, but it wouldn't be as useful of a change by itself.
When I suggested
resource_list_url
I was referring to the attribute that stored the resource list url, not the name for the OptionSet type.@Wyzards this change was based more on @bagelbits suggestion later in the thread. I think changing the value of the
option_set_type
makes the most sense, because it's describing the structure of the data within, and the data is a URL, not a ResourceList. Theurl
attribute could be renamed as well, but it wouldn't be as useful of a change by itself.
Agree to disagree I suppose. Doesn't make too much of a difference to me in the long run.
Okay! Then
resource_list_url
probably makes sense.
No it doesn't.
I will translate that name exactly as it means:
Resource List Uniform Resource Locator
Why does anyone want to use twice the word "resource" in a single name? That makes no sense.
I strongly advise to use a different name that makes actual sense and that doesn't repeat.
Why does anyone want to use twice the word "resource" in a single name? That makes no sense.
I strongly advise to use a different name that makes actual sense.
The data the value is describing is a URL. That URL resolves to a ResourceList. Hence, resource_list_url
.
Perhaps suggesting a suitable alternative would be a more productive contribution to the discussion?
Perhaps suggesting a suitable alternative would be a more productive contribution to the discussion?
I did, but you rejected it. At least in the sense that I suggested alternatives to resource list, which is the root cause of the issue.
All those lists are not resource lists. They're item lists, spell lists, etc. Using the global name resource for those is hype-y and not descriptive. Maybe we should use a global name such as game element for those, as they're part of the game and it's a fitting name to describe what both equipment items and spells are. And then we could have something akin to "game_element_list_url", or "element_list_reference". And I insist that reference is adequate (and better than URL) because it's a pointer, it describe that the list refers to something that is described elsewhere. The reference happen to be a URL, but it's still a reference. So my prime candidate for naming that field is "element list reference". What do you think of this? Oh, and please stop saying I don't suggest alternatives when in fact I did.
I did, but you rejected it.
Are you referring to your suggestion of "reference"? I hope it's clear after the following discussion why that isn't really an appropriate alternative.
Maybe resource list is not a good name then?
Maybe. I feel that's distracting from the goal of this proposal. If we decide to change the documented name of that structure, we can always revisit the use of its name in this structure. If you think it's truly that in-need of an update, you could open an issue about it on the API repo (where the docs live)?
I did, but you rejected it.
Are you referring to your suggestion of "reference"? I hope it's clear after the following discussion why that isn't really an appropriate alternative.
Maybe resource list is not a good name then?
Maybe. I feel that's distracting from the goal of this proposal. If we decide to change the documented name of that structure, we can always revisit the use of its name in this structure. If you think it's truly that in-need of an update, you could open an issue about it on the API repo?
I still think that resource_list
is the most acceptable name. reference
isn't sufficient because it points to a resource list, which is established in the documentation at https://www.dnd5eapi.co/docs/#resource-lists.
The option_set_type
of the OptionSet essential refers to how the data is stored. In the case of the one that uses a resource list, I think that resource_list
subsequently makes the most sense...
Same case for the array
OptionSet type.
I'll also note that I agree, this is distracting from the goal of the proposal and could always be changed later.
I still think that resource_list is the most acceptable name. reference isn't sufficient because it points to a resource list, which is established in the documentation at https://www.dnd5eapi.co/docs/#resource-lists.
I'd be happy to revert to resource_list
, my original proposal. That particular change was in response to @bagelbits' suggestion, so I'd be interested to hear their thoughts on the above few comments.
I still think that
resource_list
is the most acceptable name. reference isn't sufficient because it points to a resource list, which is established in the documentation at https://www.dnd5eapi.co/docs/#resource-lists.
That's... not exactly true. The resource_list
you're referring to in the docs is for an index on an endpoint and is different shape than what we're calling a resource_list
here, i.e. /api/equipment-categories/martial-weapons
. I think @ogregoire has a point that resource_list_url
doesn't quite feel like the right fit for what we're trying to convey. But I'm having a devil of a time thinking of something that works. Let me workshop this a little.
So this is how it stands right now:
"from": {
"option_set_type": "resource_list_url",
"url": "/api/equipment-categories/martial-weapons"
}
And previously we had this which also didn't feel quite right:
"from": {
"option_set_type": "resource_list",
"url": "/api/equipment-categories/martial-weapons"
}
Hrmmm.... my first thought is doing reference_list
:
"from": {
"option_set_type": "reference_list",
"url": "/api/equipment-categories/martial-weapons"
}
If we wanted to be a little more verbose, we could even do:
"from": {
"option_set_type": "reference_list",
"reference_list": {
"name": "Martial Weapons",
"index": "martial-weapons",
"url": "/api/equipment-categories/martial-weapons"
}
}
Though, honestly, that feels a little weird because reference_list
makes you think it's going to be a list of things but you're only giving an object. What do y'all think?
It seems like everything else is mostly solidified though and this is our last piece. I think my only other question is what do we gain by differentiating between single
and multiple
?
I still think that
resource_list
is the most acceptable name. reference isn't sufficient because it points to a resource list, which is established in the documentation at https://www.dnd5eapi.co/docs/#resource-lists.That's... not exactly true. The
resource_list
you're referring to in the docs is for an index on an endpoint and is different shape than what we're calling aresource_list
here, i.e./api/equipment-categories/martial-weapons
. I think @ogregoire has a point thatresource_list_url
doesn't quite feel like the right fit for what we're trying to convey. But I'm having a devil of a time thinking of something that works. Let me workshop this a little.So this is how it stands right now:
"from": { "option_set_type": "resource_list_url", "url": "/api/equipment-categories/martial-weapons" }And previously we had this which also didn't feel quite right:
"from": { "option_set_type": "resource_list", "url": "/api/equipment-categories/martial-weapons" }Hrmmm.... my first thought is doing
reference_list
:"from": { "option_set_type": "reference_list", "url": "/api/equipment-categories/martial-weapons" }If we wanted to be a little more verbose, we could even do:
"from": { "option_set_type": "reference_list", "reference_list": { "name": "Martial Weapons", "index": "martial-weapons", "url": "/api/equipment-categories/martial-weapons" } }Though, honestly, that feels a little weird because
reference_list
makes you think it's going to be a list of things but you're only giving an object. What do y'all think?It seems like everything else is mostly solidified though and this is our last piece. I think my only other question is what do we gain by differentiating between
single
andmultiple
?
I thought of reference_list
as well but thought it might not fit, since the documentation already names the structure "resource list" in addition to it including the count
attribute, making it not literally just a list of references, as the name would indicate.
On the final note, I'm pretty sure we already agreed that there should be a distinction between single
and multiple
. I assume here you're referring to the three option types, single
, multiple
, and choice
. I feel that these should be unchanged.
Also I think just the URL is fine rather than an entire reference to the resource list, especially since the endpoint already contains information that would be stored within said APIReference.
I thought of
reference_list
as well but thought it might not fit, since the documentation already names the structure "resource list" in addition to it including thecount
attribute, making it not literally just a list of references, as the name would indicate.
To clarify here, I have no problem with using reference_list
here, although I don't see it as much more descriptive than
resource_list`
I thought of reference_list as well but thought it might not fit, since the documentation already names the structure "resource list" in addition to it including the count attribute, making it not literally just a list of references, as the name would indicate.
Just to be clear, /api/equipment-categories/martial-weapons
is not a resource list. If we look at the docs for equipment categories, it's just index
, name
, and a list of APIReference
. Do we have any other examples of how we would use this field besides links to Equipment Categories? I think that might help a little with how we think about this specific case.
I thought of reference_list as well but thought it might not fit, since the documentation already names the structure "resource list" in addition to it including the count attribute, making it not literally just a list of references, as the name would indicate.
Just to be clear,
/api/equipment-categories/martial-weapons
is not a resource list. If we look at the docs for equipment categories, it's justindex
,name
, and a list ofAPIReference
. Do we have any other examples of how we would use this field besides links to Equipment Categories? I think that might help a little with how we think about this specific case.
You're correct, this is not a resource list, that's my mistake. If starting equipment is the only application of the resource_list option-type
, then resource_list
would not be appropriate.
I looked a little through the SRD to find any other places where a Choice option or resource list OptionSet would need to be used, but couldn't find any. However, my search was by no means thorough and it doesn't seem completely unlikely that there would have to be a nested choice that actually does refer to a resource list.
If starting equipment is the only usage of this OptionSet type, then I think reference_list
would actually be the most appropriate.
I don't know how I missed that an equipment category endpoint doesn't return a ResourceList... That complicates things somewhat, and it's completely on me for not checking π¬
I don't feel then that something like reference_list
would be appropriate, given that resolving the value doesn't give you a list of references, or a generic structure that would be easy to extract a list of references from. The options are under the equipment
attribute of the returned document, which is obviously very specific to equipment categories. Even if we named the resource_list
type more appropriately, it'd still be unique to equipment categories.
This makes me feel that it would be worth going even more specific and creating a new option_set_type
called equipment_category
? And we could use a full APIReference like bagelbits suggests. Going this specific increases the complexity for consumers a little bit, but starting equipment is probably one of the most important places where Choices are used, so I feel it would be acceptable.
My thinking behind resource_list
was that it could be used to include query params in the URL to filter a ResourceList. For example, the Choice in the High Elf's wizard cantrip trait could be from
the ResourceList returned by /api/spells?level=0&class=wizard
.
Of course, at the time I was assuming that equipment categories returned ResourceLists, which we've now learned is wrong, so that approach is now less generalisable. But I think there may be some value in introducing it alongside a equipment-category
type.
I don't know how I missed that an equipment category endpoint doesn't return a ResourceList... That complicates things somewhat, and it's completely on me for not checking π¬
I don't feel then that something like
reference_list
would be appropriate, given that resolving the value doesn't give you a list of references, or a generic structure that would be easy to extract a list of references from. The options are under theequipment
attribute of the returned document, which is obviously very specific to equipment categories. Even if we named theresource_list
type more appropriately, it'd still be unique to equipment categories.This makes me feel that it would be worth going even more specific and creating a new
option_set_type
calledequipment_category
? And we could use a full APIReference like bagelbits suggests. Going this specific increases the complexity for consumers a little bit, but starting equipment is probably one of the most important places where Choices are used, so I feel it would be acceptable.My thinking behind
resource_list
was that it could be used to include query params in the URL to filter a ResourceList. For example, the Choice in the High Elf's wizard cantrip trait could befrom
the ResourceList returned by/api/spells?level=0&class=wizard
.Of course, at the time I was assuming that equipment categories returned ResourceLists, which we've now learned is wrong, so that approach is now less generalisable. But I think there may be some value in introducing it alongside a
equipment-category
type.
I have no objections to this.
@fergcb I'd love to see an example of where we actually use a resource list as well. Also, how does this structure work with other places we use choices, like monsters
for example?
I'd love to see an example of where we actually use a resource list as well.
@bagelbits Currently, we don't. Like I explained in my previous comment, I was initially working under the assumption that equipment categories returned ResourceLists, but under the realisation that they don't, I think there still could be value in supporting them as a source of Options for a Choice; we could use this for choosing languages (where we could just refer to the /api/languages
ResourceList, rather than listing every single language as APIReferences), or the high elf cantrip example I gave earlier (/api/spells?level=0&class=wizard
[although now I think of it, I'm not sure the class
query param exists on the spells endpoint - maybe it should]).
Also, how does this structure work with other places we use choices, like monsters for example?
This raises a good point that not all things being chosen from are references to other documents, though I think Monsters' attacks are unique in that regard? Class and Background StartingEquipment, feature/trait choices, proficiency choices, and spell choices, etc. all only use APIReferences (and therefore work the exact same way as the StartingEquipment example given), so I must have skimmed over multiattacks being different.
To handle Monsters' multiattacks, we'll either have to split the single
Option type into something like reference
and attack
, or change the way monster attacks work. The former seems favourable.
I would love to see some examples of that then! And we might want to scour the rest of our choice usage to make sure we aren't missing any other edge cases. π
Apologies for the inactivity; it's a busy time for me rn.
I've updated the schema in the following ways:
- Reverted the
resource_list
name change, and changed the attribute fromurl
toresource_list_url
, as per @Wyzards' suggestion. - The
equipment_category
OptionSet type has been added to support equipment categories properly (which have a structure distinct from ResourceLists). EquipmentCategories are now linked with an APIReference. - The
single
Option type has been split intoreference
andaction
. Thereference
type is identical to the previoussingle
type, corresponding to a counted APIReference. Theaction
type is intended for use within "Multiattack" actions, referring to actions, by name, within the same Monster document. An example based on the "Captain" monster has been added to the Gist (@bagelbits).
@fergcb just got the chance to look at your changes.
Obviously I agree with the first change. I also agree with equipment_category
being its own OptionSet. As for splitting single
Options, there's a couple nitpicks I have but overall I agree with the idea.
First of all, I feel that the Option type currently named reference
should stay as single
. It just seems more intuitive to me personally. Additionally, the top-level options
attribute within the Multiattack Action you provided should be named something along the lines of choice
, action_choice
or attack_choice
, since the attribute contains a choice, not a list of options. Finally, I think it could make more sense for the new option's type to be "attack" instead of "action". I can't really see this new option being used outside of attacks. If I'm wrong, please provide an example to correct me. If that is the case, then "action" is an appropriate name.
Otherwise, I think this newest rendition looks great.
First of all, I feel that the Option type currently named reference should stay as single.
That feels misleading, as actions may also be "single" items in the choice.
the top-level options attribute within the Multiattack Action you provided should be named something along the lines of choice, action_choice or attack_choice, since the attribute contains a choice, not a list of options.
I haven't changed/added anything, there. That attribute already exists in action objects. Changing that is unrelated to the Choice structure itself and belongs in a separate issue.
I think it could make more sense for the new option's type to be "attack" instead of "action". I can't really see this new option being used outside of attacks. If I'm wrong, please provide an example to correct me. If that is the case, then "action" is an appropriate name.
Dragons use their Frightful Presence action as part of their multiattack:
Multiattack. The dragon can use its Frightful Presence. It then makes three attacks: one with its bite and two with its claws.
I think it could make more sense for the new option's type to be "attack" instead of "action". I can't really see this new option being used outside of attacks. If I'm wrong, please provide an example to correct me. If that is the case, then "action" is an appropriate name.
Additionally, this structure will get reused for Legendary Actions, which are currently not broken out. I think there's an open issue for it.
IIRC how Legendary Actions work.
If that's the case, then I have no other issues with this proposal.
I'll try to review this again later tonight so we can get cracking on this and unblock everyone.
I think that looks good. @ogregoire do you have any additional feedback before we try and roll this out?
I still dislike the word array
. The rest seems to have been properly iterated upon.
We use resource_list
which indicates a string but refers to some other data which are resource lists. So that's fine.
We use equipment_category
which indicates an API reference that refers to some other data which are equipment categories. So that's fine.
Then we use array
which indicates an array of options but the type just calls it array
. It's not an array, it's an array of options. So that's not fine.
We have two elements that are defined by what they will contain, and one that is defined by its json-type. That's inconsistent. If we want consistency, but keep array
, we could rename the other two string
and object
, respectively. (Please don't, that was for the purpose of the argument.) I don't see why the work is good for two out of three, but for the third, we just stop caring about proper naming.
For the rest, I totally agree. It's a clear improvement: I can read the JSON and understand it without checking the type definitions.
@ogregoire Keeping with the theme. Would it make more sense to call it options
instead of array
?
Yes, I'm glad someone else thought of that name. options
is perfectly fine. option_list
as well. option_array
is not consistent because then we'd sometimes use list
and other times array
. So yes, please, use options
, that's my request from day 1.
option_array
is not consistent because then we'd sometimes uselist
and other timesarray
.
option_list
would be misleading when contrasted with resource_list
, as a ResourceList is structurally very different from an Array of Option objects. If one saw an option_list
was an Array of Options, they would expect a resource_list
to be an Array of Resources, which it is not.
options
also feels like a bad choice given that all of these structures resolve to a selection of options to be chosen from.
options_array
appears to be the best choice, to me. It describes clearly that the underlying data is a JSON Array ("Array" being the accepted standard word for that data type in JSON, not "List") containing Options.
I imagine this conversation:
- John, you must choose between blue, red and yellow.
- Can I choose green?
- No, green is not on the array.
That doesn't feel right.
- John, you must choose between blue, red and yellow.
- Can I choose green?
- No, green is not on the list.
Now, this sounds way better!
Actually, I don't see an example of using resource_list
. Is there one that exists?
I imagine this conversation:
- John, you must choose between blue, red and yellow.
- Can I choose green?
- No, green is not on the array.
That doesn't feel right.
- John, you must choose between blue, red and yellow.
- Can I choose green?
- No, green is not on the list.
Now, this sounds way better!
Green is not in the array. Of course it sounds weird if you use the wrong preposition.
Actually, I don't see an example of using
resource_list
. Is there one that exists?
We've talked about a few examples earlier in the thread. I can draw up some demo JSON later.
Sorry @fergcb if you don't mind when you have time.
I think aside from the correct name for array
, this looks golden.
@ogregoire Also, to @fergcb's point, it would be No, green is not in the array.
and No, green is not (in|on) the list.
but that's linguistic semantics. Both of which are understandable and valid.
Well, let's look at our raw material, the SRD.
Page 57:
one skill from the classβs skill list
Page 143:
Choose one of the forms from the above list. (Present twice)
Page 152:
Choose the effect from the following list, or choose an effect offered by the GM.
On the other hand, array is mentioned only one time in the whole document, on page 125:
A dazzling array of flashing, colored light springs from your hand.
So basically, four out of the 94 times the word "list" is mentioned is in direct relation with choice, and the only time the word "array" is mentioned at all, it's only for in-game description, not for rules.
So yes, "list" is more suitable than "array".
....language is hard.
In this case, I'd argue that the wording in the SRD is almost entirely irrelevant. If the programmer is faced with option_list
and resource_list
we should not expect them to have an intimate knowledge of how the SRD phrases things in order to interpret these type descriptors.
Remember, the programmer is faced with the type
attribute. Not the end user. The programmer would be better off being able to infer from the value option_array
that the underlying data is an Array of Options, rather than having to pick apart the difference between an option_list
(an Array of Options) and a reference_list
(a URL string pointing to a ReferenceList object).
I'll list the options below. The first is the most explicit and the most descriptive, to me. The second is entirely misleading, by the use of list
implying that the structures are similar, which they are not. The last is much less verbose than the first, but is at least less contradictory than the second.
option_array
= Array of Option objects
resource_list
= URL resolving to a ResourceList object
option_list
= Array of Option objects
resource_list
= URL resolving to a ResourceList object
options
= Array of Option objects
resource_list
= URL resolving to a ResourceList object
I'm not asking to rename array
to option_list
: it was one suggestion out of two, and I left the list of suggestions (not array) open. If you don't like option_list
, why don't you like options
? What is irremediably wrong about options
?
I don't want array
, you don't want list
. Why can't we settle on options
?
I addressed options
in my last post. In two of my last three posts, in fact.
No, you didn't. At least not in your last few posts. You did in one of your first posts. And in there, you said:
The solution to this is not to give the attribute a value of
options
. That does not describe the structure of the data.
You're still wrong. The "s" of "options" imply the structure, saying that there are multiple options. And what address the plurality in json? The array. So options
describes perfectly the underlying structure! Am I the only one to see that?
Plus, the number of times we use in this API a plural to say that we have a JSON array is huge. We use prerequisites
, we use proficiencies
, class_levels
, etc. Should we change all of those to have array
, array
and array
? Should we change all of them to have prerequisite_array
, proficiency_array
and class_level_array
? No: we should keep them as is.
The appropriate word here is options
, not array
and you still have no explanations for your refusal to use it.
There's little value in comparing attribute names (e.g. prerequisites
, proficiencies
, etc.) with the value of the type
attribute .
This value is supposed to describe the structure, for the programmer, not to be a "name" for the underlying value. That's what the attribute name does. I have been clear and consistent on the purpose of the type
attribute from the start. It is not a name. It is a type; a description of the object's structure.
you still have no explanations for your refusal to use it.
I will list my objections, directly quoting from previous comments in this thread, below.
The last [referring to
options
] is much less verbose than the first [option_array
], but is at least less contradictory than the second [option_list
].
options
also feels like a bad choice given that all of these structures resolve to a selection of options to be chosen from.
I feel these two very recent comments summarise the key objections well enough, though I'm sure if you scroll back far enough, or check previous issues where we've talked about Choice reforms, you may find further comments about this. If you need any clarification I can try to expound upon these points, but to suggest that I haven't offered any objection at all is untrue.
I will list my objections, directly quoting from previous comments in this thread, below.
The last [referring to
options
] is much less verbose than the first [option_array
], but is at least less contradictory than the second [option_list
].
That's not an objection: it's the opposite, an endorsement for options
.
options
also feels like a bad choice given that all of these structures resolve to a selection of options to be chosen from.
No: there are the plain options that we could call, you know, options
, and then there are the other types that are called resource_list
and equipment_category
.
You keep speaking about programmers versus data users, well let me break it to you: attribute names, type names and type hints (the content of the type
attribute) are all present exclusively for the programmer. Yet, you seem to make a hierarchy between those and allow for different rules when in fact they're all only programmer helpers. So yes, there is value in comparing attribute names to type hints.
Tonight I keep having logical explanation over logical explanations, yet you seem to entirely disregard those for the sake of "I said so". I don't want to lose my energy to naysayers today. So if you want to use array
, just do it. I'll do the rewriting after you're done.
Edit: my last sentence could be badly taken in this project, but I actually meant in my personal copies where I actually use the data. Sorry for the possible misunderstanding.
That's not an objection: it's the opposite, an endorsement for
options
.
It is an objection. I believe verbosity is a positive quality in this case. Certainly the latter half of my statement is an "endorsement" over option_list
, but not over option_array
.
No: there are the plain options that we could call, you know,
options
, and then there are the other types that are calledresource_list
andequipment_category
.
ResourceLists and EquipmentCategories both present collections of options (in the regular spoken/written English sense of the word "options") for the Choice.
You keep speaking about programmers versus data users, well let me break it to you: attribute names, type names and type hints (the content of the
type
attribute) are all present exclusively for the programmer. Yet, you seem to make a hierarchy between those and allow for different rules when in fact they're all only programmer helpers. So yes, there is value in comparing attribute names to type hints.
I mentioned the values here being programmer facing simply to reinforce the idea that verbosity is a positive thing, here. Given that the data is in a JSON Array, how does it detract to say that the type
of this particular option set is an option_array
? That value conveys two useful pieces of information to the programmer: the value is an array, and the array contains Option objects. Sure, options
kind of implies that, but less explicitly. What's the benefit in leaving that ambiguity? You yourself have expressed that you don't like checking the docs, so why not let the data be self-documenting?
Tonight I keep having logical explanation over logical explanations, yet you seem to entirely disregard those for the sake of "I said so". I don't want to lose my energy to naysayers today. So if you want to use
array
, just do it. I'll do the rewriting after you're done.
If you think that my tireless expansion, redevelopment and reiteration of this proposal boils down to me saying "I said so", then I believe you are contesting this in bad faith. I challenge you to find an example of me indicating that this proposal should pass because "I said so". Not only have I taken most all of the criticism on board and made amendments to the proposal where agreed upon, I have welcomed, sought out, and taken on-board opinions from all of the contributors.
I said "you win", take it.
I said "you win", take it.
It's... not a competition, I'm not trying to "win". See my previous comment RE: bad faith, I guess :/
Y'all, I go away for checks watch four hours... please. This is a silly project that I, personally, like to spend my free time on for fun. It's not that serious. It's not a contest that someone has to win.
That being said. After reviewing this, I think we should go with option_array
.
options
while being accurate is also vague when it's all options
array
is fine but honestly pretty vague
option_list
is going to confused with reference_list
which is a very different data shape. The only way I can see this one working is if we call reference_list
something else which I assume isn't going to happn.
I feel like option_array
works as a decent compromise. If you want to change it options
or array
in your own personal projects, please feel free.
@ogregoire @fergcb I'm sorry. My company is launching it's first store tomorrow and I'm a little shorter on patience than normal and that is not fair to either of you.
@ogregoire I would like to remind you that there is a Code of Conduct for this repo. You can review it here. Please reach out to me privately if you would like to discuss this further.
@fergcb I want to call out a huge thank you for driving this discussion. I know Choices have been a pain point for a lot of users and this is a huge undertaking to champion. This will also unblock a few other projects once we get this in.
@fergcb Thinking about this a little bit more, option_list
could work if we called it reference_list_url
instead. I think that reference_list_url
would more accurately model the data since it will be a url to a reference list.
Also, come to think of it, we use list
to describe arrays in our documentation. Which also lends credit to using option_list
as well.
Also, come to think of it, we use
list
to describe arrays in our documentation.
Which feels like a bad thing, given that the API serves JSON and there's no such thing as a "list" in JSON.
@fergcb Thinking about this a little bit more,
option_list
could work if we called itreference_list_url
instead. I think thatreference_list_url
would more accurately model the data since it will be a url to a reference list.
I don't like this because (a) the reason above - lists aren't a JSON concept, and (b) the set of options itself isn't a URL, it's a ResourceList. We just provide the URL so the consumer can fetch the actual ResourceList object.
We just provide the URL so the consumer can fetch the actual ResourceList object.
But isn't it still a URL? So by that logic, wouldn't reference_list_url
make the most sense? Also do we have an example of this? I think a lot of the confusion all of us are having is due us not even knowing what this looks like in practice.
Which feels like a bad thing, given that the API serves JSON and there's no such thing as a "list" in JSON.
I don't think we've done any of our field naming based on JSON types up this point? All of our naming conventions have been based on the SRD?
Additionally, if we use reference_list_url
, it makes it really easy for an end user to make a reference_list
method that just fetches the reference_list
based on the reference_list_url
.
I can understand naming attributes and such after things in the SRD when they align nicely, but the type names of generic structures like Arrays seem like they should live outside the realm of SRD knowledge and should be designed to help the consumer deserialise the JSON. (ETA: see my previous comment regarding how we shouldn't expect the consumer to have an intimate knowledge of how things are worded in the SRD just to fetch the data) Especially in the docs. E.g. if I'm looking at the docs figuring out how to process a certain property, it would be more obvious if I was told that the property's value was an array, rather than a list. The org.json
library for Java would parse the data as a JSONArray, for example. Or more obviously, perhaps, JavaScript would give me an Array.
I can only apologise for a lack of an example so far, I've been unbelievably busy. I'll draw one up now, it's relatively straightforward.
One of the examples I gave previously was referring to the entire languages collection for Background language choices, rather than listing each language separately. This would make maintenance much easier. It would look like this:
{
"language_options": {
"desc": "any 2 languages",
"choose": 2,
"type": "language",
"from": {
"option_set_type": "resource_list",
"resource_list_url": "/api/languages"
}
}
}
As you can see, the option_set_type
of "resource_list"
indicates that the options are contained within a ResourceList (just as "options_array"
indicates that the options are contained within an Array of Option objects), and then the attribute resource_list_url
is given to allow that ResourceList to be fetched.
Thank you for providing an example, that makes it much easier to visualize. And thank you for taking the time to do that given how busy you are. I really think we should call the type resource_list_url
instead of resource_list
, since it is literally a url for the reference list.
And given your points on array
vs list
, I can see the benefit of having generic types not tied to the SRD but the JSON concepts. So I think we should go with my initial suggestion of options_array
. Thanks for talking that one out with me some more. As an aside, we should probably clean up the docs to say array
instead of list
to conform with JSON naming conventions.
I really think we should call the type
resource_list_url
instead ofresource_list
It feels weird to revert back to that after people didn't like it the first time it was changed to that, but if that's really what you think is best, I'm happy to go back to it. I don't have any strong feelings against it other than not aligning with the original purpose of that field π
Thanks for talking that one out with me some more.
No problem! It's something that's bugged me for the duration of this discussion and long before, so I'm glad I was finally able to find the right words to put the point across. I'll update the gist to include the options_array
change when I can.
Frankly, resource_list
is just a weird one to model correctly.
It's fairly similar to equipment_category
. If we're going to go for resource_list_url
, do we need to go for equipment_category_reference
?
I mean, a level of verbosity is good but this is getting unwieldy π
Nah. I think equipment_category_reference
would be silly. equipment_category
matches how we do APIReferences everywhere else. We could rename it to api_reference
if we wanted to be pedantic though and have it be more generic.
Calling it resource_list
only feels like it would make sense if we did this:
"from": {
"option_set_type": "reference_list",
"reference_list": {
"name": "Martial Weapons",
"index": "martial-weapons",
"url": "/api/equipment-categories/martial-weapons"
}
}
We could call it reference_list_reference
though π€£
I agree, equipment_category_reference
is a bit silly. Also, api_reference
doesn't work, because the option_set_type
needs to indicate how the resulting data should be treated. I'm not aware of any other Documents that can be pointed to by an APIReference that would make sense to support as OptionSets, but each would have different steps needed to extract the options. For example, an EquipmentCategory has its options as an array of APIReferences under the equipment
attribute.
equipment_category
matches how we do APIReferences everywhere else
Doesn't resource_list
match how we do URLs everywhere else, in the same way? E.g. spells
in Class documents. Though, bear in mind the difference between the value of the type
attribute and the names of attributes elsewhere in the database means such comparisons might not be that useful.
Calling it
resource_list
only feels like it would make sense if we did this:
Resource lists aren't Documents that can be referenced with APIReferences like that, sadly. They don't have names or indices.
However, I wonder why you feel that it would make more sense if it was an APIReference, but not a more generic reference by URL?
Yeah. That makes sense why api_reference
wouldn't work for equipment_category
E.g.
spells
in Class documents.
I actually wonder if we should do to spells
in Class documents the same thing we still need to do with class_levels
. Probably can add that to what still needs to be done in #251
However, I wonder why you feel that it would make more sense if it was an APIReference, but not a more generic reference by URL?
It's kind of a feeling thing? I think other than the places you have mentioned in Class, which honestly need to be cleaned up still, every time we have a value of a url, the key is url
. Mostly this is due to almost everything using an APIReference. However, it feels more consistent that way. And the top level key for an APIReference is always a reference to something in the SRD. The term url
is our way of designating a reference to another part of the DB or API.
Yeah, spells could be put in the Class document directly.
You mention that every time there's a URL (besides that one example), the attribute name is url
. You'll notice that in this proposal, the name of the attribute holding the URL for a ResourceList actually was url
, but we changed it to resource_list_url
to make it extra obvious.
The value of the option_set_type
attribute is different to the name of the separate attribute that contains the URL. The type
of the thing containing the options (the option_set
) is a ResourceList, not URL/string. Hence, "option_set_type": "resource_list"
. However, it would be unwieldy and difficult to maintain to put a whole ResourceList in the Choice structure, so we let the consumer resolve it themselves, and we give them a URL to do that. We call the attribute holding that URL resource_list_url
to make it clear and somewhat self-documenting.
It's the same reasoning behind equipment_category
: the EquipmentCategory is the thing containing the options, so it would be weird to say the type
of the option_set
was a reference to that category. The only difference is that we call the attribute containing that reference equipment_category
rather than something like equipment_category_reference
for consistency with the rest of the repo. Originally that attribute was just called reference
(as seen in Proficiencies), but that didn't seem like it would be popular given the distaste for url
in the resource_list
option set.
I hope I'm explaining this okay.
Yeah I think you are. However, I want to point out that the value of the option_set_type
attribute is inherently arbitrary and we are just trying out to figure out the semantics of an ENUM that makes the most sense.
The type of the thing containing the options (the option_set) is a ResourceList, but it is shown using a URL/string. I think that's the distinction I'm trying to make here. resource_list
would make more sense if we were to put the whole ResourceList in the Choice structure. But instead, we're putting a reference. That is different from the ResourceList itself.
Heh. It's hard to keep track of the various iterations of this discussion.
resource_list would make more sense if we were to put the whole ResourceList in the Choice structure. But instead, we're putting a reference. That is different from the ResourceList itself.
I'm afraid I really do struggle, then, to see why EquipmentCategory/equipment_category
is acceptable, but ResourceList/resource_list
isn't? They both contain references to objects with those types. An APIReference is pretty much as different from an EquipmentCategory as a URL is from a ResourceList.
The fact that the URL is given rather than the full object is clear from the attribute on the object being called resource_list_url
. The docs can make it even clearer that both the equipment_category
and resource_list
types first need to be resolved with an additional request, if it isn't clear enough from the attribute names.
I feel like I've said this already, but I think api_reference
makes more sense than equipment_category
if we wanted things to be generic for a type. I don't exactly see it as the most acceptable solution but I'm willing to make the compromise for it. Just because EquipmentCategory is the only current use case for it, doesn't mean that it's the only future use case for it.
As I mentioned previously, EquipmentCategory is the only use-case for it. EquipmentCategories store their options as an array of APIReferences in the equipment
field. And if the consumer is using a typed language, they're gonna want to deserialize the data they fetch from that reference as an EquipmentCategory so that they can handle that. The same can't be said for any other Document that can be referred to with an APIReference. If the option_set_type
was api_reference
, which doesn't indicate any information about the option set's type, the consumer would have to infer the type themselves.
Hopefully this illustrates the purpose of the option_set_type
attribute: to indicate the structure, and therefore the steps needed to deserialize and access, the actual object containing the options. The name of the attribute(s) under that (should) adequately indicate that we're providing a reference rather than the object itself.
Now of course resource_list_url
does indicate that the resulting option set is a resource_list
, but the _url
suffix is redundant (as it is already indicated by the resource_list_url
attribute), and introduces inconsistency between resource_list_url
and equipment_category
.
Now, if we were going to push that purpose to one side in favour of only indicating the immediate type of the data in this Choice structure, and not the type of the option set, then we'd need to include more information in the object to help the user decode the result of resolving the reference. For example:
{
"option_set_type": "api_reference",
"document_type": "equipment-category",
"reference": { "index": "..." }
}
This increases the complexity of the structure somewhat, to solve a problem that doesn't really seem to exist? Even if we did discover a need for more APIReference resolving to different kinds of OptionSets, it would be just as easy to add a new value for option_set_type
as it would a new value for document_type
(or whatever that attribute would be named).
Fine. You seem to know exactly what you want built. You should just do it. I'm tired of discussing this and I'd rather just have it be done. We can always revisit this later.
Oh... ok. I was happy to continue discussing this until we find a solution that works for everyone, but I don't wanna push my luck. Did you have any thoughts about the suggestion I made in my last comment at all?
I didn't come into this knowing what I wanted to build besides having a couple of end goals: consistency and "deserializability". The proposal has already changed so much since the first draft thanks to input from yourself and others. So thanks for that :)
I'm sorry. I should not have written that last response right before going to bed. It was passive aggressive, which was unwarranted for the discussion we were having. That response was also unkind and unfair to you. I should be better than that. It was also hard to tell that you were enjoying the discussion and not just getting frustated, but honestly, there was a better way to do that which was just to reach out to you directly over to Discord to check in, which I should have done. Instead I just shut down a discussion that I didn't need to shut down. I'm sorry.
I can see what you mean by equipment_category
vs. api_reference
and I remember you making a similar argument before and I believe that you are correct. And I think based on what you're saying, resource_list
makes sense and we should just go from there.
I don't think I had considered "deserializability" in our discussions but I can see where you're coming from by mentioning that.
No worries.
I'll update the Gist with the latest amendments, but it may be some time before I can actually see the implementation through. If someone else would like to pick it up in the meantime, they'd be more than welcome.
I've updated the Gist and added a summary of the final state of the proposal to the end of the original comment, as a sort of implementation guide for whoever picks this up.
Very late note, but I've been asked to include this finding here.
This structure will have some issues handling the choices for Ideals, Flaws, Bonds and Personality Traits stored within Backgrounds. Two types of single option must be added in order for these to be used as Options. An "ideal" option will be needed in addition to the "reference" and "action" OptionTypes. Additionally a "string" OptionType will be needed to use Personality Traits, Bonds and Flaws since all of these are just strings.
Fairly self explanatory, just other option types. This would leave us with singular option types of action
, reference
, ideal
, and string
For any unaware, Ideals are not just strings. Here's an example of an Ideal in the Acolyte background.
{
"desc": "Power. I hope to one day rise to the top of my faith's religious hierarchy.",
"alignments": [
{
"index": "lawful-good",
"name": "Lawful Good",
"url": "api/alignments/lawful-good"
},
{
"index": "lawful-neutral",
"name": "Lawful Neutral",
"url": "api/alignments/lawful-neutral"
},
{
"index": "lawful-evil",
"name": "Lawful Evil",
"url": "api/alignments/lawful-evil"
}
]
}
I'm just going to assign this to myself to own it, since I'm not sure it will get done otherwise.
Is this actively being worked on? I'm writing an app that consumes the API, so if the choice structure is going to be changed soon I may have to avoid working with them.
Also, if no work is being done on this currently, I may be able to do it. I need this to be done before I can finish working on an API issue anyway.