Nookipedia / nookipedia-api

Nookipedia's custom API for querying data from the Animal Crossing video game series.
https://api.nookipedia.com/
MIT License
40 stars 12 forks source link

Added fossil endpoints #50

Closed Micalobia closed 3 years ago

Micalobia commented 3 years ago

Fossils endpoint (Resolves #7)

There are a few reasons this is a draft PR atm

I'm not sure how nh_fossil and nh_fossil_group should be joined

  1. We could attach nh_fossil data as lists to nh_fossil_group, but that makes it so it would be /nh/fossils/<groupname>, and to search by raw name you'd do /nh/fossils?name=

  2. Alternatively, we can attach nh_fossil_group to nh_fossil (as it is right now), but that duplicates group info a lot, so you get several of the same description attached to different fossils. However, the name searches are swapped, so you get something like /nh/fossils/<name> and /nh/fossils?group=

  3. The last way is to have /nh/fossils/<name> not return group data except group name, and have a separate endpoint /nh/fossil_groups/<group> (name just an example) to return groups with lists of specific fossils.

So the first and second only involve one endpoint, but return single element lists when searching by name or group, respectively. The last one solves that issue but splits fossils into two endpoints.

KevinPayravi commented 3 years ago

Re. image_url, that has been added 👍

KevinPayravi commented 3 years ago

Re. querying, tricky...fossils are weird, especially since not all fossils have a group. I'm leaning towards the second option out of the three. Straightforward for users to use, and nh_fossil_groups has only two fields (room # and description) so we're not looking at too much repetitive data.

But I've also got an unconventional fourth option: querying both tables at the same time, without the user having to specify which (e.g. WHERE nh_fossil.name = "Ankylo Torso" OR nh_fossil_group.name = "Ankylo Torso"). Example of querying for Ankylo Torso, and example for querying for Ankylosaurus group. I've been thinking about how a Discord bot dev might user this endpoint, and this option would allow their users to ask for both groups and individual fossils without having to specify which type. The bot dev will know if a group has been queried if they get back > 1 results. This is a bit odd and I'm not totally married to it, but I think it could work.

Micalobia commented 3 years ago

I like the idea a lot, the only hurdle I see with it is what to return if they query the list and not by name, as it might be ambiguous.

Duplicate info isn't the biggest deal, the only reason it bothers me in any capacity is that duplicate descriptions make the amount of data being sent a lot higher, because of how long they are (If a description is 250 characters long, then suddenly that description ups the return text by 1.5kb because it was dupped 6 times). Realistically, that isn't the biggest deal (the item endpoints return a lot more just on their own), but it is something to keep in mind.

Also an idea building off yours, it could be something like /nh/fossils/<name> for mixed results, /nh/fossils/group/<name> for groups and /nh/fossils/unique/<name> for individual (unique would probably be different)

Micalobia commented 3 years ago

Waiting on #55 to do any modifications atm, probably going to rebase that or just remake the branch when that is merged, as it'll be a mess otherwise.

I think the approach that'll work best is to have 3 endpoints:

Notes:

KevinPayravi commented 3 years ago

Looks good, though I'm still going back and forth on the all endpoint. I think I'd expect it to return as much data as possible; if someone queries all for an individual fossil, I think they should receive the details for that individual fossil.

One idea is to return something like this, which merges group and individual fossil data (the latter as a nested list). Like what we do for NH item variations.

{
  "group": "Ankylosaurus",
  "description": "Oho! Ankylosaurus was the herbivore hero, the grazing gladiator, the vegetarian barbarian of antiquity! Between its club-like tail, heavy armor, and honest-to-goodness SPIKES, it was a formidable beast! Can you keep a secret? I have even heard recent theories that it actively ATTACKED predators. Can you imagine such behavior in an herbivore? It simply beggars the imagination!",
  "room": 2,
  "fossils": [
    { "name": "Ankylo Skull", "image_url": "https://dodo.ac/np/images/4/45/Ankylo_Skull_NH_Icon.png", "sell": 3500, ...},
    { "name": "Ankylo Tail", "image_url": "https://dodo.ac/np/images/b/bf/Ankylo_Tail_NH_Icon.png", "sell": 2500, ...},
    { "name": "Ankylo Torso", "image_url": "https://dodo.ac/np/images/c/c4/Ankylo_Torso_NH_Icon.png", "sell": 3000, ...}
  ]
}

This would keep a consistent structure while still providing flexibility on the fossil list, and without duplicating group data. If the user asks for a group, they get back group details + all the fossils. If the user asks for a single fossil, they get back the group details + the fossil list with just the one fossil inside.

KevinPayravi commented 3 years ago

Additional note, I updated the wiki/tables so that standalone fossils now also have a group listed.

Micalobia commented 3 years ago

That's actually very similar to what I had in mind, which I'm not sure I communicated super well. I think what you said is better, but what I was thinking was something like

{
  "group": "Ankylosaurus",
  "description": "Oho! Ankylosaurus was the herbivore hero, the grazing gladiator, the vegetarian barbarian of antiquity! Between its club-like tail, heavy armor, and honest-to-goodness SPIKES, it was a formidable beast! Can you keep a secret? I have even heard recent theories that it actively ATTACKED predators. Can you imagine such behavior in an herbivore? It simply beggars the imagination!",
  "room": 2,
  "matched": { "name": "Ankylo Skull", "image_url": "https://dodo.ac/np/images/4/45/Ankylo_Skull_NH_Icon.png", "sell": 3500, ...},
  "fossils": [
    { "name": "Ankylo Skull", "image_url": "https://dodo.ac/np/images/4/45/Ankylo_Skull_NH_Icon.png", "sell": 3500, ...},
    { "name": "Ankylo Tail", "image_url": "https://dodo.ac/np/images/b/bf/Ankylo_Tail_NH_Icon.png", "sell": 2500, ...},
    { "name": "Ankylo Torso", "image_url": "https://dodo.ac/np/images/c/c4/Ankylo_Torso_NH_Icon.png", "sell": 3000, ...}
  ]
}

Where matched shows which thing got matched in the search (maybe a name, instead of the whole object), and null for if it matched the group

Micalobia commented 3 years ago

Something I also hadn't thought of is what to return if excludedetails is called, as it isn't super clear if it should return mixed names, group names, or individual names.

Something that could be done is it would return a structure like

[
  {
    "group": "Ankylosaurus",
    "fossils": [ "Ankylo Skull", "Ankylo Tail", "Ankylo Torso" ]
  },
]