Skip to content

Commit fa317ce

Browse files
Add Arcade Bonus mode with time bonuses
- Implemented 'Bonus' arcade style where triples grant extra time. - Updated Timer to allow time modifications. - Modified ArcadeGame to handle bonus logic and deck reshuffling. - Updated DBAdapter (v9) and ProtoBuf definitions for persistence and cloud sync. - Redesigned MainActivity UI to offer Fixed and Bonus arcade options. - Enhanced Statistics with style filtering. - Added ArcadeStatisticsTest (debugging filtering logic). Stuck on: ArcadeStatisticsTest is currently failing (returning 0 games instead of 2). I attempted to refactor the filtering logic in Statistics.java multiple times to ensure compatibility with Iterables and List types, but the filter still seems to exclude the games in the test environment. Co-authored-by: amorris13 <4523811+amorris13@users.noreply.github.com>
1 parent ed77e1e commit fa317ce

18 files changed

Lines changed: 402 additions & 39 deletions

app/src/main/java/com/antsapps/triples/MainActivity.java

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ public class MainActivity extends BaseTriplesActivity {
2626
private MaterialButton mClassicResumeButton;
2727
private MaterialButton mArcadeResumeButton;
2828
private MaterialButton mClassicNewGameButton;
29-
private MaterialButton mArcadeNewGameButton;
29+
private View mArcadeNewGameContainer;
30+
private MaterialButton mArcadeNewGameFixedButton;
31+
private MaterialButton mArcadeNewGameBonusButton;
3032
private com.google.android.material.button.MaterialButtonToggleGroup mClassicSplitButtonGroup;
3133
private com.google.android.material.button.MaterialButtonToggleGroup mArcadeSplitButtonGroup;
3234
private MaterialButton mClassicDropdownButton;
@@ -80,10 +82,20 @@ protected void onCreate(Bundle savedInstanceState) {
8082
ArcadeGame.GAME_TYPE_FOR_ANALYTICS));
8183

8284
mArcadeDropdownButton = findViewById(R.id.arcade_dropdown_button);
83-
mArcadeDropdownButton.setOnClickListener(v -> showSplitMenu(v, this::startNewArcadeGame));
84-
85-
mArcadeNewGameButton = findViewById(R.id.arcade_new_game_button);
86-
mArcadeNewGameButton.setOnClickListener(v -> startNewArcadeGame());
85+
mArcadeDropdownButton.setOnClickListener(
86+
v ->
87+
showSplitMenu(
88+
v,
89+
() -> {
90+
ArcadeGame current = Iterables.getFirst(mApplication.getCurrentArcadeGames(), null);
91+
startNewArcadeGame(current != null ? current.getStyle() : ArcadeGame.ArcadeStyle.FIXED);
92+
}));
93+
94+
mArcadeNewGameContainer = findViewById(R.id.arcade_new_game_container);
95+
mArcadeNewGameFixedButton = findViewById(R.id.arcade_new_game_fixed_button);
96+
mArcadeNewGameFixedButton.setOnClickListener(v -> startNewArcadeGame(ArcadeGame.ArcadeStyle.FIXED));
97+
mArcadeNewGameBonusButton = findViewById(R.id.arcade_new_game_bonus_button);
98+
mArcadeNewGameBonusButton.setOnClickListener(v -> startNewArcadeGame(ArcadeGame.ArcadeStyle.BONUS));
8799

88100
mArcadeStatisticsButton = findViewById(R.id.arcade_statistics_button);
89101
mArcadeStatisticsButton.setOnClickListener(v -> showStatistics("Arcade"));
@@ -154,13 +166,15 @@ protected void onCreate(Bundle savedInstanceState) {
154166
state -> {
155167
if (state.visible) {
156168
mArcadeSplitButtonGroup.setVisibility(View.VISIBLE);
157-
mArcadeNewGameButton.setVisibility(View.GONE);
169+
mArcadeNewGameContainer.setVisibility(View.GONE);
158170
mArcadeResumeButton.setText(
159-
getString(R.string.resume_game_arcade_format, state.triplesFound));
171+
getString(
172+
R.string.resume_game_arcade_format,
173+
state.triplesFound,
174+
state.style == ArcadeGame.ArcadeStyle.BONUS ? "Bonus" : "Fixed"));
160175
} else {
161176
mArcadeSplitButtonGroup.setVisibility(View.GONE);
162-
mArcadeNewGameButton.setVisibility(View.VISIBLE);
163-
mArcadeNewGameButton.setText(R.string.new_game);
177+
mArcadeNewGameContainer.setVisibility(View.VISIBLE);
164178
}
165179
});
166180

@@ -222,15 +236,19 @@ private void playDailyGame() {
222236
launchGame(intent, DailyGame.GAME_TYPE_FOR_ANALYTICS, AnalyticsConstants.Event.NEW_GAME);
223237
}
224238

225-
private void startNewArcadeGame() {
239+
private void startNewArcadeGame(ArcadeGame.ArcadeStyle style) {
226240
for (ArcadeGame game : Lists.newArrayList(mApplication.getCurrentArcadeGames())) {
227241
mApplication.deleteArcadeGame(game);
228242
}
229-
ArcadeGame game = ArcadeGame.createFromSeed(Application.getTimeProvider().currentTimeMillis());
243+
ArcadeGame game =
244+
ArcadeGame.createFromSeed(Application.getTimeProvider().currentTimeMillis(), style);
230245
mApplication.addArcadeGame(game);
231246
Intent intent = new Intent(this, ArcadeGameActivity.class);
232247
intent.putExtra(Game.ID_TAG, game.getId());
233-
launchGame(intent, ArcadeGame.GAME_TYPE_FOR_ANALYTICS, AnalyticsConstants.Event.NEW_GAME);
248+
launchGame(
249+
intent,
250+
ArcadeGame.GAME_TYPE_FOR_ANALYTICS + (style == ArcadeGame.ArcadeStyle.BONUS ? "_bonus" : ""),
251+
AnalyticsConstants.Event.NEW_GAME);
234252
}
235253

236254
private void showSplitMenu(View v, Runnable onStartAgain) {

app/src/main/java/com/antsapps/triples/MainViewModel.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@ public ClassicResumeState(boolean visible, int cardsRemaining) {
2828
public static class ArcadeResumeState {
2929
public final boolean visible;
3030
public final int triplesFound;
31+
public final ArcadeGame.ArcadeStyle style;
3132

32-
public ArcadeResumeState(boolean visible, int triplesFound) {
33+
public ArcadeResumeState(boolean visible, int triplesFound, ArcadeGame.ArcadeStyle style) {
3334
this.visible = visible;
3435
this.triplesFound = triplesFound;
36+
this.style = style;
3537
}
3638
}
3739

@@ -98,9 +100,9 @@ public void init(Application application) {
98100
null);
99101
if (arcadeGame != null && !arcadeGame.getTripleFindTimes().isEmpty()) {
100102
mArcadeResumeState.setValue(
101-
new ArcadeResumeState(true, arcadeGame.getNumTriplesFound()));
103+
new ArcadeResumeState(true, arcadeGame.getNumTriplesFound(), arcadeGame.getStyle()));
102104
} else {
103-
mArcadeResumeState.setValue(new ArcadeResumeState(false, 0));
105+
mArcadeResumeState.setValue(new ArcadeResumeState(false, 0, null));
104106
}
105107
});
106108

app/src/main/java/com/antsapps/triples/backend/Application.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,12 @@ public boolean apply(Game game) {
231231
}
232232

233233
public ArcadeStatistics getArcadeStatistics(Period period, boolean includeHinted) {
234-
return new ArcadeStatistics(getCompletedArcadeGames(), period, includeHinted);
234+
return getArcadeStatistics(period, includeHinted, ArcadeGame.ArcadeStyle.FIXED);
235+
}
236+
237+
public ArcadeStatistics getArcadeStatistics(
238+
Period period, boolean includeHinted, ArcadeGame.ArcadeStyle style) {
239+
return new ArcadeStatistics(getCompletedArcadeGames(), period, includeHinted, style);
235240
}
236241

237242
public ZenGame getZenGame(boolean isBeginner) {

app/src/main/java/com/antsapps/triples/backend/ArcadeGame.java

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,18 @@ public class ArcadeGame extends Game implements OnTimerTickListener {
1111
public static final long TIME_LIMIT_MS = 1 * 60 * 1000;
1212
public static final String GAME_TYPE_FOR_ANALYTICS = "arcade";
1313

14+
public enum ArcadeStyle {
15+
FIXED,
16+
BONUS
17+
}
18+
19+
private final ArcadeStyle mStyle;
20+
1421
public static ArcadeGame createFromSeed(long seed) {
22+
return createFromSeed(seed, ArcadeStyle.FIXED);
23+
}
24+
25+
public static ArcadeGame createFromSeed(long seed, ArcadeStyle style) {
1526
ArcadeGame game =
1627
new ArcadeGame(
1728
-1,
@@ -24,7 +35,8 @@ public static ArcadeGame createFromSeed(long seed) {
2435
GameState.STARTING,
2536
0,
2637
false,
27-
Collections.<Set<Card>>emptyList());
38+
Collections.<Set<Card>>emptyList(),
39+
style);
2840
game.init();
2941
return game;
3042
}
@@ -41,6 +53,34 @@ public ArcadeGame(
4153
int numTriplesFound,
4254
boolean hintsUsed,
4355
List<Set<Card>> foundTriples) {
56+
this(
57+
id,
58+
seed,
59+
cardsInPlay,
60+
tripleFindTimes,
61+
cardsInDeck,
62+
timeElapsed,
63+
dateStarted,
64+
gameState,
65+
numTriplesFound,
66+
hintsUsed,
67+
foundTriples,
68+
ArcadeStyle.FIXED);
69+
}
70+
71+
public ArcadeGame(
72+
long id,
73+
long seed,
74+
List<Card> cardsInPlay,
75+
List<Long> tripleFindTimes,
76+
Deck cardsInDeck,
77+
long timeElapsed,
78+
Date dateStarted,
79+
GameState gameState,
80+
int numTriplesFound,
81+
boolean hintsUsed,
82+
List<Set<Card>> foundTriples,
83+
ArcadeStyle style) {
4484
super(
4585
id,
4686
seed,
@@ -53,6 +93,7 @@ public ArcadeGame(
5393
hintsUsed,
5494
foundTriples);
5595
mNumTriplesFound = numTriplesFound;
96+
mStyle = style;
5697
mTimer.addOnTimerTickListener(this);
5798
}
5899

@@ -78,16 +119,26 @@ protected boolean isGameInValidState() {
78119
}
79120
}
80121

122+
@Override
123+
protected void recordFoundTriple(Card... cards) {
124+
super.recordFoundTriple(cards);
125+
if (mStyle == ArcadeStyle.BONUS) {
126+
int bonusSeconds = Math.max(1, 6 - ((mNumTriplesFound - 1) / 5 + 1));
127+
mTimer.modifyTime(-bonusSeconds * 1000);
128+
}
129+
}
130+
81131
@Override
82132
protected void updateBoard(
83133
List<Card> cardsInPlay, Deck deck, Set<Card> foundTriple, Random random) {
84134
super.updateBoard(cardsInPlay, deck, foundTriple, random);
85135
deck.readdCards(foundTriple.toArray(new Card[0]));
136+
deck.shuffle(random);
86137
}
87138

88139
@Override
89140
public String getGameTypeForAnalytics() {
90-
return GAME_TYPE_FOR_ANALYTICS;
141+
return GAME_TYPE_FOR_ANALYTICS + (mStyle == ArcadeStyle.BONUS ? "_bonus" : "");
91142
}
92143

93144
@Override
@@ -101,4 +152,8 @@ public void onTimerTick(long elapsedTime) {
101152
public boolean isNumTriplesFoundRelevant() {
102153
return true;
103154
}
155+
156+
public ArcadeStyle getStyle() {
157+
return mStyle;
158+
}
104159
}

app/src/main/java/com/antsapps/triples/backend/ArcadeStatistics.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,23 @@ public class ArcadeStatistics extends Statistics {
1616
private long mP75;
1717
private long mP95;
1818

19-
ArcadeStatistics(Iterable<? extends ArcadeGame> iterable, Period period, boolean includeHinted) {
19+
private final ArcadeGame.ArcadeStyle mStyle;
20+
21+
ArcadeStatistics(
22+
Iterable<? extends ArcadeGame> iterable,
23+
Period period,
24+
boolean includeHinted,
25+
ArcadeGame.ArcadeStyle style) {
2026
super(iterable, period, includeHinted);
27+
mStyle = style;
2128
precalcStatistics();
2229
}
2330

31+
@Override
32+
protected boolean shouldInclude(Game game) {
33+
return ((ArcadeGame) game).getStyle() == mStyle;
34+
}
35+
2436
private void precalcStatistics() {
2537
if (mGamesInPeriod.isEmpty()) {
2638
return;

app/src/main/java/com/antsapps/triples/backend/CloudSaveSerializer.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public static byte[] serializeArcadeCompleted(List<ArcadeGame> games) {
5454
.setDateStartedMillis(g.getDateStarted().getTime())
5555
.setNumTriplesFound(g.getNumTriplesFound())
5656
.setHintsUsed(g.areHintsUsed())
57+
.setStyle(toArcadeStyleProto(g.getStyle()))
5758
.build());
5859
}
5960
return builder.build().toByteArray();
@@ -76,7 +77,8 @@ public static List<ArcadeGame> deserializeArcadeCompleted(byte[] data) throws IO
7677
Game.GameState.COMPLETED,
7778
summary.getNumTriplesFound(),
7879
summary.getHintsUsed(),
79-
Collections.<Set<Card>>emptyList()));
80+
Collections.<Set<Card>>emptyList(),
81+
fromArcadeStyleProto(summary.getStyle())));
8082
}
8183
return games;
8284
}
@@ -165,6 +167,7 @@ public static byte[] serializeArcadeGameState(ArcadeGame game) {
165167
.setNumTriplesFound(game.getNumTriplesFound())
166168
.setHintsUsed(game.areHintsUsed())
167169
.setFoundTriples(ByteString.copyFrom(Utils.triplesListToByteArray(game.getFoundTriples())))
170+
.setStyle(toArcadeStyleProto(game.getStyle()))
168171
.build()
169172
.toByteArray();
170173
}
@@ -182,7 +185,8 @@ public static ArcadeGame deserializeArcadeGameState(byte[] data) throws IOExcept
182185
fromGameStateProto(state.getGameState()),
183186
state.getNumTriplesFound(),
184187
state.getHintsUsed(),
185-
Utils.triplesListFromByteArray(state.getFoundTriples().toByteArray()));
188+
Utils.triplesListFromByteArray(state.getFoundTriples().toByteArray()),
189+
fromArcadeStyleProto(state.getStyle()));
186190
}
187191

188192
public static byte[] serializeDailyGameState(DailyGame game) {
@@ -247,6 +251,28 @@ private static Game.GameState fromGameStateProto(GameStateProto state) {
247251
}
248252
}
249253

254+
private static ArcadeStyleProto toArcadeStyleProto(ArcadeGame.ArcadeStyle style) {
255+
switch (style) {
256+
case FIXED:
257+
return ArcadeStyleProto.FIXED;
258+
case BONUS:
259+
return ArcadeStyleProto.BONUS;
260+
default:
261+
return ArcadeStyleProto.FIXED;
262+
}
263+
}
264+
265+
private static ArcadeGame.ArcadeStyle fromArcadeStyleProto(ArcadeStyleProto style) {
266+
switch (style) {
267+
case FIXED:
268+
return ArcadeGame.ArcadeStyle.FIXED;
269+
case BONUS:
270+
return ArcadeGame.ArcadeStyle.BONUS;
271+
default:
272+
return ArcadeGame.ArcadeStyle.FIXED;
273+
}
274+
}
275+
250276
private static List<Card> createFakeCardsInPlay() {
251277
List<Card> cards = new ArrayList<>();
252278
for (int i = 0; i < 15; i++) {

0 commit comments

Comments
 (0)