Compare commits
44 Commits
realmasync
...
master
@ -0,0 +1,139 @@ |
||||
# CLAUDE.md |
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
||||
|
||||
## Project Overview |
||||
|
||||
This is **Poker Analytics**, a comprehensive Android application for tracking and analyzing poker sessions. The app supports both cash games and tournaments, providing detailed statistics, reporting, and data visualization capabilities. |
||||
|
||||
### Key Features |
||||
- Session tracking (cash games and tournaments) |
||||
- Advanced filtering and reporting |
||||
- Bankroll management |
||||
- Hand history import and replay |
||||
- Statistical analysis and charting |
||||
- Data backup and export functionality |
||||
- Multi-currency support |
||||
|
||||
## Development Commands |
||||
|
||||
### Building the Project |
||||
```bash |
||||
./gradlew assembleStandardRelease # Build release APK |
||||
./gradlew assembleStandardDebug # Build debug APK |
||||
./gradlew build # Build all variants |
||||
``` |
||||
|
||||
### Running Tests |
||||
```bash |
||||
./gradlew test # Run unit tests |
||||
./gradlew connectedAndroidTest # Run instrumented tests (requires device/emulator) |
||||
./gradlew testStandardDebugUnitTest # Run specific unit tests |
||||
``` |
||||
|
||||
### Cleaning |
||||
```bash |
||||
./gradlew clean # Clean build artifacts |
||||
``` |
||||
|
||||
### Build Configuration |
||||
- **Target SDK**: 35 (Android 15) |
||||
- **Min SDK**: 23 (Android 6.0) |
||||
- **Build Tools**: 30.0.3 |
||||
- **Kotlin Version**: 1.9.24 |
||||
- **Realm Schema Version**: 14 |
||||
|
||||
## Architecture Overview |
||||
|
||||
### Package Structure |
||||
The main source code is organized under `app/src/main/java/net/pokeranalytics/android/`: |
||||
|
||||
#### Core Components |
||||
- **`model/`** - Data models and business logic |
||||
- `realm/` - Realm database models (Session, Bankroll, Result, etc.) |
||||
- `filter/` - Query system for filtering sessions |
||||
- `migrations/` - Database migration handling |
||||
- `handhistory/` - Hand history data structures |
||||
|
||||
- **`ui/`** - User interface components |
||||
- `activity/` - Main activities (HomeActivity, SessionActivity, etc.) |
||||
- `fragment/` - UI fragments organized by feature |
||||
- `adapter/` - RecyclerView adapters and data sources |
||||
- `modules/` - Feature-specific UI modules |
||||
|
||||
- **`calculus/`** - Statistics and calculation engine |
||||
- Core calculation logic for poker statistics |
||||
- Report generation system |
||||
- Performance tracking |
||||
|
||||
- **`util/`** - Utility classes |
||||
- `csv/` - CSV import/export functionality |
||||
- `billing/` - In-app purchase handling |
||||
- `extensions/` - Kotlin extension functions |
||||
|
||||
#### Key Classes |
||||
- **`Session`** (`model/realm/Session.kt`): Core session data model |
||||
- **`HomeActivity`** (`ui/activity/HomeActivity.kt`): Main app entry point with tab navigation |
||||
- **`PokerAnalyticsApplication`**: Application class handling initialization |
||||
|
||||
### Database Architecture |
||||
The app uses **Realm** database with these key entities: |
||||
- `Session` - Individual poker sessions |
||||
- `Bankroll` - Bankroll management |
||||
- `Result` - Session results and statistics |
||||
- `ComputableResult` - Pre-computed statistics for performance |
||||
- `Filter` - Saved filter configurations |
||||
- `HandHistory` - Hand-by-hand game data |
||||
|
||||
### UI Architecture |
||||
- **MVVM pattern** with Android Architecture Components |
||||
- **Fragment-based navigation** with bottom navigation tabs |
||||
- **Custom RecyclerView adapters** for data presentation |
||||
- **Material Design** components |
||||
|
||||
## Key Technologies |
||||
|
||||
### Core Dependencies |
||||
- **Realm Database** (10.15.1) - Local data storage |
||||
- **Kotlin Coroutines** - Asynchronous programming |
||||
- **Firebase Crashlytics** - Crash reporting and analytics |
||||
- **Material Design Components** - UI framework |
||||
- **MPAndroidChart** - Data visualization |
||||
- **CameraX** - Image capture functionality |
||||
|
||||
### Testing |
||||
- **JUnit** for unit testing |
||||
- **Android Instrumented Tests** for integration testing |
||||
- Test files located in `app/src/androidTest/` and `app/src/test/` |
||||
|
||||
## Development Guidelines |
||||
|
||||
### Working with Sessions |
||||
- Sessions are the core data model representing individual poker games |
||||
- Use `Session.newInstance()` to create new sessions properly |
||||
- Always call `computeStats()` after modifying session data |
||||
- Sessions can be in various states: PENDING, STARTED, PAUSED, ENDED |
||||
|
||||
### Database Operations |
||||
- Use Realm transactions for data modifications |
||||
- The app uses schema version 14 - increment when making schema changes |
||||
- Migration logic is in `PokerAnalyticsMigration.kt` |
||||
|
||||
### Testing Data |
||||
- Use `FakeDataManager.createFakeSessions()` for generating test data |
||||
- Seed data is available through the `Seed` class |
||||
|
||||
### Build Variants |
||||
- **standard** - Main production flavor |
||||
- Release builds are optimized and obfuscated with ProGuard |
||||
|
||||
## Performance Considerations |
||||
- Sessions use `ComputableResult` for pre-computed statistics |
||||
- Large datasets are handled with Realm's lazy loading |
||||
- Chart rendering is optimized for large data sets |
||||
- Background processing uses Kotlin Coroutines |
||||
|
||||
## Security & Privacy |
||||
- Sensitive data is encrypted in Realm database |
||||
- Crash logging excludes personal information |
||||
- Backup functionality includes data encryption |
||||
@ -0,0 +1,86 @@ |
||||
package net.pokeranalytics.android.util |
||||
|
||||
import android.content.Context |
||||
import androidx.work.Worker |
||||
import androidx.work.WorkerParameters |
||||
import io.realm.Realm |
||||
import kotlinx.coroutines.CoroutineScope |
||||
import kotlinx.coroutines.Dispatchers |
||||
import kotlinx.coroutines.launch |
||||
import net.pokeranalytics.android.api.BackupApi |
||||
import net.pokeranalytics.android.model.realm.Session |
||||
import net.pokeranalytics.android.model.realm.Transaction |
||||
import net.pokeranalytics.android.util.csv.DataType |
||||
import net.pokeranalytics.android.util.csv.ProductCSVDescriptors |
||||
import net.pokeranalytics.android.util.extensions.dateTimeFileFormatted |
||||
import timber.log.Timber |
||||
import java.util.* |
||||
|
||||
|
||||
class BackupWorker(var context: Context, var params: WorkerParameters) : Worker(context, params) { |
||||
|
||||
enum class ParamKeys(val value: String) { |
||||
DATA("title"), |
||||
} |
||||
|
||||
override fun doWork(): Result { |
||||
|
||||
val data = params.inputData |
||||
|
||||
val dataTypeInt = data.getInt(ParamKeys.DATA.value, 0) |
||||
val dataType = DataType.values()[dataTypeInt] |
||||
|
||||
Preferences.getBackupEmail(context)?.let { email -> |
||||
val task = BackupTask(dataType, email, context) |
||||
task.start() |
||||
} |
||||
|
||||
return Result.success() |
||||
} |
||||
|
||||
} |
||||
|
||||
class BackupTask(val dataType: DataType, val email: String, val context: Context) { |
||||
|
||||
fun start() { |
||||
when(this.dataType) { |
||||
DataType.SESSION -> { |
||||
backupSessions() |
||||
} |
||||
DataType.TRANSACTION -> { |
||||
backupTransactions() |
||||
} |
||||
} |
||||
} |
||||
|
||||
private fun backupSessions() { |
||||
|
||||
Timber.d(">>>> backup sessions") |
||||
val realm = Realm.getDefaultInstance() |
||||
val sessions = realm.where(Session::class.java).findAll().sort("startDate") |
||||
val csv = ProductCSVDescriptors.pokerAnalyticsAndroid6Sessions.toCSV(sessions) |
||||
val fileName = "sessions_${Date().dateTimeFileFormatted}.csv" |
||||
|
||||
CoroutineScope(context = Dispatchers.IO).launch { |
||||
val success = BackupApi.backupFile(context, email, fileName, csv) |
||||
Preferences.setSessionsBackupSuccess(success, context) |
||||
} |
||||
realm.close() |
||||
} |
||||
|
||||
private fun backupTransactions() { |
||||
|
||||
Timber.d(">>>> backup transactions") |
||||
val realm = Realm.getDefaultInstance() |
||||
val transactions = realm.where(Transaction::class.java).findAll().sort("date") |
||||
val csv = ProductCSVDescriptors.pokerAnalyticsAndroidTransactions.toCSV(transactions) |
||||
val fileName = "transactions_${Date().dateTimeFileFormatted}.csv" |
||||
|
||||
CoroutineScope(context = Dispatchers.IO).launch { |
||||
val success = BackupApi.backupFile(context, email, fileName, csv) |
||||
Preferences.setTransactionsBackupSuccess(success, context) |
||||
} |
||||
realm.close() |
||||
} |
||||
|
||||
} |
||||
Binary file not shown.
Loading…
Reference in new issue