# Бъг: Гостенска карта отваря всички стаи

**Файл:** `src/main.cpp`, функция `checkOfflineCardAccess()`
**Редове:** ~2830–2868

---

## Описание на проблема

Проверката на стаята за гостенски карти (`user_type == 0`) е закоментирана.
В момента фърмуерът проверява само дали `room != 0`, но **не** сравнява стаята
от картата (`card_block1[2-3]`) с конфигурираната стая на вратата (`config.room`).

**Резултат:** Карта за стая 3614 отваря врата на стая 3414 (и всяка друга стая в хотела).

---

## Засегнат код

```cpp
// USER CARD
if (user_type == 0)
{
    if (room == 0)
    {
        error_late = "Guests must have a room!";
        return 0;
    }
    // TODO: виж docs/bugfix-room-access.md
    // else if (room != config.room)   <-- ЗАКОМЕНТИРАНО — тук е проблемът
    // {
    //   if (!groupAcces(group))
    //   {
    //     error_late = "Wrong group!";
    //     return 0;
    //   }
    // }
    else if (c_guest_count < config.guest_count)   // <-- else-if е прикачен към if (room == 0)
    {
        error_late = "Expired guest counter!";
        return 0;
    }
    ...
}
```

---

## Сценарий на грешката

| Стъпка | Стойност |
|--------|----------|
| Стая на картата (`room`) | 3614 |
| Стая на вратата (`config.room`) | 3414 |
| `room == 0`? | НЕ → не се блокира |
| `room != config.room`? | ДА, но проверката е закоментирана |
| Резултат | Картата **отваря** вратата |

---

## Решение

Разкоментирай блока `else if (room != config.room)` и преструктурирай `else-if` веригата:

```cpp
if (user_type == 0)
{
    if (room == 0)
    {
        Serial << "Guests must have a room!" << endl;
        error_late = "Guests must have a room!";
        return 0;
    }
    else if (room != config.room)
    {
        Serial << "Wrong room! In card " << room << " vs door " << config.room << endl;
        // Позволява group достъп (напр. cleaning staff с гостенска карта)
        if (!groupAcces(group))
        {
            Serial << "Wrong room!" << endl;
            error_late = "Wrong room!";
            return 0;
        }
        else
        {
            Serial << "Group access for user!" << endl;
        }
    }
    else if (c_guest_count < config.guest_count)
    {
        Serial << "Expired guest counter " << c_guest_count << "! New is:" << config.guest_count << endl;
        error_late = "Expired guest counter!";
        return 0;
    }
    else if (c_guest_count > config.guest_count)
    {
        config.guest_count = c_guest_count;
        Serial << "Update guest count!" << endl;
        saveConfiguration();
    }
}
```

### Важни детайли при промяната

1. **Counter проверката** (`c_guest_count`) трябва да остане в последния `else` клон —
   тя важи само когато стаите съвпадат. При group достъп counter-ът не се проверява.

2. **`groupAcces(group)`** проверява `(group & config.group) > 0` (битова AND операция).
   Картата трябва да има ненулев group (`group != 0`), иначе `groupAcces` връща `false`.

3. **Тест след промяната** — провери следните сценарии:
   - Карта за правилната стая → отваря
   - Карта за грешна стая, без group → не отваря
   - Карта за грешна стая, с валиден group → отваря (cleaning staff)
   - Карта с `room == 0` → не отваря
   - Изтекъл counter → не отваря

---

## Структура на card_block1 (след декриптиране)

| Байтове | Съдържание |
|---------|------------|
| [0–1]   | `hotel_code` (uint16) |
| [2–3]   | `room` (uint16) — стая от картата |
| [4–10]  | допълнителни данни |
| [11]    | `user_type`: `0` = гост, `255` = персонал/мастер |
| [12–15] | UID на картата (clone check) |

---

## Свързани типове карти

| `user_type` | `group` | Тип | Проверка |
|-------------|---------|-----|----------|
| `0` | всякакъв | Гост | room + counter (**след fix**) |
| `255` | `0` | Глобален мастер | само master_count |
| `255` | `!= 0` | Персонал | само group (битова маска) |
