# Расписания

Интеграция расписаний аэропортов: табло вылетов и прилётов с историческими и ближайшими будущими временными окнами.



Готовые к запуску примеры табло вылетов и прилётов аэропорта с использованием эндпоинта [Расписания](/docs/v31/schedules). Охватывают табло одного аэропорта, аналитику задержек и сравнение трафика бок о бок.

| # | Вопрос                                                | Используемые данные           |
| - | ----------------------------------------------------- | ----------------------------- |
| 1 | Показать ближайшие сегодняшние вылеты из KJFK         | Расписания (вылеты)           |
| 2 | Сколько рейсов задержано или отменено в EGLL сегодня? | Расписания (вылеты)           |
| 3 | Сравнение числа прилётов и вылетов в KJFK бок о бок   | Расписания (прилёты + вылеты) |

<DocRequirements>
  <DocRequirementAuth />
</DocRequirements>

### Установка [#install]

Приведённые ниже скрипты используют `requests` для вызовов API и `rich` для вывода в терминал. Установите один раз:

```bash
pip install requests rich
```

***

### 1. Сегодняшние вылеты из KJFK [#1-todays-departures-from-kjfk]

**Вопрос:** показать ближайшие сегодняшние вылеты из KJFK.

Ключи строк рейсов пишутся с заглавной буквы: `Flight`, `Time`, `Status`, `Airline`, `Airport`. Ключи в нижнем регистре возвращают `None`.

```python
import os

import requests
from rich.console import Console
from rich.table import Table

console = Console()

HEADERS = {
    "X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
    "X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"

STATUS_STYLE: dict[str, str] = {
    "Departed": "green",
    "Delayed": "yellow",
    "Cancelled": "red",
    "Scheduled": "white",
    "Arrived": "green",
}


def fetch_departures(icao: str) -> list[dict]:
    r = requests.get(
        f"{BASE}/schedules/departures",
        headers=HEADERS,
        params={"icao": icao},
        timeout=(10, 15),
    )
    if r.status_code == 404:
        return []
    r.raise_for_status()
    return r.json().get("flights", [])


def main() -> None:
    flights = fetch_departures("KJFK")
    if not flights:
        console.print("[yellow]No departure data returned for KJFK.[/]")
        return

    display = flights[:10]

    table = Table(title=f"KJFK Departures — showing {len(display)} of {len(flights)}")
    table.add_column("Flight", style="cyan")
    table.add_column("Airline")
    table.add_column("Destination")
    table.add_column("Time")
    table.add_column("Status")

    for f in display:
        status = f.get("Status", "—")
        style = STATUS_STYLE.get(status, "white")
        table.add_row(
            f.get("Flight", "—"),
            f.get("Airline", "—"),
            f.get("Airport", "—"),
            f.get("Time", "—"),
            f"[{style}]{status}[/]",
        )

    console.print(table)


if __name__ == "__main__":
    main()
```

**Результат:** таблица до 10 вылетов с номером рейса, авиакомпанией, кодом аэропорта назначения, временем по расписанию и статусом с цветовой маркировкой (зелёный = Departed, жёлтый = Delayed, красный = Cancelled).

***

### 2. Сводка задержек и отмен в EGLL [#2-delay-and-cancellation-summary-at-egll]

**Вопрос:** сколько рейсов в EGLL сегодня сейчас задержано или отменено?

```python
import os

import requests
from rich.console import Console
from rich.panel import Panel
from rich.table import Table

console = Console()

HEADERS = {
    "X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
    "X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"


def fetch_departures(icao: str) -> list[dict]:
    r = requests.get(
        f"{BASE}/schedules/departures",
        headers=HEADERS,
        params={"icao": icao},
        timeout=(10, 15),
    )
    if r.status_code == 404:
        return []
    r.raise_for_status()
    return r.json().get("flights", [])


def main() -> None:
    flights = fetch_departures("EGLL")
    if not flights:
        console.print("[yellow]No departure data returned for EGLL.[/]")
        return

    delayed = [f for f in flights if f.get("Status") == "Delayed"]
    cancelled = [f for f in flights if f.get("Status") == "Cancelled"]
    on_time = len(flights) - len(delayed) - len(cancelled)

    summary = (
        f"Total departures: [bold]{len(flights)}[/]\n"
        f"On time / departed: [green]{on_time}[/]\n"
        f"Delayed: [yellow]{len(delayed)}[/]\n"
        f"Cancelled: [red]{len(cancelled)}[/]"
    )
    console.print(Panel(summary, title="EGLL Departure Summary"))

    if delayed or cancelled:
        table = Table(title="Delayed and Cancelled Flights")
        table.add_column("Flight", style="cyan")
        table.add_column("Airline")
        table.add_column("Time")
        table.add_column("Status")

        for f in delayed:
            table.add_row(
                f.get("Flight", "—"),
                f.get("Airline", "—"),
                f.get("Time", "—"),
                "[yellow]Delayed[/]",
            )
        for f in cancelled:
            table.add_row(
                f.get("Flight", "—"),
                f.get("Airline", "—"),
                f.get("Time", "—"),
                "[red]Cancelled[/]",
            )

        console.print(table)


if __name__ == "__main__":
    main()
```

**Результат:** сводная панель с общим числом рейсов, числом рейсов по расписанию, задержанных и отменённых, а затем таблица со всеми затронутыми рейсами: авиакомпания, время и статус.

***

### 3. Прилёты и вылеты в KJFK бок о бок [#3-side-by-side-arrivals-and-departures-at-kjfk]

**Вопрос:** как соотносятся общее число прилётов и вылетов в KJFK сегодня, включая число нарушений графика?

Скрипт запрашивает оба направления параллельно, чтобы сократить общее время выполнения.

```python
import os
import concurrent.futures

import requests
from rich.console import Console
from rich.table import Table

console = Console()

HEADERS = {
    "X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
    "X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"


def fetch_schedule(icao: str, direction: str) -> list[dict]:
    r = requests.get(
        f"{BASE}/schedules/{direction}",
        headers=HEADERS,
        params={"icao": icao},
        timeout=(10, 15),
    )
    if r.status_code == 404:
        return []
    r.raise_for_status()
    return r.json().get("flights", [])


def summarize(flights: list[dict]) -> dict[str, int]:
    delayed = sum(1 for f in flights if f.get("Status") == "Delayed")
    cancelled = sum(1 for f in flights if f.get("Status") == "Cancelled")
    return {
        "total": len(flights),
        "delayed": delayed,
        "cancelled": cancelled,
        "on_time": len(flights) - delayed - cancelled,
    }


def main() -> None:
    with concurrent.futures.ThreadPoolExecutor(max_workers=2) as ex:
        fut_arr = ex.submit(fetch_schedule, "KJFK", "arrivals")
        fut_dep = ex.submit(fetch_schedule, "KJFK", "departures")
        arrivals = fut_arr.result()
        departures = fut_dep.result()

    arr_stats = summarize(arrivals)
    dep_stats = summarize(departures)

    table = Table(title="KJFK Traffic Summary — Today")
    table.add_column("Direction", style="cyan")
    table.add_column("Total", justify="right")
    table.add_column("Delayed", justify="right")
    table.add_column("Cancelled", justify="right")
    table.add_column("On Time", justify="right")

    table.add_row(
        "Arrivals",
        str(arr_stats["total"]),
        f"[yellow]{arr_stats['delayed']}[/]",
        f"[red]{arr_stats['cancelled']}[/]",
        f"[green]{arr_stats['on_time']}[/]",
    )
    table.add_row(
        "Departures",
        str(dep_stats["total"]),
        f"[yellow]{dep_stats['delayed']}[/]",
        f"[red]{dep_stats['cancelled']}[/]",
        f"[green]{dep_stats['on_time']}[/]",
    )

    console.print(table)


if __name__ == "__main__":
    main()
```

**Результат:** таблица из двух строк, сравнивающая прилёты и вылеты в KJFK: общее число рейсов, число задержанных, отменённых и выполненных по расписанию рейсов бок о бок.
