Skip to content

Overview

This programming assignment is another enhancement to the 1024 Game where you will add the following features:

  1. Ask the user to log in with email and password before playing the actual game. This feature allows your game to be played by different players, one at a time.

  2. If the user has not created an account, allow the user to navigation to a different screen for creating a new account

  3. Store the game statistics when the user won or lost the game. The details of the game statistics are provided in a separate section below

  4. Allow the user to browse past game statistics and sort them by some criteria (number of steps, max score, etc.)

UI Design

Login Screen

The login screen should include (at least) the following widgets:

  • A text field to enter the user email
  • A text field to enter the password (with the password masked)
  • A text to show any error messages related to account authentication, i.e. error messages returned by Firebase Authentication
  • A button to authenticate the email/password
  • A button to navigate to the "New Account" screen

New Account Screen

The new account screen should include (at least) the following widgets:

  • A text field to enter the user email
  • A text field to enter the user real name
  • A text field to enter the password (with the password masked)
  • Another text field to confirm the password (with the password masked)
  • A text to show any error messages related to account authentication, i.e. error messages returned by Firebase Authentication
  • A button to create a new account. This button should stay disabled when both the user email and password fields are empty and when the two password fields do not match.
  • A button to the "Cancel" creating a new account and go back to the login screen.

important

After a new account is successfully created the user (real) name shall be stored in Firebase. Subsequent login to your game shall display this real name on the game main screen.

Game Statistics Screen

This screen shall show (at least):

  • The user (real) name
  • The total number of game sessions have been played
  • The average number of steps
  • A list of game statistics (one record per row). Show each in a 2- or 3-line format (showing all the details in one line will not fit the available screen width)
  • Use two different backgrounds for rows showing a win/lost
  • One button to sort the statistics by the number of steps (ascending)
  • One button to sort the statistics by the number of steps (descending)
  • One button to sort the statistics by date/time
  • One button to go back (and resume) the current game

Main (Game) Screen

Modify the main game screen to include two more buttons

  • A button to browse the game statistics.
  • A button to leave the game

Game Statistics

The game statistics essentially record the achievement of the player after each game session. Each record shall include (at least) the following information:

  • Number of valid steps to win or lose

  • The board size

  • The final state of the game (won/lost)

  • The maximum score achieved when the user lost/won

  • For extra credit you can also include extra fields:

    • date and time of the game stored in ISO8601 format, i.e. 2023-11-28T19:05:37 for 7:05pm on Nov 28, 2023.
    • the number of seconds to win/lose the game

important

The game statistics of each user shall be stored separately from the other users. The common technique in Firestore is to use the Firebase Auth UID as the document ID for each player's data. For instance, if you name the top-level collection players and you have two users with UID GY238F123h and Zw9Hz772qR, then you can use two separate Firestore documents players/GY238F123h and players/Zw9Hz772qR to store the details of each player.

Extra Credit Feature: Resume saved game

When the player leaves the game while the game is still in progress, save the current game state to Firestore. On the next login, reload the save game and allow the player to continue where he left off. This means that you have to save the number of steps made, the board size, and the current board content

Resources

Project Setup

As a reference for integrating Firebase Authentication and Firestore in your game app, use the sample code provided on your instructor's GitHub repository. A few important details from the sample code:

  1. The sample code is provided without the instructor's copy of google-services.json. You have to create one yourself (from Firebase project dashboard), by registering it using the package name of the provided sample code.
  2. Setting up Google Services Plugin so your app is linked correctly with your Firebase project.
  3. To enable access to Firebase from your 1024 game, you must register it separately from (1) above.

It is important that your App build.gradle(.kts) includes the following "Bill of Materials" libraries (the latest version numbers may be different by the time you read this)

implementation("androidx.compose:compose-bom:2024.04.01")
implementation(platform("com.google.firebase:firebase-bom:31.0.0"))

Instantiating LifeCycle Aware ViewModels

The provided example of GitHub may have created an instance of the view model using explicit construction invocation:

setContent {
   val vm = SomeViewModel()
   // More code here
}

The above snippet is not aware of lifecycle changes of your Android app. A better approach is to use a delegation by the lifecycle aware function viewModels() (provided in one of the dependencies):

setContent {
   val vm : SomeViewModel by viewModels()
   // More code here
}

Likewise, functions which are define with a default initializer for a view model should use the lifecycle aware funcion viewModel(). Unlike the delegate above (plural name), this function name is singular.

fun MyFunction(/* other args */, 
    vm: SomeViewModel = SomeViewModel()) {  // Don't use this
    // more code
}

fun MyFunction(/* other args */, 
    vm: SomeViewModel = viewModel()) {  // USE THIS
    // more code
}

Jetpack Compose NavHostController provides several function variants to "return" to a previous screen. All the variants essentially pop entries from the (current) navigation stack.

navCtrl.popBackStack()                // pop the top-most screen on the navigation stack
navCtrl.popBackStack(route = "whereTo", inclusive = false) // pop all screens until "whereTo" is the topmost
navCtrl.popBackStack(route = "whereTo", inclusive = true) // pop all screens until the screen below "whereTo" is the topmost

Perform Work Outside of (Re)Composition Flow

A @Composable function may be invoked many times when the UI needs to be updated. However, sometimes we need to hava a block of statement in that @Composable "excluded" from the UI update cycles (recomposition). Jetpack Compose LaunchedEffect function can be used for this purpose.

A specific use case in this assigment is loading game statistic data from Firestore.

@Composable
fun GameStatisticsScreen() {
    Column {
      // Your UI is built here
    }

    LaunchedEffect(Unit) {
      // Invoke a function in view model to load data from Firestore
    }
}

Providing Unit as the argument to LauchedEffect implies the lambda block executes only once at the time the UI is begin composed (but not during subsequent recompositions).

If a variable is provided as an argument to LaunchedEffect, the lambda block will execute again when that variable changes.

Deliverables

  • Be sure that your google-services.json is pushed to your Git repo

  • Add dulimarh@mail.gvsu.edu as a member in your Firebase project

  • Include the following in your Bb submission:

    • The URL to your GitHub repo
    • The URL to your Firebase console

Grading Rubrics

Grading ItemPoints
Overall navigation flow6
Login screen3
Firebase Auth Login & Error handling4
New Account screen4
New Account error handling3
Firestore document per user2
Firestore game statistics collection per user3
Game statistics screen design4
Game statistics row details3
List of game statistics use two colors for win/lose2
Sort game statistics by two criteria4

Deliverables

  • Be sure to commit your google-services.json file into your repository.

  • Create two new user accounts for testing your game

  • Upload the following to Bb:

    1. The name of your Firebase Project
    2. The email and password of the two user accounts created above
  • Invite dulimarh@mail.gvsu.edu to your Firebase Project