/* This file is part of RateBeer For Android. RateBeer for Android is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. RateBeer for Android is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RateBeer for Android. If not, see <http://www.gnu.org/licenses/>. */ package com.ratebeer.android.api.command; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import org.json.JSONException; import android.os.Parcel; import android.os.Parcelable; import com.ratebeer.android.api.ApiConnection; import com.ratebeer.android.api.ApiException; import com.ratebeer.android.api.ApiMethod; import com.ratebeer.android.api.HtmlCommand; import com.ratebeer.android.api.HttpHelper; import com.ratebeer.android.api.UserSettings; public class GetUserDetailsCommand extends HtmlCommand { private final int userId; private UserDetails details; public GetUserDetailsCommand(UserSettings api, int userId) { super(api, ApiMethod.GetUserDetails); this.userId = userId; } public UserDetails getDetails() { return details; } @Override protected String makeRequest(ApiConnection apiConnection) throws ApiException { return apiConnection.get("http://www.ratebeer.com/user/" + userId + "/"); } @Override protected void parse(String html) throws JSONException, ApiException { // Parse the user's details and recent ratings int userStart = html.indexOf("class=\"selected\">profile</a><br>"); if (userStart < 0) { throw new ApiException(ApiException.ExceptionType.CommandFailed, "The response HTML did not contain the unique event content string"); } final String nameText = "<span class=\"userIsDrinking\">"; int nameStart = html.indexOf(nameText, userStart) + nameText.length(); String name = html.substring(nameStart, html.indexOf("</span>", nameStart)).trim(); if (name.indexOf(" ") >= 0) name = name.substring(0, name.indexOf(" ")); String locationText = "<span>"; int locationStart = html.indexOf(locationText, nameStart) + locationText.length(); String location = HttpHelper.cleanHtml(html.substring(locationStart, html.indexOf("<br>", locationStart))) .trim(); String joinedText = "class=\"GrayItalic\">"; int joinedStart = html.indexOf(joinedText, locationStart) + joinedText.length(); String joined = html.substring(joinedStart, html.indexOf("<", joinedStart)).trim(); String lastSeenText = "class=\"GrayItalic\">"; int lastSeenStart = html.indexOf(lastSeenText, joinedStart) + lastSeenText.length(); String lastSeen = html.substring(lastSeenStart, html.indexOf("<", lastSeenStart)); int beerRateCountStart = html.indexOf("<b>", lastSeenStart) + "<b>".length(); int beerRateCount = Integer.parseInt(html.substring(beerRateCountStart, html.indexOf("</b>", beerRateCountStart))); int placeRateCountStart = html.indexOf("<b>", beerRateCountStart) + "<b>".length(); int placeRateCount = Integer.parseInt(html.substring(placeRateCountStart, html.indexOf("</b>", placeRateCountStart))); int avgScoreGivenPresent = html.indexOf("Avg Score Given: ", placeRateCountStart); String avgScoreGiven = null; if (avgScoreGivenPresent >= 0) { int avgScoreGivenStart = avgScoreGivenPresent + "Avg Score Given: ".length(); avgScoreGiven = HttpHelper.cleanHtml(html.substring(avgScoreGivenStart, html.indexOf(" ", avgScoreGivenStart))); } int avgBeerRatedPresent = html.indexOf("Avg Beer Rated: ", avgScoreGivenPresent); String avgBeerRated = null; if (avgBeerRatedPresent >= 0) { int avgBeerRatedStart = avgBeerRatedPresent + "Avg Beer Rated: ".length(); avgBeerRated = HttpHelper .cleanHtml(html.substring(avgBeerRatedStart, html.indexOf(" ", avgBeerRatedStart))); } String styleText = "Favorite style: <a href=\"/beerstyles/"; int styleStart = html.indexOf(styleText, placeRateCountStart); int styleId = -1; String styleName = null; if (styleStart >= 0) { styleStart += styleText.length(); int styleIdStart = html.indexOf("/", styleStart) + 1; styleId = Integer.parseInt(html.substring(styleIdStart, html.indexOf("/", styleIdStart))); int styleNameStart = html.indexOf("<b>", styleStart) + "<b>".length(); styleName = HttpHelper.cleanHtml(html.substring(styleNameStart, html.indexOf("</b>", styleNameStart))); } List<RecentBeerRating> ratings = new ArrayList<RecentBeerRating>(); String ratingText = "style=\"height: 21px;\"><A HREF=\"/beer/"; int ratingStart = html.indexOf(ratingText, styleStart); SimpleDateFormat dateFormat = new SimpleDateFormat("M/d/yyyy", Locale.US); while (ratingStart >= 0) { int beerIdStart = html.indexOf("/", ratingStart + ratingText.length()) + 1; int beerId = Integer.parseInt(html.substring(beerIdStart, html.indexOf("/", beerIdStart))); int beerNameStart = html.indexOf(">", beerIdStart) + ">".length(); String beerName = HttpHelper.cleanHtml(html.substring(beerNameStart, html.indexOf("<", beerNameStart))); int beerStyleStart = html.indexOf("smallGray\">", beerNameStart) + "smallGray\">".length(); String beerStyle = HttpHelper.cleanHtml(html.substring(beerStyleStart, html.indexOf("<", beerStyleStart))); int beerRatingStart = html.indexOf("bold;\">", beerStyleStart) + "bold;\">".length(); String beerRating = html.substring(beerRatingStart, html.indexOf("<", beerRatingStart)); int beerDateStart = html.indexOf("smallGray\">", beerRatingStart) + "smallGray\">".length(); String beerDateString = html.substring(beerDateStart, html.indexOf("<", beerDateStart)); Date beerDate; try { beerDate = dateFormat.parse(beerDateString); } catch (ParseException e) { beerDate = null; } ratings.add(new RecentBeerRating(beerId, beerName, beerStyle, beerRating, beerDate)); ratingStart = html.indexOf(ratingText, beerDateStart); } // Set the user's rating on the original command as result details = new UserDetails(name, joined, lastSeen, location, beerRateCount, placeRateCount, avgScoreGiven, avgBeerRated, styleName, styleId, ratings); } public static class RecentBeerRating implements Parcelable { public final int id; public final String name; public final String styleName; public final String rating; public final Date date; public RecentBeerRating(int id, String name, String styleName, String rating, Date date) { this.id = id; this.name = name; this.styleName = styleName; this.rating = rating; this.date = date; } public int describeContents() { return 0; } public void writeToParcel(Parcel out, int flags) { out.writeInt(id); out.writeString(name); out.writeString(styleName); out.writeString(rating); out.writeLong(date.getTime()); } public static final Parcelable.Creator<RecentBeerRating> CREATOR = new Parcelable.Creator<RecentBeerRating>() { public RecentBeerRating createFromParcel(Parcel in) { return new RecentBeerRating(in); } public RecentBeerRating[] newArray(int size) { return new RecentBeerRating[size]; } }; private RecentBeerRating(Parcel in) { id = in.readInt(); name = in.readString(); styleName = in.readString(); rating = in.readString(); date = new Date(in.readLong()); } } public static class UserDetails implements Parcelable { public final String name; public final String location; public final String joined; public final String lastSeen; public final int beerRateCount; public final int placeRateCount; public final String avgScoreGiven; public final String avgBeerRated; public final String favStyleName; public final int favStyleId; public final List<RecentBeerRating> recentBeerRatings; public UserDetails(String name, String joined, String lastSeen, String location, int beerRateCount, int placeRateCount, String avgScoreGiven, String avgBeerRated, String favStyleName, int favStyleId, List<RecentBeerRating> recentBeerRatings) { this.name = name; this.location = location; this.joined = joined; this.lastSeen = lastSeen; this.beerRateCount = beerRateCount; this.placeRateCount = placeRateCount; this.avgScoreGiven = avgScoreGiven; this.avgBeerRated = avgBeerRated; this.favStyleName = favStyleName; this.favStyleId = favStyleId; this.recentBeerRatings = recentBeerRatings; } public int describeContents() { return 0; } public void writeToParcel(Parcel out, int flags) { out.writeString(name); out.writeString(location); out.writeString(joined); out.writeString(lastSeen); out.writeInt(beerRateCount); out.writeInt(placeRateCount); out.writeString(avgScoreGiven); out.writeString(avgBeerRated); out.writeString(favStyleName); out.writeInt(favStyleId); out.writeTypedList(recentBeerRatings); } public static final Parcelable.Creator<UserDetails> CREATOR = new Parcelable.Creator<UserDetails>() { public UserDetails createFromParcel(Parcel in) { return new UserDetails(in); } public UserDetails[] newArray(int size) { return new UserDetails[size]; } }; private UserDetails(Parcel in) { name = in.readString(); location = in.readString(); joined = in.readString(); lastSeen = in.readString(); beerRateCount = in.readInt(); placeRateCount = in.readInt(); avgScoreGiven = in.readString(); avgBeerRated = in.readString(); favStyleName = in.readString(); favStyleId = in.readInt(); recentBeerRatings = new ArrayList<GetUserDetailsCommand.RecentBeerRating>(); in.readTypedList(recentBeerRatings, RecentBeerRating.CREATOR); } } }