Java tutorial
/* * ****************************************************** * * Copyright (C) 2016 Will Davies wdavies973@gmail.com * * * * This file is part of Roblu * * * * Roblu cannot be distributed for a price or to people outside of your local robotics team. * ****************************************************** */ package com.cpjd.roblu.bluealliance; import com.cpjd.roblu.toolbox.Text; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.ProtocolException; import java.net.URL; import java.security.Key; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Set; /* * View BlueAlliance-License for licensing information. */ /** * Provides an interface for the The Blue Alliance REST API. */ public class BLUE { /** * Describes an API exception. */ @SuppressWarnings("serial") public static class BLUEApiException extends Exception { Exception _innerException; /** * Creates an instance of BLUEApiException. * * @param message The exception message. * @param inner The underlying message. */ public BLUEApiException(String message, Exception inner) { super(message); _innerException = inner; } /** * Gets the underlying exception. * * @return The underlying exception. */ public Exception getInnerException() { return _innerException; } } private static final String API_BASE = "http://www.thebluealliance.com/api/v2"; private static String X_TBA_APP_ID = ""; private static final JSONParser parser = new JSONParser(); /** * Sets the App ID for the application. * * @param appId The application ID, in the format <team/person id>:<app description>:<version> */ public static void setAppId(String appId) { X_TBA_APP_ID = appId; } private static boolean isInitialized() { return X_TBA_APP_ID.length() > 0 && X_TBA_APP_ID.split(":").length == 3; } /** * Makes an API call to The Blue Alliance. * * @param apiReq The REST endpoint to make a request to. * @return The parsed JSON data. */ public static Object api(String apiReq) throws BLUEApiException { if (!isInitialized()) throw new BLUEApiException("BLUE was not initialized.", null); String endpoint = API_BASE + apiReq; URL endpointUrl; try { endpointUrl = new URL(endpoint); } catch (MalformedURLException e) { throw new BLUEApiException("Malformed API request.", e); } HttpURLConnection conn; try { conn = (HttpURLConnection) endpointUrl.openConnection(); } catch (IOException e) { throw new BLUEApiException("Could not open connection.", e); } try { conn.setRequestMethod("GET"); } catch (ProtocolException e) { throw new BLUEApiException("Could not set the request type.", e); } conn.setRequestProperty("X-TBA-App-Id", X_TBA_APP_ID); conn.setUseCaches(false); InputStream is; BufferedReader reader; try { is = conn.getInputStream(); reader = new BufferedReader(new InputStreamReader(is)); } catch (IOException e) { throw new BLUEApiException("Fatal! No internet!", e); } String jsonString = ""; String respLine = ""; try { while ((respLine = reader.readLine()) != null) { jsonString += respLine; } reader.close(); } catch (IOException e) { throw new BLUEApiException("Error reading the response.", e); } Object obj; try { obj = parser.parse(jsonString); } catch (ParseException e) { throw new BLUEApiException("Malformed response received.", e); } return obj; } /** * Provides functionality for requesting team data. */ public static class Teams { /** * Describes an alliance's color. */ public static enum AllianceColor { RED, BLUE } /** * Represents a team. */ public static class Team { String _website; String _name; String _locality; String _region; String _country; String _location; int _teamNumber; String _key; String _nickName; private Team(String website, String name, String locality, String region, String country, String location, int teamNumber, String key, String nickName) { _website = website; _name = name; _locality = locality; _region = region; _country = country; _location = location; _teamNumber = teamNumber; _key = key; _nickName = nickName; } /** * Gets the team's website. * * @return The team's website. */ public String getWebsite() { return _website; } /** * Gets the team's name. * * @return The team's name. */ public String getName() { return _name; } /** * Gets the team's locality. * * @return The team's locality. */ public String getLocality() { return _locality; } /** * Gets the team's region. * * @return The team's region. */ public String getRegion() { return _region; } /** * Gets the team's locality. * * @return The team's region. */ public String getCountry() { return _country; } /** * Gets the team's location. * * @return The team's location. */ public String getLocation() { return _location; } /** * Gets the team's number. * * @return The team's number. */ public int getTeamNumber() { return _teamNumber; } /** * Gets the team's API reference key. * * @return The team's API reference key. */ public String getTeamKey() { return _key; } /** * Gets the team's nickname. * * @return The team's nickname. */ public String getNickName() { return _nickName; } /** * Gets the <code>String</code> representation of this <code>Team</code>. */ public String toString() { return String.format("{ %s, %s, %s, %s, %s, %s, %d, %s, %s }", getWebsite(), getName(), getLocality(), getRegion(), getCountry(), getLocation(), getTeamNumber(), getTeamKey(), getNickName()); } /** * Gets the events attended by this team in <code>year</code> * @param year The requested year. * @return Events that this team attended in <code>year</code> * @throws BLUEApiException */ @SuppressWarnings("rawtypes") public Events.Event[] getEvents(int year) throws BLUEApiException { HashMap obj; obj = (HashMap) BLUE.api("/team/" + _key + "/" + year); JSONArray arr = (JSONArray) obj.get("events"); Events.Event[] events = new Events.Event[arr.size()]; for (int i = 0; i < events.length; i++) { JSONObject event = (JSONObject) arr.get(i); events[i] = Events.parseEvent(event); } return events; } } /** * Gets the team with team number <code>teamNumber</code> * @param teamNumber The requested team number. * @return The team with team number <code>teamNumber</code>, represented as a <code>Team</code> * @throws BLUEApiException */ @SuppressWarnings("rawtypes") public static Team getTeam(int teamNumber) throws BLUEApiException { String teamKey = "frc" + teamNumber; HashMap obj; obj = (HashMap) BLUE.api("/team/" + teamKey); return parseTeam(obj); } /** * Returns the <code>Team</code> representation from a hashmap with data. * @param obj The hashmap with data. * @return The hashmap represented as a <code>Team</code> */ @SuppressWarnings("rawtypes") public static Team parseTeam(HashMap obj) { return new Team((String) obj.get("website"), (String) obj.get("name"), (String) obj.get("locality"), (String) obj.get("region"), (String) obj.get("country_name"), (String) obj.get("location"), (int) (long) (Long) obj.get("team_number"), (String) obj.get("key"), (String) obj.get("nickname")); } } /** * Provides functionality for requesting event data. */ public static class Events { /** * Represents an event. */ public static class Event { private String _key; private String _name; private String _shortName; private String _eventCode; private String _eventType; private int _eventTypeCode; private int _year; private String _location; private boolean _official; private Event(String key, String name, String shortName, String eventCode, String eventType, int eventTypeCode, int year, String location, boolean official) { _key = key; _name = name; _shortName = shortName; _eventCode = eventCode; _eventType = eventType; _eventTypeCode = eventTypeCode; _year = year; _location = location; _official = official; } /** * Gets the event key. * * @return The event key. */ public String getEventKey() { return _key; } /** * Gets the event name. * * @return The event name. */ public String getName() { return _name; } /** * Gets the event short name. * * @return The event short name. */ public String getShortName() { return _shortName; } /** * Gets the event code. * @return The event code. */ public String getEventCode() { return _eventCode; } /** * Gets the <code>String</code> representation of the event type. * * @return The <code>String</code> representation of the event type. */ public String getEventTypeString() { return _eventType; } /** * Gets the event type. * * @return The event type. */ public int getEventType() { return _eventTypeCode; } /** * Gets the year of this event. * * @return The year of this event. */ public int getYear() { return _year; } /** * Gets the event location. * * @return The event location. */ public String getLocation() { return _location; } /** * Determines if this event is an official event. * * @return <code>true</code> if the event is an official event; <code>false</code> otherwise. */ public boolean isOfficial() { return _official; } /** * Returns the <code>String</code> representation of this <code>Event</code>. */ public String toString() { return String.format("{ %s, %s, %s, %s, %s, %d, %d, %s, %s }", getEventKey(), getName(), getShortName(), getEventCode(), getEventTypeString(), getEventType(), getYear(), getLocation(), (isOfficial() ? "true" : "false")); } /** * Gets a list of all teams that attended this event. * * @return An array of the teams that attended this event. * @throws BLUEApiException */ public Teams.Team[] getTeams() throws BLUEApiException { String eventKey = getEventKey(); JSONArray arr; arr = (JSONArray) BLUE.api("/event/" + eventKey + "/teams"); Teams.Team[] teams = new Teams.Team[arr.size()]; for (int i = 0; i < teams.length; i++) { teams[i] = Teams.parseTeam((JSONObject) arr.get(i)); } return teams; } /** * Gets a list of matches played at this event. * * @return An array of the matches played at this event. * @throws BLUEApiException */ public Matches.Match[] getMatches() throws BLUEApiException { String eventKey = getEventKey(); JSONArray arr; arr = (JSONArray) BLUE.api("/event/" + eventKey + "/matches"); Matches.Match[] matches = new Matches.Match[arr.size()]; for (int i = 0; i < matches.length; i++) { matches[i] = Matches.parseMatch((JSONObject) arr.get(i)); } return matches; } } /** * Gets the event with event code <code>eventCode</code> in <code>year</code> * @param eventCode The eventCode of the requested event. * @param year The requested year. * @return The event with event code <code>eventCode</code> in <code>year</code>. * @throws BLUEApiException */ @SuppressWarnings("rawtypes") public static Event getEvent(String eventCode, int year) throws BLUEApiException { String eventKey = year + eventCode; HashMap obj; obj = (HashMap) BLUE.api("/event/" + eventKey); return parseEvent(obj); } /** * Returns the <code>Event</code> representation from a hashmap with data. * @return The hashmap represented as an <code>Event</code> */ @SuppressWarnings("rawtypes") public static Event parseEvent(HashMap event) { return new Event((String) event.get("key"), (String) event.get("name"), (String) event.get("short_name"), (String) event.get("event_code"), (String) event.get("event_type_string"), (int) (long) (Long) event.get("event_type"), (int) (long) (Long) event.get("year"), (String) event.get("location"), (Boolean) event.get("official")); } } /** * Provides functionality for requesting match data. */ public static class Matches { /** * Represents a match. */ public static class Match { /** * Represents an alliance in a match. */ public static class Alliance { Teams.AllianceColor _color; String[] _teams; private Alliance(Teams.AllianceColor color, String[] teams) { _color = color; _teams = teams; } /** * Gets the teams in this alliance. * * @return The teams in this alliance. */ public String[] getTeams() { String[] copy = new String[_teams.length]; System.arraycopy(_teams, 0, copy, 0, copy.length); return copy; } /** * Returns the <code>String</code> representation of this <code>Alliance</code>. */ public String toString() { return String.format("{ %s, %s }", _color.name(), Arrays.toString(_teams)); } } String _key; String _compLevel; int _setNumber; int _matchNumber; String _eventKey; Alliance _redAlliance; int _redAllianceScore; Alliance _blueAlliance; int _blueAllianceScore; long time; String[] score_items; String[] score_breakdown_red; String[] score_breakdown_blue; private Match(String key, String compLevel, int setNumber, int matchNumber, String eventKey, Alliance redAlliance, int redAllianceScore, Alliance blueAlliance, int blueAllianceScore, long time, String[] items, String[] score_breakdown_red, String[] score_breakdown_blue) { _key = key; _compLevel = compLevel; _setNumber = setNumber; _matchNumber = matchNumber; _eventKey = eventKey; _redAlliance = redAlliance; _redAllianceScore = redAllianceScore; _blueAlliance = blueAlliance; _blueAllianceScore = blueAllianceScore; this.time = time; this.score_items = items; this.score_breakdown_red = score_breakdown_red; this.score_breakdown_blue = score_breakdown_blue; } public String[] getBlueBreakdown() { return this.score_breakdown_blue; } public String[] getRedBreakdown() { return this.score_breakdown_red; } /** * Gets the match key. * * @return The match key. */ public String getMatchKey() { return _key; } /** * Gets the competition level. * * @return The competition level. */ public String getCompLevel() { return _compLevel; } public long getTime() { return time; }; /** * Gets the set number. * * @return The set number. */ public int getSetNumber() { return _setNumber; } /** * Gets the match number. * * @return The match number. */ public int getMatchNumber() { return _matchNumber; } /** * Gets the event key. * * @return The event key. */ public String getEventKey() { return _eventKey; } /** * Gets the red alliance <code>Alliance</code> object. * * @return The red alliance <code>Alliance</code> object. */ public Alliance getRedAlliance() { return _redAlliance; } /** * Gets the red alliance score. * * @return The red alliance score. */ public int getRedAllianceScore() { return _redAllianceScore; } /** * Gets the blue alliance <code>Alliance</code> object. * * @return The blue alliance <code>Alliance</code> object. */ public Alliance getBlueAlliance() { return _blueAlliance; } /** * Gets the blue alliance score. * * @return The blue alliance score. */ public int getBlueAllianceScore() { return _blueAllianceScore; } /** * Returns the <code>String</code> representation of this <code>Match</code> */ public String toString() { return String.format("{ %s, %s, %d, %d, %s, %s, %d, %s, %d }", getMatchKey(), getCompLevel(), getSetNumber(), getMatchNumber(), getEventKey(), getRedAlliance().toString(), getRedAllianceScore(), getBlueAlliance().toString(), getBlueAllianceScore()); } } /** * Returns the <code>Match</code> representation from a hashmap with data. * @param obj The hashmap with data. * @return The hashmap represented as a <code>Match</code> */ @SuppressWarnings("rawtypes") public static Match parseMatch(HashMap obj) { JSONObject alliances = (JSONObject) obj.get("alliances"); JSONObject blueAllianceJson = (JSONObject) alliances.get("blue"); JSONObject redAllianceJson = (JSONObject) alliances.get("red"); JSONObject scorebreakdown = (JSONObject) obj.get("score_breakdown"); JSONObject items = (JSONObject) scorebreakdown.get("blue"); JSONObject items2 = (JSONObject) scorebreakdown.get("red"); ArrayList<String> red = new ArrayList<>(); ArrayList<String> blue = new ArrayList<>(); String[] stringArray = null; if (items != null) { Set<Key> keys = items.keySet(); Object[] toArray = keys.toArray(); stringArray = Arrays.copyOf(toArray, toArray.length, String[].class); Arrays.sort(stringArray); } // Output data ArrayList<String> better_items = Text.convertStringArray(stringArray); String[] finalItems = Text.convertList(better_items); // Calculate scores for (int i = 0; i < finalItems.length; i++) { if (items2 != null) red.add(items2.get(finalItems[i]).toString()); if (items != null) blue.add(items.get(finalItems[i]).toString()); } JSONArray blueTeams = (JSONArray) blueAllianceJson.get("teams"); JSONArray redTeams = (JSONArray) redAllianceJson.get("teams"); int blueScore = (int) (int) (long) (Long) blueAllianceJson.get("score"); int redScore = (int) (int) (long) (Long) redAllianceJson.get("score"); long time = (long) obj.get("time"); Match.Alliance blueAlliance = new Match.Alliance(Teams.AllianceColor.BLUE, new String[] { (String) blueTeams.get(0), (String) blueTeams.get(1), (String) blueTeams.get(2) }); Match.Alliance redAlliance = new Match.Alliance(Teams.AllianceColor.RED, new String[] { (String) redTeams.get(0), (String) redTeams.get(1), (String) redTeams.get(2) }); return new Match((String) obj.get("key"), (String) obj.get("comp_level"), (int) (long) (Long) obj.get("set_number"), (int) (long) (Long) obj.get("match_number"), (String) obj.get("event_key"), redAlliance, redScore, blueAlliance, blueScore, time, finalItems, Text.convertList(red), Text.convertList(blue)); } } }