> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dloopiq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# completeTask

> Soumet la réponse d'un utilisateur et déclenche l'algorithme de consensus.

## Signature

```typescript theme={null}
dloopiq.completeTask(options: CompleteTaskOptions): Promise<CompleteTaskResult>
```

***

## Options

```typescript theme={null}
interface CompleteTaskOptions {
  /** ID de la tâche retourné par getNextTask */
  taskId: string

  /** Identifiant opaque de l'utilisateur dans votre app */
  userId: string

  /** Réponse choisie parmi task.options */
  answer: string

  /** Temps passé sur la tâche en millisecondes */
  timeSpentMs: number
}
```

***

## Résultat

```typescript theme={null}
interface CompleteTaskResult {
  /** Statut de soumission */
  status: 'accepted' | 'already_responded'

  /** Centimes gagnés par le développeur pour cette réponse */
  earnedCents: number

  /** Indique si la tâche était une golden task */
  isGolden: boolean
}
```

***

## Exemple complet

```typescript theme={null}
const startTime = Date.now()

// ... l'utilisateur répond dans votre UI ...

const result = await dloopiq.completeTask({
  taskId: task.taskId,
  userId: 'user_abc123',
  answer: 'Positif',
  timeSpentMs: Date.now() - startTime
})

if (result.status === 'already_responded') {
  console.log('Cet utilisateur a déjà répondu à cette tâche')
  return
}

if (result.isGolden) {
  // Ne pas afficher de gain — earnedCents vaut 0 pour les golden tasks
  console.log('Merci pour votre réponse !')
} else {
  console.log(`Vous avez gagné ${result.earnedCents}¢ !`)
}
```

***

## Anti-doublon

Un utilisateur ne peut répondre qu'**une seule fois** à la même tâche. Si `completeTask` est appelé deux fois avec le même `taskId` + `userId`, la seconde réponse retourne :

```json theme={null}
{
  "status": "already_responded",
  "earnedCents": 0,
  "isGolden": false
}
```

***

## Comportement selon le type de tâche

### Tâche standard

* La réponse est ajoutée au pool de réponses
* L'algorithme de consensus est déclenché si `validationsNeeded` réponses sont collectées
* `earnedCents` = part développeur (environ 6¢ par tâche)

### Golden task

* La réponse est comparée à `goldenAnswer`
* Si correcte : score réputation `+1`
* Si incorrecte : score réputation `-3`
* `earnedCents` est toujours `0`
* `isGolden` est toujours `true`

<Tip>
  L'utilisateur ne sait pas s'il répond à une golden task. Gardez le même affichage pour préserver l'effet de mesure.
</Tip>

***

## Calcul des gains

```
earnedCents = floor(task.maxCents × 0.30)
```

Pour une tâche à `maxCents: 20` → `earnedCents: 6`.

Les gains sont cumulés côté développeur et accessibles via `getEarnings()`. Un virement est possible dès 1 000¢ (\$10) accumulés.

***

## Gestion d'erreurs

```typescript theme={null}
try {
  const result = await dloopiq.completeTask({
    taskId: 'inexistant',
    userId: 'user_123',
    answer: 'Positif',
    timeSpentMs: 2000
  })
} catch (err) {
  // TASK_NOT_FOUND → taskId invalide
  // INVALID_ANSWER → answer non présent dans task.options
  // RATE_LIMITED → trop de requêtes
  console.error(err.message)
}
```
