# Activity Suite LCMA Sample

Activity Suite is the first official live-event mini app sample. Version
`0.1.0` ships two playable vertical slices: a host can run a live poll or draw
ordered lucky winners from nearby participants plus an optional manual list.

The sample intentionally uses only the current `localchat-miniapp-v1` bridge:

- `localchat.room.create(params)`
- `localchat.room.join(params)`
- `localchat.room.message(params)`
- `localchat.room.poll(params)`
- `localchat.storage.local.get(key)`
- `localchat.storage.local.set(key, value)`
- `localchat.ui.showToast(input)`
- `localchat.ui.setKeepScreenOn(enabled)`

The shared protocol prefix is `localchat.activity.v1`. Later Bingo, guessing,
blessing wall, bullet wall, and word wall slices should add event types under
the same prefix instead of inventing separate room protocols.

## Package

From `apps/gobaby_transfer`:

```sh
dart --disable-dart-dev tool/lcma_packager.dart \
  --source samples/mini_apps/activity_suite \
  --output build/mini-app-center/activity-suite-0.1.0.lcma \
  --metadata build/mini-app-center/activity-suite-0.1.0.submission.json \
  --artifact-url https://localchat.me/v1/mini-app-center/artifacts/<staged-package-storage-key> \
  --key-id localchat-miniapp-beta-<developer> \
  --private-key-seed-base64url <developer-signing-seed>
```

For local unsigned smoke checks, omit `--private-key-seed-base64url` and keep
the generated package out of external beta submissions.

## Activity Contract

The live vote slice sends concise room messages with `type: "activity.event"`
and payloads shaped like:

```json
{
  "protocol": "localchat.activity.v1",
  "event": "poll.opened",
  "sessionId": "ACT-1234",
  "pollId": "poll-1710000000000",
  "question": "Choose tonight's first activity",
  "options": [
    { "id": "bingo", "label": "Bingo" },
    { "id": "lottery", "label": "Lucky Draw" }
  ]
}
```

Hosts announce rooms with `session.created`. Participants enter the shared
activity pool with `participant.joined`.

Votes use `poll.vote`; the host keeps the latest vote per `memberId`. Closing
the poll broadcasts `poll.closed` with the host's result summary so participants
can show the same final state after polling.

The lucky draw slice uses the same room message envelope. Participant names come
from `participant.joined` events or from a host-maintained manual list. The
host runs a seeded draw so the result can be reproduced, then broadcasts
`lottery.draw` with the seed, `fnv1a32-lcg-fisher-yates-v1` algorithm id,
draw id, candidate count, and ordered winners list.

## Smoke Tests

These tests package and validate the committed sample:

```sh
flutter test test/lcma_packager_test.dart --plain-name "packager validates the repository Activity Suite sample"
```
