diff --git a/app/src/main/java/com/mintris/MainActivity.kt b/app/src/main/java/com/mintris/MainActivity.kt
index d6eac7e..fd49615 100644
--- a/app/src/main/java/com/mintris/MainActivity.kt
+++ b/app/src/main/java/com/mintris/MainActivity.kt
@@ -21,6 +21,9 @@ import com.mintris.model.GameBoard
import com.mintris.audio.GameMusic
import com.mintris.model.HighScoreManager
import android.content.Intent
+import com.mintris.model.StatsManager
+import java.text.SimpleDateFormat
+import java.util.*
class MainActivity : AppCompatActivity() {
@@ -32,6 +35,7 @@ class MainActivity : AppCompatActivity() {
private lateinit var gameMusic: GameMusic
private lateinit var titleScreen: TitleScreen
private lateinit var highScoreManager: HighScoreManager
+ private lateinit var statsManager: StatsManager
// Game state
private var isSoundEnabled = true
@@ -40,6 +44,8 @@ class MainActivity : AppCompatActivity() {
private val maxLevel = 20
private var currentScore = 0
private var currentLevel = 1
+ private var gameStartTime: Long = 0
+ private var piecesPlaced: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -53,6 +59,7 @@ class MainActivity : AppCompatActivity() {
titleScreen = binding.titleScreen
gameMusic = GameMusic(this)
highScoreManager = HighScoreManager(this)
+ statsManager = StatsManager(this)
// Set up game view
gameView.setGameBoard(gameBoard)
@@ -117,6 +124,8 @@ class MainActivity : AppCompatActivity() {
} else {
android.util.Log.d("MainActivity", "Sound is disabled, skipping haptic feedback")
}
+ // Record line clear in stats
+ statsManager.recordLineClear(lineCount)
}
// Add callbacks for piece movement and locking
@@ -130,6 +139,7 @@ class MainActivity : AppCompatActivity() {
if (isSoundEnabled) {
gameHaptics.vibrateForPieceLock()
}
+ piecesPlaced++
}
// Set up button click listeners with haptic feedback
@@ -187,6 +197,13 @@ class MainActivity : AppCompatActivity() {
}
}
+ // Set up stats button
+ binding.statsButton.setOnClickListener {
+ gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
+ val intent = Intent(this, StatsActivity::class.java)
+ startActivity(intent)
+ }
+
// Initialize level selector
updateLevelSelector()
@@ -205,6 +222,9 @@ class MainActivity : AppCompatActivity() {
binding.linesText.text = lines.toString()
binding.comboText.text = gameBoard.getCombo().toString()
+ // Update current level for stats
+ currentLevel = level
+
// Force redraw of next piece preview
binding.nextPieceView.invalidate()
}
@@ -213,7 +233,35 @@ class MainActivity : AppCompatActivity() {
* Show game over screen
*/
private fun showGameOver(score: Int) {
- binding.finalScoreText.text = getString(R.string.score) + ": " + score
+ val gameTime = System.currentTimeMillis() - gameStartTime
+
+ // Update session stats
+ statsManager.updateSessionStats(
+ score = score,
+ lines = gameBoard.lines,
+ pieces = piecesPlaced,
+ time = gameTime,
+ level = currentLevel
+ )
+
+ // End session and save stats
+ statsManager.endSession()
+
+ // Update session stats display
+ val timeFormat = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
+ timeFormat.timeZone = TimeZone.getTimeZone("UTC")
+
+ binding.sessionScoreText.text = getString(R.string.session_score, score)
+ binding.sessionLinesText.text = getString(R.string.session_lines, gameBoard.lines)
+ binding.sessionPiecesText.text = getString(R.string.session_pieces, piecesPlaced)
+ binding.sessionTimeText.text = getString(R.string.session_time, timeFormat.format(gameTime))
+ binding.sessionLevelText.text = getString(R.string.session_level, currentLevel)
+
+ // Update session line clear stats
+ binding.sessionSinglesText.text = getString(R.string.singles, statsManager.getSessionSingles())
+ binding.sessionDoublesText.text = getString(R.string.doubles, statsManager.getSessionDoubles())
+ binding.sessionTriplesText.text = getString(R.string.triples, statsManager.getSessionTriples())
+ binding.sessionTetrisesText.text = getString(R.string.tetrises, statsManager.getSessionTetrises())
// Check if this is a high score
if (highScoreManager.isHighScore(score)) {
@@ -291,10 +339,13 @@ class MainActivity : AppCompatActivity() {
private fun startGame() {
gameView.start()
- gameMusic.setEnabled(isMusicEnabled) // Explicitly set enabled state
+ gameMusic.setEnabled(isMusicEnabled)
if (isMusicEnabled) {
gameMusic.start()
}
+ gameStartTime = System.currentTimeMillis()
+ piecesPlaced = 0
+ statsManager.startNewSession()
}
private fun restartGame() {
diff --git a/app/src/main/java/com/mintris/StatsActivity.kt b/app/src/main/java/com/mintris/StatsActivity.kt
new file mode 100644
index 0000000..269adb0
--- /dev/null
+++ b/app/src/main/java/com/mintris/StatsActivity.kt
@@ -0,0 +1,54 @@
+package com.mintris
+
+import android.os.Bundle
+import android.widget.Button
+import android.widget.TextView
+import androidx.appcompat.app.AppCompatActivity
+import com.mintris.databinding.ActivityStatsBinding
+import com.mintris.model.StatsManager
+import java.text.SimpleDateFormat
+import java.util.*
+
+class StatsActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityStatsBinding
+ private lateinit var statsManager: StatsManager
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityStatsBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ statsManager = StatsManager(this)
+
+ // Set up back button
+ binding.backButton.setOnClickListener {
+ finish()
+ }
+
+ updateStats()
+ }
+
+ private fun updateStats() {
+ // Format time duration
+ val timeFormat = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
+ timeFormat.timeZone = TimeZone.getTimeZone("UTC")
+
+ // Update lifetime stats
+ binding.totalGamesText.text = getString(R.string.total_games, statsManager.getTotalGames())
+ binding.totalScoreText.text = getString(R.string.total_score, statsManager.getTotalScore())
+ binding.totalLinesText.text = getString(R.string.total_lines, statsManager.getTotalLines())
+ binding.totalPiecesText.text = getString(R.string.total_pieces, statsManager.getTotalPieces())
+ binding.totalTimeText.text = getString(R.string.total_time, timeFormat.format(statsManager.getTotalTime()))
+
+ // Update line clear stats
+ binding.totalSinglesText.text = getString(R.string.singles, statsManager.getTotalSingles())
+ binding.totalDoublesText.text = getString(R.string.doubles, statsManager.getTotalDoubles())
+ binding.totalTriplesText.text = getString(R.string.triples, statsManager.getTotalTriples())
+ binding.totalTetrisesText.text = getString(R.string.tetrises, statsManager.getTotalTetrises())
+
+ // Update best performance stats
+ binding.maxLevelText.text = getString(R.string.max_level, statsManager.getMaxLevel())
+ binding.maxScoreText.text = getString(R.string.max_score, statsManager.getMaxScore())
+ binding.maxLinesText.text = getString(R.string.max_lines, statsManager.getMaxLines())
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/mintris/model/StatsManager.kt b/app/src/main/java/com/mintris/model/StatsManager.kt
new file mode 100644
index 0000000..3a3eae7
--- /dev/null
+++ b/app/src/main/java/com/mintris/model/StatsManager.kt
@@ -0,0 +1,175 @@
+package com.mintris.model
+
+import android.content.Context
+import android.content.SharedPreferences
+
+class StatsManager(context: Context) {
+ private val prefs: SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
+
+ // Lifetime stats
+ private var totalGames: Int = 0
+ private var totalScore: Long = 0
+ private var totalLines: Int = 0
+ private var totalPieces: Int = 0
+ private var totalTime: Long = 0
+ private var maxLevel: Int = 0
+ private var maxScore: Int = 0
+ private var maxLines: Int = 0
+
+ // Line clear stats (lifetime)
+ private var totalSingles: Int = 0
+ private var totalDoubles: Int = 0
+ private var totalTriples: Int = 0
+ private var totalTetrises: Int = 0
+
+ // Session stats
+ private var sessionScore: Int = 0
+ private var sessionLines: Int = 0
+ private var sessionPieces: Int = 0
+ private var sessionTime: Long = 0
+ private var sessionLevel: Int = 0
+
+ // Line clear stats (session)
+ private var sessionSingles: Int = 0
+ private var sessionDoubles: Int = 0
+ private var sessionTriples: Int = 0
+ private var sessionTetrises: Int = 0
+
+ init {
+ loadStats()
+ }
+
+ private fun loadStats() {
+ totalGames = prefs.getInt(KEY_TOTAL_GAMES, 0)
+ totalScore = prefs.getLong(KEY_TOTAL_SCORE, 0)
+ totalLines = prefs.getInt(KEY_TOTAL_LINES, 0)
+ totalPieces = prefs.getInt(KEY_TOTAL_PIECES, 0)
+ totalTime = prefs.getLong(KEY_TOTAL_TIME, 0)
+ maxLevel = prefs.getInt(KEY_MAX_LEVEL, 0)
+ maxScore = prefs.getInt(KEY_MAX_SCORE, 0)
+ maxLines = prefs.getInt(KEY_MAX_LINES, 0)
+
+ // Load line clear stats
+ totalSingles = prefs.getInt(KEY_TOTAL_SINGLES, 0)
+ totalDoubles = prefs.getInt(KEY_TOTAL_DOUBLES, 0)
+ totalTriples = prefs.getInt(KEY_TOTAL_TRIPLES, 0)
+ totalTetrises = prefs.getInt(KEY_TOTAL_TETRISES, 0)
+ }
+
+ private fun saveStats() {
+ prefs.edit()
+ .putInt(KEY_TOTAL_GAMES, totalGames)
+ .putLong(KEY_TOTAL_SCORE, totalScore)
+ .putInt(KEY_TOTAL_LINES, totalLines)
+ .putInt(KEY_TOTAL_PIECES, totalPieces)
+ .putLong(KEY_TOTAL_TIME, totalTime)
+ .putInt(KEY_MAX_LEVEL, maxLevel)
+ .putInt(KEY_MAX_SCORE, maxScore)
+ .putInt(KEY_MAX_LINES, maxLines)
+ .putInt(KEY_TOTAL_SINGLES, totalSingles)
+ .putInt(KEY_TOTAL_DOUBLES, totalDoubles)
+ .putInt(KEY_TOTAL_TRIPLES, totalTriples)
+ .putInt(KEY_TOTAL_TETRISES, totalTetrises)
+ .apply()
+ }
+
+ fun startNewSession() {
+ sessionScore = 0
+ sessionLines = 0
+ sessionPieces = 0
+ sessionTime = 0
+ sessionLevel = 0
+ sessionSingles = 0
+ sessionDoubles = 0
+ sessionTriples = 0
+ sessionTetrises = 0
+ }
+
+ fun updateSessionStats(score: Int, lines: Int, pieces: Int, time: Long, level: Int) {
+ sessionScore = score
+ sessionLines = lines
+ sessionPieces = pieces
+ sessionTime = time
+ sessionLevel = level
+ }
+
+ fun recordLineClear(lineCount: Int) {
+ when (lineCount) {
+ 1 -> {
+ sessionSingles++
+ totalSingles++
+ }
+ 2 -> {
+ sessionDoubles++
+ totalDoubles++
+ }
+ 3 -> {
+ sessionTriples++
+ totalTriples++
+ }
+ 4 -> {
+ sessionTetrises++
+ totalTetrises++
+ }
+ }
+ }
+
+ fun endSession() {
+ totalGames++
+ totalScore += sessionScore
+ totalLines += sessionLines
+ totalPieces += sessionPieces
+ totalTime += sessionTime
+
+ if (sessionLevel > maxLevel) maxLevel = sessionLevel
+ if (sessionScore > maxScore) maxScore = sessionScore
+ if (sessionLines > maxLines) maxLines = sessionLines
+
+ saveStats()
+ }
+
+ // Getters for lifetime stats
+ fun getTotalGames(): Int = totalGames
+ fun getTotalScore(): Long = totalScore
+ fun getTotalLines(): Int = totalLines
+ fun getTotalPieces(): Int = totalPieces
+ fun getTotalTime(): Long = totalTime
+ fun getMaxLevel(): Int = maxLevel
+ fun getMaxScore(): Int = maxScore
+ fun getMaxLines(): Int = maxLines
+
+ // Getters for line clear stats (lifetime)
+ fun getTotalSingles(): Int = totalSingles
+ fun getTotalDoubles(): Int = totalDoubles
+ fun getTotalTriples(): Int = totalTriples
+ fun getTotalTetrises(): Int = totalTetrises
+
+ // Getters for session stats
+ fun getSessionScore(): Int = sessionScore
+ fun getSessionLines(): Int = sessionLines
+ fun getSessionPieces(): Int = sessionPieces
+ fun getSessionTime(): Long = sessionTime
+ fun getSessionLevel(): Int = sessionLevel
+
+ // Getters for line clear stats (session)
+ fun getSessionSingles(): Int = sessionSingles
+ fun getSessionDoubles(): Int = sessionDoubles
+ fun getSessionTriples(): Int = sessionTriples
+ fun getSessionTetrises(): Int = sessionTetrises
+
+ companion object {
+ private const val PREFS_NAME = "mintris_stats"
+ private const val KEY_TOTAL_GAMES = "total_games"
+ private const val KEY_TOTAL_SCORE = "total_score"
+ private const val KEY_TOTAL_LINES = "total_lines"
+ private const val KEY_TOTAL_PIECES = "total_pieces"
+ private const val KEY_TOTAL_TIME = "total_time"
+ private const val KEY_MAX_LEVEL = "max_level"
+ private const val KEY_MAX_SCORE = "max_score"
+ private const val KEY_MAX_LINES = "max_lines"
+ private const val KEY_TOTAL_SINGLES = "total_singles"
+ private const val KEY_TOTAL_DOUBLES = "total_doubles"
+ private const val KEY_TOTAL_TRIPLES = "total_triples"
+ private const val KEY_TOTAL_TETRISES = "total_tetrises"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 7271d89..ab63a51 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -135,10 +135,92 @@
android:textStyle="bold" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -209,6 +291,16 @@
android:text="@string/high_scores"
android:textColor="@color/white"
android:textSize="18sp" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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 871a7af..41c0fc2 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -20,4 +20,28 @@
New High Score!
Save
Back
+
+
+ Lifetime Stats
+ Best Performance
+ Total Games: %d
+ Total Score: %d
+ Total Lines: %d
+ Total Pieces: %d
+ Total Time: %s
+ Max Level: %d
+ Max Score: %d
+ Max Lines: %d
+ Stats
+ Session Stats
+ Score: %d
+ Lines: %d
+ Pieces: %d
+ Time: %s
+ Level: %d
+ Line Clears
+ Singles: %d
+ Doubles: %d
+ Triples: %d
+ Tetrises: %d
\ No newline at end of file