feat: Full rework to support both Kotlin and Java and make it work like the Other SDKs (#2)

This commit is contained in:
2022-05-04 15:25:49 +02:00
committed by GitHub
parent 82aaf7cb01
commit 7ad76513e0
56 changed files with 2126 additions and 1789 deletions

View File

@ -1,79 +0,0 @@
package net.tcgdex;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Describes a single ability of a pokemon
*
*/
public class Ability {
static List<Ability> parse(JSONArray array) {
if (array == null) {
return Collections.emptyList();
}
List<Ability> result = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
result.add(new Ability(array.getJSONObject(i)));
}
return result;
}
private final String type;
private final String name;
private final String effect;
Ability(JSONObject json) {
this(json.getString("type"), json.getString("name"), json.getString("effect"));
}
Ability(String type, String name, String effect) {
this.type = type;
this.name = name;
this.effect = effect;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Ability)) {
return false;
}
Ability other = (Ability) o;
return Objects.deepEquals(new Object[] { this.type, this.name, this.effect },
new Object[] { other.type, other.name, other.effect });
}
/**
*
* @return Description/Effect of the ability
*/
public String getEffect() {
return effect;
}
/**
* @return Name of the ability
*/
public String getName() {
return name;
}
/**
* @return Type of the ability, for example 'Poke-POWER'
*/
public String getType() {
return type;
}
@Override
public int hashCode() {
return Objects.hash(this.type, this.name, this.effect);
}
}

View File

@ -1,90 +0,0 @@
package net.tcgdex;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Describes a single attack of a pokemon, for example 'Confuse Ray'
*
*/
public class Attack {
static List<Attack> parse(JSONArray array) {
if (array == null) {
return Collections.emptyList();
}
List<Attack> result = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
result.add(new Attack(array.getJSONObject(i)));
}
return result;
}
private final List<Types> cost;
private final String name;
private final String effect;
private final String damage;
Attack(JSONObject json) {
this(Types.parse(json.optJSONArray("cost")), json.getString("name"), json.optString("effect"),
json.optString("damage"));
}
Attack(List<Types> cost, String name, String effect, String damage) {
super();
this.cost = cost;
this.name = name;
this.effect = effect;
this.damage = damage;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Attack)) {
return false;
}
Attack other = (Attack) o;
return Objects.deepEquals(new Object[] { this.cost, this.name, this.effect, this.damage },
new Object[] { other.cost, other.name, other.effect, other.damage });
}
/**
* @return Cost of the attack in the same order as listed on the card
*/
public List<Types> getCost() {
return cost;
}
/**
* @return Damage the attack deals. May just be a number like '30', but can also
* be a multiplier like 'x20'
*/
public String getDamage() {
return damage;
}
/**
* @return Effect/Description of the attack, may be null for attacks without text
*/
public String getEffect() {
return effect;
}
/**
* @return Name of the attack
*/
public String getName() {
return name;
}
@Override
public int hashCode() {
return Objects.hash(this.cost, this.name, this.effect, this.damage);
}
}

View File

@ -1,259 +0,0 @@
package net.tcgdex;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Full description of a card, including all information available about it
*
*/
public class CardInfo extends CardResume {
private final String illustrator;
private final Rarities rarity;
private final Categories category;
private final boolean hasNormalVariant;
private final boolean hasReverseVariant;
private final boolean hasHolo;
private final boolean hasFirstEditionPic;
private final SetResume set;
private final List<Integer> dexIDs;
private final Integer hp;
private final List<Types> types;
private final String evolveFrom;
private final String description;
private final String level;
private final String stage;
private final String suffix;
private final List<Attack> attacks;
private final List<Weakness> weakness;
private final List<Ability> abilities;
private final Integer retreat;
private final String regulationMark;
CardInfo(JSONObject json) {
super(json);
this.illustrator = json.optString("illustrator");
this.rarity = Rarities.parse(json.getString("rarity"));
this.category = Categories.parse(json.getString("category"));
JSONObject variantSection = json.getJSONObject("variants");
this.hasNormalVariant = variantSection.getBoolean("normal");
this.hasReverseVariant = variantSection.getBoolean("reverse");
this.hasHolo = variantSection.getBoolean("holo");
this.hasFirstEditionPic = variantSection.getBoolean("firstEdition");
this.set = new SetResume(json.getJSONObject("set"));
this.dexIDs = new ArrayList<>(1);
JSONArray dexArray = json.optJSONArray("dexId");
if (dexArray != null) {
for (int i = 0; i < dexArray.length(); i++) {
this.dexIDs.add(dexArray.getInt(i));
}
}
this.hp = json.optInt("hp", -1) > 0 ? json.getInt("hp") : null;
this.types = Types.parse(json.optJSONArray("types"));
this.stage = json.optString("stage");
this.suffix = json.optString("suffix");
this.attacks = Attack.parse(json.optJSONArray("attacks"));
this.weakness = Weakness.parse(json.optJSONArray("weaknesses"));
this.retreat = json.optInt("retreat", -1) > 0 ? json.getInt("retreat") : null;
this.regulationMark = json.optString("regulationMark");
this.level = json.optString("level");
this.evolveFrom = json.optString("evolveFrom");
this.description = json.optString("effect");
this.abilities = Ability.parse(json.optJSONArray("abilities"));
}
public CardInfo(String id, String localId, String name, String image, String illustrator, Rarities rarity,
Categories category, boolean hasNormalVariant, boolean hasReverseVariant, boolean hasHolo,
boolean hasFirstEditionPic, SetResume set, List<Integer> dexIDs, Integer hp, List<Types> types,
String evolveFrom, String description, String level, String stage, String suffix, List<Attack> attacks,
List<Weakness> weakness, List<Ability> abilities, Integer retreat, String regulationMark) {
super(id, localId, name, image);
this.illustrator = illustrator;
this.rarity = rarity;
this.category = category;
this.hasNormalVariant = hasNormalVariant;
this.hasReverseVariant = hasReverseVariant;
this.hasHolo = hasHolo;
this.hasFirstEditionPic = hasFirstEditionPic;
this.set = set;
this.dexIDs = dexIDs;
this.hp = hp;
this.types = types;
this.evolveFrom = evolveFrom;
this.description = description;
this.level = level;
this.stage = stage;
this.suffix = suffix;
this.attacks = attacks;
this.weakness = weakness;
this.abilities = abilities;
this.retreat = retreat;
this.regulationMark = regulationMark;
}
/**
* @return Pokemon's abilities. May be empty if it doesn't have any, but never
* null
*/
public List<Ability> getAbilities() {
return abilities;
}
/**
* @return Attacks the pokemon has. Empty for cards without attacks
*/
public List<Attack> getAttacks() {
return attacks;
}
/**
*
* @return Card category
*/
public Categories getCategory() {
return category;
}
/**
*
* @return List of the national pokedex IDs of the pokemon on the card (may be
* multiple)
*/
public List<Integer> getDexIDs() {
return dexIDs;
}
/**
*
* @return Card effect/description, may be null
*/
public String getEffect() {
return description;
}
/**
*
* @return Name of the pokemon this one evolves from
*/
public String getEvolveFrom() {
return evolveFrom;
}
/**
* @return HP of the pokemon, will be null if the card is not a pokemon
*/
public Integer getHp() {
return hp;
}
/**
*
* @return Card illustrator, may be null
*/
public String getIllustrator() {
return illustrator;
}
/**
*
* @return Pokemon level, may be 'X', hence not an integer
*/
public String getLevel() {
return level;
}
/**
*
* @return Card rarity
*/
public Rarities getRarity() {
return rarity;
}
/**
*
* @return Card's regulation mark. May be null if unknown or doesn't exist
*/
public String getRegulationMark() {
return regulationMark;
}
/**
* @return Card's retreat. Will be null for cards without retreat
*/
public Integer getRetreat() {
return retreat;
}
/**
* @return Resume of the set the card belongs to
*/
public SetResume getSet() {
return set;
}
/**
* @return Pokemon's stage, like 'Basic'
*/
public String getStage() {
return stage;
}
/**
* @return Suffix, like 'V', may be null
*/
public String getSuffix() {
return suffix;
}
/**
* @return Types of the pokemon
*/
public List<Types> getTypes() {
return types;
}
/**
* @return Weaknesses the pokemon has. Empty for cards without attacks
*/
public List<Weakness> getWeakness() {
return weakness;
}
/**
*
* @return Does the card have a small first edition in the middle left
*/
public boolean hasFirstEditionPic() {
return hasFirstEditionPic;
}
/**
*
* @return Does the card have a holo variant (picture is shining)
*/
public boolean hasHoloVariant() {
return hasHolo;
}
/**
*
* @return Does the card have a normal variant without any shines
*/
public boolean hasNormalVariant() {
return hasNormalVariant;
}
/**
*
* @return Does the card have a reverse variant (colored background is shining)
*/
public boolean hasReverseVariant() {
return hasReverseVariant;
}
}

View File

@ -1,95 +0,0 @@
package net.tcgdex;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Core information to describe a single card
*
*/
public class CardResume implements Comparable<CardResume> {
static List<CardResume> parse(JSONArray array) {
if (array == null) {
return Collections.emptyList();
}
List<CardResume> result = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
result.add(new CardResume(array.getJSONObject(i)));
}
return result;
}
private final String id;
private final String localId;
private final String name;
private final String image;
CardResume(JSONObject json) {
this(json.getString("id"), json.getString("localId"), json.getString("name"), json.optString("image"));
}
CardResume(String id, String localId, String name, String image) {
this.id = id;
this.localId = localId;
this.name = name;
this.image = image;
}
public String toString() {
return String.format("%s (%s): %s,%s", name, id, localId, image);
}
/**
* @return Globally unique card ID based on the set ID and the cards ID within the set
*/
public String getId() {
return id;
}
/**
*
* @return Card image, can be null
*/
public String getImage() {
return image;
}
/**
* @return ID indexing this card within its set, usually just its number
*/
public String getLocalId() {
return localId;
}
/**
*
* @return Card name
*/
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof CardResume)) {
return false;
}
CardResume other = (CardResume) o;
return this.id.equals(other.id);
}
@Override
public int hashCode() {
return this.id.hashCode();
}
@Override
public int compareTo(CardResume arg0) {
return this.id.compareTo(arg0.id);
}
}

View File

@ -1,15 +0,0 @@
package net.tcgdex;
public enum Categories {
POKEMON, ENERGY, TRAINER;
static Categories parse(String raw) {
return Categories.valueOf(raw.toUpperCase().replace(" ", "_"));
}
public String toPrettyString() {
return Utils.prettifyEnumName(this);
}
}

View File

@ -1,16 +0,0 @@
package net.tcgdex;
public enum Rarities {
RARE, COMMON, NONE, ULTRA_RARE, UNCOMMON, AMAZING, SECRET_RARE;
static Rarities parse(String raw) {
return Rarities.valueOf(raw.toUpperCase().replace(" ", "_"));
}
public String toPrettyString() {
return Utils.prettifyEnumName(this);
}
}

View File

@ -1,31 +0,0 @@
package net.tcgdex;
import java.util.List;
import org.json.JSONObject;
/**
* Detailed info regarding a series, including which sets it includes
*
*/
public class SeriesInfo extends SeriesResume {
private final List<SetResume> sets;
SeriesInfo(JSONObject json) {
super(json);
this.sets = SetResume.parse(json.optJSONArray("sets"));
}
SeriesInfo(String id, String name, List<SetResume> sets) {
super(id, name);
this.sets = sets;
}
/**
* @return Resumes of the sets part of this series
*/
public List<SetResume> getSets() {
return sets;
}
}

View File

@ -1,37 +0,0 @@
package net.tcgdex;
import org.json.JSONObject;
/**
* Contains all information describing a series, an overarching group of sets, for example XY
*
*/
public class SeriesResume {
private final String id;
private final String name;
SeriesResume(JSONObject json) {
this(json.getString("id"), json.getString("name"));
}
SeriesResume(String id, String name) {
this.id = id;
this.name = name;
}
/**
* @return Serie unique ID
*/
public String getId() {
return id;
}
/**
* @return Serie name
*/
public String getName() {
return name;
}
}

View File

@ -1,130 +0,0 @@
package net.tcgdex;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import org.json.JSONObject;
/**
* Detailed information regarding a set
*
*/
public class SetInfo extends SetResume {
private static final DateTimeFormatter timeParser = DateTimeFormatter.ofPattern("yyyy-MM-dd");
private final int holo;
private final int normal;
private final int firstEd;
private final int reverse;
private final SeriesResume series;
private final String tcgOnlineCode;
private final LocalDate releaseDate;
private final boolean legalInStandard;
private final boolean legalInExpanded;
private final List<CardResume> cards;
SetInfo(JSONObject json) {
super(json);
JSONObject count = json.getJSONObject("cardCount");
this.holo = count.getInt("holo");
this.firstEd = count.getInt("firstEd");
this.reverse = count.getInt("reverse");
this.normal = count.getInt("normal");
this.series = new SeriesResume(json.getJSONObject("serie"));
this.tcgOnlineCode = json.getString("tcgOnline");
this.releaseDate = LocalDate.parse(json.getString("releaseDate"), timeParser);
JSONObject legality = json.getJSONObject("legal");
this.legalInExpanded = legality.getBoolean("expanded");
this.legalInStandard = legality.getBoolean("standard");
this.cards = CardResume.parse(json.getJSONArray("cards"));
}
SetInfo(String id, String name, String logo, String symbol, int officialCardCount, int totalCardCount, int holo,
int normal, int firstEd, int reverse, SeriesResume series, String tcgOnlineCode, LocalDate releaseDate,
boolean legalInStandard, boolean legalInExpanded, List<CardResume> cards) {
super(id, name, logo, symbol, officialCardCount, totalCardCount);
this.holo = holo;
this.normal = normal;
this.firstEd = firstEd;
this.reverse = reverse;
this.series = series;
this.tcgOnlineCode = tcgOnlineCode;
this.releaseDate = releaseDate;
this.legalInStandard = legalInStandard;
this.legalInExpanded = legalInExpanded;
this.cards = cards;
}
/**
* @return All cards part of the set
*/
public List<CardResume> getCards() {
return cards;
}
/**
* @return Amount of first edition cards the set has
*/
public int getFirstEdCardCount() {
return firstEd;
}
/**
* @return Amount of holo cards the set has
*/
public int getHoloCardCount() {
return holo;
}
/**
* @return Amount of normal cards the set has
*/
public int getNormalCardCount() {
return normal;
}
/**
* @return When the set was released
*/
public LocalDate getReleaseDate() {
return releaseDate;
}
/**
* @return Amount of reverse cards the set has
*/
public int getReverseCardCount() {
return reverse;
}
/**
* @return Series the set is part of
*/
public SeriesResume getSeries() {
return series;
}
/**
* @return Pokémon TCG Online Set code
*/
public String getTcgOnlineCode() {
return tcgOnlineCode;
}
/**
* @return Ability to use this set in Expanded competitions
*/
public boolean isLegalInExpanded() {
return legalInExpanded;
}
/**
* @return Ability to use this set in standard competitions
*/
public boolean isLegalInStandard() {
return legalInStandard;
}
}

View File

@ -1,89 +0,0 @@
package net.tcgdex;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Contains all information describing a set of cards
*
*/
public class SetResume {
static List<SetResume> parse(JSONArray array) {
if (array == null) {
return Collections.emptyList();
}
List<SetResume> result = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
result.add(new SetResume(array.getJSONObject(i)));
}
return result;
}
private final String id;
private final String name;
private final String logo;
private final String symbol;
private final int officialCardCount;
private final int totalCardCount;
public SetResume(JSONObject json) {
this(json.getString("id"), json.getString("name"), json.optString("logo"), json.optString("symbol"),
json.getJSONObject("cardCount").getInt("total"), json.getJSONObject("cardCount").getInt("official"));
}
SetResume(String id, String name, String logo, String symbol, int officialCardCount, int totalCardCount) {
this.id = id;
this.name = name;
this.logo = logo;
this.symbol = symbol;
this.officialCardCount = officialCardCount;
this.totalCardCount = totalCardCount;
}
/**
* @return Set unique ID
*/
public String getId() {
return id;
}
/**
* @return Set logo URL, may be null
*/
public String getLogo() {
return logo;
}
/**
* @return Set name
*/
public String getName() {
return name;
}
/**
* @return Official amount of cards in this set
*/
public int getOfficialCardCount() {
return officialCardCount;
}
/**
* @return Set symbol URL, may be null
*/
public String getSymbol() {
return symbol;
}
/**
* @return Total amount of cards in this set
*/
public int getTotalCardCount() {
return totalCardCount;
}
}

View File

@ -1,243 +0,0 @@
package net.tcgdex;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
public class TCGDexAPI {
public enum Language {
DE, EN, ES, FR, IT, PT;
public String getAPIID() {
return toString().toLowerCase();
}
}
public enum ImageResolution {
HIGH, LOW;
public String forUseInURL() {
return this.name().toLowerCase();
}
}
private static final String API_URL = "https://api.tcgdex.net/v2/%s/%s";
private Language language;
/**
* Construct a new API instance. Does not do any networking, merely initialized
* the local state. Multiple instances of this class may be held and used at the
* same time without issue
*
* @param language Language to use for all queries
*/
public TCGDexAPI(Language language) {
this.language = language;
}
private String buildURL(String path, String... optional) {
String result = String.format(API_URL, this.language.getAPIID(), path);
// not gonna do a string builder here, because we intend this array to be of
// length 1 in almost all cases
for (String opt : optional) {
result += "/" + opt;
}
return result;
}
/**
* Loads the image of a card
* @param card Card to get image for
* @param resolution High is recommended if the card is supposed to be readable and more than a thumbnail
* @return BufferedImage loaded, possibly null if no image of this card exists for this language
* @throws IOException Thrown in response to any kind of networking error
*/
public BufferedImage getImage(CardResume card, ImageResolution resolution) throws IOException {
String url = card.getImage() + "/" + resolution.forUseInURL() + ".png";
return Utils.getImage(url);
}
/**
* Gets a list containing the core information for every core
*
* @return Resume of every card available
* @throws IOException Thrown in response to any kind of networking error
*/
public List<CardResume> getAllCards() throws IOException {
String data = Utils.doGet(buildURL("cards"));
return CardResume.parse(new JSONArray(data));
}
/**
* Gets a list of all known card illustrators
*
* @return List of all illustrators
* @throws IOException Thrown in response to any kind of networking error
*/
public List<String> getAllIllustrators() throws IOException {
return loadStringArrayFrom("illustrators");
}
public List<Integer> getAllPossibleHPValues() throws IOException {
String data = Utils.doGet(buildURL("hp"));
JSONArray json = new JSONArray(data);
List<Integer> result = new ArrayList<>();
for (int i = 0; i < json.length(); i++) {
result.add(json.getInt(i));
}
return result;
}
/**
* Gets a list containing the core information regarding all series
*
* @return Resume of each series
* @throws IOException Thrown in response to any kind of networking error
*/
public List<SeriesResume> getAllSeries() throws IOException {
String data = Utils.doGet(buildURL("series"));
JSONArray json = new JSONArray(data);
List<SeriesResume> result = new ArrayList<>();
for (int i = 0; i < json.length(); i++) {
result.add(new SeriesResume(json.getJSONObject(i)));
}
return result;
}
/**
* Gets a list containing the core information regarding all sets
*
* @return Resume of each set
* @throws IOException Thrown in response to any kind of networking error
*/
public List<SetResume> getAllSets() throws IOException {
String data = Utils.doGet(buildURL("sets"));
return SetResume.parse(new JSONArray(data));
}
/**
* Gets detailed information of a card based on its resume
*
* @param card Card to get info for
* @return Card info obtained
* @throws IOException Thrown in response to any kind of networking error
*/
public CardInfo getCardInfo(CardResume card) throws IOException {
return getCardInfo(card.getId());
}
/**
* Gets detailed information of a card based on its globally unique identifier,
* for example 'base4-1'
*
* @param globalCardID Globally unique ID of the card
* @return Card info obtained
* @throws IOException Thrown in response to any kind of networking error
*/
public CardInfo getCardInfo(String globalCardID) throws IOException {
String data = Utils.doGet(buildURL("cards", globalCardID));
JSONObject json = new JSONObject(data);
if (json.has("error")) {
return null;
}
return new CardInfo(json);
}
/**
* Gets detailed information of a card based on a sets identifier and the
* identifier/index of a card within this set. Note that for example 'base4-1'
* is already a combined identifier, here the correct setID would be 'base4' and
* the cardID '1'
*
* @param setID Unique ID of the set
* @param cardID ID/index describing the card within the set
* @return Card info obtained
* @throws IOException Thrown in response to any kind of networking error
*/
public CardInfo getCardInfo(String setID, String cardID) throws IOException {
String data = Utils.doGet(buildURL("sets", setID, cardID));
JSONObject json = new JSONObject(data);
if (json.has("error")) {
return null;
}
return new CardInfo(json);
}
/**
* Gets detailed information of a series based on a set belonging to it
*
* @param set Set the series belongs to
* @return Detailed information of the series
* @throws IOException Thrown in response to any kind of networking error
*/
public SeriesInfo getSeriesInfo(SetInfo set) throws IOException {
String data = Utils.doGet(buildURL("series", set.getSeries().getId()));
return new SeriesInfo(new JSONObject(data));
}
/**
* Gets detailed information of a series based on its ID
*
* @param seriesID ID of the series
* @return Detailed information of the series
* @throws IOException Thrown in response to any kind of networking error
*/
public SeriesInfo getSeriesInfo(String seriesID) throws IOException {
String data = Utils.doGet(buildURL("series", seriesID));
return new SeriesInfo(new JSONObject(data));
}
/**
* Gets detailed information of a set based on a card belonging to it
*
* @param setID ID of the set
* @return Detailed information of the set
* @throws IOException Thrown in response to any kind of networking error
*/
public SetInfo getSetInfo(CardResume card) throws IOException {
String id = card.getId();
String data = Utils.doGet(buildURL("sets", id.substring(0, id.lastIndexOf("-"))));
return new SetInfo(new JSONObject(data));
}
/**
* Gets detailed information of a set based on its ID
*
* @param setID ID of the set
* @return Detailed information of the set
* @throws IOException Thrown in response to any kind of networking error
*/
public SetInfo getSetInfo(String setID) throws IOException {
String data = Utils.doGet(buildURL("sets", setID));
return new SetInfo(new JSONObject(data));
}
List<String> loadCategories() throws IOException {
return loadStringArrayFrom("categories");
}
List<String> loadRarities() throws IOException {
return loadStringArrayFrom("rarities");
}
private List<String> loadStringArrayFrom(String path) throws IOException {
String data = Utils.doGet(buildURL(path));
JSONArray json = new JSONArray(data);
List<String> result = new ArrayList<>();
for (int i = 0; i < json.length(); i++) {
result.add(json.getString(i));
}
return result;
}
List<String> loadTypes() throws IOException {
return loadStringArrayFrom("types");
}
}

View File

@ -1,39 +0,0 @@
package net.tcgdex;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.json.JSONArray;
public enum Types {
PSYCHIC, FIGHTING, COLORLESS, LIGHTNING, GRASS, DRAGON, METAL, FIRE, WATER, DARKNESS, FAIRY;
static List<Types> parse(JSONArray array) {
if (array == null) {
return Collections.emptyList();
}
List<Types> result = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
Types type = parse(array.getString(i));
if (type != null) {
result.add(type);
}
}
return result;
}
static Types parse(String raw) {
try {
return Types.valueOf(raw.toUpperCase().replace(" ", "_"));
} catch (IllegalArgumentException e) {
return null;
}
}
public String toPrettyString() {
return Utils.prettifyEnumName(this);
}
}

View File

@ -1,64 +0,0 @@
package net.tcgdex;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import javax.imageio.ImageIO;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
class Utils {
static String doGet(String url) throws IOException {
CloseableHttpClient client = null;
CloseableHttpResponse response = null;
client = HttpClients.createDefault();
HttpGet httpPost = new HttpGet(url);
response = client.execute(httpPost);
String output = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line = null;
StringBuilder builder = new StringBuilder();
while ((line = reader.readLine()) != null) {
builder.append(line);
}
output = builder.toString();
return output;
}
public static BufferedImage getImage(String imageUrl) throws IOException {
return ImageIO.read(new URL(imageUrl));
}
public static String prettifyEnumName(Enum<?> enumInstance) {
boolean space = true;
String rawRepresentation = enumInstance.name();
StringBuilder output = new StringBuilder(rawRepresentation.length());
for (int i = 0; i < rawRepresentation.length(); i++) {
String character = rawRepresentation.substring(i, i + 1);
if (character.equals("_")) {
output.append(" ");
space = true;
continue;
}
if (space) {
// keep upper case
space = false;
output.append(character);
} else {
output.append(character.toLowerCase());
}
}
return output.toString();
}
}

View File

@ -1,77 +0,0 @@
package net.tcgdex;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Describes the weakness of a single pokemon, for example: 2x to Fire
*
*/
public class Weakness {
static List<Weakness> parse(JSONArray array) {
if (array == null) {
return Collections.emptyList();
}
List<Weakness> result = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
result.add(new Weakness(array.getJSONObject(i)));
}
return result;
}
private final Types type;
private final String value;
Weakness(JSONObject json) {
this(Types.parse(json.getString("type")), json.optString("value"));
}
Weakness(Types type, String value) {
this.type = type;
this.value = value;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Weakness)) {
return false;
}
Weakness other = (Weakness) o;
return Objects.deepEquals(new Object[] { this.type, this.value},
new Object[] { other.type, other.value});
}
/**
* @return Type the weakness is to
*/
public Types getType() {
return type;
}
/**
* @return Descriptor of the weakness multiplier, including a leading x, for example 'x2'. May be null
*/
public String getValue() {
return value;
}
@Override
public int hashCode() {
return Objects.hash(this.type, this.value);
}
@Override
public String toString() {
return String.format("%s %s", this.type, this.value);
}
}

View File

@ -0,0 +1,28 @@
package net.tcgdex.sdk
/**
* The different extension an image is available in
*/
enum class Extension(
/**
* the string representation of the extension
*/
val value: String
) {
/**
* .png image, with transparent background
*/
PNG("png"),
/**
* .jpg image, with white background
*/
JPG("jpg"),
/**
* .webp image, with transparent background
*/
WEBP("webp")
}

View File

@ -0,0 +1,24 @@
package net.tcgdex.sdk
/**
* Image quality if applicable
* (only cards does have quality selector)
*/
enum class Quality(
/**
* the string representation of the quality
*/
val value: String
) {
/**
* A High quality image
*/
HIGH("high"),
/**
* A Low quality image
*/
LOW("low")
}

View File

@ -0,0 +1,355 @@
package net.tcgdex.sdk
import net.tcgdex.sdk.models.Card
import net.tcgdex.sdk.models.CardResume
import net.tcgdex.sdk.models.Serie
import net.tcgdex.sdk.models.SerieResume
import net.tcgdex.sdk.models.Set
import net.tcgdex.sdk.models.SetResume
import net.tcgdex.sdk.models.StringEndpoint
/**
* The main TCGdex SDK instance
*
* @constructor Create the TCGdex Instance in the specific language
*/
class TCGdex(
/**
* the language you want to use, values: [en,fr,es,de,pt,it]
*/
var language: String
) {
/**
* The API Endpoint you want to use
*/
var URI = "https://api.tcgdex.net/v2"
/**
* Fetch every Pokémon cards
*
* _note: take some time as there is around 13k-15k cards depending on the language_
*
* @return the list of Pokémon Cards
*/
fun fetchCards(): Array<CardResume>? {
return this.fetch(Array<CardResume>::class.java, "cards")
}
/**
* Fetch a specific card
*
* @param card the card ID
* @return The card
*/
fun fetchCard(cardId: String): Card? {
return this.fetch(Card::class.java, "cards", cardId)
}
/**
* Fetch a specific card by its set and local IDs
*
* @param setId the set ID/name
* @param cardId the card local ID
* @return the card you want
*/
fun fetchCard(setId: String, cardId: String): Card? {
return this.fetch(Card::class.java, "sets", setId, cardId)
}
/**
* Fetch every pokémon TCG Sets
*
* @return the list of Pokémon TCG sets
*/
fun fetchSets(): Array<SetResume>? {
return this.fetch(Array<SetResume>::class.java, "sets")
}
/**
* Fetch a specific set
*
* @param set the set you want to fetch (you can use the Set ID or name)
* @return The set you searched
*/
fun fetchSet(set: String): Set? {
return this.fetch(Set::class.java, "sets", set)
}
/**
* Fetch every pokémon TCG Series
*
* @return the list of Pokémon TCG Series
*/
fun fetchSeries(): Array<SerieResume>? {
return this.fetch(Array<SerieResume>::class.java, "series")
}
/**
* Fetch a specific serie
*
* @param serie the serie you want to fetch (you can use the Serie ID or name)
* @return The serie you searched
*/
fun fetchSerie(serie: String): Serie? {
return this.fetch(Serie::class.java, "series", serie)
}
/**
* Fetch evey variants it is possible to have
*
* @return the list of evey variants it is possible to have
*/
fun fetchVariants(): Array<String>? {
return this.fetch(Array<String>::class.java, "variants")
}
/**
* Fetch cards by variant
*
* @param variant the variant you want to filter by
* @return a StringEndpoint containing the cards with the specified variant
*/
fun fetchVariant(variant: String): StringEndpoint? {
return this.fetch(StringEndpoint::class.java, "variants", variant)
}
/**
* Fetch evey Trainer Types it is possible to have
*
* @return the list of evey Trainer Types it is possible to have
*/
fun fetchTrainerTypes(): Array<String>? {
return this.fetch(Array<String>::class.java, "trainer-types")
}
/**
* Fetch cards by trainer type
*
* @param type the trainer type you want to filter by
* @return a StringEndpoint containing the cards with the specified trainer type
*/
fun fetchTrainerType(type: String): StringEndpoint? {
return this.fetch(StringEndpoint::class.java, "trainer-types", type)
}
/**
* Fetch evey suffixes it is possible to have
*
* @return the list of evey suffixes it is possible to have
*/
fun fetchSuffixes(): Array<String>? {
return this.fetch(Array<String>::class.java, "suffixes")
}
/**
* Fetch cards by suffix
*
* @param suffix the suffix you want to filter by
* @return a StringEndpoint containing the cards with the specified suffix
*/
fun fetchSuffix(suffix: String): StringEndpoint? {
return this.fetch(StringEndpoint::class.java, "suffixes", suffix)
}
/**
* Fetch evey stages it is possible to have
*
* @return the list of evey stages it is possible to have
*/
fun fetchStages(): Array<String>? {
return this.fetch(Array<String>::class.java, "stages")
}
/**
* Fetch cards by stage
*
* @param stage the stage you want to filter by
* @return a StringEndpoint containing the cards with the specified stage
*/
fun fetchStage(stage: String): StringEndpoint? {
return this.fetch(StringEndpoint::class.java, "stages", stage)
}
/**
* Fetch evey Regulation Marks it is possible to have
*
* @return the list of evey Regulation Marks it is possible to have
*/
fun fetchRegulationMarks(): Array<String>? {
return this.fetch(Array<String>::class.java, "regulation-marks")
}
/**
* Fetch cards by regulation mark
*
* @param regulationMark the regulation mark you want to filter by
* @return a StringEndpoint containing the cards with the specified regulation mark
*/
fun fetchRegulationMark(regulationMark: String): StringEndpoint? {
return this.fetch(StringEndpoint::class.java, "regulation-marks", regulationMark)
}
/**
* Fetch evey Energy Types it is possible to have
*
* @return the list of evey Energy Types it is possible to have
*/
fun fetchEnergyTypes(): Array<String>? {
return this.fetch(Array<String>::class.java, "energy-types")
}
/**
* Fetch cards by Energy type
*
* @param energyType the Energy type you want to filter by
* @return a StringEndpoint containing the cards with the specified Energy type
*/
fun fetchEnergyType(energyType: String): StringEndpoint? {
return this.fetch(StringEndpoint::class.java, "energy-types", energyType)
}
/**
* Fetch evey Pokédex IDS it is possible to have
*
* @return the list of evey Pokédex IDS it is possible to have
*/
fun fetchDexIds(): Array<String>? {
return this.fetch(Array<String>::class.java, "dex-ids")
}
/**
* Fetch cards by pokédex ID
*
* @param dexId the pokédex ID you want to filter by
* @return a StringEndpoint containing the cards with the specified pokédex ID
*/
fun fetchDexId(dexId: String): StringEndpoint? {
return this.fetch(StringEndpoint::class.java, "dex-ids", dexId)
}
/**
* Fetch evey types it is possible to have
*
* @return the list of evey types it is possible to have
*/
fun fetchTypes(): Array<String>? {
return this.fetch(Array<String>::class.java, "types")
}
/**
* Fetch cards by type
*
* @param type the type you want to filter by
* @return a StringEndpoint containing the cards with the specified type
*/
fun fetchType(type: String): StringEndpoint? {
return this.fetch(StringEndpoint::class.java, "types", type)
}
/**
* Fetch evey categories it is possible to have
*
* @return the list of evey categories it is possible to have
*/
fun fetchCategories(): Array<String>? {
return this.fetch(Array<String>::class.java, "categories")
}
/**
* Fetch cards by category
*
* @param category the category you want to filter by
* @return a StringEndpoint containing the cards with the specified category
*/
fun fetchCategory(category: String): StringEndpoint? {
return this.fetch(StringEndpoint::class.java, "categories", category)
}
/**
* Fetch evey retreat count it is possible to have
*
* @return the list of evey retreat count it is possible to have
*/
fun fetchRetreats(): Array<String>? {
return this.fetch(Array<String>::class.java, "retreats")
}
/**
* Fetch cards by retreat
*
* @param retreat the retreat count you want to filter by
* @return a StringEndpoint containing the cards with the specified retreat count
*/
fun fetchRetreat(retreat: String): StringEndpoint? {
return this.fetch(StringEndpoint::class.java, "retreats", retreat)
}
/**
* Fetch every Card rarities you can have (in your language)
*
* @return the list of Card rarities you can have (in your language)
*/
fun fetchRarities(): Array<String>? {
return this.fetch(Array<String>::class.java, "rarities")
}
/**
* Fetch cards by rarity
*
* @param rarity the rarity you want to filter by (language specific)
* @return a StringEndpoint containing the cards with the specified rarity
*/
fun fetchRarity(rarity: String): StringEndpoint? {
return this.fetch(StringEndpoint::class.java, "rarities", rarity)
}
/**
* Fetch every cards illustrators
*
* @return the list of ilustrators
*/
fun fetchIllustrators(): Array<String>? {
return this.fetch(Array<String>::class.java, "illustrators")
}
/**
* Fetch cards by illustrator
*
* @param illustrator the illustrator you want to filter by
* @return a StringEndpoint containing the cards with the specified illustrator
*/
fun fetchIllustrator(illustrator: String): StringEndpoint? {
return this.fetch(StringEndpoint::class.java, "illustrators", illustrator)
}
/**
* Fetch the list of possible value the HP field can take
*
* @return the list of possible value the HP field can take
*/
fun fetchHPs(): Array<String>? {
return this.fetch(Array<String>::class.java, "hp")
}
/**
* Fetch cards by hp
*
* @param hp the hp count you want to filter by
* @return a StringEndpoint containing the cards with the specified hp count
*/
fun fetchHP(hp: String): StringEndpoint? {
return this.fetch(StringEndpoint::class.java, "hp", hp)
}
private fun <T> fetch(cls: Class<T>, vararg path: String): T? {
return Utils.fetch(this, "$URI/$language/${
path.joinToString("/") {
it.replace(
" ",
"%20"
)
}
}", cls)
}
}

View File

@ -0,0 +1,81 @@
package net.tcgdex.sdk
import com.google.gson.Gson
import net.tcgdex.sdk.internal.CacheEntry
import net.tcgdex.sdk.internal.Model
import java.awt.image.BufferedImage
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
import java.net.URL
import java.time.LocalDateTime
import javax.imageio.ImageIO
object Utils {
/**
* Request Time to Live
* in minutes
*/
var ttl: Long = 60
/**
* requests cache
*/
private val cache: HashMap<String, CacheEntry<String>> = HashMap()
private val gson = Gson()
/**
* fetch from the API
*
* @param tcgdex the TCGdex instance to link with it
* @param url the url to fetch from
* @param cls the Class to build the response into
*
* @return an initialized cls or null
*/
fun <T> fetch(tcgdex: TCGdex, url: String, cls: Class<T>): T? {
var entry = this.cache[url]
val now = LocalDateTime.now().minusMinutes(ttl)
if (entry == null || entry.time.isBefore(now)) {
val req = URL(url).openConnection()
req.setRequestProperty("user-agent", "@tcgdex/java-sdk")
val br = BufferedReader(InputStreamReader(req.getInputStream()));
var txt = ""
var line = br.readLine()
while (line != null)
{
txt += line
line = br.readLine()
}
entry = CacheEntry(txt)
this.cache[url] = entry
}
try {
val model = gson.fromJson<T>(
entry.value, cls
)
if (model is Model) {
model.tcgdex = tcgdex
}
return model
} catch (e: IOException) {
return null
}
}
/**
* download an image from the internet
*
* @param path the url to the image
*
* @return the download image buffer
*/
fun downloadImage(path: String): BufferedImage {
return ImageIO.read(URL(path))
}
}

View File

@ -0,0 +1,8 @@
package net.tcgdex.sdk.internal
import java.time.LocalDateTime
data class CacheEntry <T> (
val value: T,
val time: LocalDateTime = LocalDateTime.now()
)

View File

@ -0,0 +1,18 @@
package net.tcgdex.sdk.internal
import com.google.gson.Gson
import net.tcgdex.sdk.TCGdex
abstract class Model {
/**
* Give you a string representation of the Model
*
* @return the model data as JSON
*/
override fun toString(): String {
val gson = Gson()
return gson.toJson(this)
}
public lateinit var tcgdex: TCGdex
}

View File

@ -0,0 +1,187 @@
package net.tcgdex.sdk.models
import net.tcgdex.sdk.Extension
import net.tcgdex.sdk.Quality
import net.tcgdex.sdk.Utils
import net.tcgdex.sdk.internal.Model
import net.tcgdex.sdk.models.subs.CardAbility
import net.tcgdex.sdk.models.subs.CardAttack
import net.tcgdex.sdk.models.subs.CardItem
import net.tcgdex.sdk.models.subs.CardVariants
import net.tcgdex.sdk.models.subs.CardWeakRes
import net.tcgdex.sdk.models.subs.Legal
import java.awt.image.BufferedImage
/**
* Pokémon TCG Card, It contains every informations about a specific card
*/
data class Card internal constructor(
/**
* Globally unique card ID based on the set ID and the cards ID within the set
*/
val id: String,
/**
* ID indexing this card within its set, usually just its number
*/
val localId: String,
/**
* Card name
*/
val name: String,
/**
* Card image url without the extension and quality
*/
val image: String?,
/**
* Card illustrator
*/
val illustrator: String?,
/**
* Card rarity
*/
val rarity: String,
/**
* Card category
*/
val category: String,
/**
* The card possible variants
*/
val variants: CardVariants?,
/**
* Resume of the set the card belongs to
*/
val set: SetResume,
/**
* the Pokémon Pokédex IDs (multiple if multiple pokémon appears on the card)
*/
val dexIDs: List<Int>?,
/**
* HP of the pokemon
*/
val hp: Int?,
/**
* Types of the pokemon (multiple because some have multiple in the older sets)
*/
val types: List<String>?,
/**
* Name of the pokemon this one evolves from
*/
val evolveFrom: String?,
/**
* the Pokémon Pokédex like description
*/
val description: String?,
/**
*the Pokémon Level (can be "X" if the card is of level X)
*/
val level: String?,
/**
* the Pokémon Stage (changes depending on the API language)
*/
val stage: String?,
/**
* the Pokémon Suffix (changes depending on the API language)
*/
val suffix: String?,
/**
* the Item the Pokémon have
*/
val item: CardItem?,
/**
* the Card abilities (some cards have multiple abilities)
*/
val abilities: List<CardAbility>,
/**
* the Card Attacks
*/
val attacks: List<CardAttack>,
/**
*
* the Pokémon Weaknesses
*/
val weaknesses: List<CardWeakRes>,
/**
*
* the Pokémon Resistances
*/
val resistances: List<CardWeakRes>,
/**
*
* the Pokémon retreat Cost
*/
val retreat: Int?,
/**
* effect the Card Effect (Trainer/Energy only)
*/
val effect: String?,
/**
* the trainer sub type (changes depending on the API language)
*/
val trainerType: String?,
/**
* the energy sub type (changes depending on the API language)
*/
val energyType: String?,
/**
* the Card Regulation mark
*/
val regulationMark: String?,
/**
* the card ability to be played in tournaments
*/
val legal: Legal
) : Model() {
/**
* the Card Image full URL
*
* @param quality the quality you want your image to be in
* @param extension extension you want you image to be
* @return the full card URL with the extension and quality
*/
fun getImageUrl(quality: Quality, extension: Extension): String {
return "${this.image}/${quality.value}.${extension}"
}
/**
* Get image buffer
*
* @param quality the quality you want your image to be in
* @param format extension you want you image to be
* @return the full card Buffer in the format you want
*/
fun getImage(quality: Quality, format: Extension): BufferedImage {
return Utils.downloadImage(this.getImageUrl(quality, format))
}
}

View File

@ -0,0 +1,67 @@
package net.tcgdex.sdk.models
import net.tcgdex.sdk.Extension
import net.tcgdex.sdk.Quality
import net.tcgdex.sdk.Utils
import net.tcgdex.sdk.internal.Model
import java.awt.image.BufferedImage
/**
* Card Resume class, contains basic informations about a specific card
*
* to get the full card you can use the `getFullCard()` function
*/
data class CardResume internal constructor(
/**
* Globally unique card ID based on the set ID and the cards ID within the set
*/
val id: String,
/**
* ID indexing this card within its set, usually just its number
*/
val localId: String,
/**
* Card name
*/
val name: String,
/**
* Card image url without the extension and quality
*/
val image: String?
) : Model() {
/**
* the the Card Image full URL
*
* @param quality the quality you want your image to be in
* @param extension extension you want you image to be
* @return the full card URL with the extension and quality
*/
fun getImageUrl(quality: Quality, extension: Extension): String {
return "${this.image}/${quality}.${extension.value}"
}
/**
* Get image buffer
*
* @param quality the quality you want your image to be in
* @param format extension you want you image to be
* @return the full card Buffer in the format you want
*/
fun getImage(quality: Quality, format: Extension): BufferedImage {
return Utils.downloadImage(this.getImageUrl(quality, format))
}
/**
* Get the full Card
*
* @return the full card if available
*/
fun getFullCard(): Card? {
return this.tcgdex.fetchCard(this.id)
}
}

View File

@ -0,0 +1,57 @@
package net.tcgdex.sdk.models
import net.tcgdex.sdk.Extension
import net.tcgdex.sdk.Utils
import net.tcgdex.sdk.internal.Model
import java.awt.image.BufferedImage
/**
* Pokémon TCG Serie
*/
class Serie (
/**
* the list of sets the Serie contains
*/
val sets: List<SetResume>,
/**
* the Serie unique ID
*/
val id: String,
/**
* the Serie name
*/
val name: String,
/**
* the Serie Logo (basically also the first set logo)
*/
val logo: String?
) : Model() {
/**
* Get the logo full url
*
* @param extension the file extension you want to use
* @return the full URL of the logo
*/
fun getLogoUrl(extension: Extension): String? {
if (this.logo == null) {
return null
}
return "${this.logo}.${extension.value}"
}
/**
* Get the logo buffer
*
* @param format the image format
* @return a buffer containing the image
*/
fun getLogo(format: Extension): BufferedImage? {
val logo = this.getLogoUrl(format) ?: return null
return Utils.downloadImage(logo)
}
}

View File

@ -0,0 +1,62 @@
package net.tcgdex.sdk.models
import net.tcgdex.sdk.Extension
import net.tcgdex.sdk.Utils
import net.tcgdex.sdk.internal.Model
import java.awt.image.BufferedImage
/**
* Serie Resume
*/
open class SerieResume internal constructor(
/**
* the Serie unique ID
*/
val id: String,
/**
* the Serie name
*/
val name: String,
/**
* the Serie Logo (basically also the first set logo)
*/
val logo: String?
) : Model() {
/**
* Get the logo full url
*
* @param extension
* @return
*/
fun getLogoUrl(extension: Extension): String? {
if (this.logo == null) {
return null
}
return "${this.logo}.${extension}"
}
/**
* Get the logo buffer
*
* @param format
* @return
*/
fun getLogo(format: Extension): BufferedImage? {
val logo = this.getLogoUrl(format) ?: return null
return Utils.downloadImage(logo)
}
/**
* Get the full Serie
*
* @return the full serie if available
*/
fun getFullSerie(): Serie? {
return this.tcgdex.fetchSerie(this.id)
}
}

View File

@ -0,0 +1,113 @@
package net.tcgdex.sdk.models
import net.tcgdex.sdk.Extension
import net.tcgdex.sdk.Utils
import net.tcgdex.sdk.internal.Model
import net.tcgdex.sdk.models.subs.Legal
import net.tcgdex.sdk.models.subs.SetCardCount
import java.awt.image.BufferedImage
/**
* Pokémon TCG Set class
*/
data class Set internal constructor(
/**
* Globally unique set ID
*/
val id: String?,
/**
* the Set mame
*/
val name: String?,
/**
* the Set Logo incomplete URL (use getLogoUrl/getLogo)
*/
val logo: String?,
/**
* the Set Symbol imcomplete URL (use getSymbolUrl/getSymbol)
*/
val symbol: String?,
/**
* the serie this set is a part of
*/
val serie: SerieResume,
/**
* the TCG Online Code
*/
val tcgOnline: String?,
/**
* the Set release date as yyyy-mm-dd
*/
val releaseDate: String?,
/**
* the set legality (won't indicate if a card is banned)
*/
val legal: Legal,
/**
* the number of card in the set
*/
val cardCount: SetCardCount,
/**
* the cards contained in this set
*/
val cards: List<CardResume>
) : Model() {
/**
* Get logo url
*
* @param extension
* @return
*/
fun getLogoUrl(extension: Extension): String? {
if (this.logo == null) {
return null
}
return "${this.logo}.${extension.value}"
}
/**
* Get logo
*
* @param extension
* @return
*/
fun getLogo(extension: Extension): BufferedImage? {
val logo = this.getLogoUrl(extension) ?: return null
return Utils.downloadImage(logo)
}
/**
* Get symbol url
*
* @param extension
* @return
*/
fun getSymbolUrl(extension: Extension): String? {
if (this.symbol == null) {
return null
}
return "${this.symbol}.${extension.value}"
}
/**
* Get symbol
*
* @param extension
* @return
*/
fun getSymbol(extension: Extension): BufferedImage? {
val symbol = this.getSymbolUrl(extension) ?: return null
return Utils.downloadImage(symbol)
}
}

View File

@ -0,0 +1,96 @@
package net.tcgdex.sdk.models
import net.tcgdex.sdk.Extension
import net.tcgdex.sdk.Utils
import net.tcgdex.sdk.internal.Model
import net.tcgdex.sdk.models.subs.SetCardCountResume
import java.awt.image.BufferedImage
/**
* Set resume
*/
data class SetResume internal constructor(
/**
* Globally unique set ID
*/
val id: String,
/**
* the Set mame
*/
val name: String,
/**
* the Set Logo incomplete URL (use getLogoUrl/getLogo)
*/
val logo: String?,
/**
* the Set Symbol incomplete URL (use getSymbolUrl/getSymbol)
*/
val symbol: String?,
/**
* the number of card in the set
*/
val cardCount: SetCardCountResume
) : Model() {
/**
* Get logo url
*
* @param extension
* @return
*/
fun getLogoUrl(extension: Extension): String? {
if (this.logo == null) {
return null
}
return "${this.logo}.${extension}"
}
/**
* Get logo
*
* @param extension
* @return
*/
fun getLogo(extension: Extension): BufferedImage? {
val logo = this.getLogoUrl(extension) ?: return null
return Utils.downloadImage(logo)
}
/**
* Get symbol url
*
* @param extension
* @return
*/
fun getSymbolUrl(extension: Extension): String? {
if (this.symbol == null) {
return null
}
return "${this.symbol}.${extension}"
}
/**
* Get symbol
*
* @param extension
* @return
*/
fun getSymbol(extension: Extension): BufferedImage? {
val symbol = this.getSymbolUrl(extension) ?: return null
return Utils.downloadImage(symbol)
}
/**
* Get the full set
*
* @return the full set if available
*/
fun getFullSet(): Set? {
return this.tcgdex.fetchSet(this.id)
}
}

View File

@ -0,0 +1,20 @@
package net.tcgdex.sdk.models
import net.tcgdex.sdk.internal.Model
/**
* Generix class that handle a lot of Endpoints
*
* @constructor Create empty String endpoint
*/
data class StringEndpoint(
/**
* the endpoint value
*/
val name: String,
/**
* the cards that contain `name` in them
*/
val cards: List<CardResume>
) : Model()

View File

@ -0,0 +1,23 @@
package net.tcgdex.sdk.models.subs
/**
* Describes a single ability of a pokemon
*/
data class CardAbility internal constructor(
/**
* The Ability type (language dependant)
*/
val type: String,
/**
* Name of the ability
*/
val name: String,
/**
*
* Description/Effect of the ability
*/
val effect: String
)

View File

@ -0,0 +1,28 @@
package net.tcgdex.sdk.models.subs
/**
* Describes a single attack of a pokemon, for example 'Confuse Ray'
*/
data class CardAttack internal constructor(
/**
* Name of the attack
*/
val name: String,
/**
* Cost of the attack in the same order as listed on the card
*/
val cost: List<String>? = null,
/**
* Effect/Description of the attack, may be null for attacks without text
*/
val effect: String? = null,
/**
* Damage the attack deals. May just be a number like '30', but can also be a multiplier like 'x20'
*/
val damage: String? = null
)

View File

@ -0,0 +1,17 @@
package net.tcgdex.sdk.models.subs
/**
* Card Item
*/
data class CardItem(
/**
* the Item name
*/
val name: String,
/**
* the item effect
*/
val effect: String
)

View File

@ -0,0 +1,32 @@
package net.tcgdex.sdk.models.subs
/**
* Card variants
*/
data class CardVariants(
/**
* basic variant no special effects
*/
val normal: Boolean?,
/**
* the card have some shine behind colored content
*/
val reverse: Boolean?,
/**
* the card picture have some shine to it
*/
val holo: Boolean?,
/**
* the card contains a First Edition Stamp (only Base serie)
*/
val firstEdition: Boolean?,
/**
* the card has a wPromo stamp on it
*/
val wPromo: Boolean?
)

View File

@ -0,0 +1,18 @@
package net.tcgdex.sdk.models.subs
/**
* Describes the weakness/resistance of a single pokemon, for example: 2x to Fire
*/
data class CardWeakRes internal constructor(
/**
* the affecting type
*/
val type: String,
/**
* the multiplier mostly `x2` but can also be `-30`, `+30` depending on the card
*/
val value: String?
)

View File

@ -0,0 +1,19 @@
package net.tcgdex.sdk.models.subs
/**
* Card Legality
*
* _note: cards are always usable in the unlimited tournaments_
*/
data class Legal(
/**
* card is usable in standard tournaments
*/
val standard: Boolean,
/**
* card is usable in expanded tournaments
*/
val expanded: Boolean
)

View File

@ -0,0 +1,37 @@
package net.tcgdex.sdk.models.subs
/**
* Set card count
*/
data class SetCardCount (
/**
* total of number of cards
*/
val total: Int,
/**
* number of cards officialy (on the bottom of each cards)
*/
val official: Int,
/**
* number of cards having a normal version
*/
val normal: Int,
/**
* number of cards having an reverse version
*/
val reverse: Int,
/**
* number of cards having an holo version
*/
val holo: Int,
/**
* Number of possible cards
*/
val firstEd: Int?
)

View File

@ -0,0 +1,17 @@
package net.tcgdex.sdk.models.subs
/**
* Set card count resume
*/
data class SetCardCountResume (
/**
* total of number of cards
*/
val total: Int,
/**
* number of cards officialy (on the bottom of each cards)
*/
val official: Int
)

View File

@ -1,169 +0,0 @@
package net.tcgdex;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.time.Month;
import java.util.Arrays;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import net.tcgdex.TCGDexAPI.ImageResolution;
import net.tcgdex.TCGDexAPI.Language;
public class TestAPI {
private TCGDexAPI api;
@Before
public void initAPI() {
this.api = new TCGDexAPI(Language.EN);
}
@Test
public void testRarities() {
assertEquals("Rare", Rarities.RARE.toPrettyString());
assertEquals("Ultra Rare", Rarities.ULTRA_RARE.toPrettyString());
assertEquals("Secret Rare", Rarities.SECRET_RARE.toPrettyString());
assertEquals("Common", Rarities.COMMON.toPrettyString());
}
@Test
public void compareRarityEnumToAPI() throws IOException {
List<String> rarities = api.loadRarities();
assertNotNull(rarities);
assertEquals(rarities.size(), Rarities.values().length);
for (String rawRarity : rarities) {
Rarities rarity = Rarities.parse(rawRarity);
assertNotNull(rarity);
assert (rarity.toPrettyString().equals(rawRarity));
}
}
@Test
public void compareCategoryEnumToAPI() throws IOException {
List<String> categories = api.loadCategories();
assertNotNull(categories);
assertEquals(categories.size(), Categories.values().length);
for (String rawCategory : categories) {
Categories category = Categories.parse(rawCategory);
assertNotNull(category);
assert (category.toPrettyString().equals(rawCategory));
}
}
@Test
public void compareTypeEnumToAPI() throws IOException {
List<String> types = api.loadTypes();
assertNotNull(types);
assertEquals(types.size(), Types.values().length);
for (String rawType : types) {
Types type = Types.parse(rawType);
assertNotNull(type);
assert (type.toPrettyString().equals(rawType));
}
}
@Test
public void testHPAPI() throws IOException {
List<Integer> hp = api.getAllPossibleHPValues();
assertNotNull(hp);
assert (hp.size() > 30);
assert (hp.contains(60));
assert (hp.contains(140));
assert (hp.contains(320));
}
@Test
public void testFullCardInfo() throws IOException {
CardInfo info = api.getCardInfo("base4", "1");
assertNotNull(info);
assertEquals(Categories.POKEMON, info.getCategory());
assertEquals("base4-1", info.getId());
assertEquals("Ken Sugimori", info.getIllustrator());
assertEquals("1", info.getLocalId());
assertEquals("Alakazam", info.getName());
assertEquals(Rarities.RARE, info.getRarity());
SetResume resume = info.getSet();
assertNotNull(resume);
assertEquals(130, resume.getOfficialCardCount());
assertEquals(130, resume.getTotalCardCount());
assertEquals("base4", resume.getId());
assertEquals("Base Set 2", resume.getName());
assertFalse(info.hasFirstEditionPic());
assertTrue(info.hasHoloVariant());
assertTrue(info.hasNormalVariant());
assertTrue(info.hasReverseVariant());
assertArrayEquals(new Integer[] { 65 }, info.getDexIDs().toArray());
Attack attack = new Attack(Arrays.asList(Types.PSYCHIC, Types.PSYCHIC, Types.PSYCHIC), "Confuse Ray",
"Flip a coin. If heads, the Defending Pokémon is now Confused.", "30");
assertArrayEquals(new Attack[] { attack }, info.getAttacks().toArray());
assertEquals(80, (int) info.getHp());
assertArrayEquals(new Types[] { Types.PSYCHIC }, info.getTypes().toArray());
Ability ability = new Ability("Poke-POWER", "Damage Swap",
"As often as you like during your turn (before your attack), you may move 1 damage counter from 1 of your "
+ "Pokémon to another as long as you don't Knock Out that Pokémon. This power can't be used if Alakazam is Asleep, "
+ "Confused, or Paralyzed.");
assertArrayEquals(new Ability[] { ability }, info.getAbilities().toArray());
assertEquals("Stage2", info.getStage());
assertEquals("Kadabra", info.getEvolveFrom());
assertArrayEquals(new Weakness[] { new Weakness(Types.PSYCHIC, "×2") }, info.getWeakness().toArray());
// fetch a few more cards of different types to make sure there are no
// exceptions due to weird combinations of fields missing
assertNotNull(api.getCardInfo("sm10-183"));
assertNotNull(api.getCardInfo("ex8-90"));
assertNotNull(api.getCardInfo("swsh3-84"));
assertNotNull(api.getCardInfo("swsh4-98"));
assertNotNull(api.getCardInfo("ex13-96"));
assertEquals("ex13", api.getSetInfo(api.getCardInfo("ex13-96")).getId());
}
@Test
public void testSets() throws IOException {
SetInfo set = api.getSetInfo("sm10");
assertNotNull(set);
assertEquals(234, set.getCards().size());
assertEquals(234, set.getOfficialCardCount());
assertEquals(0, set.getReverseCardCount());
assertEquals(0, set.getHoloCardCount());
assertEquals(0, set.getFirstEdCardCount());
assertEquals("Unbroken Bonds", set.getName());
assertEquals(3, set.getReleaseDate().getDayOfMonth());
assertEquals(Month.MAY, set.getReleaseDate().getMonth());
assertEquals("UNB", set.getTcgOnlineCode());
assertEquals("Sun & Moon", set.getSeries().getName());
assertTrue(set.isLegalInExpanded());
assertFalse(set.isLegalInStandard());
}
@Test
public void testSeries() throws IOException {
SeriesInfo info = api.getSeriesInfo("sm");
assertEquals("sm", info.getId());
assertEquals("Sun & Moon", info.getName());
assertEquals(18, info.getSets().size());
assertEquals("Shining Legends", info.getSets().get(4).getName());
}
@Test
public void testImage() throws IOException {
CardInfo info = api.getCardInfo("base4", "1");
BufferedImage high = api.getImage(info, ImageResolution.HIGH);
assertNotNull(high);
assertEquals(825, high.getHeight());
assertEquals(600, high.getWidth());
BufferedImage low = api.getImage(info, ImageResolution.LOW);
assertNotNull(low);
assertEquals(337, low.getHeight());
assertEquals(245, low.getWidth());
}
}

View File

@ -0,0 +1,52 @@
package net.tcgdex.sdk
import java.io.IOException
import kotlin.test.Test
import kotlin.test.BeforeTest
import kotlin.test.assertNotNull
class APITest {
private lateinit var api: TCGdex
@BeforeTest
fun initAPI() {
api = TCGdex("en")
}
@Test
@Throws(IOException::class)
fun testFullCardInfo() {
assertNotNull(api.fetchCards())
assertNotNull(api.fetchCard("swsh3-136"))
assertNotNull(api.fetchCard("swsh3", "136"))
assertNotNull(api.fetchSet("swsh3"))
assertNotNull(api.fetchSets())
assertNotNull(api.fetchSerie("swsh"))
assertNotNull(api.fetchSeries())
assertNotNull(api.fetchTypes())
assertNotNull(api.fetchType("Colorless"))
assertNotNull(api.fetchRetreats())
assertNotNull(api.fetchRetreat("1"))
assertNotNull(api.fetchRarities())
assertNotNull(api.fetchRarity("Uncommon"))
assertNotNull(api.fetchIllustrators())
assertNotNull(api.fetchIllustrator("tetsuya koizumi"))
assertNotNull(api.fetchHPs())
assertNotNull(api.fetchHP("110"))
assertNotNull(api.fetchCategories())
assertNotNull(api.fetchCategory("Pokemon"))
assertNotNull(api.fetchDexIds())
assertNotNull(api.fetchDexId("162"))
assertNotNull(api.fetchEnergyTypes())
assertNotNull(api.fetchEnergyType("Special"))
assertNotNull(api.fetchRegulationMarks())
assertNotNull(api.fetchRegulationMark("D"))
assertNotNull(api.fetchStages())
assertNotNull(api.fetchStage("Basic"))
assertNotNull(api.fetchSuffixes())
assertNotNull(api.fetchSuffix("EX"))
assertNotNull(api.fetchTrainerTypes())
assertNotNull(api.fetchTrainerType("Tool"))
assertNotNull(api.fetchVariants())
assertNotNull(api.fetchVariant("holo"))
}
}