### Set Up Hilt for Dependency Injection (Kotlin) Source: https://context7.com/ministerofsalt-cell/arc-raiders-companion/llms.txt Configures Hilt for application-wide dependency injection, providing instances for JSON, Retrofit, API services, and Room Database components. Includes setup for the Application class and a sample ViewModel. ```kotlin @Module @InstallIn(SingletonComponent::class) object AppModule { @Provides @Singleton fun provideJson(): Json = Json { ignoreUnknownKeys = true isLenient = true } @Provides @Singleton fun provideRetrofit(json: Json): Retrofit { return Retrofit.Builder() .baseUrl("https://metaforge-api.arc-raiders.com/api/") .addConverterFactory( json.asConverterFactory("application/json".toMediaType()) ) .build() } @Provides @Singleton fun provideMetaForgeApi(retrofit: Retrofit): MetaForgeApi { return retrofit.create(MetaForgeApi::class.java) } @Provides @Singleton fun provideAppDatabase(@ApplicationContext context: Context): AppDatabase { return AppDatabase.getDatabase(context) } @Provides fun provideItemDao(database: AppDatabase): ItemDao { return database.itemDao() } @Provides fun provideQuestDao(database: AppDatabase): QuestDao { return database.questDao() } } // Application class setup @HiltAndroidApp class ArcRaidersApplication : Application() // Activity setup @AndroidEntryPoint class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ArcRaidersTheme { MainScreen() } } } } // ViewModel with automatic injection @HiltViewModel class ItemsViewModel @Inject constructor( private val repository: ItemsRepository ) : ViewModel() { // ViewModel implementation } ``` -------------------------------- ### Configure Room Database for Offline Caching (Kotlin) Source: https://context7.com/ministerofsalt-cell/arc-raiders-companion/llms.txt Sets up the Room Database for the application, defining entities, version, and DAOs. It includes a singleton instance getter for the database and example entity and DAO definitions for items. ```kotlin @Database( entities = [ItemEntity::class, QuestEntity::class], version = 1, exportSchema = false ) abstract class AppDatabase : RoomDatabase() { abstract fun itemDao(): ItemDao abstract fun questDao(): QuestDao companion object { @Volatile private var INSTANCE: AppDatabase? = null fun getDatabase(context: Context): AppDatabase { return INSTANCE ?: synchronized(this) { val instance = Room.databaseBuilder( context.applicationContext, AppDatabase::class.java, "arc_raiders_database" ) .fallbackToDestructiveMigration() .build() INSTANCE = instance instance } } } } // Entity definition example @Entity(tableName = "items") data class ItemEntity( @PrimaryKey val id: String, val name: String, val description: String?, val rarity: String, val category: String, val iconUrl: String?, val stats: String? ) // DAO definition example @Dao interface ItemDao { @Query("SELECT * FROM items") fun getAllItems(): Flow> @Query("SELECT * FROM items WHERE category = :category") fun getItemsByCategory(category: String): Flow> @Query("SELECT * FROM items WHERE name LIKE '%' || :query || '%'") fun searchItems(query: String): Flow> @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertAll(items: List) @Query("SELECT * FROM items WHERE id = :id") suspend fun getItemById(id: String): ItemEntity? } // Usage in repository class ItemsRepository @Inject constructor( private val api: MetaForgeApi, private val itemDao: ItemDao ) { fun getAllItems(): Flow> = itemDao.getAllItems() suspend fun refreshItems(): Result { return try { val response = api.getItems() val entities = response.items.map { it.toEntity() } itemDao.insertAll(entities) Result.success(Unit) } catch (e: Exception) { Result.failure(e) } } } ``` -------------------------------- ### Integrate Room DAO into Repository Source: https://github.com/ministerofsalt-cell/arc-raiders-companion/blob/main/IMPLEMENTATION_GUIDE.md Demonstrates how to integrate the `ItemDao` into an `ItemsRepository` to manage item data. It prioritizes fetching data from the cache and falls back to the API if the cache is empty or an error occurs. ```kotlin class ItemsRepository @Inject constructor( private val api: MetaForgeApi, private val itemDao: ItemDao ) { fun getItems(): Flow> = flow { // Try cache first itemDao.getAllItems().collect { cachedItems -> if (cachedItems.isNotEmpty()) { emit(cachedItems.map { it.toItem() }) } } // Fetch fresh data try { val items = api.getItems() itemDao.insertAll(items.map { it.toCachedItem() }) emit(items) } catch (e: Exception) { // Fall back to cache if API fails } } } ``` -------------------------------- ### Add Room Database Dependencies for Android Source: https://github.com/ministerofsalt-cell/arc-raiders-companion/blob/main/IMPLEMENTATION_GUIDE.md Adds the necessary Room database dependencies to the `build.gradle.kts` file for Android projects. This includes the runtime, KTX extensions, and compiler for Room. ```kotlin dependencies { // Room implementation("androidx.room:room-runtime:2.6.1") implementation("androidx.room:room-ktx:2.6.1") kapt("androidx.room:room-compiler:2.6.1") // Existing dependencies... } ``` -------------------------------- ### Android App Build Configuration (build.gradle.kts) Source: https://github.com/ministerofsalt-cell/arc-raiders-companion/blob/main/IMPLEMENTATION_GUIDE.md Configures the Android application build for the ARC Raiders Companion project. It specifies plugins, SDK versions, build features like Jetpack Compose, and lists all project dependencies including Compose, Hilt, Retrofit, Room, WorkManager, and Coroutines. ```kotlin plugins { id("com.android.application") id("org.jetbrains.kotlin.android") id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") } android { namespace = "com.arcraiders.companion" compileSdk = 34 defaultConfig { applicationId = "com.arcraiders.companion" minSdk = 24 targetSdk = 34 versionCode = 1 versionName = "1.0" } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } kotlinOptions { jvmTarget = "17" } buildFeatures { compose = true } composeOptions { kotlinCompilerExtensionVersion = "1.5.3" } } dependencies { // Compose implementation("androidx.compose.ui:ui:1.5.4") implementation("androidx.compose.material3:material3:1.1.2") implementation("androidx.compose.ui:ui-tooling-preview:1.5.4") implementation("androidx.activity:activity-compose:1.8.2") implementation("androidx.navigation:navigation-compose:2.7.6") // Lifecycle implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2") // Hilt implementation("com.google.dagger:hilt-android:2.48.1") ksp("com.google.dagger:hilt-compiler:2.48.1") implementation("androidx.hilt:hilt-navigation-compose:1.1.0") // Retrofit implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0") // Room implementation("androidx.room:room-runtime:2.6.1") implementation("androidx.room:room-ktx:2.6.1") ksp("androidx.room:room-compiler:2.6.1") // WorkManager implementation("androidx.work:work-runtime-ktx:2.9.0") // Coroutines implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") } ``` -------------------------------- ### Implement Event Notification Worker Source: https://github.com/ministerofsalt-cell/arc-raiders-companion/blob/main/IMPLEMENTATION_GUIDE.md Implements a `CoroutineWorker` named `EventNotificationWorker` to handle background tasks for push notifications. This worker checks for upcoming events and displays notifications if an event is starting soon. ```kotlin class EventNotificationWorker( context: Context, params: WorkerParameters ) : CoroutineWorker(context, params) { override suspend fun doWork(): Result { val repository = EventTimersRepository(/* inject API */) repository.getEventTimers().collect { timers -> timers.forEach { timer -> val nextTime = repository.calculateNextEventTime(timer) if (nextTime != null && nextTime - System.currentTimeMillis() <= 15 * 60 * 1000) { // Event starting in 15 minutes showNotification(timer.event, "Starting in 15 minutes!") } } } return Result.success() } private fun showNotification(title: String, message: String) { val notification = NotificationCompat.Builder(applicationContext, CHANNEL_ID) .setContentTitle(title) .setContentText(message) .setSmallIcon(R.drawable.ic_notification) .setPriority(NotificationCompat.PRIORITY_HIGH) .build() NotificationManagerCompat.from(applicationContext) .notify(Random.nextInt(), notification) } } ``` -------------------------------- ### Schedule Periodic Checks with WorkManager (Kotlin) Source: https://github.com/ministerofsalt-cell/arc-raiders-companion/blob/main/IMPLEMENTATION_GUIDE.md Schedules a periodic work request for event notifications using Android's WorkManager library. This ensures that notifications are checked and potentially displayed at regular intervals (every 15 minutes in this example). It uses a unique work name to prevent duplicate scheduling. ```kotlin fun scheduleEventNotifications() { val workRequest = PeriodicWorkRequestBuilder( 15, TimeUnit.MINUTES ).build() WorkManager.getInstance(applicationContext) .enqueueUniquePeriodicWork( "event_notifications", ExistingPeriodicWorkPolicy.KEEP, workRequest ) } ``` -------------------------------- ### Add WorkManager Dependency for Push Notifications Source: https://github.com/ministerofsalt-cell/arc-raiders-companion/blob/main/IMPLEMENTATION_GUIDE.md Adds the WorkManager dependency to the `build.gradle.kts` file for Android projects. WorkManager is used for deferrable, guaranteed background work, such as scheduling push notifications. ```kotlin dependencies { // WorkManager for scheduled notifications implementation("androidx.work:work-runtime-ktx:2.9.0") // Existing dependencies... } ``` -------------------------------- ### Create Notification Channel (Kotlin) Source: https://github.com/ministerofsalt-cell/arc-raiders-companion/blob/main/IMPLEMENTATION_GUIDE.md Creates a notification channel for event alerts on Android devices running API level 26 (Oreo) or higher. This is required for sending channel-based notifications and allows users to customize notification settings. It defines the channel ID, name, and importance. ```kotlin private fun createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( CHANNEL_ID, "Event Alerts", NotificationManager.IMPORTANCE_HIGH ).apply { description = "Notifications for upcoming ARC Raiders events" } val notificationManager = getSystemService(NotificationManager::class.java) notificationManager.createNotificationChannel(channel) } } companion object { const val CHANNEL_ID = "arc_raiders_events" } ``` -------------------------------- ### Define Room Database Entity for Cached Items Source: https://github.com/ministerofsalt-cell/arc-raiders-companion/blob/main/IMPLEMENTATION_GUIDE.md Defines a Room Entity named `CachedItem` to represent item data stored in the local cache. It includes fields for item ID, name, type, rarity, description, and a timestamp for caching. ```kotlin @Entity(tableName = "cached_items") data class CachedItem( @PrimaryKey val id: String, val name: String, val type: String?, val rarity: String?, val description: String?, val cachedAt: Long = System.currentTimeMillis() ) ``` -------------------------------- ### Define Room DAO for Item Operations Source: https://github.com/ministerofsalt-cell/arc-raiders-companion/blob/main/IMPLEMENTATION_GUIDE.md Defines a Room Data Access Object (DAO) named `ItemDao` for performing CRUD operations on the `cached_items` table. It includes methods for fetching all items, inserting items, and deleting expired items. ```kotlin @Dao interface ItemDao { @Query("SELECT * FROM cached_items") fun getAllItems(): Flow> @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertAll(items: List) @Query("DELETE FROM cached_items WHERE cachedAt < :expiryTime") suspend fun deleteExpired(expiryTime: Long) } ``` -------------------------------- ### Jetpack Compose ItemsScreen with Loading/Error/Success States (Kotlin) Source: https://github.com/ministerofsalt-cell/arc-raiders-companion/blob/main/IMPLEMENTATION_GUIDE.md A Jetpack Compose composable function for displaying a list of items with different UI states: Loading, Error, and Success. It utilizes ViewModel and StateFlow to manage UI state and provides a Retry button in case of errors. This pattern can be applied to other screens like QuestsScreen, MapsScreen, and SkillTreeScreen. ```kotlin @Composable fun ItemsScreen( viewModel: ItemsViewModel = hiltViewModel(), modifier: Modifier = Modifier ) { val uiState by viewModel.uiState.collectAsState() Box(modifier = modifier.fillMaxSize()) { when (val state = uiState) { is ItemsUiState.Loading -> { CircularProgressIndicator( modifier = Modifier.align(Alignment.Center) ) } is ItemsUiState.Error -> { Column( modifier = Modifier .fillMaxSize() .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Icon( imageVector = Icons.Default.Warning, contentDescription = null, modifier = Modifier.size(64.dp), tint = MaterialTheme.colorScheme.error ) Spacer(modifier = Modifier.height(16.dp)) Text( text = state.message, style = MaterialTheme.typography.bodyLarge, color = MaterialTheme.colorScheme.error, textAlign = TextAlign.Center ) Spacer(modifier = Modifier.height(16.dp)) Button(onClick = { viewModel.retry() }) { Text("Retry") } } } is ItemsUiState.Success -> { LazyColumn( modifier = Modifier.fillMaxSize(), contentPadding = PaddingValues(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp) ) { items(state.items) { ItemCard(item = item) } } } } } } ``` -------------------------------- ### Required Permissions for Notifications and Alarms (XML) Source: https://github.com/ministerofsalt-cell/arc-raiders-companion/blob/main/IMPLEMENTATION_GUIDE.md Declares necessary permissions in the AndroidManifest.xml file. `POST_NOTIFICATIONS` is required for displaying notifications on Android 13+, and `SCHEDULE_EXACT_ALARM` is needed for scheduling precise alarms, which might be used for time-sensitive event notifications. ```xml ``` -------------------------------- ### MetaForge API Integration with Retrofit (Kotlin) Source: https://context7.com/ministerofsalt-cell/arc-raiders-companion/llms.txt Defines the Retrofit interface for interacting with the MetaForge API and configures a singleton Retrofit client. It includes methods to fetch items, event timers, and traders, with basic error handling for API calls. ```kotlin // MetaForgeApi.kt - Retrofit interface definition interface MetaForgeApi { @GET("items") suspend fun getItems( @Query("page") page: Int = 1, @Query("pageSize") pageSize: Int = 20, @Query("rarity") rarity: String? = null, @Query("category") category: String? = null ): ItemsResponse @GET("event-timers") suspend fun getEventTimers( @Query("map") map: String? = null, @Query("name") name: String? = null ): EventTimersResponse @GET("traders") suspend fun getTraders(): TradersResponse } // RetrofitClient.kt - Singleton client configuration object RetrofitClient { private const val BASE_URL = "https://api.metaforge.gg/v1/" private val json = Json { ignoreUnknownKeys = true coerceInputValues = true isLenient = true } private val okHttpClient = OkHttpClient.Builder() .addInterceptor(HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY }) .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .build() val metaForgeApi: MetaForgeApi by lazy { Retrofit.Builder() .baseUrl(BASE_URL) .client(okHttpClient) .addConverterFactory(json.asConverterFactory("application/json".toMediaType())) .build() .create(MetaForgeApi::class.java) } } // Usage example with error handling viewModelScope.launch { try { val response = RetrofitClient.metaForgeApi.getItems(page = 1, pageSize = 50) println("Fetched ${response.items.size} items") println("Total pages: ${response.pagination.totalPages}") } catch (e: Exception) { println("API error: ${e.message}") } } ``` -------------------------------- ### Trader Search Repository Management in Kotlin Source: https://context7.com/ministerofsalt-cell/arc-raiders-companion/llms.txt Manages trader information, including fetching all traders, searching by name, and finding traders who sell specific items. It interacts with an API for data retrieval and uses StateFlow for reactive search results. A ViewModel demonstrates its usage with a search query. ```kotlin import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.stateIn import javax.inject.Inject import javax.inject.Singleton // Assuming Trader, MetaForgeApi are defined elsewhere @Singleton class TradersRepository @Inject constructor( private val api: MetaForgeApi ) { // Get all traders from API fun getTraders(): Flow> = flow { try { val traders = api.getTraders() emit(traders) } catch (e: Exception) { emit(emptyList()) } } // Search for specific trader by name fun getTraderByName(traderName: String): Flow = flow { try { val traders = api.getTraders() val trader = traders.find { it.name.equals(traderName, ignoreCase = true) } emit(trader) } catch (e: Exception) { emit(null) } } // Find traders selling specific item fun searchTradersByItem(itemName: String): Flow> = flow { try { val traders = api.getTraders() val filteredTraders = traders.filter { it.inventory.any { it.name.contains(itemName, ignoreCase = true) } } emit(filteredTraders) } catch (e: Exception) { emit(emptyList()) } } } // Usage example with search class TradersViewModel @Inject constructor( private val repository: TradersRepository ) : ViewModel() { private val _searchQuery = MutableStateFlow("") val searchQuery: StateFlow = _searchQuery.asStateFlow() val filteredTraders: StateFlow> = searchQuery .flatMapLatest { if (it.isBlank()) { repository.getTraders() } else { repository.searchTradersByItem(it) } } .stateIn(viewModelScope, SharingStarted.Lazily, emptyList()) fun updateSearchQuery(query: String) { _searchQuery.value = query } } // Placeholder data classes and interfaces for compilation data class Trader(val name: String, val inventory: List) data class Item(val name: String) interface MetaForgeApi { suspend fun getTraders(): List } ``` -------------------------------- ### Quest Tracking Repository Management in Kotlin Source: https://context7.com/ministerofsalt-cell/arc-raiders-companion/llms.txt Manages quest data, including fetching, updating completion status, and progress tracking. It utilizes a cache-first strategy and integrates with a DAO for data persistence. Usage is demonstrated in a Composable function for UI display. ```kotlin import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import javax.inject.Inject import javax.inject.Singleton // Assuming Quest, QuestDao, MetaforgeApi, and toQuest() are defined elsewhere @Singleton class QuestsRepository @Inject constructor( private val api: MetaforgeApi, private val dao: QuestDao ) { // Get all quests with cache-first strategy fun getQuests(): Flow> = flow { val cachedQuests = dao.getAllQuests().map { entities -> entities.map { it.toQuest() } } cachedQuests.collect { emit(it) } try { refreshQuests() } catch (e: Exception) { // Continue with cached data on error } } // Toggle quest completion status suspend fun toggleQuestCompletion(questId: String): Boolean { return try { val quest = dao.getQuestByIdSync(questId) quest?.let { val updatedQuest = it.copy(isCompleted = !it.isCompleted) dao.update(updatedQuest) updatedQuest.isCompleted } ?: false } catch (e: Exception) { false } } // Update quest progress percentage suspend fun updateQuestProgress(questId: String, progress: Int) { try { dao.updateQuestProgress(questId, progress) } catch (e: Exception) { // Handle error } } // Get quests by completion status fun getCompletedQuests(): Flow> = dao.getCompletedQuests().map { entities -> entities.map { it.toQuest() } } fun getIncompleteQuests(): Flow> = dao.getIncompleteQuests().map { entities -> entities.map { it.toQuest() } } // Placeholder for refreshQuests if it exists private suspend fun refreshQuests() { // Implementation to refresh quests from API } } // Usage in Composable @Composable fun QuestTracker(repository: QuestsRepository) { val quests by repository.getIncompleteQuests().collectAsState(initial = emptyList()) LazyColumn { items(quests) { QuestItem( quest = it, onToggle = { repository.toggleQuestCompletion(it.id) }, onProgressUpdate = { progress -> repository.updateQuestProgress(it.id, progress) } ) } } } // Placeholder data classes and interfaces for compilation data class Quest(val id: String, val name: String, var isCompleted: Boolean, var progress: Int) interface QuestDao { suspend fun getAllQuests(): Flow>; suspend fun getQuestByIdSync(id: String): QuestEntity?; suspend fun update(quest: QuestEntity); suspend fun updateQuestProgress(questId: String, progress: Int); fun getCompletedQuests(): Flow>; fun getIncompleteQuests(): Flow>} interface MetaforgeApi { suspend fun getTraders(): List } interface QuestEntity { val id: String; val isCompleted: Boolean; val progress: Int; fun toQuest(): Quest } data class QuestItem(val quest: Quest, val onToggle: () -> Unit, val onProgressUpdate: (Int) -> Unit) ``` -------------------------------- ### Event Timers API Source: https://github.com/ministerofsalt-cell/arc-raiders-companion/blob/main/README.md Provides real-time information about ongoing and upcoming in-game events. ```APIDOC ## GET /api/arc-raiders/event-timers ### Description Fetches live data on current and upcoming in-game events, including timers and status. Essential for countdown functionality. ### Method GET ### Endpoint /api/arc-raiders/event-timers ### Parameters No specific parameters are documented for this endpoint. ### Request Example ```json { "example": "GET /api/arc-raiders/event-timers" } ``` ### Response #### Success Response (200) - **events** (array) - A list of active and upcoming event objects. - **id** (string) - The unique identifier for the event. - **name** (string) - The name of the event. - **startTime** (string) - The start time of the event (ISO 8601 format). - **endTime** (string) - The end time of the event (ISO 8601 format). - **status** (string) - The current status of the event (e.g., 'active', 'upcoming', 'ended'). #### Response Example ```json { "example": "{\"events\": [{\"id\": \"event_xyz\", \"name\": \"Special Ops Event\", \"startTime\": \"2024-07-26T10:00:00Z\", \"endTime\": \"2024-07-26T12:00:00Z\", \"status\": \"active\"}] }" } ``` ``` -------------------------------- ### Items Repository with Offline Caching (Kotlin) Source: https://context7.com/ministerofsalt-cell/arc-raiders-companion/llms.txt Implements the repository pattern for managing item data, including fetching from the API and storing in a local Room database. It provides reactive streams (Flow) for item data and a function to refresh the cache. ```kotlin @Singleton class ItemsRepository @Inject constructor( private val api: MetaForgeApi, private val itemDao: ItemDao ) { // Get all items as reactive Flow from local database fun getAllItems(): Flow> = itemDao.getAllItems() // Search items with query filter fun searchItems(query: String): Flow> = itemDao.searchItems(query) // Refresh items from API and update local cache suspend fun refreshItems(): Result = try { val response = api.getItems() if (response.isSuccessful && response.body() != null) { val items = response.body()!!.data.map { item -> ItemEntity( id = item.id, name = item.name, description = item.description, rarity = item.rarity, category = item.category, iconUrl = item.iconUrl, stats = item.stats?.toString() ) } itemDao.insertAll(items) Result.success(Unit) } else { Result.failure(Exception("Failed to fetch items: ${response.code()}")) } } catch (e: Exception) { Result.failure(e) } } // Usage in ViewModel class ItemsViewModel @Inject constructor( private val repository: ItemsRepository ) : ViewModel() { val items: StateFlow> = repository.getAllItems() .stateIn(viewModelScope, SharingStarted.Lazily, emptyList()) fun refreshItems() { viewModelScope.launch { repository.refreshItems().onFailure { error -> _errorState.value = "Failed to refresh: ${error.message}" } } } } ``` -------------------------------- ### Trader Inventories API Source: https://github.com/ministerofsalt-cell/arc-raiders-companion/blob/main/README.md Fetches the current inventory of in-game traders. ```APIDOC ## GET /api/arc-raiders/traders ### Description Retrieves information about trader inventories, detailing the items they currently have for sale or trade. ### Method GET ### Endpoint /api/arc-raiders/traders ### Parameters No specific parameters are documented for this endpoint. ### Request Example ```json { "example": "GET /api/arc-raiders/traders" } ``` ### Response #### Success Response (200) - **traders** (array) - A list of trader objects. - **id** (string) - The unique identifier for the trader. - **name** (string) - The name of the trader. - **inventory** (array) - A list of items available from the trader. - **itemId** (string) - The ID of the item. - **quantity** (integer) - The number of items available. - **price** (integer) - The cost of the item. #### Response Example ```json { "example": "{\"traders\": [{\"id\": \"trader_001\", \"name\": \"Scrap Merchant\", \"inventory\": [{\"itemId\": \"item_456\", \"quantity\": 5, \"price\": 100}]}] }" } ``` ``` -------------------------------- ### MetaForge API - Traders Endpoint Source: https://context7.com/ministerofsalt-cell/arc-raiders-companion/llms.txt Retrieves a list of all in-game traders and their available inventory or services. ```APIDOC ## GET /traders ### Description Fetches information about all traders available in the game, potentially including their location, inventory, and available services. ### Method GET ### Endpoint /v1/traders ### Parameters None ### Response #### Success Response (200) - **traders** (array of objects) - An array containing trader objects. - **id** (string) - The unique identifier for the trader. - **name** (string) - The name of the trader. - **location** (string) - The in-game location of the trader. - **inventory** (array of objects) - A list of items the trader offers (structure may vary). #### Response Example { "traders": [ { "id": "trader-001", "name": "The Quartermaster", "location": "Base Camp", "inventory": [ { "itemId": "item-005", "price": 1500, "currency": "credits" } ] } ] } ``` -------------------------------- ### MetaForge API - Items Endpoint Source: https://context7.com/ministerofsalt-cell/arc-raiders-companion/llms.txt Retrieves a list of all items available in ARC Raiders. Supports pagination and filtering by rarity and category. ```APIDOC ## GET /items ### Description Fetches a paginated list of game items. You can filter items by rarity and category, and specify the page size and number. ### Method GET ### Endpoint /v1/items ### Parameters #### Query Parameters - **page** (integer) - Optional - The page number of the results to retrieve. - **pageSize** (integer) - Optional - The number of items to return per page. Defaults to 20. - **rarity** (string) - Optional - Filters items by their rarity (e.g., 'common', 'uncommon', 'rare', 'epic', 'legendary'). - **category** (string) - Optional - Filters items by their category (e.g., 'weapon', 'armor', 'consumable'). ### Response #### Success Response (200) - **data** (array of objects) - An array containing item objects. - **id** (string) - The unique identifier for the item. - **name** (string) - The name of the item. - **description** (string) - A description of the item. - **rarity** (string) - The rarity level of the item. - **category** (string) - The category the item belongs to. - **iconUrl** (string) - The URL of the item's icon. - **stats** (object) - An object containing the item's statistics (may be null). - **pagination** (object) - Pagination details for the response. - **currentPage** (integer) - The current page number. - **totalPages** (integer) - The total number of pages available. - **pageSize** (integer) - The number of items per page. - **totalItems** (integer) - The total number of items matching the query. #### Response Example { "data": [ { "id": "item-001", "name": "Assault Rifle", "description": "A versatile assault rifle.", "rarity": "rare", "category": "weapon", "iconUrl": "https://example.com/icons/ar.png", "stats": { "damage": 30, "fireRate": 600 } } ], "pagination": { "currentPage": 1, "totalPages": 10, "pageSize": 20, "totalItems": 200 } } ``` -------------------------------- ### Kotlin Event Timer Repository and Countdown Logic Source: https://context7.com/ministerofsalt-cell/arc-raiders-companion/llms.txt This Kotlin class, EventTimersRepository, fetches in-game event timers from an API and provides methods to calculate the time until the next event occurrence. It also includes a utility to format countdown durations into a human-readable string. Dependencies include the MetaForgeApi for data retrieval and standard Kotlin Coroutines for asynchronous operations. ```Kotlin import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.launch import java.util.Calendar import javax.inject.Inject import javax.inject.Singleton // Assuming these are defined elsewhere: // interface MetaForgeApi { suspend fun getEventTimers(map: String?, name: String?): ApiResponse> } // data class EventTimer(val name: String, val days: List, val times: List) // data class ApiResponse(val success: Boolean, val data: T) @Singleton class EventTimersRepository @Inject constructor( private val api: MetaForgeApi ) { // Fetch event timers with optional filters fun getEventTimers( map: String? = null, name: String? = null ): Flow> = flow { try { val response = api.getEventTimers(map, name) if (response.success) { emit(response.data) } else { emit(emptyList()) } } catch (e: Exception) { emit(emptyList()) } } // Calculate milliseconds until next event occurrence fun calculateNextEventTime(days: List, times: List): Long? { if (days.isEmpty() || times.isEmpty()) return null val now = System.currentTimeMillis() val dayMap = mapOf( "Sun" to Calendar.SUNDAY, "Mon" to Calendar.MONDAY, "Tue" to Calendar.TUESDAY, "Wed" to Calendar.WEDNESDAY, "Thu" to Calendar.THURSDAY, "Fri" to Calendar.FRIDAY, "Sat" to Calendar.SATURDAY ) val dayNumbers = days.mapNotNull { dayMap[it] } var nearestEventTime: Long? = null for (dayOffset in 0..6) { val checkCalendar = Calendar.getInstance().apply { add(Calendar.DAY_OF_YEAR, dayOffset) } val checkDay = checkCalendar.get(Calendar.DAY_OF_WEEK) if (checkDay in dayNumbers) { for (time in times) { val parts = time.split(":") if (parts.size != 2) continue val hour = parts[0].toIntOrNull() ?: continue val minute = parts[1].toIntOrNull() ?: continue val eventCalendar = Calendar.getInstance().apply { add(Calendar.DAY_OF_YEAR, dayOffset) set(Calendar.HOUR_OF_DAY, hour) set(Calendar.MINUTE, minute) set(Calendar.SECOND, 0) set(Calendar.MILLISECOND, 0) } val eventTime = eventCalendar.timeInMillis if (eventTime > now) { if (nearestEventTime == null || eventTime < nearestEventTime) { nearestEventTime = eventTime } } } } } return nearestEventTime?.let { it - now } } // Format countdown for display fun formatCountdown(millis: Long): String { val seconds = millis / 1000 val minutes = seconds / 60 val hours = minutes / 60 val days = hours / 24 return when { days > 0 -> "${days}d ${hours % 24}h" hours > 0 -> "${hours}h ${minutes % 60}m" minutes > 0 -> "${minutes}m" else -> "${seconds}s" } } } // Usage example (assuming 'repository' is an instance of EventTimersRepository and viewModelScope is available) // viewModelScope.launch { // repository.getEventTimers().collect { // timers -> // timers.forEach { // timer -> // val nextTime = repository.calculateNextEventTime(timer.days, timer.times) // if (nextTime != null) { // val countdown = repository.formatCountdown(nextTime) // println("${timer.name} starts in $countdown") // } // } // } // } ``` -------------------------------- ### Items API Source: https://github.com/ministerofsalt-cell/arc-raiders-companion/blob/main/README.md Retrieves a paginated list of all items available in ARC Raiders. ```APIDOC ## GET /api/arc-raiders/items ### Description Fetches a paginated list of items available in the game. This endpoint is crucial for browsing and managing item data within the companion app. ### Method GET ### Endpoint /api/arc-raiders/items ### Parameters #### Query Parameters - **page** (integer) - Optional - The page number for pagination. - **pageSize** (integer) - Optional - The number of items to return per page. ### Request Example ```json { "example": "GET /api/arc-raiders/items?page=1&pageSize=20" } ``` ### Response #### Success Response (200) - **items** (array) - A list of item objects. - **id** (string) - The unique identifier for the item. - **name** (string) - The name of the item. - **description** (string) - A description of the item. - **type** (string) - The category or type of the item. #### Response Example ```json { "example": "{\"items\": [{\"id\": \"item_123\", \"name\": \"Medkit\", \"description\": \"Restores health.\", \"type\": \"Consumable\"}] }" } ``` ``` -------------------------------- ### Manage Item List UI State with Kotlin Flow and Coroutines Source: https://context7.com/ministerofsalt-cell/arc-raiders-companion/llms.txt This Kotlin code defines the UI state for displaying a list of items, including loading status, errors, and pagination information. The ViewModel uses Kotlin Flow and Coroutines to manage this state reactively, fetching data from an API and updating the UI state accordingly. It handles loading, error states, and pagination logic. ```kotlin data class ItemsUiState( val items: List = emptyList(), val isLoading: Boolean = false, val error: String? = null, val currentPage: Int = 1, val hasMorePages: Boolean = true ) class ItemsViewModel : ViewModel() { private val _uiState = MutableStateFlow(ItemsUiState()) val uiState: StateFlow = _uiState.asStateFlow() private val api = RetrofitClient.metaForgeApi init { loadItems() } fun loadItems(page: Int = 1) { viewModelScope.launch { _uiState.value = _uiState.value.copy(isLoading = true, error = null) try { val response = api.getItems(page = page) _uiState.value = _uiState.value.copy( items = if (page == 1) response.items else _uiState.value.items + response.items, isLoading = false, currentPage = page, hasMorePages = page < response.pagination.totalPages ) } catch (e: Exception) { _uiState.value = _uiState.value.copy( isLoading = false, error = "Failed to load items: ${e.message}" ) } } } fun loadNextPage() { if (!_uiState.value.isLoading && _uiState.value.hasMorePages) { loadItems(_uiState.value.currentPage + 1) } } fun retry() { loadItems(_uiState.value.currentPage) } fun refresh() { loadItems(1) } } // Usage in Composable @Composable fun ItemsScreen(viewModel: ItemsViewModel = viewModel()) { val uiState by viewModel.uiState.collectAsState() LazyColumn { items(uiState.items) { ItemCard(item = item) } if (uiState.hasMorePages) { item { Button(onClick = { viewModel.loadNextPage() }) { Text("Load More") } } } if (uiState.isLoading) { item { CircularProgressIndicator() } } uiState.error?.let { error -> item { ErrorMessage(error, onRetry = { viewModel.retry() }) } } } } ``` -------------------------------- ### Quests API Source: https://github.com/ministerofsalt-cell/arc-raiders-companion/blob/main/README.md Fetches all available quest data for ARC Raiders. ```APIDOC ## GET /api/arc-raiders/quests ### Description Retrieves detailed information about all quests in ARC Raiders. This includes objectives, rewards, and prerequisites. ### Method GET ### Endpoint /api/arc-raiders/quests ### Parameters No specific parameters are documented for this endpoint. ### Request Example ```json { "example": "GET /api/arc-raiders/quests" } ``` ### Response #### Success Response (200) - **quests** (array) - A list of quest objects. - **id** (string) - The unique identifier for the quest. - **title** (string) - The title of the quest. - **description** (string) - A detailed description of the quest objectives. - **rewards** (object) - Information about quest rewards. #### Response Example ```json { "example": "{\"quests\": [{\"id\": \"quest_abc\", \"title\": \"Secure the Artifact\", \"description\": \"Locate and extract the ancient artifact from the ruins.\", \"rewards\": {}}] }" } ``` ``` -------------------------------- ### MetaForge API - Event Timers Endpoint Source: https://context7.com/ministerofsalt-cell/arc-raiders-companion/llms.txt Retrieves information about active and upcoming in-game events, with options to filter by map and event name. ```APIDOC ## GET /event-timers ### Description Fetches details about game events, including their start and end times. Events can be filtered by the map they occur on or by their specific name. ### Method GET ### Endpoint /v1/event-timers ### Parameters #### Query Parameters - **map** (string) - Optional - Filters events by the map they are associated with. - **name** (string) - Optional - Filters events by their specific name. ### Response #### Success Response (200) - **events** (array of objects) - An array containing event timer objects. - **id** (string) - The unique identifier for the event. - **name** (string) - The name of the event. - **map** (string) - The map where the event takes place. - **startTime** (string) - The start time of the event in ISO 8601 format. - **endTime** (string) - The end time of the event in ISO 8601 format. - **isActive** (boolean) - Indicates if the event is currently active. #### Response Example { "events": [ { "id": "event-001", "name": "Raid Incursion", "map": "The Outpost", "startTime": "2024-07-26T10:00:00Z", "endTime": "2024-07-26T12:00:00Z", "isActive": true } ] } ``` -------------------------------- ### Game Map Data API Source: https://github.com/ministerofsalt-cell/arc-raiders-companion/blob/main/README.md Retrieves data for interactive maps, including markers and points of interest. ```APIDOC ## GET /api/game-map-data ### Description Fetches data required for interactive maps, including geographical markers, points of interest (POIs), and their details. ### Method GET ### Endpoint /api/game-map-data ### Parameters No specific parameters are documented for this endpoint. ### Request Example ```json { "example": "GET /api/game-map-data" } ``` ### Response #### Success Response (200) - **mapData** (array) - A list of map data objects. - **id** (string) - The unique identifier for a map element. - **name** (string) - The name of the marker or POI. - **type** (string) - The type of map element (e.g., 'landmark', 'resource_node'). - **coordinates** (object) - The geographical coordinates (e.g., latitude, longitude) of the element. #### Response Example ```json { "example": "{\"mapData\": [{\"id\": \"poi_1\", \"name\": \"Ancient Ruin\", \"type\": \"landmark\", \"coordinates\": {\"lat\": 12.34, \"lon\": 56.78}}] }" } ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.