2024 · transport · линия «учёба»

Транспортный справочник

Финальный проект курса C++: маршруты, JSON-запросы и SVG-карта.

status
архив
stack
C++17 · STL · JSON · SVG
since
2024

черновик · текст собрал Claude по репозиториям и заметкам, перепишу сам

Финальный проект курса C++, сентябрь–октябрь 2024 года.

Программа хранит остановки с координатами и автобусные маршруты и отвечает на запросы: сколько остановок на маршруте, какая у него длина, какие автобусы проходят через остановку. Длина считается по реальным дорожным расстояниям, и программа сравнивает её с расстоянием по прямой — получается «извилистость» маршрута.

Этапы

Сначала был текстовый ввод (он остался в репозитории cpp-bus-directory). Потом — дорожные расстояния. На последнем этапе ввод и вывод перешли на JSON, а по запросу Map программа рисует карту маршрутов в SVG: линии автобусов разными цветами, подписи маршрутов и остановок.

Внутри несколько модулей: каталог, JSON-библиотека, SVG-библиотека, рендерер карты и обработчик запросов. Остановки хранятся в std::deque, чтобы указатели на них не ломались при добавлении новых, а для расстояний между парами остановок есть свой хешер.

Код писал руками, и времени на рефакторинг не хватило — это видно. Оставляю проект как есть.

Фрагмент

Добавление маршрута: дорожная длина, длина по прямой и их отношение.

void TransportCatalogue::AddBus(std::string_view name, std::vector<std::string_view> route, bool is_roundtrip) {
    double fact_route_length = 0.0;
    double geo_route_length = 0.0;
    for (auto it = route.begin() + 1; it != route.end(); ++it) {
        auto prev_stop = stopname_to_stop_.find(*(it - 1));
        auto stop = stopname_to_stop_.find(*it);
        fact_route_length +=
            distance_between_stops_.count(std::make_pair(prev_stop->second, stop->second))
            ? distance_between_stops_.at(std::make_pair(prev_stop->second, stop->second))
            : distance_between_stops_.at(std::make_pair(stop->second, prev_stop->second));
        geo_route_length += ComputeDistance(prev_stop->second->coordinates, stop->second->coordinates);
    }
    double route_curvature = fact_route_length / geo_route_length;
    buses_.emplace_back(Bus{std::string(name), {}, fact_route_length, route_curvature, is_roundtrip});
    for (const auto& stop_name : route) {
        buses_.back().route.push_back(stopname_to_stop_.at(std::string(stop_name)));
    }
    busname_to_bus_[buses_.back().name] = &buses_.back();
}