# Connection Helpers

This folder contains the shared browser-side API helpers used by the game `index.html` files.

## Files

### `env.js`

Shared runtime config for browser pages and CommonJS usage.

Current shape:

```js
window.ByteLiftEnv = {
  API_BASE_URL: "https://bytelift.rorens.com/api/v1",
};
```

Load this before the other connection scripts in browser pages:

```html
<script src="../connection/env.js"></script>
<script src="../connection/start_game.js"></script>
<script src="../connection/submit_answer.js"></script>
```

### `start_game.js`

Exports `startGame()` for the API launch request.

Behavior:

- reads `token` from the page query string
- posts `{ token }` to `${API_BASE_URL}/interactive_games/start`
- returns the parsed JSON response
- throws when the URL token is missing or the API responds with a non-2xx status

Helpers:

- `getLaunchTokenFromUrl()`
- `getApiBaseUrl()`

### `submit_answer.js`

Exports `submitAnswer(payload)` for the API completion request.

Behavior:

- validates `payload.token`, `payload.score`, and `payload.metadata`
- posts the payload to `${API_BASE_URL}/interactive_games/complete`
- on success, performs shared client completion handling:
  - redirects to `redirect_url` when that query param exists
  - otherwise posts a message to `window.ReactNativeWebView.postMessage(...)` when available
- throws when the payload is invalid or the API responds with a non-2xx status

Helpers:

- `validateCompletionPayload(payload)`
- `getApiBaseUrl()`
- `getRedirectUrlFromParams()`
- `notifyReactNative(responsePayload)`
- `completeGameClientFlow(responsePayload)`

React Native message format:

```json
{
  "type": "interactive_game_completed",
  "payload": {
    "request": {
      "token": "SESSION_TOKEN_HERE",
      "score": 95,
      "metadata": {
        "time_spent_seconds": 132,
        "level": 3,
        "correct_answers": 19
      }
    },
    "response": {}
  }
}
```

## Integration Rules

Each game page should follow the same integration pattern.

### 1. Load scripts in order

```html
<script src="../connection/env.js"></script>
<script src="../connection/start_game.js"></script>
<script src="../connection/submit_answer.js"></script>
```

### 2. Preserve helper references before local game functions overwrite globals

Some pages already define local `startGame()` or `submitAnswer()` functions. Preserve the shared helpers first:

```html
<script>
  window.byteLiftApiStartGame = window.startGame;
  window.byteLiftApiSubmitAnswer = window.submitAnswer;
</script>
```

Then use:

```js
const startGameRequest = window.byteLiftApiStartGame;
const submitAnswerRequest = window.byteLiftApiSubmitAnswer;
```

### 3. Start the API session on page ready

Each page should initialize the game session as soon as the document is ready, not when gameplay ends.

Expected flow:

1. call `startGameRequest()`
2. extract the session token from the API response
3. fall back to the launch token only if no session token field is present

Recommended response token lookup order:

```js
response.token ||
response.session_token ||
response.sessionToken ||
response.data?.token ||
response.data?.session_token ||
response.data?.sessionToken ||
null
```

### 4. Submit once at the true game-complete state

Do not submit per round unless that game genuinely defines completion that way.

Submit only when the game reaches its final results state, for example:

- final score screen
- all houses completed
- run ended / game over state

### 5. Build game-specific metadata in the page

`submit_answer.js` handles the API request and shared redirect / WebView behavior, but each game still needs to build the right payload:

```js
{
  token,
  score,
  metadata: {
    time_spent_seconds,
    level,
    correct_answers,
    rounds_total,
    rounds_completed,
    game_mode,
  },
}
```

Only include fields that are meaningful for the game. Keep naming consistent across games where possible.

## Score Guidance

For most round-based games, use:

- `score`: percentage score, for example `Math.round((correctAnswers / totalRounds) * 100)`
- `metadata.correct_answers`: raw count of correct answers
- `metadata.level`: current or final level / round-set identifier when the game has one
- `metadata.time_spent_seconds`: total play duration for the finished run

For non-round games like endless runners, use:

- `score`: the actual in-game score or a normalized score if needed later
- `metadata.correct_answers`: `null` or omit when the game has no correct/incorrect answer model
- `metadata.level`: omit or use the current stage / speed tier if the game defines one

## Notes

- Helpers fall back to the production API base URL if `env.js` is not loaded yet.
- Network calls were not executed from this workspace because outbound network access is restricted here.
- Redirect and React Native postMessage happen inside `submit_answer.js`, so this behavior is reusable across all games.
