From 039350e988eef10f3f5831db962c69b2ff67ea86 Mon Sep 17 00:00:00 2001 From: Alexander Doerflinger Date: Tue, 3 Feb 2026 15:38:58 +0100 Subject: [PATCH] Left over files from previous comit :/ --- .../apps/ochecompanion/AddPlayerActivity.java | 41 ++++- .../aldo/apps/ochecompanion/BaseActivity.java | 2 +- .../apps/ochecompanion/MainMenuActivity.java | 75 +++++---- .../aldo/apps/ochecompanion/TestActivity.java | 2 +- .../database/DatabaseHelper.java | 102 +++++++++++- .../ochecompanion/database/dao/MatchDao.java | 14 +- .../ochecompanion/database/objects/Match.java | 59 ++++--- .../database/objects/Statistics.java | 2 +- .../ui/MainMenuPreferencesFragment.java | 2 +- .../apps/ochecompanion/ui/MatchRecapView.java | 7 + .../ui/adapter/MainMenuGroupMatchAdapter.java | 2 +- .../ui/adapter/MainMenuPlayerAdapter.java | 2 +- .../aldo/apps/ochecompanion/utils/Log.java | 149 ++++++++++++++++++ .../ochecompanion/utils/MatchProgress.java | 31 +++- .../apps/ochecompanion/utils/SoundEngine.java | 2 +- .../converters/MatchProgressConverter.java | 24 ++- .../main/res/layout/activity_add_player.xml | 16 ++ app/src/main/res/values/strings.xml | 1 + 18 files changed, 467 insertions(+), 66 deletions(-) diff --git a/app/src/main/java/com/aldo/apps/ochecompanion/AddPlayerActivity.java b/app/src/main/java/com/aldo/apps/ochecompanion/AddPlayerActivity.java index 4087f05..6ccfee9 100644 --- a/app/src/main/java/com/aldo/apps/ochecompanion/AddPlayerActivity.java +++ b/app/src/main/java/com/aldo/apps/ochecompanion/AddPlayerActivity.java @@ -8,7 +8,9 @@ import android.graphics.RectF; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.util.Log; + +import com.aldo.apps.ochecompanion.ui.PlayerStatsView; +import com.aldo.apps.ochecompanion.utils.Log; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.View; @@ -88,6 +90,11 @@ public class AddPlayerActivity extends BaseActivity { */ private MaterialButton mSaveButton; + /** + * Button to show the player stats. + */ + private MaterialButton mShowStatsButton; + /** * Button to delete a players profile from the database. */ @@ -105,7 +112,17 @@ public class AddPlayerActivity extends BaseActivity { */ private CropOverlayView mCropOverlay; + /** + * View displaying the player's statistics. + */ + private PlayerStatsView mPlayerStatsView; + // ========== Data State ========== + + /** + * Boolean flag indicating whether the stats view is shown. + */ + private boolean mIsStatsViewShown = false; /** * Absolute file path to the saved profile picture in internal storage. @@ -201,6 +218,17 @@ public class AddPlayerActivity extends BaseActivity { } } + @Override + public void onBackPressed() { + Log.d(TAG, "onBackPressed() called with StatsView shown = [" + mIsStatsViewShown + "]"); + if (mIsStatsViewShown) { + mPlayerStatsView.setVisibility(View.GONE); + mIsStatsViewShown = false; + return; + } + super.onBackPressed(); + } + /** * Initializes all UI component references and sets up click listeners. */ @@ -213,6 +241,8 @@ public class AddPlayerActivity extends BaseActivity { mProfilePictureView = findViewById(R.id.ivAddPlayerProfile); mUserNameInput = findViewById(R.id.etUsername); mTitleView = findViewById(R.id.tvTitle); + mShowStatsButton = findViewById(R.id.btnShowStats); + mPlayerStatsView = findViewById(R.id.player_stats_view); mSaveButton = findViewById(R.id.btnSavePlayer); mBtnDelete = findViewById(R.id.btnDeletePlayer); @@ -452,6 +482,7 @@ public class AddPlayerActivity extends BaseActivity { new Thread(() -> { // Query the database for the player (background thread) mExistingPlayer = AppDatabase.getDatabase(this).playerDao().getPlayerById(mExistingPlayerId); + final Statistics statistics = AppDatabase.getDatabase(this).statisticsDao().getStatisticsForPlayer(mExistingPlayerId); // Update UI on the main thread runOnUiThread(() -> { @@ -463,6 +494,14 @@ public class AddPlayerActivity extends BaseActivity { mTitleView.setText(R.string.txt_update_profile_header); mSaveButton.setText(R.string.txt_update_profile_username_save); if (mBtnDelete != null) mBtnDelete.setVisibility(View.VISIBLE); + if (mShowStatsButton != null) mShowStatsButton.setVisibility(View.VISIBLE); + mShowStatsButton.setOnClickListener(v -> { + mPlayerStatsView.setVisibility(View.VISIBLE); + mIsStatsViewShown = true; + }); + if (statistics != null && mPlayerStatsView != null) { + mPlayerStatsView.bind(mExistingPlayer, statistics); + } // Load existing profile picture if available if (mExistingPlayer.profilePictureUri != null) { diff --git a/app/src/main/java/com/aldo/apps/ochecompanion/BaseActivity.java b/app/src/main/java/com/aldo/apps/ochecompanion/BaseActivity.java index d901583..454ee02 100644 --- a/app/src/main/java/com/aldo/apps/ochecompanion/BaseActivity.java +++ b/app/src/main/java/com/aldo/apps/ochecompanion/BaseActivity.java @@ -3,7 +3,7 @@ package com.aldo.apps.ochecompanion; import android.content.SharedPreferences; import android.content.res.Configuration; import android.os.Bundle; -import android.util.Log; +import com.aldo.apps.ochecompanion.utils.Log; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatDelegate; diff --git a/app/src/main/java/com/aldo/apps/ochecompanion/MainMenuActivity.java b/app/src/main/java/com/aldo/apps/ochecompanion/MainMenuActivity.java index 5634277..0d033a5 100644 --- a/app/src/main/java/com/aldo/apps/ochecompanion/MainMenuActivity.java +++ b/app/src/main/java/com/aldo/apps/ochecompanion/MainMenuActivity.java @@ -3,7 +3,7 @@ package com.aldo.apps.ochecompanion; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; -import android.util.Log; +import com.aldo.apps.ochecompanion.utils.Log; import android.view.View; import android.widget.TextView; @@ -16,6 +16,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.aldo.apps.ochecompanion.database.AppDatabase; +import com.aldo.apps.ochecompanion.database.DatabaseHelper; import com.aldo.apps.ochecompanion.database.objects.Player; import com.aldo.apps.ochecompanion.database.objects.Match; import com.aldo.apps.ochecompanion.ui.MatchRecapView; @@ -55,6 +56,13 @@ public class MainMenuActivity extends BaseActivity { */ private SharedPreferences mSettingsPref; + /** + * Centralized database helper that manages all database operations with proper synchronization. + */ + private DatabaseHelper mDatabaseHelper; + + private Match mOngoingMatch; + /** * Initializes the activity: enables edge-to-edge display, configures window insets, * and sets up the match recap view with test data click listener. @@ -69,6 +77,7 @@ public class MainMenuActivity extends BaseActivity { EdgeToEdge.enable(this); setContentView(R.layout.activity_main); mSettingsPref = PreferenceManager.getDefaultSharedPreferences(this); + mDatabaseHelper = DatabaseHelper.getInstance(this); // Configure window insets to properly handle system bars (status bar, navigation bar) ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { @@ -84,12 +93,22 @@ public class MainMenuActivity extends BaseActivity { quickStartBtn.setOnClickListener(v -> quickStart()); findViewById(R.id.btnSettings).setOnClickListener(v -> launchSettings()); + final List ongoingMatches = (List) mDatabaseHelper.getOngoingMatches(); + if (ongoingMatches != null && !ongoingMatches.isEmpty()) { + mOngoingMatch = ongoingMatches.get(0); + } + if (mOngoingMatch != null) { + Log.d(TAG, "onCreate: Found ongoing match [" + mOngoingMatch + "]"); + quickStartBtn.setSubText("Continue match with " + mOngoingMatch.gameMode + " score"); + } + // Set up match recap view with test data functionality mMatchRecap = findViewById(R.id.match_recap); mMatchRecap.setOnClickListener(v -> { // Cycle through test data scenarios on each click applyTestData(mTestCounter); mTestCounter++; + new Thread(() -> mDatabaseHelper.printAllMatches()).start(); }); findViewById(R.id.title_view).setOnClickListener(v -> startActivity(new Intent(MainMenuActivity.this, TestActivity.class))); @@ -115,19 +134,26 @@ public class MainMenuActivity extends BaseActivity { startActivity(intent); } - /** - * Initiates a quick-start 501 game with two test players. - * Creates test players "Test1" and "Test2" and launches GameActivity. - * Test players are not persisted to the database. + /**game. + * Checks for any ongoing matches and resumes them if found, + * otherwise starts a new game with the default score. */ private void quickStart() { - final Player playerOne = new Player(DartsConstants.TEST_PLAYER_1, null); - final Player playerTwo = new Player(DartsConstants.TEST_PLAYER_2, null); - final ArrayList players = new ArrayList<>(); - players.add(playerOne); - players.add(playerTwo); - - GameActivity.start(MainMenuActivity.this, players, DartsConstants.DEFAULT_GAME_SCORE); + // Check for ongoing matches in background thread + int startingScore = DartsConstants.DEFAULT_GAME_SCORE; + int matchId = -1; + if (mOngoingMatch != null) { + try { + Log.d(TAG, "quickStart: Parsing [" + mOngoingMatch + "]"); + startingScore = Integer.parseInt(mOngoingMatch.gameMode); + matchId = mOngoingMatch.id; + } catch (final NumberFormatException exception) { + Log.e(TAG, "quickStart: Could not extract score from [" + mOngoingMatch + "], use default"); + } + } + Log.d(TAG, "quickStart: Starting match with StartingScore = [" + startingScore + + "] and matchId = [" + matchId + "]"); + GameActivity.start(MainMenuActivity.this, startingScore, matchId); } /** @@ -151,19 +177,10 @@ public class MainMenuActivity extends BaseActivity { final Intent intent = new Intent(MainMenuActivity.this, AddPlayerActivity.class); startActivity(intent); }); - - // Database operations must be run on a background thread to keep the UI responsive. new Thread(() -> { - // Access the singleton database and query all players - final List allPlayers = AppDatabase.getDatabase(getApplicationContext()) - .playerDao() - .getAllPlayers(); + final List allPlayers = (List) mDatabaseHelper.getAllPlayers(); + runOnUiThread(() -> adapter.updatePlayers(allPlayers)); - // Post-database query UI updates must happen back on the main (UI) thread - runOnUiThread(() -> { - // Update the adapter with the retrieved player data - adapter.updatePlayers(allPlayers); - }); }).start(); } @@ -171,14 +188,12 @@ public class MainMenuActivity extends BaseActivity { * Applies the last completed match from the database to the match recap view. */ private void applyLastMatch() { - // Database operations must be run on a background thread to keep the UI responsive. new Thread(() -> { - final Match lastMatch = AppDatabase.getDatabase(getApplicationContext()) - .matchDao() - .getLastCompletedMatch(); - - // Post-database query UI updates must happen back on the main (UI) thread - runOnUiThread(() -> mMatchRecap.setMatch(lastMatch)); + final Match lastCompleted = mDatabaseHelper.getLastCompletedMatch(); + if (lastCompleted != null) { + Log.d(TAG, "applyLastMatch: Applying last completed match [" + lastCompleted + "]"); + runOnUiThread(() -> mMatchRecap.setMatch(lastCompleted)); + } }).start(); } diff --git a/app/src/main/java/com/aldo/apps/ochecompanion/TestActivity.java b/app/src/main/java/com/aldo/apps/ochecompanion/TestActivity.java index d7d374b..215bcb7 100644 --- a/app/src/main/java/com/aldo/apps/ochecompanion/TestActivity.java +++ b/app/src/main/java/com/aldo/apps/ochecompanion/TestActivity.java @@ -1,7 +1,7 @@ package com.aldo.apps.ochecompanion; import android.os.Bundle; -import android.util.Log; +import com.aldo.apps.ochecompanion.utils.Log; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; diff --git a/app/src/main/java/com/aldo/apps/ochecompanion/database/DatabaseHelper.java b/app/src/main/java/com/aldo/apps/ochecompanion/database/DatabaseHelper.java index 131a4e4..6c50dda 100644 --- a/app/src/main/java/com/aldo/apps/ochecompanion/database/DatabaseHelper.java +++ b/app/src/main/java/com/aldo/apps/ochecompanion/database/DatabaseHelper.java @@ -1,11 +1,13 @@ package com.aldo.apps.ochecompanion.database; import android.content.Context; -import android.util.Log; +import com.aldo.apps.ochecompanion.utils.Log; +import com.aldo.apps.ochecompanion.database.objects.Match; import com.aldo.apps.ochecompanion.database.objects.Player; import com.aldo.apps.ochecompanion.database.objects.Statistics; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -306,6 +308,104 @@ public class DatabaseHelper { } } + public long createNewMatch(final String gameMode, final List players) { + final Match match = new Match(System.currentTimeMillis(), gameMode, players.size(), null, Match.MatchState.ONGOING); + try { + return mExecutor.submit(() -> { + try { + return mDatabase.matchDao().insert(match); + } catch (Exception e) { + Log.e(TAG, "createNewMatch: Failed to insert match", e); + return -1L; + } + }).get(); + } catch (Exception e) { + Log.e(TAG, "createNewMatch: Failed to submit task", e); + return -1; + } + } + + /** + * Updates an existing match in the database. + * + * @param match The Match entity to update + */ + public void updateMatch(final Match match) { + mExecutor.execute(() -> { + try { + mDatabase.matchDao().update(match); + } catch (Exception e) { + Log.e(TAG, "updateMatch: Failed to update match", e); + } + }); + } + + public List getOngoingMatches() { + try { + return mExecutor.submit(() -> { + try { + return mDatabase.matchDao().getOngoingMatches(); + } catch (Exception e) { + Log.d(TAG, "getOngoingMatch() failed"); + return new ArrayList<>(); + } + }).get(); + } catch (Exception e) { + Log.e(TAG, "getOngoingMatch: Failed fetching ongoing matches"); + return new ArrayList<>(); + } + } + + public void printAllMatches() { + Log.d(TAG, "printAllMatches() called"); + try { + mExecutor.submit(() -> { + final List allMatches = mDatabase.matchDao().getAllMatches(); + if (allMatches != null && !allMatches.isEmpty()) { + for (final Match match : allMatches) { + Log.d(TAG, "printAllMatches: Match = [" + match + "]"); + } + } else { + Log.d(TAG, "printAllMatches: allMatches = [" + allMatches + "]"); + } + }); + } catch (Exception e) { + Log.e(TAG, "printAllMatches: Failed to submit task", e); + } + } + + public Match getLastCompletedMatch() { + try { + return mExecutor.submit(() -> { + try { + return mDatabase.matchDao().getLastCompletedMatch(); + } catch (Exception e) { + Log.e(TAG, "getLastCompletedMatch: Failed to retrieve last completed match", e); + return null; + } + }).get(); + } catch (Exception e) { + Log.e(TAG, "getLastCompletedMatch: Failed to submit task", e); + return null; + } + } + + public Match getMatchById(final int matchId) { + try { + return mExecutor.submit(() -> { + try { + return mDatabase.matchDao().getMatchById(matchId); + } catch (Exception e) { + Log.e(TAG, "getMatchById: Failed to retrieve match", e); + return null; + } + }).get(); + } catch (Exception e) { + Log.e(TAG, "getMatchById: Failed to submit task", e); + return null; + } + } + /** * Retrieves statistics for a specific player synchronously. * Blocks until the operation completes to ensure consistency with any pending writes. diff --git a/app/src/main/java/com/aldo/apps/ochecompanion/database/dao/MatchDao.java b/app/src/main/java/com/aldo/apps/ochecompanion/database/dao/MatchDao.java index fcce018..690dd26 100644 --- a/app/src/main/java/com/aldo/apps/ochecompanion/database/dao/MatchDao.java +++ b/app/src/main/java/com/aldo/apps/ochecompanion/database/dao/MatchDao.java @@ -20,7 +20,16 @@ public interface MatchDao { * @param match The Match entity to persist */ @Insert - void insert(final Match match); + long insert(final Match match); + + /** + * Updates an existing match record in the database. + * Must be called on a background thread. + * + * @param match The Match entity to update + */ + @androidx.room.Update + void update(final Match match); /** * Retrieves all match records ordered by most recent first. @@ -40,6 +49,9 @@ public interface MatchDao { @Query("SELECT * FROM matches ORDER BY timestamp DESC LIMIT 1") Match getLastMatch(); + @Query("SELECT * FROM matches WHERE id = :matchId") + Match getMatchById(final int matchId); + /** * Retrieves the most recently completed match. * Must be called on a background thread. diff --git a/app/src/main/java/com/aldo/apps/ochecompanion/database/objects/Match.java b/app/src/main/java/com/aldo/apps/ochecompanion/database/objects/Match.java index 6b5217f..75da47b 100644 --- a/app/src/main/java/com/aldo/apps/ochecompanion/database/objects/Match.java +++ b/app/src/main/java/com/aldo/apps/ochecompanion/database/objects/Match.java @@ -1,8 +1,15 @@ package com.aldo.apps.ochecompanion.database.objects; +import android.util.Log; + import androidx.room.Entity; import androidx.room.Ignore; import androidx.room.PrimaryKey; + +import com.aldo.apps.ochecompanion.utils.DartsConstants; +import com.aldo.apps.ochecompanion.utils.MatchProgress; +import com.aldo.apps.ochecompanion.utils.converters.MatchProgressConverter; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -27,6 +34,8 @@ import java.util.Map; @Entity(tableName = "matches") public class Match implements Serializable { + private static final String TAG = "Match"; + /** * Represents the current state of a match. */ @@ -157,14 +166,9 @@ public class Match implements Serializable { * @return The username of the player, or "Unknown" if unavailable */ public String getPlayerNameByPosition(final int position) { - try { - final JSONArray participants = new JSONArray(participantData); - if (position >= 0 && position < participants.length()) { - final JSONObject participant = participants.getJSONObject(position); - return participant.optString("username", "Unknown"); - } - } catch (JSONException e) { - // Return default if JSON parsing fails + final MatchProgress progress = MatchProgressConverter.fromString(participantData); + if (progress != null && progress.players != null && position < progress.players.size()) { + return progress.players.get(position).name; } return "Unknown"; } @@ -176,14 +180,14 @@ public class Match implements Serializable { * @return The career average, or 0.0 if unavailable */ public double getPlayerAverageByPosition(final int position) { - try { - final JSONArray participants = new JSONArray(participantData); - if (position >= 0 && position < participants.length()) { - final JSONObject participant = participants.getJSONObject(position); - return participant.optDouble("careerAverage", 0.0); - } - } catch (JSONException e) { - // Return default if JSON parsing fails + final MatchProgress progress = MatchProgressConverter.fromString(participantData); + if (progress != null && progress.players != null && position < progress.players.size()) { + final int dartsThrown = progress.players.get(position).dartsThrown; + final int startingScore = progress.startingScore; + final int scoreLeft = progress.players.get(position).remainingScore; + final int scoredPoints = (scoreLeft - startingScore) * -1; + + return (double) scoredPoints / dartsThrown * 3; } return 0.0; } @@ -195,14 +199,9 @@ public class Match implements Serializable { * @return The match score, or 0 if unavailable */ public int getPlayerScoreByPosition(final int position) { - try { - final JSONArray participants = new JSONArray(participantData); - if (position >= 0 && position < participants.length()) { - final JSONObject participant = participants.getJSONObject(position); - return participant.optInt("score", 0); - } - } catch (JSONException e) { - // Return default if JSON parsing fails + final MatchProgress progress = MatchProgressConverter.fromString(participantData); + if (progress != null && progress.players != null && position < progress.players.size()) { + return progress.players.get(position).remainingScore; } return 0; } @@ -360,4 +359,16 @@ public class Match implements Serializable { public boolean isCanceled() { return this.state == MatchState.CANCELED; } + + @Override + public String toString() { + return "Match{" + + "id=" + id + + ", timestamp=" + timestamp + + ", gameMode='" + gameMode + '\'' + + ", playerCount=" + playerCount + + ", participantData='" + participantData + '\'' + + ", state=" + state + + '}'; + } } diff --git a/app/src/main/java/com/aldo/apps/ochecompanion/database/objects/Statistics.java b/app/src/main/java/com/aldo/apps/ochecompanion/database/objects/Statistics.java index 26faea3..d2ac071 100644 --- a/app/src/main/java/com/aldo/apps/ochecompanion/database/objects/Statistics.java +++ b/app/src/main/java/com/aldo/apps/ochecompanion/database/objects/Statistics.java @@ -1,6 +1,6 @@ package com.aldo.apps.ochecompanion.database.objects; -import android.util.Log; +import com.aldo.apps.ochecompanion.utils.Log; import androidx.annotation.NonNull; import androidx.room.Entity; diff --git a/app/src/main/java/com/aldo/apps/ochecompanion/ui/MainMenuPreferencesFragment.java b/app/src/main/java/com/aldo/apps/ochecompanion/ui/MainMenuPreferencesFragment.java index 4d1961c..4a78708 100644 --- a/app/src/main/java/com/aldo/apps/ochecompanion/ui/MainMenuPreferencesFragment.java +++ b/app/src/main/java/com/aldo/apps/ochecompanion/ui/MainMenuPreferencesFragment.java @@ -1,7 +1,7 @@ package com.aldo.apps.ochecompanion.ui; import android.os.Bundle; -import android.util.Log; +import com.aldo.apps.ochecompanion.utils.Log; import androidx.appcompat.app.AppCompatDelegate; import androidx.preference.Preference; diff --git a/app/src/main/java/com/aldo/apps/ochecompanion/ui/MatchRecapView.java b/app/src/main/java/com/aldo/apps/ochecompanion/ui/MatchRecapView.java index 8a9bc2c..636e097 100644 --- a/app/src/main/java/com/aldo/apps/ochecompanion/ui/MatchRecapView.java +++ b/app/src/main/java/com/aldo/apps/ochecompanion/ui/MatchRecapView.java @@ -2,6 +2,7 @@ package com.aldo.apps.ochecompanion.ui; import android.content.Context; import android.util.AttributeSet; +import com.aldo.apps.ochecompanion.utils.Log; import android.view.View; import android.widget.FrameLayout; import android.widget.TextView; @@ -19,6 +20,11 @@ import com.aldo.apps.ochecompanion.ui.adapter.MainMenuGroupMatchAdapter; */ public class MatchRecapView extends FrameLayout { + /** + * Tag for debugging purposes. + */ + private static final String TAG = "MatchRecapView"; + /** View container for empty state (no match history). */ private View mStateEmpty; @@ -75,6 +81,7 @@ public class MatchRecapView extends FrameLayout { /** Binds match and updates display (empty, 1v1, or group state). */ public void setMatch(@Nullable final Match match) { + Log.d(TAG, "setMatch() called with: match = [" + match + "]"); if (match == null) { updateVisibility(mStateEmpty); return; diff --git a/app/src/main/java/com/aldo/apps/ochecompanion/ui/adapter/MainMenuGroupMatchAdapter.java b/app/src/main/java/com/aldo/apps/ochecompanion/ui/adapter/MainMenuGroupMatchAdapter.java index 52438e6..cd947b2 100644 --- a/app/src/main/java/com/aldo/apps/ochecompanion/ui/adapter/MainMenuGroupMatchAdapter.java +++ b/app/src/main/java/com/aldo/apps/ochecompanion/ui/adapter/MainMenuGroupMatchAdapter.java @@ -1,7 +1,7 @@ package com.aldo.apps.ochecompanion.ui.adapter; import android.annotation.SuppressLint; -import android.util.Log; +import com.aldo.apps.ochecompanion.utils.Log; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; diff --git a/app/src/main/java/com/aldo/apps/ochecompanion/ui/adapter/MainMenuPlayerAdapter.java b/app/src/main/java/com/aldo/apps/ochecompanion/ui/adapter/MainMenuPlayerAdapter.java index 20b1cb0..8b018a7 100644 --- a/app/src/main/java/com/aldo/apps/ochecompanion/ui/adapter/MainMenuPlayerAdapter.java +++ b/app/src/main/java/com/aldo/apps/ochecompanion/ui/adapter/MainMenuPlayerAdapter.java @@ -5,7 +5,7 @@ import static com.aldo.apps.ochecompanion.AddPlayerActivity.EXTRA_PLAYER_ID; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; -import android.util.Log; +import com.aldo.apps.ochecompanion.utils.Log; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; diff --git a/app/src/main/java/com/aldo/apps/ochecompanion/utils/Log.java b/app/src/main/java/com/aldo/apps/ochecompanion/utils/Log.java index 6511b71..153da46 100644 --- a/app/src/main/java/com/aldo/apps/ochecompanion/utils/Log.java +++ b/app/src/main/java/com/aldo/apps/ochecompanion/utils/Log.java @@ -1,4 +1,153 @@ package com.aldo.apps.ochecompanion.utils; + +/** + * Class {@link Log} is a wrapper class around android.util.Log. + * + * The sole purpose of this class is to have a single TAG by which all log output from the + * CoreSyncService can later on be found in the log. The classes using this logging class may + * still define their custom tag. This will ease identifying OcheCompanion logs. + */ public class Log { + /** + * The TAG that identifies OcheCompanion messages in the log. + */ + private static final String TAG = "OcheCompanion_Log"; + + /** + * Send a debug message. + * + * @param tag string used to identify the source of a log message + * @param msg the message to be logged + */ + public static void d(final String tag, final String msg) { + android.util.Log.d(TAG, String.format("(%s): %s", tag, msg)); + } + + /** + * Send a debug message and print the exception. + * + * @param tag string used to identify the source of a log message + * @param msg the message to be logged + * @param throwable the exception to be logged + */ + public static void d(final String tag, final String msg, final Throwable throwable) { + android.util.Log.d(TAG, String.format("(%s): %s", tag, msg), throwable); + } + + /** + * Send a info message. + * + * @param tag string used to identify the source of a log message + * @param msg the message to be logged + */ + public static void i(final String tag, final String msg) { + android.util.Log.i(TAG, String.format("(%s): %s", tag, msg)); + } + + /** + * Send a info message and print the exception. + * + * @param tag string used to identify the source of a log message + * @param msg the message to be logged + * @param throwable the exception to be logged + */ + public static void i(final String tag, final String msg, final Throwable throwable) { + android.util.Log.i(TAG, String.format("(%s): %s", tag, msg), throwable); + } + + /** + * Send a error message. + * + * @param tag string used to identify the source of a log message + * @param msg the message to be logged + */ + public static void e(final String tag, final String msg) { + android.util.Log.e(TAG, String.format("(%s): %s", tag, msg)); + } + + /** + * Send a error message and print the exception. + * + * @param tag string used to identify the source of a log message + * @param msg the message to be logged + * @param throwable the exception to be logged + */ + public static void e(final String tag, final String msg, final Throwable throwable) { + android.util.Log.e(TAG, String.format("(%s): %s", tag, msg), throwable); + } + + /** + * Send a verbose message. + * + * @param tag string used to identify the source of a log message + * @param msg the message to be logged + */ + public static void v(final String tag, final String msg) { + android.util.Log.v(TAG, String.format("(%s): %s", tag, msg)); + } + + /** + * Send a verbose message and print the exception. + * + * @param tag string used to identify the source of a log message + * @param msg the message to be logged + * @param throwable the exception to be logged + */ + public static void v(final String tag, final String msg, final Throwable throwable) { + android.util.Log.v(TAG, String.format("(%s): %s", tag, msg), throwable); + } + + /** + * Send a warning message. + * + * @param tag string used to identify the source of a log message + * @param msg the message to be logged + */ + public static void w(final String tag, final String msg) { + android.util.Log.w(TAG, String.format("(%s): %s", tag, msg)); + } + + /** + * Send a warning message and print the exception. + * + * @param tag string used to identify the source of a log message + * @param msg the message to be logged + * @param throwable the exception to be logged + */ + public static void w(final String tag, final String msg, final Throwable throwable) { + android.util.Log.w(TAG, String.format("(%s): %s", tag, msg), throwable); + } + + /** + * Send a "what a terrible failure" message and print the exception. + * + * @param tag string used to identify the source of a log message + * @param msg the message to be logged + * @param throwable the exception to be logged + */ + public static void wtf(final String tag, final String msg, final Throwable throwable) { + android.util.Log.wtf(TAG, String.format("(%s): %s", tag, msg), throwable); + } + + /** + * Send a "what a terrible failure" message. + * + * @param tag string used to identify the source of a log message + * @param msg the message to be logged + */ + public static void wtf(final String tag, final String msg) { + android.util.Log.wtf(TAG, String.format("(%s): %s", tag, msg)); + } + + /** + * Send a "what a terrible failure" tag and print the exception. + * + * @param tag string used to identify the source of a log message + * @param throwable the exception to be logged + */ + public static void wtf(final String tag, final Throwable throwable) { + android.util.Log.wtf(TAG, String.format("(%s):", tag), throwable); + } } + diff --git a/app/src/main/java/com/aldo/apps/ochecompanion/utils/MatchProgress.java b/app/src/main/java/com/aldo/apps/ochecompanion/utils/MatchProgress.java index 9c0a1e3..f6d46b8 100644 --- a/app/src/main/java/com/aldo/apps/ochecompanion/utils/MatchProgress.java +++ b/app/src/main/java/com/aldo/apps/ochecompanion/utils/MatchProgress.java @@ -1,4 +1,33 @@ package com.aldo.apps.ochecompanion.utils; +import java.util.List; + +/** + * MatchProgress: A serializable snapshot of an ongoing X01 session. + * Stores the current scores, darts thrown, and active player index + * to allow resuming matches from the database. + */ public class MatchProgress { -} + public int activePlayerIndex; + public int startingScore; + public List players; + + /** + * Represents the state of an individual player at a point in time. + */ + public static class PlayerStateSnapshot { + public long playerId; // 0 for guests + public String name; + public int remainingScore; + public int dartsThrown; + + public PlayerStateSnapshot() {} + + public PlayerStateSnapshot(final long playerId, final String name, final int remainingScore, final int dartsThrown) { + this.playerId = playerId; + this.name = name; + this.remainingScore = remainingScore; + this.dartsThrown = dartsThrown; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/aldo/apps/ochecompanion/utils/SoundEngine.java b/app/src/main/java/com/aldo/apps/ochecompanion/utils/SoundEngine.java index 2bb74b0..3901e98 100644 --- a/app/src/main/java/com/aldo/apps/ochecompanion/utils/SoundEngine.java +++ b/app/src/main/java/com/aldo/apps/ochecompanion/utils/SoundEngine.java @@ -7,7 +7,7 @@ import android.content.Context; import android.media.AudioAttributes; import android.media.SoundPool; import android.os.Build; -import android.util.Log; +import com.aldo.apps.ochecompanion.utils.Log; import com.aldo.apps.ochecompanion.R; diff --git a/app/src/main/java/com/aldo/apps/ochecompanion/utils/converters/MatchProgressConverter.java b/app/src/main/java/com/aldo/apps/ochecompanion/utils/converters/MatchProgressConverter.java index b3d8ca4..05e49de 100644 --- a/app/src/main/java/com/aldo/apps/ochecompanion/utils/converters/MatchProgressConverter.java +++ b/app/src/main/java/com/aldo/apps/ochecompanion/utils/converters/MatchProgressConverter.java @@ -1,4 +1,26 @@ package com.aldo.apps.ochecompanion.utils.converters; +import androidx.room.TypeConverter; + +import com.aldo.apps.ochecompanion.utils.MatchProgress; +import com.google.gson.Gson; + +/** + * MatchProgressConverter: Handles serialization of complex match states + * into JSON strings for storage in the Room 'matches' table. + */ public class MatchProgressConverter { -} + private static final Gson gson = new Gson(); + + @TypeConverter + public static MatchProgress fromString(String value) { + if (value == null || value.isEmpty()) return null; + return gson.fromJson(value, MatchProgress.class); + } + + @TypeConverter + public static String fromProgress(MatchProgress progress) { + if (progress == null) return null; + return gson.toJson(progress); + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_add_player.xml b/app/src/main/res/layout/activity_add_player.xml index 1288d7b..1abec4c 100644 --- a/app/src/main/res/layout/activity_add_player.xml +++ b/app/src/main/res/layout/activity_add_player.xml @@ -61,6 +61,16 @@ android:textColor="@color/text_primary" /> + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a0a2ef1..d40046e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -17,6 +17,7 @@ Create Profile Add your username Save to Squad + Show Stats Update Profile Update Squad Cancel