Repair project layout and fix Lab024B spectrum detection

This commit is contained in:
LittleSam129
2026-07-21 13:51:41 +03:00
parent acf7a76546
commit 1ff04b12b9
108 changed files with 8270 additions and 8221 deletions

View File

@@ -0,0 +1,254 @@
"""
Lab005. Передача пакетов через виртуальный радиоканал.
Эксперимент:
1. Формируем 100 цифровых пакетов.
2. Передаём их через виртуальный канал.
3. Канал может:
- полностью потерять пакет;
- изменить отдельные биты.
4. Приёмник проверяет структуру пакета и CRC-32.
5. Выводится статистика доставки.
"""
import random
from protocol.packet import (
CRCError,
MESSAGE_TYPE_TEXT,
PacketError,
build_packet,
parse_packet,
)
from tools.virtual_channel import transmit
# ============================================================
# Настройки эксперимента
# ============================================================
# Количество передаваемых пакетов.
PACKET_COUNT = 100
# Вероятность полной потери одного пакета.
#
# 0.10 означает 10 %.
DROP_PROBABILITY = 0.10
# Вероятность повреждения каждого отдельного бита.
#
# 0.002 означает:
# 0,2 % вероятности ошибки для каждого бита.
BIT_ERROR_PROBABILITY = 0.002
# Генератор случайных чисел.
#
# Число 2026 позволяет получать одинаковый результат
# при каждом запуске программы.
random_generator = random.Random(2026)
# ============================================================
# Счётчики результатов
# ============================================================
sent_packets = 0
# Пакеты, полностью исчезнувшие в канале.
dropped_packets = 0
# Доставленные, но повреждённые пакеты.
rejected_packets = 0
# Пакеты, правильно принятые и разобранные.
received_ok = 0
# Общее количество изменённых битов.
total_flipped_bits = 0
# ============================================================
# Передача серии пакетов
# ============================================================
for sequence_number in range(PACKET_COUNT):
# Создаём уникальное сообщение для каждого пакета.
message = f"ПАКЕТ {sequence_number}"
# Текст превращается в байты UTF-8.
payload = message.encode("utf-8")
# Формируем полный пакет с заголовком и CRC-32.
packet = build_packet(
payload=payload,
message_type=MESSAGE_TYPE_TEXT,
sequence_number=sequence_number,
)
sent_packets += 1
# Передаём пакет через виртуальный канал.
received_packet, flipped_bits = transmit(
packet=packet,
drop_probability=DROP_PROBABILITY,
bit_error_probability=BIT_ERROR_PROBABILITY,
random_generator=random_generator,
)
total_flipped_bits += flipped_bits
# None означает, что пакет полностью потерян.
if received_packet is None:
dropped_packets += 1
continue
# Пытаемся разобрать принятый пакет.
try:
parsed_packet = parse_packet(received_packet)
except (CRCError, PacketError):
# CRCError:
# контрольная сумма не совпала.
#
# PacketError:
# повреждены SYNC, версия, длина
# или другая часть структуры.
rejected_packets += 1
continue
# Восстанавливаем текст из полезной нагрузки.
restored_message = parsed_packet.payload.decode("utf-8")
# Проверяем, что получен именно тот пакет,
# который был передан.
assert parsed_packet.sequence_number == sequence_number
assert restored_message == message
received_ok += 1
# ============================================================
# Вывод настроек
# ============================================================
print("=== Lab005. Виртуальный канал ===")
print("\nНастройки эксперимента:")
print(
"Количество пакетов:",
PACKET_COUNT,
)
print(
"Вероятность полной потери пакета:",
DROP_PROBABILITY,
)
print(
"Вероятность ошибки отдельного бита:",
BIT_ERROR_PROBABILITY,
)
# ============================================================
# Вывод результатов
# ============================================================
print("\nРезультаты:")
print(
"Передано пакетов:",
sent_packets,
)
print(
"Потеряно полностью:",
dropped_packets,
)
print(
"Отклонено из-за повреждений:",
rejected_packets,
)
print(
"Принято правильно:",
received_ok,
)
print(
"Всего изменено битов:",
total_flipped_bits,
)
# ============================================================
# Расчёт процентов
# ============================================================
delivery_rate = (
received_ok
/ sent_packets
* 100
)
drop_rate = (
dropped_packets
/ sent_packets
* 100
)
rejection_rate = (
rejected_packets
/ sent_packets
* 100
)
packet_failure_rate = (
dropped_packets
+ rejected_packets
) / sent_packets * 100
print("\nСтатистика:")
print(
f"Успешно доставлено: "
f"{delivery_rate:.1f} %"
)
print(
f"Потеряно полностью: "
f"{drop_rate:.1f} %"
)
print(
f"Отклонено приёмником: "
f"{rejection_rate:.1f} %"
)
print(
f"Общая доля недоставленных пакетов: "
f"{packet_failure_rate:.1f} %"
)
# ============================================================
# Контроль правильности
# ============================================================
accounted_packets = (
received_ok
+ dropped_packets
+ rejected_packets
)
assert accounted_packets == sent_packets
print(
"\nПроверка пройдена: "
"все переданные пакеты учтены."
)