mirror of
https://github.com/cmclark00/mintris.git
synced 2025-05-18 20:05:20 +01:00
Add stats system with lifetime and session statistics, including line clear tracking
This commit is contained in:
parent
44c4c73feb
commit
cdd80e5796
6 changed files with 547 additions and 4 deletions
|
@ -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() {
|
||||
|
|
54
app/src/main/java/com/mintris/StatsActivity.kt
Normal file
54
app/src/main/java/com/mintris/StatsActivity.kt
Normal file
|
@ -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())
|
||||
}
|
||||
}
|
175
app/src/main/java/com/mintris/model/StatsManager.kt
Normal file
175
app/src/main/java/com/mintris/model/StatsManager.kt
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue