mirror of
https://github.com/cmclark00/TetriStats.git
synced 2025-05-18 15:15:21 +01:00
Compare commits
No commits in common. "main" and "v1.0-19" have entirely different histories.
5 changed files with 0 additions and 124 deletions
|
@ -83,9 +83,6 @@ dependencies {
|
||||||
implementation("androidx.navigation:navigation-fragment-ktx:2.7.6")
|
implementation("androidx.navigation:navigation-fragment-ktx:2.7.6")
|
||||||
implementation("androidx.navigation:navigation-ui-ktx:2.7.6")
|
implementation("androidx.navigation:navigation-ui-ktx:2.7.6")
|
||||||
|
|
||||||
// MPAndroidChart for progress visualization
|
|
||||||
implementation("com.github.PhilJay:MPAndroidChart:v3.1.0")
|
|
||||||
|
|
||||||
// Room
|
// Room
|
||||||
implementation("androidx.room:room-runtime:2.6.1")
|
implementation("androidx.room:room-runtime:2.6.1")
|
||||||
implementation("androidx.room:room-ktx:2.6.1")
|
implementation("androidx.room:room-ktx:2.6.1")
|
||||||
|
|
|
@ -12,9 +12,6 @@ interface ScoreDao {
|
||||||
@Query("SELECT * FROM scores WHERE gameVersion = :gameVersion")
|
@Query("SELECT * FROM scores WHERE gameVersion = :gameVersion")
|
||||||
fun getScoresForGame(gameVersion: String): LiveData<List<Score>>
|
fun getScoresForGame(gameVersion: String): LiveData<List<Score>>
|
||||||
|
|
||||||
@Query("SELECT * FROM scores WHERE gameVersion = :gameVersion ORDER BY dateRecorded ASC")
|
|
||||||
fun getScoresForGameByDate(gameVersion: String): LiveData<List<Score>>
|
|
||||||
|
|
||||||
@Query("SELECT DISTINCT gameVersion FROM scores")
|
@Query("SELECT DISTINCT gameVersion FROM scores")
|
||||||
fun getGamesWithScores(): LiveData<List<String>>
|
fun getGamesWithScores(): LiveData<List<String>>
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.accidentalproductions.tetristats.ui.stats
|
package com.accidentalproductions.tetristats.ui.stats
|
||||||
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -9,16 +8,7 @@ import android.widget.ArrayAdapter
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.accidentalproductions.tetristats.R
|
|
||||||
import com.accidentalproductions.tetristats.databinding.FragmentStatsBinding
|
import com.accidentalproductions.tetristats.databinding.FragmentStatsBinding
|
||||||
import com.github.mikephil.charting.components.XAxis
|
|
||||||
import com.github.mikephil.charting.data.Entry
|
|
||||||
import com.github.mikephil.charting.data.LineData
|
|
||||||
import com.github.mikephil.charting.data.LineDataSet
|
|
||||||
import com.github.mikephil.charting.formatter.ValueFormatter
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Date
|
|
||||||
import java.util.Locale
|
|
||||||
|
|
||||||
class StatsFragment : Fragment() {
|
class StatsFragment : Fragment() {
|
||||||
private var _binding: FragmentStatsBinding? = null
|
private var _binding: FragmentStatsBinding? = null
|
||||||
|
@ -40,7 +30,6 @@ class StatsFragment : Fragment() {
|
||||||
|
|
||||||
setupRecyclerView()
|
setupRecyclerView()
|
||||||
setupGameFilter()
|
setupGameFilter()
|
||||||
setupProgressChart()
|
|
||||||
observeStats()
|
observeStats()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,64 +52,6 @@ class StatsFragment : Fragment() {
|
||||||
viewModel.setSelectedGame(selectedGame)
|
viewModel.setSelectedGame(selectedGame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupProgressChart() {
|
|
||||||
with(binding.chartProgress) {
|
|
||||||
description.isEnabled = false
|
|
||||||
legend.isEnabled = true
|
|
||||||
setTouchEnabled(true)
|
|
||||||
setDrawGridBackground(false)
|
|
||||||
isDragEnabled = true
|
|
||||||
setScaleEnabled(true)
|
|
||||||
setPinchZoom(true)
|
|
||||||
|
|
||||||
axisRight.isEnabled = false
|
|
||||||
|
|
||||||
xAxis.position = XAxis.XAxisPosition.BOTTOM
|
|
||||||
xAxis.granularity = 1f
|
|
||||||
xAxis.setDrawGridLines(false)
|
|
||||||
|
|
||||||
axisLeft.setDrawGridLines(true)
|
|
||||||
axisLeft.axisMinimum = 0f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateProgressChart(scores: List<Entry>, dates: List<Long>) {
|
|
||||||
if (scores.isEmpty()) {
|
|
||||||
binding.chartProgress.clear()
|
|
||||||
binding.chartProgress.invalidate()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val dataSet = LineDataSet(scores, "Score Progress").apply {
|
|
||||||
mode = LineDataSet.Mode.CUBIC_BEZIER
|
|
||||||
color = resources.getColor(R.color.tetris_navy, null)
|
|
||||||
lineWidth = 2f
|
|
||||||
setDrawCircles(true)
|
|
||||||
setCircleColor(resources.getColor(R.color.tetris_navy, null))
|
|
||||||
circleRadius = 4f
|
|
||||||
setDrawValues(false)
|
|
||||||
highLightColor = Color.rgb(244, 117, 117)
|
|
||||||
}
|
|
||||||
|
|
||||||
val lineData = LineData(dataSet)
|
|
||||||
binding.chartProgress.data = lineData
|
|
||||||
|
|
||||||
// Format X-axis labels (dates)
|
|
||||||
val dateFormat = SimpleDateFormat("MM/dd", Locale.getDefault())
|
|
||||||
binding.chartProgress.xAxis.valueFormatter = object : ValueFormatter() {
|
|
||||||
override fun getFormattedValue(value: Float): String {
|
|
||||||
val index = value.toInt()
|
|
||||||
return if (index >= 0 && index < dates.size) {
|
|
||||||
dateFormat.format(Date(dates[index]))
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.chartProgress.invalidate()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun observeStats() {
|
private fun observeStats() {
|
||||||
viewModel.filteredScores.observe(viewLifecycleOwner) { scores ->
|
viewModel.filteredScores.observe(viewLifecycleOwner) { scores ->
|
||||||
|
@ -134,24 +65,6 @@ class StatsFragment : Fragment() {
|
||||||
viewModel.highScore.observe(viewLifecycleOwner) { highScore ->
|
viewModel.highScore.observe(viewLifecycleOwner) { highScore ->
|
||||||
binding.textViewHighScore.text = "%,d".format(highScore)
|
binding.textViewHighScore.text = "%,d".format(highScore)
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.scoresByDate.observe(viewLifecycleOwner) { scores ->
|
|
||||||
// Convert scores to entries for the chart
|
|
||||||
if (scores.isNotEmpty()) {
|
|
||||||
val entries = mutableListOf<Entry>()
|
|
||||||
val dates = mutableListOf<Long>()
|
|
||||||
|
|
||||||
scores.forEachIndexed { index, score ->
|
|
||||||
entries.add(Entry(index.toFloat(), score.scoreValue.toFloat()))
|
|
||||||
dates.add(score.dateRecorded)
|
|
||||||
}
|
|
||||||
|
|
||||||
updateProgressChart(entries, dates)
|
|
||||||
} else {
|
|
||||||
binding.chartProgress.clear()
|
|
||||||
binding.chartProgress.invalidate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -18,10 +18,6 @@ class StatsViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
scoreDao.getScoresForGame(game)
|
scoreDao.getScoresForGame(game)
|
||||||
}
|
}
|
||||||
|
|
||||||
val scoresByDate: LiveData<List<Score>> = _selectedGame.switchMap { game ->
|
|
||||||
scoreDao.getScoresForGameByDate(game)
|
|
||||||
}
|
|
||||||
|
|
||||||
val averageScore: LiveData<Double> = _selectedGame.switchMap { game ->
|
val averageScore: LiveData<Double> = _selectedGame.switchMap { game ->
|
||||||
scoreDao.getAverageScore(game)
|
scoreDao.getAverageScore(game)
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,33 +31,6 @@
|
||||||
android:inputType="none"/>
|
android:inputType="none"/>
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
app:cardCornerRadius="8dp"
|
|
||||||
app:cardElevation="4dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="16dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Progress Chart"
|
|
||||||
android:textAppearance="?attr/textAppearanceSubtitle1" />
|
|
||||||
|
|
||||||
<com.github.mikephil.charting.charts.LineChart
|
|
||||||
android:id="@+id/chartProgress"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="200dp"
|
|
||||||
android:layout_marginTop="8dp" />
|
|
||||||
</LinearLayout>
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerViewScores"
|
android:id="@+id/recyclerViewScores"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue