com.github.koraktor.steamcondenser.community.SteamGame.java Source code

Java tutorial

Introduction

Here is the source code for com.github.koraktor.steamcondenser.community.SteamGame.java

Source

/**
 * This code is free software; you can redistribute it and/or modify it under
 * the terms of the new BSD License.
 *
 * Copyright (c) 2011-2013, Sebastian Staudt
 */

package com.github.koraktor.steamcondenser.community;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.json.JSONException;
import org.json.JSONObject;

import com.github.koraktor.steamcondenser.exceptions.SteamCondenserException;
import com.github.koraktor.steamcondenser.exceptions.WebApiException;

/**
 * This class represents a game available on Steam
 *
 * @author Sebastian Staudt
 */
public class SteamGame {

    private static Map<Integer, SteamGame> games = new HashMap<Integer, SteamGame>();

    private int appId;

    private String iconUrl;

    private String logoHash;

    private String name;

    private String shortName;

    /**
     * Clears the game cache
     */
    public static void clearCache() {
        games.clear();
    }

    /**
     * Checks if a game is up-to-date by reading information from a
     * <code>steam.inf</code> file and comparing it using the Web API
     *
     * @param path The file system path of the `steam.inf` file
     * @return <code>true</code> if the game is up-to-date
     * @throws IOException if the steam.inf cannot be read
     * @throws JSONException if the JSON data is malformed
     * @throws SteamCondenserException if the given steam.inf is invalid or
     *         the Web API request fails
     */
    public static boolean checkSteamInf(String path) throws IOException, JSONException, SteamCondenserException {
        BufferedReader steamInf = new BufferedReader(new FileReader(path));
        String steamInfContents = "";

        while (steamInf.ready()) {
            steamInfContents += steamInf.readLine() + "\n";
        }
        steamInf.close();

        Pattern appIdPattern = Pattern.compile("^\\s*appID=(\\d+)\\s*$",
                Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
        Matcher appIdMatcher = appIdPattern.matcher(steamInfContents);
        Pattern versionPattern = Pattern.compile("^\\s*PatchVersion=([\\d\\.]+)\\s*$",
                Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
        Matcher versionMatcher = versionPattern.matcher(steamInfContents);

        if (!(appIdMatcher.find() && versionMatcher.find())) {
            throw new SteamCondenserException("The steam.inf file at \"" + path + "\" is invalid.");
        }

        int appId = Integer.parseInt(appIdMatcher.group(1));
        int version = Integer.parseInt(versionMatcher.group(1).replace(".", ""));

        return isUpToDate(appId, version);
    }

    /**
     * Creates a new or cached instance of the game specified by the given XML
     * data
     *
     * @param appId The application ID of the game
     * @param gameData The XML data of the game
     * @return The game instance for the given data
     * @see SteamGame#SteamGame
     */
    public static SteamGame create(int appId, XMLData gameData) {
        if (games.containsKey(appId)) {
            return games.get(appId);
        } else {
            return new SteamGame(appId, gameData);
        }
    }

    /**
     * Returns whether the given version of the game with the given application
     * ID is up-to-date
     *
     * @param appId The application ID of the game to check
     * @param version The version to check against the Web API
     * @return <code>true</code> if the given version is up-to-date
     * @throws JSONException if the JSON data is malformed
     * @throws SteamCondenserException if the Web API request fails
     */
    public static boolean isUpToDate(int appId, int version) throws JSONException, SteamCondenserException {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("appid", appId);
        params.put("version", version);
        String json = WebApi.getJSON("ISteamApps", "UpToDateCheck", 1, params);
        JSONObject result = new JSONObject(json).getJSONObject("response");
        if (!result.getBoolean("success")) {
            throw new SteamCondenserException(result.getString("error"));
        }
        return result.getBoolean("up_to_date");
    }

    /**
     * Creates a new instance of a game with the given data and caches it
     *
     * @param appId The application ID of the game
     * @param gameData The XML data of the game
     */
    private SteamGame(int appId, XMLData gameData) {
        this.appId = appId;

        String logoUrl;
        if (gameData.hasElement("name")) {
            logoUrl = gameData.getString("logo");
            this.name = gameData.getString("name");

            if (gameData.hasElement("globalStatsLink")) {
                Pattern regex = Pattern.compile("http://steamcommunity.com/stats/([^?/]+)/achievements/");
                Matcher matcher = regex.matcher(gameData.getString("globalStatsLink"));
                matcher.find();
                shortName = matcher.group(1).toLowerCase();
                this.shortName = matcher.group(1).toLowerCase();
            } else {
                this.shortName = null;
            }
        } else {
            this.iconUrl = gameData.getString("gameIcon");
            logoUrl = gameData.getString("gameLogo");
            this.name = gameData.getString("gameName");
            this.shortName = gameData.getString("gameFriendlyName").toLowerCase();
        }

        Pattern regex = Pattern.compile("/" + appId + "/([0-9a-f]+).jpg");
        Matcher matcher = regex.matcher(logoUrl);
        if (matcher.find()) {
            this.logoHash = matcher.group(1).toLowerCase();
        }

        games.put(appId, this);
    }

    /**
     * Returns the Steam application ID of this game
     *
     * @return The Steam application ID of this game
     */
    public int getAppId() {
        return this.appId;
    }

    /**
     * Returns the URL for the icon image of this game
     *
     * @return The URL for the game icon
     */
    public String getIconUrl() {
        return this.iconUrl;
    }

    /**
     * Returns a unique identifier for this game
     *
     * This is either the numeric application ID or the unique short name
     *
     * @return The application ID or short name of the game
     */
    public Object getId() {
        if (String.valueOf(this.appId).equals(this.shortName)) {
            return this.appId;
        } else {
            return this.shortName;
        }
    }

    /**
     * Returns the full name of this game
     *
     * @return The full name of this game
     */
    public String getName() {
        return this.name;
    }

    /**
     * Returns the leaderboard for this game and the given leaderboard ID
     *
     * @param id The ID of the leaderboard to return
     * @return The matching leaderboard if available
     */
    public GameLeaderboard getLeaderboard(int id) throws SteamCondenserException {
        return GameLeaderboard.getLeaderboard(this.shortName, id);
    }

    /**
     * Returns the leaderboard for this game and the given leaderboard name
     *
     * @param name The name of the leaderboard to return
     * @return The matching leaderboard if available
     */
    public GameLeaderboard getLeaderboard(String name) throws SteamCondenserException {
        return GameLeaderboard.getLeaderboard(this.shortName, name);
    }

    /**
     * Returns an array containing all of this game's leaderboards
     *
     * @return The leaderboards for this game
     */
    public Map<Integer, GameLeaderboard> getLeaderboards() throws SteamCondenserException {
        return GameLeaderboard.getLeaderboards(this.shortName);
    }

    /**
     * Returns the URL for the logo image of this game
     *
     * @return The URL for the game logo
     */
    public String getLogoUrl() {
        if (this.logoHash == null) {
            return null;
        } else {
            return "http://media.steampowered.com/steamcommunity/public/images/apps/" + this.appId + "/"
                    + this.logoHash + ".jpg";
        }
    }

    /**
     * Returns the URL for the logo thumbnail image of this game
     *
     * @return  The URL for the game logo thumbnail
     */
    public String getLogoThumbnailUrl() {
        if (this.logoHash == null) {
            return null;
        } else {
            return "http://media.steampowered.com/steamcommunity/public/images/apps/" + this.appId + "/"
                    + this.logoHash + "_thumb.jpg";
        }
    }

    /**
     * Returns the overall number of players currently playing this game
     *
     * @return The number of players playing this game
     * @throws JSONException In case of misformatted JSON data
     * @throws WebApiException on Web API errors
     */
    public int getPlayerCount() throws JSONException, WebApiException {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("appid", this.appId);
        String jsonString = WebApi.getJSON("ISteamUserStats", "GetNumberOfCurrentPlayers", 1, params);
        JSONObject result = new JSONObject(jsonString).getJSONObject("response");

        return result.getInt("player_count");
    }

    /**
     * Returns the short name of this game (also known as "friendly name")
     *
     * @return The short name of this game
     */
    public String getShortName() {
        return this.shortName;
    }

    /**
     * Returns the URL of this game's page in the Steam Store
     *
     * @return This game's store page
     */
    public String getStoreUrl() {
        return "http://store.steampowered.com/app/" + this.appId;
    }

    /**
     * Creates a stats object for the given user and this game
     *
     * @param steamId The custom URL or the 64bit Steam ID of the user
     * @return The stats of this game for the given user
     */
    public GameStats getUserStats(Object steamId) throws SteamCondenserException {
        if (!this.hasStats()) {
            return null;
        }

        return GameStats.createGameStats(steamId, this.shortName);
    }

    /**
     * Returns whether this game has statistics available
     *
     * @return <code>true</code> if this game has stats
     */
    public boolean hasStats() {
        return this.shortName != null;
    }

    /**
     * Returns whether the given version of this game is up-to-date
     *
     * @param version The version to check against the Web API
     * @return <code>true</code> if the given version is up-to-date
     * @throws JSONException if the JSON data is malformed
     * @throws SteamCondenserException if the Web API request fails
     */
    public boolean isUpToDate(int version) throws JSONException, SteamCondenserException {
        return SteamGame.isUpToDate(this.appId, version);
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("appId", this.appId)
                .append("name", this.name).append("shortName", this.shortName).toString();
    }

}