Skip to content

Commit

Permalink
Share activity. Still needs a better icon.
Browse files Browse the repository at this point in the history
git-svn-id: http://publicobject.googlecode.com/svn@111 afa747b4-d56b-11dd-86c2-0f8696b7b6f9
  • Loading branch information
limpbizkit@gmail.com committed Jul 28, 2012
1 parent 3d7febb commit 81a23ca
Show file tree
Hide file tree
Showing 9 changed files with 313 additions and 130 deletions.
4 changes: 2 additions & 2 deletions rounds/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
android:theme="@style/Theme.Sherlock"
android:windowSoftInputMode="adjustResize|stateVisible"/>
</application>
<uses-permission
android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15"/>
Expand Down
6 changes: 6 additions & 0 deletions rounds/src/com/publicobject/rounds/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,12 @@ public int roundScore(int player) {
}
}

public int winningTotal() {
return getWinCondition() == WinCondition.LOW_SCORE
? minTotal()
: maxTotal(); // also used for WinCondition.NONE
}

private static class Player implements Cloneable {
private String name;
private int color;
Expand Down
55 changes: 14 additions & 41 deletions rounds/src/com/publicobject/rounds/GameActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.text.SpannableStringBuilder;
import android.text.style.RelativeSizeSpan;
Expand All @@ -40,13 +39,11 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

public final class GameActivity extends SherlockActivity {
private Game game;
private PowerManager.WakeLock wakeLock;
private GameDatabase database;
private Handler handler = new Handler();
private GameSaver gameSaver;

private View layout;
private JogWheel jogWheel;
Expand All @@ -61,14 +58,6 @@ public final class GameActivity extends SherlockActivity {
private TextView roundTextView;
private ImageButton previousRound;

private volatile boolean savePending = false;
private final Runnable saveRunnable = new Runnable() {
@Override public void run() {
savePending = false;
database.saveLater(game);
}
};

/** True for landscape layout. */
private boolean tablet;

Expand All @@ -80,7 +69,7 @@ public final class GameActivity extends SherlockActivity {
? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
: ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

database = GameDatabase.getInstance(getApplicationContext());
GameDatabase database = GameDatabase.getInstance(getApplicationContext());

Intent intent = getIntent();
String gameId = savedState != null
Expand All @@ -89,6 +78,8 @@ public final class GameActivity extends SherlockActivity {
game = database.get(gameId);
game.setRound(game.roundCount() - 1);

gameSaver = new GameSaver(database, game);

PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, getPackageName());

Expand Down Expand Up @@ -145,7 +136,7 @@ public final class GameActivity extends SherlockActivity {
scoreHistoryTable.scoreChanged(player, round);
updateActionBarBackground();
roundChanged();
saveLater();
gameSaver.saveLater();
}
@Override public void cancelled() {
roundChanged();
Expand Down Expand Up @@ -199,19 +190,6 @@ public void onClick(View view) {
savedState.putString(IntentExtras.GAME_ID, game.getId());
}

/**
* Saves the game at some point in the future. Multiple calls to this method
* will be coalesced into a single filesystem write.
*/
private void saveLater() {
if (savePending) {
return;
}

handler.postDelayed(saveRunnable, TimeUnit.SECONDS.toMillis(30));
savePending = true;
}

private void roundChanged() {
scoreHistoryTable.roundCountChanged();
roundTextView.setText("Round " + Integer.toString(game.round() + 1));
Expand All @@ -232,34 +210,29 @@ private void roundChanged() {
}

private void updateActionBarBackground() {
int color = Color.WHITE;
int maxTotal = Integer.MIN_VALUE;
int color = Color.BLACK; // BLACK indicates the winning color hasn't yet been found.
int winningTotal = game.winningTotal();
for (int p = 0; p < game.playerCount(); p++) {
int playerTotal = game.playerTotal(p);
if (playerTotal > maxTotal) {
if (game.playerTotal(p) != winningTotal) {
continue;
}
if (color == Color.BLACK) {
color = game.playerColor(p);
maxTotal = playerTotal;
} else if (playerTotal == maxTotal) {
color = Color.WHITE;
} else {
color = Color.WHITE; // WHITE indicates a tie.
}
}
actionBarBackground.setColor(color);
}

@Override protected void onDestroy() {
super.onDestroy();
database = null;
}

@Override protected void onPause() {
super.onPause();

if (wakeLock.isHeld()) {
wakeLock.release();
}

handler.removeCallbacks(saveRunnable);
database.save(game);
gameSaver.onPause();
}

@Override protected void onResume() {
Expand Down
59 changes: 59 additions & 0 deletions rounds/src/com/publicobject/rounds/GameSaver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* Copyright (C) 2012 Jesse Wilson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.publicobject.rounds;

import android.os.Handler;
import java.util.concurrent.TimeUnit;

/**
* Manages saving a game to durable storage. Methods on this class may only be
* called on the main thread.
*/
final class GameSaver implements Runnable {
private final Handler handler = new Handler();
private final GameDatabase database;
private final Game game;
private volatile boolean savePending = false;

GameSaver(GameDatabase database, Game game) {
this.database = database;
this.game = game;
}

/**
* Saves the game at some point in the future. Multiple calls to this
* method may be coalesced into a single filesystem write.
*/
public void saveLater() {
if (savePending) {
return;
}

handler.postDelayed(this, TimeUnit.SECONDS.toMillis(30));
savePending = true;
}

public void onPause() {
handler.removeCallbacks(this);
database.save(game);
}

@Override public void run() {
savePending = false;
database.saveLater(game);
}
}
116 changes: 116 additions & 0 deletions rounds/src/com/publicobject/rounds/GameSummarizer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/**
* Copyright (C) 2012 Jesse Wilson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.publicobject.rounds;

import android.text.SpannableStringBuilder;
import android.text.TextPaint;
import android.text.style.ClickableSpan;
import android.text.style.UnderlineSpan;
import android.view.View;
import java.util.ArrayList;
import java.util.List;

final class GameSummarizer {
private static final String[] DEFEAT_WORDS = {
"defeated",
"beat",
"conquered",
"destroyed",
"pwned",
"got lucky vs.",
"narrowly defeated",
};

private ClickableSpan defeatWordSpan;
private UnderlineSpan underlineSpan;
private String defeatWord = DEFEAT_WORDS[0];

public GameSummarizer(final ShareActivity activity) {
defeatWordSpan = new ClickableSpan() {
int index = 0;
@Override public void onClick(View view) {
defeatWord = DEFEAT_WORDS[++index % DEFEAT_WORDS.length];
activity.updateMessagePreview();
}
@Override public void updateDrawState(TextPaint ds) {
}
};
underlineSpan = new UnderlineSpan();
}

public CharSequence summarize(Game game, String url) {
List<String> winners = new ArrayList<String>();
List<String> losers = new ArrayList<String>();

if (game.getWinCondition() == WinCondition.NONE) {
for (int p = 0; p < game.playerCount(); p++) {
winners.add(game.playerName(p));
}
} else {
int winningTotal = game.winningTotal();
for (int p = 0; p < game.playerCount(); p++) {
if (winningTotal == game.playerTotal(p)) {
winners.add(game.playerName(p));
} else {
losers.add(game.playerName(p));
}
}
}

SpannableStringBuilder ssb = new SpannableStringBuilder();
appendNames(ssb, winners);

if (game.getWinCondition() == WinCondition.NONE) {
ssb.append(" played ");
} else if (!losers.isEmpty()) {
ssb.append(" ");
ssb.append(defeatWord);
if (defeatWordSpan != null && underlineSpan != null) {
ssb.setSpan(defeatWordSpan,
ssb.length() - defeatWord.length(), ssb.length(), 0);
ssb.setSpan(underlineSpan,
ssb.length() - defeatWord.length(), ssb.length(), 0);
}
ssb.append(" ");
appendNames(ssb, losers);
ssb.append(" at ");
} else {
ssb.append(" tied at ");
}

String gameName = game.getName();
if (gameName == null || gameName.isEmpty()) {
gameName = "a game";
}
ssb.append(gameName).append(". ");
ssb.append(url);
return ssb;
}

private static void appendNames(SpannableStringBuilder message, List<String> players) {
for (int i = 0; i < players.size(); i++) {
String player = players.get(i);
if (i == 0) {
message.append(player);
} else if (i < players.size() - 1) {
message.append(", ").append(player);
} else {
message.append(" and ").append(player);
}
}
}
}
19 changes: 12 additions & 7 deletions rounds/src/com/publicobject/rounds/HomeActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -252,17 +252,22 @@ private View getGame(int position, View recycle, ViewGroup parent) {

players.setText(Names.styleScores(game));

StringBuilder rounds = new StringBuilder();
StringBuilder summaryText = new StringBuilder();
if (game.getName() != null && !game.getName().isEmpty()) {
summaryText.append(game.getName());
summaryText.append(". ");
}
if (game.roundCount() == 1) {
rounds.append("1 round. ");
summaryText.append("1 round. ");
} else {
rounds.append(Integer.toString(game.roundCount()));
rounds.append(" rounds. ");
summaryText.append(Integer.toString(game.roundCount()));
summaryText.append(" rounds. ");
}
rounds.append("Started ");
rounds.append(DateUtils.getRelativeTimeSpanString(getApplicationContext(),
summaryText.append("Started ");
summaryText.append(DateUtils.getRelativeTimeSpanString(getApplicationContext(),
game.getDateStarted(), true));
summary.setText(rounds);
summaryText.append(".");
summary.setText(summaryText);

// Remove listeners before changing any observed state. Necessary for recycling.
checked.setOnCheckedChangeListener(null);
Expand Down
8 changes: 0 additions & 8 deletions rounds/src/com/publicobject/rounds/Json.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,4 @@
*/
public final class Json {
static final Gson gson = new Gson();

public static Game jsonToGame(String json) {
return gson.fromJson(json, Game.class);
}

public static String gameToJson(Game game) {
return gson.toJson(game);
}
}
4 changes: 2 additions & 2 deletions rounds/src/com/publicobject/rounds/Names.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public final class Names {
* Returns styled text containing alternating player names and scores.
*/
public static SpannableStringBuilder styleScores(Game game) {
int maxTotal = game.maxTotal();
int winningTotal = game.winningTotal();
SpannableStringBuilder ssb = new SpannableStringBuilder();
for (int p = 0, size = game.playerCount(); p < size; p++) {
if (p > 0) {
Expand All @@ -40,7 +40,7 @@ public static SpannableStringBuilder styleScores(Game game) {
ssb.append(total);
ssb.setSpan(new ForegroundColorSpan(game.playerColor(p)),
ssb.length() - total.length(), ssb.length(), 0);
if (maxTotal == game.playerTotal(p)) {
if (winningTotal == game.playerTotal(p)) {
ssb.setSpan(new StyleSpan(Typeface.BOLD),
ssb.length() - total.length(), ssb.length(), 0);
}
Expand Down
Loading

0 comments on commit 81a23ca

Please sign in to comment.