|
|
|
@@ -9,7 +9,6 @@ import android.os.Build;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.os.VibrationEffect;
|
|
|
|
import android.os.VibrationEffect;
|
|
|
|
import android.os.Vibrator;
|
|
|
|
import android.os.Vibrator;
|
|
|
|
import android.util.Log;
|
|
|
|
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.animation.AlphaAnimation;
|
|
|
|
import android.view.animation.AlphaAnimation;
|
|
|
|
import android.view.animation.Animation;
|
|
|
|
import android.view.animation.Animation;
|
|
|
|
@@ -19,7 +18,6 @@ import android.widget.GridLayout;
|
|
|
|
import android.widget.LinearLayout;
|
|
|
|
import android.widget.LinearLayout;
|
|
|
|
import android.widget.TextView;
|
|
|
|
import android.widget.TextView;
|
|
|
|
import android.widget.Toast;
|
|
|
|
import android.widget.Toast;
|
|
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
|
|
|
|
|
|
import androidx.core.content.ContextCompat;
|
|
|
|
import androidx.core.content.ContextCompat;
|
|
|
|
import androidx.core.graphics.Insets;
|
|
|
|
import androidx.core.graphics.Insets;
|
|
|
|
import androidx.core.view.ViewCompat;
|
|
|
|
import androidx.core.view.ViewCompat;
|
|
|
|
@@ -27,18 +25,21 @@ import androidx.core.view.WindowInsetsCompat;
|
|
|
|
import androidx.preference.PreferenceManager;
|
|
|
|
import androidx.preference.PreferenceManager;
|
|
|
|
|
|
|
|
|
|
|
|
import com.aldo.apps.ochecompanion.database.DatabaseHelper;
|
|
|
|
import com.aldo.apps.ochecompanion.database.DatabaseHelper;
|
|
|
|
|
|
|
|
import com.aldo.apps.ochecompanion.database.objects.Match;
|
|
|
|
import com.aldo.apps.ochecompanion.database.objects.Player;
|
|
|
|
import com.aldo.apps.ochecompanion.database.objects.Player;
|
|
|
|
import com.aldo.apps.ochecompanion.database.objects.Statistics;
|
|
|
|
import com.aldo.apps.ochecompanion.database.objects.Statistics;
|
|
|
|
import com.aldo.apps.ochecompanion.ui.PlayerStatsView;
|
|
|
|
import com.aldo.apps.ochecompanion.ui.PlayerStatsView;
|
|
|
|
import com.aldo.apps.ochecompanion.utils.CheckoutEngine;
|
|
|
|
import com.aldo.apps.ochecompanion.utils.CheckoutEngine;
|
|
|
|
import com.aldo.apps.ochecompanion.utils.DartsConstants;
|
|
|
|
import com.aldo.apps.ochecompanion.utils.DartsConstants;
|
|
|
|
|
|
|
|
import com.aldo.apps.ochecompanion.utils.Log;
|
|
|
|
|
|
|
|
import com.aldo.apps.ochecompanion.utils.MatchProgress;
|
|
|
|
import com.aldo.apps.ochecompanion.utils.SoundEngine;
|
|
|
|
import com.aldo.apps.ochecompanion.utils.SoundEngine;
|
|
|
|
import com.aldo.apps.ochecompanion.utils.UIConstants;
|
|
|
|
import com.aldo.apps.ochecompanion.utils.UIConstants;
|
|
|
|
|
|
|
|
import com.aldo.apps.ochecompanion.utils.converters.MatchProgressConverter;
|
|
|
|
import com.google.android.material.button.MaterialButton;
|
|
|
|
import com.google.android.material.button.MaterialButton;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.UUID;
|
|
|
|
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
|
|
|
|
|
|
import nl.dionsegijn.konfetti.core.PartyFactory;
|
|
|
|
import nl.dionsegijn.konfetti.core.PartyFactory;
|
|
|
|
@@ -56,11 +57,6 @@ public class GameActivity extends BaseActivity {
|
|
|
|
|
|
|
|
|
|
|
|
private static final String TAG = "GameActivity";
|
|
|
|
private static final String TAG = "GameActivity";
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Intent extra key for player list. Type: ArrayList<Player>
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private static final String EXTRA_PLAYERS = "extra_players";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Intent extra key for starting score. Type: int (typically 501, 301, or 701)
|
|
|
|
* Intent extra key for starting score. Type: int (typically 501, 301, or 701)
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
@@ -69,7 +65,7 @@ public class GameActivity extends BaseActivity {
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Intent extra for a match ID. Making it possible to load a match from the database.
|
|
|
|
* Intent extra for a match ID. Making it possible to load a match from the database.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private static final String EXTRA_MATCH_UUID = "extra_match_uuid";
|
|
|
|
private static final String EXTRA_MATCH_ID = "extra_match_uuid";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ========================================================================================
|
|
|
|
// ========================================================================================
|
|
|
|
@@ -77,9 +73,9 @@ public class GameActivity extends BaseActivity {
|
|
|
|
// ========================================================================================
|
|
|
|
// ========================================================================================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* The matches UUID from the database.
|
|
|
|
* The matches ID from the database.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private String mMatchUuid;
|
|
|
|
private int mMatchId;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Index of the current active player (0 to playerCount-1).
|
|
|
|
* Index of the current active player (0 to playerCount-1).
|
|
|
|
@@ -129,6 +125,12 @@ public class GameActivity extends BaseActivity {
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private boolean mIsBustedTurn = false;
|
|
|
|
private boolean mIsBustedTurn = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Flag indicating the match has been completed (a player has won).
|
|
|
|
|
|
|
|
* When true, pressing back will return to main menu instead of restarting.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private boolean mIsMatchCompleted = false;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Helper class to track dart hit details for statistics.
|
|
|
|
* Helper class to track dart hit details for statistics.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
@@ -266,14 +268,13 @@ public class GameActivity extends BaseActivity {
|
|
|
|
* Starts GameActivity with specified players and starting score.
|
|
|
|
* Starts GameActivity with specified players and starting score.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param context The context from which to start the activity
|
|
|
|
* @param context The context from which to start the activity
|
|
|
|
* @param players The list of players (can be null/empty)
|
|
|
|
|
|
|
|
* @param startScore The starting score (typically 501, 301, or 701)
|
|
|
|
* @param startScore The starting score (typically 501, 301, or 701)
|
|
|
|
|
|
|
|
* @param matchId The ID of the match to be started/loaded.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
public static void start(final Context context, final ArrayList<Player> players, final int startScore) {
|
|
|
|
public static void start(final Context context, final int startScore, final int matchId) {
|
|
|
|
Intent intent = new Intent(context, GameActivity.class);
|
|
|
|
Intent intent = new Intent(context, GameActivity.class);
|
|
|
|
intent.putParcelableArrayListExtra(EXTRA_PLAYERS, players);
|
|
|
|
|
|
|
|
intent.putExtra(EXTRA_START_SCORE, startScore);
|
|
|
|
intent.putExtra(EXTRA_START_SCORE, startScore);
|
|
|
|
intent.putExtra(EXTRA_MATCH_UUID, UUID.randomUUID().toString());
|
|
|
|
intent.putExtra(EXTRA_MATCH_ID, matchId);
|
|
|
|
context.startActivity(intent);
|
|
|
|
context.startActivity(intent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -298,7 +299,7 @@ public class GameActivity extends BaseActivity {
|
|
|
|
|
|
|
|
|
|
|
|
// Extract game parameters from intent
|
|
|
|
// Extract game parameters from intent
|
|
|
|
mStartingScore = getIntent().getIntExtra(EXTRA_START_SCORE, DartsConstants.DEFAULT_GAME_SCORE);
|
|
|
|
mStartingScore = getIntent().getIntExtra(EXTRA_START_SCORE, DartsConstants.DEFAULT_GAME_SCORE);
|
|
|
|
mMatchUuid = getIntent().getStringExtra(EXTRA_MATCH_UUID);
|
|
|
|
mMatchId = getIntent().getIntExtra(EXTRA_MATCH_ID, -1);
|
|
|
|
|
|
|
|
|
|
|
|
// Initialize activity components in order
|
|
|
|
// Initialize activity components in order
|
|
|
|
initViews();
|
|
|
|
initViews();
|
|
|
|
@@ -306,13 +307,69 @@ public class GameActivity extends BaseActivity {
|
|
|
|
|
|
|
|
|
|
|
|
// Only setup a new game if we're not restoring from saved state
|
|
|
|
// Only setup a new game if we're not restoring from saved state
|
|
|
|
if (savedInstanceState == null) {
|
|
|
|
if (savedInstanceState == null) {
|
|
|
|
|
|
|
|
// New game - need to load players and create/load match
|
|
|
|
new Thread(() -> {
|
|
|
|
new Thread(() -> {
|
|
|
|
final List<Player> allAvailablePlayers = (List<Player>) mDatabaseHelper.getAllPlayers();
|
|
|
|
final List<Player> allAvailablePlayers = (List<Player>) mDatabaseHelper.getAllPlayers();
|
|
|
|
Log.d(TAG, "onCreate: allAvailablePlayers = [" + allAvailablePlayers + "]");
|
|
|
|
Log.d(TAG, "onCreate: allAvailablePlayers = [" + allAvailablePlayers + "]");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Handle match loading/creation
|
|
|
|
|
|
|
|
Match match = null;
|
|
|
|
|
|
|
|
if (mMatchId > 0) {
|
|
|
|
|
|
|
|
// Try to load existing match
|
|
|
|
|
|
|
|
match = mDatabaseHelper.getMatchById(mMatchId);
|
|
|
|
|
|
|
|
Log.d(TAG, "onCreate: Loaded match from DB: " + (match != null ? "ID=" + match.id : "null"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (match != null && match.participantData != null && !match.participantData.isEmpty()) {
|
|
|
|
|
|
|
|
// Load match progress from database
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
final MatchProgress progress = MatchProgressConverter.fromString(match.participantData);
|
|
|
|
|
|
|
|
if (progress != null) {
|
|
|
|
|
|
|
|
Log.d(TAG, "onCreate: Found saved progress with " + progress.players.size() + " players");
|
|
|
|
|
|
|
|
// Initialize player states first
|
|
|
|
|
|
|
|
runOnUiThread(() -> {
|
|
|
|
|
|
|
|
mPlayerStates = new ArrayList<>();
|
|
|
|
|
|
|
|
if (allAvailablePlayers != null && !allAvailablePlayers.isEmpty()) {
|
|
|
|
|
|
|
|
for (Player p : allAvailablePlayers) {
|
|
|
|
|
|
|
|
mPlayerStates.add(new X01State(p, mStartingScore));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
final Player guest = new Player("GUEST", null);
|
|
|
|
|
|
|
|
mPlayerStates.add(new X01State(guest, mStartingScore));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
loadMatchProgress(progress);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
Log.d(TAG, "onCreate: Loaded existing match with ID: " + mMatchId);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
Log.w(TAG, "onCreate: Progress is null, treating as new match");
|
|
|
|
|
|
|
|
match = null; // Treat as new match
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
Log.e(TAG, "onCreate: Failed to load match progress", e);
|
|
|
|
|
|
|
|
match = null; // Treat as new match on error
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (match != null) {
|
|
|
|
|
|
|
|
// Match exists but has no progress data yet (newly created)
|
|
|
|
|
|
|
|
Log.d(TAG, "onCreate: Match has no progress data, setting up new game");
|
|
|
|
|
|
|
|
match = null; // Treat as new match
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (match == null) {
|
|
|
|
|
|
|
|
// Create new match if not found or invalid ID
|
|
|
|
|
|
|
|
final long newMatchId = mDatabaseHelper.createNewMatch(String.valueOf(mStartingScore), allAvailablePlayers);
|
|
|
|
|
|
|
|
if (newMatchId > 0) {
|
|
|
|
|
|
|
|
mMatchId = (int) newMatchId;
|
|
|
|
|
|
|
|
Log.d(TAG, "onCreate: Created new match with ID: " + mMatchId);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
Log.e(TAG, "onCreate: Failed to create new match");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Setup new game
|
|
|
|
runOnUiThread(() -> setupGame(allAvailablePlayers));
|
|
|
|
runOnUiThread(() -> setupGame(allAvailablePlayers));
|
|
|
|
|
|
|
|
}
|
|
|
|
}).start();
|
|
|
|
}).start();
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// We're restoring - load players synchronously since onRestoreInstanceState is called immediately
|
|
|
|
// We're restoring from configuration change - load players synchronously since onRestoreInstanceState is called immediately
|
|
|
|
Log.d(TAG, "onCreate: Loading players for state restoration");
|
|
|
|
Log.d(TAG, "onCreate: Loading players for state restoration");
|
|
|
|
final List<Player> allAvailablePlayers = (List<Player>) mDatabaseHelper.getAllPlayers();
|
|
|
|
final List<Player> allAvailablePlayers = (List<Player>) mDatabaseHelper.getAllPlayers();
|
|
|
|
Log.d(TAG, "onCreate: restoring with players = [" + allAvailablePlayers + "]");
|
|
|
|
Log.d(TAG, "onCreate: restoring with players = [" + allAvailablePlayers + "]");
|
|
|
|
@@ -340,7 +397,18 @@ public class GameActivity extends BaseActivity {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
protected void onSaveInstanceState(Bundle outState) {
|
|
|
|
public void onBackPressed() {
|
|
|
|
|
|
|
|
if (mIsMatchCompleted) {
|
|
|
|
|
|
|
|
// Match is finished, return to main menu
|
|
|
|
|
|
|
|
finish();
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// Match is ongoing, use default back button behavior (exit with confirmation if needed)
|
|
|
|
|
|
|
|
super.onBackPressed();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
protected void onSaveInstanceState(final Bundle outState) {
|
|
|
|
super.onSaveInstanceState(outState);
|
|
|
|
super.onSaveInstanceState(outState);
|
|
|
|
Log.d(TAG, "onSaveInstanceState: Saving game state");
|
|
|
|
Log.d(TAG, "onSaveInstanceState: Saving game state");
|
|
|
|
|
|
|
|
|
|
|
|
@@ -348,7 +416,7 @@ public class GameActivity extends BaseActivity {
|
|
|
|
outState.putInt("activePlayerIndex", mActivePlayerIndex);
|
|
|
|
outState.putInt("activePlayerIndex", mActivePlayerIndex);
|
|
|
|
outState.putInt("multiplier", mMultiplier);
|
|
|
|
outState.putInt("multiplier", mMultiplier);
|
|
|
|
outState.putInt("startingScore", mStartingScore);
|
|
|
|
outState.putInt("startingScore", mStartingScore);
|
|
|
|
outState.putString("matchUuid", mMatchUuid);
|
|
|
|
outState.putInt("matchId", mMatchId);
|
|
|
|
outState.putBoolean("isTurnOver", mIsTurnOver);
|
|
|
|
outState.putBoolean("isTurnOver", mIsTurnOver);
|
|
|
|
outState.putBoolean("isBustedTurn", mIsBustedTurn);
|
|
|
|
outState.putBoolean("isBustedTurn", mIsBustedTurn);
|
|
|
|
|
|
|
|
|
|
|
|
@@ -394,7 +462,7 @@ public class GameActivity extends BaseActivity {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
|
|
|
protected void onRestoreInstanceState(final Bundle savedInstanceState) {
|
|
|
|
super.onRestoreInstanceState(savedInstanceState);
|
|
|
|
super.onRestoreInstanceState(savedInstanceState);
|
|
|
|
Log.d(TAG, "onRestoreInstanceState: Restoring game state");
|
|
|
|
Log.d(TAG, "onRestoreInstanceState: Restoring game state");
|
|
|
|
|
|
|
|
|
|
|
|
@@ -402,7 +470,7 @@ public class GameActivity extends BaseActivity {
|
|
|
|
mActivePlayerIndex = savedInstanceState.getInt("activePlayerIndex", 0);
|
|
|
|
mActivePlayerIndex = savedInstanceState.getInt("activePlayerIndex", 0);
|
|
|
|
mMultiplier = savedInstanceState.getInt("multiplier", 1);
|
|
|
|
mMultiplier = savedInstanceState.getInt("multiplier", 1);
|
|
|
|
mStartingScore = savedInstanceState.getInt("startingScore", DartsConstants.DEFAULT_GAME_SCORE);
|
|
|
|
mStartingScore = savedInstanceState.getInt("startingScore", DartsConstants.DEFAULT_GAME_SCORE);
|
|
|
|
mMatchUuid = savedInstanceState.getString("matchUuid");
|
|
|
|
mMatchId = savedInstanceState.getInt("matchId");
|
|
|
|
mIsTurnOver = savedInstanceState.getBoolean("isTurnOver", false);
|
|
|
|
mIsTurnOver = savedInstanceState.getBoolean("isTurnOver", false);
|
|
|
|
mIsBustedTurn = savedInstanceState.getBoolean("isBustedTurn", false);
|
|
|
|
mIsBustedTurn = savedInstanceState.getBoolean("isBustedTurn", false);
|
|
|
|
|
|
|
|
|
|
|
|
@@ -703,6 +771,7 @@ public class GameActivity extends BaseActivity {
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private void updatePlayerStats(final GameActivity.X01State active, final int dartsThrown, final int pointsMade, final boolean wasBust, final int checkoutValue) {
|
|
|
|
private void updatePlayerStats(final GameActivity.X01State active, final int dartsThrown, final int pointsMade, final boolean wasBust, final int checkoutValue) {
|
|
|
|
if (active.player != null && active.player.id != 0) {
|
|
|
|
if (active.player != null && active.player.id != 0) {
|
|
|
|
|
|
|
|
new Thread(() -> {
|
|
|
|
mDatabaseHelper.updatePlayerStatistics(
|
|
|
|
mDatabaseHelper.updatePlayerStatistics(
|
|
|
|
active.player.id,
|
|
|
|
active.player.id,
|
|
|
|
dartsThrown,
|
|
|
|
dartsThrown,
|
|
|
|
@@ -711,6 +780,7 @@ public class GameActivity extends BaseActivity {
|
|
|
|
checkoutValue,
|
|
|
|
checkoutValue,
|
|
|
|
active.dartsThrown
|
|
|
|
active.dartsThrown
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
}).start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -779,6 +849,8 @@ public class GameActivity extends BaseActivity {
|
|
|
|
mIsTurnOver = false;
|
|
|
|
mIsTurnOver = false;
|
|
|
|
mIsBustedTurn = false;
|
|
|
|
mIsBustedTurn = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
saveMatchProgress();
|
|
|
|
|
|
|
|
|
|
|
|
// Update UI for next player
|
|
|
|
// Update UI for next player
|
|
|
|
updateUI();
|
|
|
|
updateUI();
|
|
|
|
updateTurnIndicators();
|
|
|
|
updateTurnIndicators();
|
|
|
|
@@ -789,8 +861,70 @@ public class GameActivity extends BaseActivity {
|
|
|
|
* Saves the current game state to the database.
|
|
|
|
* Saves the current game state to the database.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private void saveMatchProgress() {
|
|
|
|
private void saveMatchProgress() {
|
|
|
|
// TODO: Persist current state to Room using mMatchUuid
|
|
|
|
final MatchProgress progress = new MatchProgress();
|
|
|
|
// This allows the "Continue Game" feature on the Main Menu
|
|
|
|
progress.activePlayerIndex = mActivePlayerIndex;
|
|
|
|
|
|
|
|
progress.startingScore = mStartingScore;
|
|
|
|
|
|
|
|
progress.players = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (X01State state : mPlayerStates) {
|
|
|
|
|
|
|
|
progress.players.add(new MatchProgress.PlayerStateSnapshot(
|
|
|
|
|
|
|
|
state.player.id,
|
|
|
|
|
|
|
|
state.name,
|
|
|
|
|
|
|
|
state.remainingScore,
|
|
|
|
|
|
|
|
state.dartsThrown
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String progressJson = MatchProgressConverter.fromProgress(progress);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mMatchId > 0) {
|
|
|
|
|
|
|
|
new Thread(() -> {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
// Load existing match and update its progress
|
|
|
|
|
|
|
|
Match match = mDatabaseHelper.getMatchById(mMatchId);
|
|
|
|
|
|
|
|
if (match != null) {
|
|
|
|
|
|
|
|
match.participantData = progressJson;
|
|
|
|
|
|
|
|
match.timestamp = System.currentTimeMillis();
|
|
|
|
|
|
|
|
mDatabaseHelper.updateMatch(match);
|
|
|
|
|
|
|
|
Log.d(TAG, "saveMatchProgress: Saved match progress for match ID: " + mMatchId);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
Log.e(TAG, "saveMatchProgress: Match not found with ID: " + mMatchId);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
Log.e(TAG, "saveMatchProgress: Failed to save progress", e);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}).start();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Loads match progress from a saved state.
|
|
|
|
|
|
|
|
* Updates all player scores and game state to match the saved progress.
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param progress The MatchProgress to load
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private void loadMatchProgress(final MatchProgress progress) {
|
|
|
|
|
|
|
|
if (progress == null || mPlayerStates == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Log.d(TAG, "loadMatchProgress: Loading saved match progress");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Restore active player index
|
|
|
|
|
|
|
|
mActivePlayerIndex = progress.activePlayerIndex;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Restore player scores and darts thrown
|
|
|
|
|
|
|
|
for (int i = 0; i < progress.players.size() && i < mPlayerStates.size(); i++) {
|
|
|
|
|
|
|
|
MatchProgress.PlayerStateSnapshot snapshot = progress.players.get(i);
|
|
|
|
|
|
|
|
X01State state = mPlayerStates.get(i);
|
|
|
|
|
|
|
|
state.remainingScore = snapshot.remainingScore;
|
|
|
|
|
|
|
|
state.dartsThrown = snapshot.dartsThrown;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Update UI to reflect loaded state
|
|
|
|
|
|
|
|
updateUI();
|
|
|
|
|
|
|
|
updateTurnIndicators();
|
|
|
|
|
|
|
|
setMultiplier(DartsConstants.MULTIPLIER_SINGLE);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Log.d(TAG, "loadMatchProgress: Match progress loaded successfully");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@@ -925,7 +1059,9 @@ public class GameActivity extends BaseActivity {
|
|
|
|
* @param isMissed true if the double-out was missed, false if successful
|
|
|
|
* @param isMissed true if the double-out was missed, false if successful
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private void trackDoubleAttempt(final X01State playerState, final boolean isMissed) {
|
|
|
|
private void trackDoubleAttempt(final X01State playerState, final boolean isMissed) {
|
|
|
|
|
|
|
|
new Thread(() -> {
|
|
|
|
mDatabaseHelper.trackDoubleAttempt(playerState.playerId, isMissed);
|
|
|
|
mDatabaseHelper.trackDoubleAttempt(playerState.playerId, isMissed);
|
|
|
|
|
|
|
|
}).start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@@ -938,7 +1074,9 @@ public class GameActivity extends BaseActivity {
|
|
|
|
for (X01State playerState : mPlayerStates) {
|
|
|
|
for (X01State playerState : mPlayerStates) {
|
|
|
|
playerIds.add(playerState.playerId);
|
|
|
|
playerIds.add(playerState.playerId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
new Thread(() -> {
|
|
|
|
mDatabaseHelper.incrementMatchesPlayed(playerIds);
|
|
|
|
mDatabaseHelper.incrementMatchesPlayed(playerIds);
|
|
|
|
|
|
|
|
}).start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@@ -959,7 +1097,9 @@ public class GameActivity extends BaseActivity {
|
|
|
|
dbDartHits.add(new DatabaseHelper.DartHit(hit.baseValue, hit.multiplier));
|
|
|
|
dbDartHits.add(new DatabaseHelper.DartHit(hit.baseValue, hit.multiplier));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
new Thread(() -> {
|
|
|
|
mDatabaseHelper.recordDartHits(playerState.playerId, dbDartHits);
|
|
|
|
mDatabaseHelper.recordDartHits(playerState.playerId, dbDartHits);
|
|
|
|
|
|
|
|
}).start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@@ -998,9 +1138,56 @@ public class GameActivity extends BaseActivity {
|
|
|
|
|
|
|
|
|
|
|
|
mShowStatsBtn.setVisibility(View.VISIBLE);
|
|
|
|
mShowStatsBtn.setVisibility(View.VISIBLE);
|
|
|
|
attachPlayerStats();
|
|
|
|
attachPlayerStats();
|
|
|
|
// TODO: Consider adding:
|
|
|
|
|
|
|
|
// - Save match to database
|
|
|
|
// Save completed match to database
|
|
|
|
// - Offer rematch
|
|
|
|
saveCompletedMatch(winner);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Mark match as completed so back button returns to main menu
|
|
|
|
|
|
|
|
mIsMatchCompleted = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Saves the completed match to the database with final results.
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param winner The winning player's game state
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private void saveCompletedMatch(final X01State winner) {
|
|
|
|
|
|
|
|
if (mMatchId <= 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
new Thread(() -> {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
Match match = mDatabaseHelper.getMatchById(mMatchId);
|
|
|
|
|
|
|
|
if (match != null) {
|
|
|
|
|
|
|
|
// Mark match as completed
|
|
|
|
|
|
|
|
match.state = Match.MatchState.COMPLETED;
|
|
|
|
|
|
|
|
match.timestamp = System.currentTimeMillis();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Save final progress state
|
|
|
|
|
|
|
|
final MatchProgress finalProgress = new MatchProgress();
|
|
|
|
|
|
|
|
finalProgress.activePlayerIndex = mActivePlayerIndex;
|
|
|
|
|
|
|
|
finalProgress.startingScore = mStartingScore;
|
|
|
|
|
|
|
|
finalProgress.players = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (X01State state : mPlayerStates) {
|
|
|
|
|
|
|
|
finalProgress.players.add(new MatchProgress.PlayerStateSnapshot(
|
|
|
|
|
|
|
|
state.player.id,
|
|
|
|
|
|
|
|
state.name,
|
|
|
|
|
|
|
|
state.remainingScore,
|
|
|
|
|
|
|
|
state.dartsThrown
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
match.participantData = MatchProgressConverter.fromProgress(finalProgress);
|
|
|
|
|
|
|
|
mDatabaseHelper.updateMatch(match);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Log.d(TAG, "saveCompletedMatch: Match " + mMatchId + " marked as completed");
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
Log.e(TAG, "saveCompletedMatch: Match not found with ID: " + mMatchId);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
Log.e(TAG, "saveCompletedMatch: Failed to save completed match", e);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}).start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void attachPlayerStats() {
|
|
|
|
private void attachPlayerStats() {
|
|
|
|
|