# Hindi Dental-Retroflex Categorization

A browser-based phonetic categorization task in which participants learn to
distinguish the Hindi dental vs. retroflex consonant contrast across several
blocks of increasing difficulty. Participants hear a Hindi speech sound on
each trial and categorize it as **A** (dental) or **B** (retroflex), with
trial-by-trial feedback during the training phase. The task measures
auditory perceptual learning and phonetic category formation for a
non-native contrast.

Part of the [NCCR Evolving Language](https://www.evolvinglanguage.ch/) task
library at the University of Geneva. Associated project: NEBULA101.

## Requirements

- Any modern desktop browser (Chrome, Firefox, Edge, Safari) on Windows, macOS
  or Linux.
- Working audio output (headphones strongly recommended) — the task is
  entirely auditory.
- JavaScript and `localStorage` enabled (the latter is used as a crash-safe
  backup of collected data).

No build step, no dependencies, no backend. Pure static HTML/JS.

## Install

Clone the repo and you're done:

```bash
git clone <this-repo-url> hindi-dental-retroflex-categorization
cd hindi-dental-retroflex-categorization
```

## Run

Open `index.html` in a browser. Because the page loads audio files from the
`stimuli/` directory via `fetch`/`<audio>`, most browsers require the page
to be served over HTTP rather than `file://`. Any static server will do:

```bash
# Python 3
python3 -m http.server 8000
# or: npx serve .
```

Then visit `http://localhost:8000/`.

In production the task is bundled by the GitLab CI pipeline defined in
`.gitlab-ci.yml` (copies every file except `task.json` and the CI config
into `dist/`, zips it as `task.zip`), and the resulting bundle is served
from the NCCR task library at `/static/tasks/hindi-dental-retroflex/`.

## Controls

The entire task runs with the mouse; no keyboard input is required.

1. **Instructions** — pick a language (EN/DE/FR) from the top-right
   switcher, then click *Begin*.
2. **Familiarization** — click the *Play A example* / *Play B example*
   buttons to hear category exemplars as many times as you want, then
   *Start Test*.
3. **Training** — a short feedback-guided block (up to 3 A and 3 B
   trials). The stimulus plays automatically; response buttons appear
   once playback ends. Click **A** or **B**; correct/incorrect feedback
   is shown for ~1.5 s before the next trial.
4. **Test** — 540 trials split into 3 training blocks of increasing
   speaker variability. Same click-A/click-B response flow; no feedback
   between trials. Breaks appear between blocks.
5. **Results** — summary (accuracy, mean RT) plus two download buttons.

## Outputs

Data is collected in memory by `DataCollector` (see
`js/data-collector.js`) and mirrored to `localStorage` under the key
`gorilla_hindi-dental-retroflex_data` after every trial, so an
accidentally closed tab can be recovered.

At the end of the task the participant clicks one of two buttons to save
their data locally — nothing is uploaded to a server.

- **CSV**: `hindi-dental-retroflex_<ISO-timestamp>.csv`, one row per trial.
- **JSON**: `hindi-dental-retroflex_<ISO-timestamp>.json`, array of trial objects.

Columns / fields written:

| Field            | Meaning                                            |
| ---------------- | -------------------------------------------------- |
| `trial_number`   | 1-indexed trial counter across the whole test      |
| `block`          | Block identifier derived from the `display` column (`train1`, `train2`, `train3`) |
| `display`        | Raw Gorilla-style display name                     |
| `stimulus`       | Audio filename played (e.g. `SB1_22050.wav`)       |
| `correct_answer` | `A` (dental) or `B` (retroflex)                    |
| `response`       | Participant's choice (`A` / `B`)                   |
| `accuracy`       | `1` if correct, else `0`                           |
| `rt_ms`          | Reaction time in ms from audio end to button press |
| `lang`           | UI language at response time (`en` / `de` / `fr`)  |
| `_timestamp`     | ISO timestamp auto-added by `DataCollector`        |

See `task.json` for the canonical `dataVariables` and experimental
design description consumed by the library catalog.

## Files

```
.
├── index.html             Single-page UI, styles, translations, trial list
├── task.json              Library metadata (id, description, variables, design)
├── .gitlab-ci.yml         CI job that zips the task and publishes artifacts
├── js/
│   ├── trial-engine.js    Spreadsheet-driven trial sequencer (Gorilla-like)
│   ├── data-collector.js  In-memory store + CSV/JSON export + localStorage backup
│   ├── timer.js           Reaction-time measurement and optional countdown
│   └── lang-switcher.js   Runtime EN/DE/FR switcher (data-i18n attributes)
└── stimuli/
    ├── SB1_22050.wav … SB7_22050.wav   Categorization stimuli (22.05 kHz)
    └── hindi*.mp3                      Narrated instruction audio
```

The trial list (`TRIALS`) and familiarization list (`FAMILIARIZATION`) are
inlined inside `index.html` as JS arrays. They preserve Gorilla's
`randomise_blocks` / `randomise_trials` / `display` / `ANSWER` / `sound`
columns so the task logic stays close to its original spreadsheet form.

## Contact

- **Narly Golestani** — <narly.golestani@unige.ch> (conceptualization, supervision)
- [Brain and Language Lab](http://brainandlanguagelab.org/), University of Geneva
