# Індыкатары настрою

> GET /3/movie/{movie_id}/moods і GET /3/tv/{tv_id}/moods вяртаюць source і спіс results. Кожны вынік мае назву настрою, напрыклад fear або humor, сярэдняе avg па шкале ад 0 да 10 і значэнні, на якіх яно заснавана. Дадайце append_to_response=moods да выкліку дэталяў, каб далучыць індыкатары без другога запыту.

## Эндпоінт

`GET /3/movie/{movie_id}/moods`

```bash
curl "https://api.amodb.dev/3/movie/155/moods" \
  -H "Authorization: Bearer $AMODB_KEY"
```

Адказ:

```json
{
  "id": 155,
  "source": "measured",
  "results": [
    {
      "name": "action",
      "avg": 3.9,
      "values": [
        3.6,
        3.4,
        4.2
      ]
    },
    {
      "name": "fear",
      "avg": 5.2,
      "values": [
        3.6,
        6,
        4.8
      ]
    },
    {
      "name": "humor",
      "avg": 0.9,
      "values": [
        2.4,
        1.8,
        0.4
      ]
    }
  ]
}
```

## Атрыманне індыкатараў настрою фільма

`GET /3/movie/{movie_id}/moods` вяртае індыкатары настрою аднаго фільма. Індыкатар настрою складаецца з назвы і сярэдняга значэння па шкале ад 0 да 10. Адказ утрымлівае `id` фільма, `source` і масіў `results`. Кожны вынік мае `name`, `avg` і `values`.

У прыкладзе загружаюцца індыкатары фільма The Dark Knight (id 155) і друкуюцца ад найсільнейшага да найслабейшага.

```bash
curl -sf "https://api.amodb.dev/3/movie/155/moods" \
  -H "Authorization: Bearer $AMODB_KEY"
```

```js
const res = await fetch('https://api.amodb.dev/3/movie/155/moods', {
  headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` },
});
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const { source, results } = await res.json();
console.log('source:', source);
for (const m of [...results].sort((a, b) => b.avg - a.avg)) {
  console.log(m.name.padEnd(10), m.avg);
}
```

```python
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/movie/155/moods",
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
data = r.json()
print("source:", data.get("source"))
for m in sorted(data["results"], key=lambda m: m["avg"], reverse=True):
    print(f"{m['name']:<10} {m['avg']}")
```

```php
<?php
$ch = curl_init('https://api.amodb.dev/3/movie/155/moods');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 10,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('AMODB_KEY')],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
    throw new RuntimeException("amodb returned $status");
}
$data = json_decode($body, true);
echo 'source: ', $data['source'] ?? 'none', PHP_EOL;
$results = $data['results'];
usort($results, fn ($a, $b) => $b['avg'] <=> $a['avg']);
foreach ($results as $m) {
    printf("%-10s %.1f\n", $m['name'], $m['avg']);
}
```

```go
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"sort"
	"time"
)

type Mood struct {
	Name   string    `json:"name"`
	Avg    float64   `json:"avg"`
	Values []float64 `json:"values"`
}

func main() {
	req, _ := http.NewRequest("GET", "https://api.amodb.dev/3/movie/155/moods", nil)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("AMODB_KEY"))
	client := &http.Client{Timeout: 10 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		panic(res.Status)
	}
	var body struct {
		Source  string `json:"source"`
		Results []Mood `json:"results"`
	}
	if err := json.NewDecoder(res.Body).Decode(&body); err != nil {
		panic(err)
	}
	fmt.Println("source:", body.Source)
	sort.Slice(body.Results, func(i, j int) bool { return body.Results[i].Avg > body.Results[j].Avg })
	for _, m := range body.Results {
		fmt.Printf("%-10s %.1f\n", m.Name, m.Avg)
	}
}
```

### Параметры

| Параметр   | Дзе   | Абавязковы   | Апісанне                                                             |
| ---------- | ----- | ------------ | -------------------------------------------------------------------- |
| `movie_id` | шлях  | так          | Лікавы id фільма, напрыклад `155`.                                   |
| `api_key`  | запыт | адзін з двух | Ваш ключ. Выкарыстоўвайце яго або загаловак `Authorization: Bearer`. |

### Палі адказу

| Поле               | Тып            | Заўвагі                                                                                                  |
| ------------------ | -------------- | -------------------------------------------------------------------------------------------------------- |
| `id`               | цэлы лік       | Id фільма.                                                                                               |
| `source`           | радок або null | `measured` для даных гледачоў, `estimated`, калі вылічана па жанрах, `null`, калі даных пра назву няма.  |
| `results`          | масіў          | Індыкатары настрою, адсартаваныя па `name`. Пусты, калі нічога невядома.                                 |
| `results[].name`   | радок          | Кароткае слова малымі літарамі, напрыклад `fear`.                                                        |
| `results[].avg`    | лік            | Сярэдняе па шкале ад 0 да 10. Адзін знак пасля коскі для вымераных назваў, цэлы лік для ацэначных.       |
| `results[].values` | масіў лікаў    | Да 24 значэнняў на той жа шкале ад 0 да 10. Сярод вымераных назваў, якія мы бачылі, іх 6, у ацэначных 5. |

Сёння сустракаюцца назвы `action`, `fear`, `humor`, `pace`, `profanity`, `romance`, `sadness`, `sex` і `violence`. Не ў кожнай назвы ёсць усе дзевяць, таму адлюстроўвайце назвы з даных, а не з фіксаванага спісу.

### Прыклад адказу

```json
{
  "id": 155,
  "source": "measured",
  "results": [
    { "name": "action", "avg": 3.9, "values": [3.6, 3.4, 4.2, 4.2, 4.8, 3] },
    { "name": "fear", "avg": 5.2, "values": [3.6, 6, 4.8, 6.4, 6.4, 3.8] },
    { "name": "humor", "avg": 0.9, "values": [2.4, 1.8, 0.4, 0.4, 0, 0.5] }
  ]
}
```

Спіс скарочаны да 3 з 9 вынікаў.

### Вымераныя і ацэначныя назвы

Fight Club (id 550) пакуль не мае даных гледачоў, таму яго індыкатары вылічаны па жанрах. Кожнае `avg` з’яўляецца цэлым лікам, а `values` мае 5 запісаў.

```json
{
  "id": 550,
  "source": "estimated",
  "results": [
    { "name": "action", "avg": 4, "values": [3, 4, 5, 4, 3] },
    { "name": "fear", "avg": 7, "values": [6, 7, 8, 7, 6] }
  ]
}
```

Правярайце `source`, калі хочаце апрацоўваць ацэначныя індыкатары інакш, чым вымераныя.

## Атрыманне індыкатараў настрою серыяла

`GET /3/tv/{tv_id}/moods` мае такую ж форму адказу, з id серыяла ў `id`. Для Breaking Bad выкарыстоўвайце `1396`.

| Метад і шлях                  | Што вяртае                           | Параметры                              |
| ----------------------------- | ------------------------------------ | -------------------------------------- |
| `GET /movie/{movie_id}/moods` | `id`, `source` і `results`           | `movie_id`                             |
| `GET /tv/{tv_id}/moods`       | `id`, `source` і `results`           | `tv_id`                                |
| `append_to_response=moods`    | `source` і `results` у ключы `moods` | Дадаецца да дэталяў фільма або серыяла |

```bash
curl -sf "https://api.amodb.dev/3/tv/1396?append_to_response=moods" -H "Authorization: Bearer $AMODB_KEY"
```

Калі вы дадаяце `moods` да выкліку дэталяў, ключ `moods` знаходзіцца на верхнім узроўні запісу побач з `title` або `name`. Ён утрымлівае `source` і `results` і ўласнага `id` не мае. Гэта каштуе адзін запыт, а два асобныя выклікі каштуюць два.

## Як чытаць шкалу

Поле `avg` паказвае інтэнсіўнасць ад 0 да 10. Чым вышэй лік, тым мацнейшы настрой у назве.

| Дыяпазон    | Інтэрпрэтацыя                 |
| ----------- | ----------------------------- |
| ад 0 да 2.9 | Настрой слабы або адсутнічае. |
| ад 3 да 5.9 | Настрой прысутнічае.          |
| ад 6 да 7.9 | Настрой выразны.              |
| ад 8 да 10  | Настрой вызначае назву.       |

Гэтыя дыяпазоны служаць прапановай для вашага інтэрфейсу, а не полем у адказе. Масіў `values` змяшчае значэнні, з якіх складзена сярэдняе, на той жа шкале.

## Значкі і фільтры

Настроі добра пасуюць да трох распаўсюджаных шаблонаў інтэрфейсу. Падбярыце парогі пад свой каталог і наладзьце іх.

| Шаблон          | Правіла                                                     | Заўвагі                                                          |
| --------------- | ----------------------------------------------------------- | ---------------------------------------------------------------- |
| Значок          | Паказваць да 3 настрояў з `avg` 6 або вышэй                 | Спачатку адсартуйце па `avg`.                                    |
| Шкала-індыкатар | Задаць шырыню шкалы як `avg`, памножанае на 10, у працэнтах | Шкала ад 0 да 10.                                                |
| Чып-фільтр      | Выбіраць назвы, дзе абраны настрой роўны 7 або вышэй        | Атрымайце індыкатары па кожнай назве, потым фільтруйце лакальна. |

```js
function topMoods(results, min = 6, limit = 3) {
  return results
    .filter((m) => m.avg >= min)
    .sort((a, b) => b.avg - a.avg)
    .slice(0, limit)
    .map((m) => m.name);
}

function matchesMood(results, name, min = 7) {
  return results.some((m) => m.name === name && m.avg >= min);
}
```

Пусты масіў `results` трэба адлюстроўваць як адсутнасць значкоў, а не як памылку.

## Памылкі

Цела памылкі мае `success`, `status_code` і `status_message`, тыя ж палі, што ў TMDB.

| HTTP | status_code | Калі                                                                |
| ---- | ----------- | ------------------------------------------------------------------- |
| 401  | 7           | Ключ адсутнічае або няправільны.                                    |
| 402  | 36          | Тэрмін дзеяння плана скончыўся.                                     |
| 429  | 25          | Перавышаны ліміт запытаў у хвіліну. Пачакайце `Retry-After` секунд. |

Эндпоінт moods не адказвае 404 на невядомы id. Ён адказвае 200 з пустым масівам `results`, а `source` роўны `null` або адсутнічае. Пры дадаванні да дэталяў невядомы id дае 404 ад выкліку дэталяў. Поўны спіс ёсць на старонцы [памылкі](https://amodb.dev/be/errors/), а ліміты на старонцы [ліміты запытаў](https://amodb.dev/be/rate-limits/).

## Практычныя заўвагі

- Як і іншыя даныя дэталяў, індыкатары настрою кэшуюцца на edge на 6 гадзін. Больш частыя запыты вяртаюць тое ж цела.
- Для спісу з 20 назваў патрэбна 20 запытаў настрою. Калі вы ўжо выклікаеце дэталі для кожнай назвы, дадайце `moods` і зэканомце другі выклік.
- Правярайце `source`, перш чым параўноўваць назвы. Вымераныя і ацэначныя індыкатары выкарыстоўваюць адну шкалу, але не аднолькавую дакладнасць.
- Калі вы часта фільтруеце, захоўвайце `name` і `avg` разам з id назвы ў сваёй базе даных. Лакальны фільтр лепшы за запыт на кожную назву.
- Спалучайце індыкатары з [рэйтынгамі](https://amodb.dev/be/ratings/) для ацэнкі і з [саўндтрэкамі](https://amodb.dev/be/soundtracks/) для музыкі той жа назвы.

## Пытанні і адказы

### Што азначае значэнне настрою?

Поле avg паказвае інтэнсіўнасць па шкале ад 0 да 10, з адным знакам пасля коскі для вымераных назваў. Значэнне avg 7 для fear азначае, што назва страшная, а 0 азначае, што настрою няма. Гэта не працэнт і не ацэнка рэцэнзіі.

### Ці фіксаваны спіс назваў настрою?

Не лічыце яго такім. Сёння сустракаюцца action, fear, humor, pace, profanity, romance, sadness, sex і violence, а ў назвы іх можа быць менш за дзевяць. Паказвайце радкі назваў, якія атрымліваеце, каб новы настрой таксама з’явіўся.

### Што азначаюць measured і estimated у source?

Measured азначае, што індыкатары ўзяты з даных гледачоў і маюць дзесятковыя долі. Estimated азначае, што яны вылічаны па жанрах назвы, таму avg будзе цэлым лікам. Назва без даных мае пусты масіў results і source, роўны null.

### Як адфільтраваць спіс назваў па настроі?

Атрымайце індыкатары для кожнай назвы са спісу праз эндпоінт moods або праз append_to_response у дэталях і пакіньце назвы, дзе абраны настрой перавышае ваш парог. Фільтр працуе ў вашым кодзе.

### Ці ёсць настрой у серыялаў?

Так. Выкарыстоўвайце GET /3/tv/{tv_id}/moods, напрыклад з id серыяла 1396. Адказ мае тую ж форму, што і эндпоінт для фільмаў.

## Звязаныя старонкі

- [API дэталяў фільма](https://amodb.dev/be/movies/): API дэталяў фільма з тымі ж шляхамі і JSON, што ў TMDB v3. Адзін фільм па id, а акцёры, рэйтынгі і настрой праз append_to_response, на 14 мовах.
- [API серыялаў](https://amodb.dev/be/tv-series/): API серыялаў з тымі ж шляхамі і JSON, што ў TMDB v3. Серыял па id з сезонамі, тэлеканаламі і наступным эпізодам, плюс узроставыя рэйтынгі і сэрвісы прагляду.
- [Рэйтынгі фільмаў і серыялаў](https://amodb.dev/be/ratings/): API рэйтынгаў фільмаў вяртае ацэнкі IMDb, Kinopoisk, Metacritic, Rotten Tomatoes і TMDB для назвы адным выклікам, з null для крыніцы, якая невядомая.
- [Саўндтрэкі](https://amodb.dev/be/soundtracks/): API саўндтрэкаў вяртае альбом саўндтрэка фільма або серыяла са спісам трэкаў. Выклічце эндпоінт або дадайце append_to_response=soundtracks да дэталяў.
- [Discover API](https://amodb.dev/be/discover/): Discover API з фільтрамі TMDB v3. Спіс фільмаў і серыялаў па жанры, акцёрах, кампаніі, ключавым слове, годзе, рэйтынгу і працягласці з сартаваннем.
- [Хуткі старт](https://amodb.dev/be/quickstart/): Першы выклік да amodb: атрымайце ключ, запытайце дэталі фільма ў curl, JavaScript, Python, PHP або Go і загрузіце постэр з img.amodb.dev. Менш за 2 хвіліны.

Абноўлена: 2026-10-18. Source: https://amodb.dev/be/moods/
