Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -----------------------------------------------------------------------
- domain.h
- -----------------------------------------------------------------------
- #pragma once
- #include <algorithm>
- #include <vector>
- #include <string>
- #include "geo.h"
- namespace domain {
- struct StatRequest {
- int id;
- std::string type;
- std::string name;
- };
- struct Bus;
- struct Stop {
- std::string name;
- double latitude;
- double longitude;
- std::vector<Bus*> buses;
- };
- struct Bus {
- std::string name;
- std::vector<Stop*> stops;
- bool is_roundtrip;
- size_t route_length;
- };
- struct Distance {
- const Stop* start;
- const Stop* end;
- int distance;
- };
- struct BusQueryResult {
- std::string_view name;
- bool not_found;
- int stops_on_route;
- int unique_stops;
- int route_length;
- double curvature;
- };
- struct StopQueryResult {
- std::string_view name;
- bool not_found;
- std::vector <std::string> buses_name;
- };
- }//end namespace domain
- -----------------------------------------------------------------------
- domain.cpp
- -----------------------------------------------------------------------
- empty
- -----------------------------------------------------------------------
- geo.h
- -----------------------------------------------------------------------
- #pragma once
- #include <cmath>
- namespace geo {
- const int EARTH_RADIUS = 6371000;
- const double PI = 3.1415926535;
- struct Coordinates {
- double latitude;
- double longitude;
- bool operator==(const Coordinates& other) const {
- return latitude == other.latitude && longitude == other.longitude;
- }
- bool operator!=(const Coordinates& other) const {
- return !(*this == other);
- }
- };
- double compute_distance(Coordinates start, Coordinates end);
- }//end namespace geo
- -----------------------------------------------------------------------
- geo.cpp
- -----------------------------------------------------------------------
- #define _USE_MATH_DEFINES
- #include "geo.h"
- #include <cmath>
- namespace geo {
- double compute_distance(Coordinates start, Coordinates end) {
- using namespace std;
- if (!(start == end)) {
- const double dr = PI / 180.;
- return acos(sin(start.latitude * dr) * sin(end.latitude * dr)
- + cos(start.latitude * dr) * cos(end.latitude * dr)
- * cos(abs(start.longitude - end.longitude) * dr)) * EARTH_RADIUS;
- } else {
- return 0.0;
- }
- }
- }//end namespace geo
- -----------------------------------------------------------------------
- json.h
- -----------------------------------------------------------------------
- #pragma once
- #include <iostream>
- #include <map>
- #include <string>
- #include <vector>
- #include <variant>
- namespace transport_catalogue {
- namespace detail {
- namespace json {
- class Node;
- using Dict = std::map<std::string, Node>;
- using Array = std::vector<Node>;
- class ParsingError : public std::runtime_error {
- public:
- using runtime_error::runtime_error;
- };
- class Node {
- public:
- using Value = std::variant<std::nullptr_t, Array, Dict, bool, int, double, std::string>;
- Node() = default;
- Node(bool value);
- Node(Array array);
- Node(Dict map);
- Node(int value);
- Node(std::string value);
- Node(std::nullptr_t);
- Node(double value);
- const Array& as_array() const;
- const Dict& as_map() const;
- int as_int() const;
- double as_double() const;
- bool as_bool() const;
- const std::string& as_string() const;
- bool is_null() const;
- bool is_int() const;
- bool is_double() const;
- bool is_real_double() const;
- bool is_bool() const;
- bool is_string() const;
- bool is_array() const;
- bool is_map() const;
- const Value& get_value() const;
- private:
- Value value_;
- };
- inline bool operator==(const Node& lhs, const Node& rhs) {
- return lhs.get_value() == rhs.get_value();
- }
- inline bool operator!=(const Node& lhs, const Node& rhs) {
- return !(lhs == rhs);
- }
- class Document {
- public:
- Document() = default;
- explicit Document(Node root);
- const Node& get_root() const;
- private:
- Node root_;
- };
- inline bool operator==(const Document& lhs, const Document& rhs) {
- return lhs.get_root() == rhs.get_root();
- }
- inline bool operator!=(const Document& lhs, const Document& rhs) {
- return !(lhs == rhs);
- }
- Document load(std::istream& input);
- void print(const Document& document, std::ostream& output);
- }//end namespace json
- }//end namespace detail
- }//end namespace transport_catalogue
- -----------------------------------------------------------------------
- json.cpp
- -----------------------------------------------------------------------
- #include "json.h"
- using namespace std;
- namespace transport_catalogue {
- namespace detail {
- namespace json {
- namespace {
- Node load_node(istream& input);
- std::string load_literal(std::istream& input) {
- std::string str;
- while (std::isalpha(input.peek())) {
- str.push_back(static_cast<char>(input.get()));
- }
- return str;
- }
- Node load_array(std::istream& input) {
- std::vector<Node> array;
- for (char ch; input >> ch && ch != ']';) {
- if (ch != ',') {
- input.putback(ch);
- }
- array.push_back(load_node(input));
- }
- if (!input) {
- throw ParsingError("unable to parse array"s);
- }
- return Node(array);
- }
- Node load_null(std::istream& input) {
- if (auto literal = load_literal(input); literal == "null"sv) {
- return Node(nullptr);
- } else {
- throw ParsingError("unable to parse '"s + literal + "' as null"s);
- }
- }
- Node load_bool(std::istream& input) {
- const auto str = load_literal(input);
- if (str == "true"sv) {
- return Node(true);
- } else if (str == "false"sv) {
- return Node(false);
- } else {
- throw ParsingError("unable to parse '"s + str + "' as bool"s);
- }
- }
- Node load_number(std::istream& input) {
- std::string number;
- auto read_char = [&number, &input] {
- number += static_cast<char>(input.get());
- if (!input) {
- throw ParsingError("unable to read number"s);
- }
- };
- auto read_digits = [&input, read_char] {
- if (!std::isdigit(input.peek())) {
- throw ParsingError("digit expected"s);
- } else {
- while (std::isdigit(input.peek())) {
- read_char();
- }
- }
- };
- if (input.peek() == '-') {
- read_char();
- }
- if (input.peek() == '0') {
- read_char();
- } else {
- read_digits();
- }
- bool is_int = true;
- if (input.peek() == '.') {
- read_char();
- read_digits();
- is_int = false;
- }
- if (int ch = input.peek(); ch == 'e' || ch == 'E') {
- read_char();
- if (ch = input.peek(); ch == '+' || ch == '-') {
- read_char();
- }
- read_digits();
- is_int = false;
- }
- try {
- if (is_int) {
- try {
- return Node(std::stoi(number));
- } catch (...) {}
- }
- return Node(std::stod(number));
- } catch (...) {
- throw ParsingError("unable to convert "s + number + " to number"s);
- }
- }
- Node load_string(std::istream& input) {
- auto it = std::istreambuf_iterator<char>(input);
- auto end = std::istreambuf_iterator<char>();
- std::string str;
- while (true) {
- if (it == end) {
- throw ParsingError("unable to parse string");
- }
- const char ch = *it;
- if (ch == '"') {
- ++it;
- break;
- } else if (ch == '\\') {
- ++it;
- if (it == end) {
- throw ParsingError("unable to parse string");
- }
- const char esc_ch = *(it);
- switch (esc_ch) {
- case 'n':
- str.push_back('\n');
- break;
- case 't':
- str.push_back('\t');
- break;
- case 'r':
- str.push_back('\r');
- break;
- case '"':
- str.push_back('"');
- break;
- case '\\':
- str.push_back('\\');
- break;
- default:
- throw ParsingError("invalid esc \\"s + esc_ch);
- }
- } else if (ch == '\n' || ch == '\r') {
- throw ParsingError("invalid line end"s);
- } else {
- str.push_back(ch);
- }
- ++it;
- }
- return Node(str);
- }
- Node load_dictionary(std::istream& input) {
- Dict dictionary;
- for (char ch; input >> ch && ch != '}';) {
- if (ch == '"') {
- std::string key = load_string(input).as_string();
- if (input >> ch && ch == ':') {
- if (dictionary.find(key) != dictionary.end()) {
- throw ParsingError("duplicate key '"s + key + "'found");
- }
- dictionary.emplace(std::move(key), load_node(input));
- } else {
- throw ParsingError(": expected. but '"s + ch + "' found"s);
- }
- } else if (ch != ',') {
- throw ParsingError("',' expected. but '"s + ch + "' found"s);
- }
- }
- if (!input) {
- throw ParsingError("unable to parse dictionary"s);
- } else {
- return Node(dictionary);
- }
- }
- Node load_node(std::istream& input) {
- char ch;
- if (!(input >> ch)) {
- throw ParsingError(""s);
- } else {
- switch (ch) {
- case '[':
- return load_array(input);
- case '{':
- return load_dictionary(input);
- case '"':
- return load_string(input);
- case 't': case 'f':
- input.putback(ch);
- return load_bool(input);
- case 'n':
- input.putback(ch);
- return load_null(input);
- default:
- input.putback(ch);
- return load_number(input);
- }
- }
- }
- }//end namespace
- Node::Node(Array array) : value_(std::move(array)) {}
- Node::Node(std::nullptr_t) : Node() {}
- Node::Node(bool value) : value_(value) {}
- Node::Node(Dict map) : value_(std::move(map)) {}
- Node::Node(int value) : value_(value) {}
- Node::Node(string value) : value_(std::move(value)) {}
- Node::Node(double value) : value_(value) {}
- const Array& Node::as_array() const {
- using namespace std::literals;
- if (!is_array()) {
- throw std::logic_error("value is not an array"s);
- } else {
- return std::get<Array>(value_);
- }
- }
- const Dict& Node::as_map() const {
- using namespace std::literals;
- if (!is_map()) {
- throw std::logic_error("value is not a dictionary"s);
- } else {
- return std::get<Dict>(value_);
- }
- }
- const std::string& Node::as_string() const {
- using namespace std::literals;
- if (!is_string()) {
- throw std::logic_error("value is not a string"s);
- } else {
- return std::get<std::string>(value_);
- }
- }
- int Node::as_int() const {
- using namespace std::literals;
- if (!is_int()) {
- throw std::logic_error("value is not an int"s);
- } else {
- return std::get<int>(value_);
- }
- }
- double Node::as_double() const {
- using namespace std::literals;
- if (!is_double()) {
- throw std::logic_error("value is not a double"s);
- } else if (is_real_double()) {
- return std::get<double>(value_);
- } else {
- return as_int();
- }
- }
- bool Node::as_bool() const {
- using namespace std::literals;
- if (!is_bool()) {
- throw std::logic_error("value is not a bool"s);
- } else {
- return std::get<bool>(value_);
- }
- }
- bool Node::is_null() const {return std::holds_alternative<std::nullptr_t>(value_);}
- bool Node::is_int() const {return std::holds_alternative<int>(value_);}
- bool Node::is_double() const {return is_real_double() || is_int();}
- bool Node::is_real_double() const {return std::holds_alternative<double>(value_);}
- bool Node::is_bool() const {return std::holds_alternative<bool>(value_);}
- bool Node::is_string() const {return std::holds_alternative<std::string>(value_);}
- bool Node::is_array() const {return std::holds_alternative<Array>(value_);}
- bool Node::is_map() const {return std::holds_alternative<Dict>(value_);}
- const Node::Value& Node::get_value() const {return value_;}
- Document::Document(Node root) : root_(std::move(root)) {}
- const Node& Document::get_root() const {return root_;}
- Document load(istream& input) {return Document(load_node(input));}
- struct PrintContext {
- std::ostream& out;
- int indent_step = 4;
- int indent = 0;
- void print_indent() const {
- for (int i = 0; i < indent; ++i) {
- out.put(' ');
- }
- }
- [[nodiscard]] PrintContext indented() const {
- return {out,
- indent_step,
- indent_step + indent};
- }
- };
- void print_node(const Node& node, const PrintContext& context);
- void print_string(const std::string& value, std::ostream& out) {
- out.put('"');
- for (const char ch : value) {
- switch (ch) {
- case '\r':
- out << R"(\r)";
- break;
- case '\n':
- out << R"(\n)";
- break;
- case '"':
- out << R"(\")";
- break;
- case '\\':
- out << R"(\\)";
- break;
- default:
- out.put(ch);
- break;
- }
- }
- out.put('"');
- }
- template <typename Value>
- void print_value(const Value& value, const PrintContext& context) {
- context.out << value;
- }
- template <>
- void print_value<std::string>(const std::string& value, const PrintContext& context) {
- print_string(value, context.out);
- }
- void print_value(const std::nullptr_t&, const PrintContext& context) {
- context.out << "null"s;
- }
- void print_value(bool value, const PrintContext& context) {
- context.out << std::boolalpha << value;
- }
- [[maybe_unused]] void print_value(Array nodes, const PrintContext& context) {
- std::ostream& out = context.out;
- out << "[\n"sv;
- bool first = true;
- auto inner_context = context.indented();
- for (const Node& node : nodes) {
- if (first) {
- first = false;
- } else {
- out << ",\n"sv;
- }
- inner_context.print_indent();
- print_node(node, inner_context);
- }
- out.put('\n');
- context.print_indent();
- out.put(']');
- }
- [[maybe_unused]] void print_value(Dict nodes, const PrintContext& context) {
- std::ostream& out = context.out;
- out << "{\n"sv;
- bool first = true;
- auto inner_context = context.indented();
- for (const auto& [key, node] : nodes) {
- if (first) {
- first = false;
- } else {
- out << ",\n"sv;
- }
- inner_context.print_indent();
- print_string(key, context.out);
- out << ": "sv;
- print_node(node, inner_context);
- }
- out.put('\n');
- context.print_indent();
- out.put('}');
- }
- void print_node(const Node& node, const PrintContext& context) {
- std::visit([&context](const auto& value) {
- print_value(value, context);
- }, node.get_value());
- }
- void print(const Document& document, std::ostream& output) {
- print_node(document.get_root(), PrintContext{output});
- }
- }//end namespace json
- }//end namespace detail
- }//end namespace transport_catalogue
- -----------------------------------------------------------------------
- json_reader.h
- -----------------------------------------------------------------------
- #pragma once
- #include "json.h"
- #include "transport_catalogue.h"
- #include "map_renderer.h"
- namespace transport_catalogue {
- namespace detail {
- namespace json {
- class JSONReader{
- public:
- JSONReader() = default;
- JSONReader(Document doc);
- JSONReader(std::istream& input);
- void parse_node_base(const Node& root, TransportCatalogue& catalogue);
- void parse_node_stat(const Node& root, std::vector<StatRequest>& stat_request);
- void parse_node_render(const Node& node, map_renderer::RenderSettings& render_settings);
- void parse_node(const Node& root, TransportCatalogue& catalogue, std::vector<StatRequest>& stat_request, map_renderer::RenderSettings& render_settings);
- void parse(TransportCatalogue& catalogue, std::vector<StatRequest>& stat_request, map_renderer::RenderSettings& render_settings);
- Stop parse_node_stop(Node& node);
- Bus parse_node_bus(Node& node, TransportCatalogue& catalogue);
- std::vector<Distance> parse_node_distances(Node& node, TransportCatalogue& catalogue);
- const Document& get_document() const;
- private:
- Document document_;
- };
- }//end namespace json
- }//end namespace detail
- }//end namespace transport_catalogue
- -----------------------------------------------------------------------
- json_reader.cpp
- -----------------------------------------------------------------------
- #include "json_reader.h"
- namespace transport_catalogue {
- namespace detail {
- namespace json {
- JSONReader::JSONReader(Document doc) : document_(std::move(doc)) {}
- JSONReader::JSONReader(std::istream& input) : document_(json::load(input)) {}
- Stop JSONReader::parse_node_stop(Node& node) {
- Stop stop;
- Dict stop_node;
- if (node.is_map()) {
- stop_node = node.as_map();
- stop.name = stop_node.at("name").as_string();
- stop.latitude = stop_node.at("latitude").as_double();
- stop.longitude = stop_node.at("longitude").as_double();
- }
- return stop;
- }
- std::vector<Distance> JSONReader::parse_node_distances(Node& node, TransportCatalogue& catalogue) {
- std::vector<Distance> distances;
- Dict stop_node;
- Dict stop_road_map;
- std::string begin_name;
- std::string last_name;
- int distance;
- if (node.is_map()) {
- stop_node = node.as_map();
- begin_name = stop_node.at("name").as_string();
- try {
- stop_road_map = stop_node.at("road_distances").as_map();
- for (auto [key, value] : stop_road_map) {
- last_name = key;
- distance = value.as_int();
- distances.push_back({catalogue.get_stop(begin_name),
- catalogue.get_stop(last_name), distance});
- }
- } catch(...) {
- std::cout << "invalide road" << std::endl;
- }
- }
- return distances;
- }
- Bus JSONReader::parse_node_bus(Node& node, TransportCatalogue& catalogue) {
- Bus bus;
- Dict bus_node;
- Array bus_stops;
- if (node.is_map()) {
- bus_node = node.as_map();
- bus.name = bus_node.at("name").as_string();
- bus.is_roundtrip = bus_node.at("is_roundtrip").as_bool();
- try {
- bus_stops = bus_node.at("stops").as_array();
- for (Node stop : bus_stops) {
- bus.stops.push_back(catalogue.get_stop(stop.as_string()));
- }
- if (!bus.is_roundtrip) {
- size_t size = bus.stops.size() - 1;
- for (size_t i = size; i > 0; i--) {
- bus.stops.push_back(bus.stops[i-1]);
- }
- }
- } catch(...) {
- std::cout << "base_requests: bus: stops is empty" << std::endl;
- }
- }
- return bus;
- }
- void JSONReader::parse_node_base(const Node& root, TransportCatalogue& catalogue){
- Array base_requests;
- Dict req_map;
- Node req_node;
- std::vector<Node> buses;
- std::vector<Node> stops;
- if (root.is_array()) {
- base_requests = root.as_array();
- for (Node& node : base_requests) {
- if (node.is_map()) {
- req_map = node.as_map();
- try {
- req_node = req_map.at("type");
- if (req_node.is_string()) {
- if (req_node.as_string() == "Bus") {
- buses.push_back(req_map);
- } else if (req_node.as_string() == "Stop") {
- stops.push_back(req_map);
- } else {
- std::cout << "base_requests are invalid";
- }
- }
- } catch(...) {
- std::cout << "base_requests does not have type value";
- }
- }
- }
- for (auto stop : stops) {
- catalogue.add_stop(parse_node_stop(stop));
- }
- for (auto stop : stops) {
- catalogue.add_distance(parse_node_distances(stop, catalogue));
- }
- for (auto bus : buses) {
- catalogue.add_bus(parse_node_bus(bus, catalogue));
- }
- } else {
- std::cout << "base_requests is not an array";
- }
- }
- void JSONReader::parse_node_stat(const Node& node, std::vector<StatRequest>& stat_request){
- Array stat_requests;
- Dict req_map;
- StatRequest req;
- if (node.is_array()) {
- stat_requests = node.as_array();
- for (Node req_node : stat_requests) {
- if (req_node.is_map()) {
- req_map = req_node.as_map();
- req.id = req_map.at("id").as_int();
- req.type = req_map.at("type").as_string();
- if (req.type != "Map") {
- req.name = req_map.at("name").as_string();
- } else {
- req.name = "";
- }
- stat_request.push_back(req);
- }
- }
- } else {
- std::cout << "base_requests is not array";
- }
- }
- void JSONReader::parse_node_render(const Node& node, map_renderer::RenderSettings& rend_set){
- Dict rend_map;
- Array bus_lab_offset;
- Array stop_lab_offset;
- Array arr_color;
- Array arr_palette;
- uint8_t red_;
- uint8_t green_;
- uint8_t blue_;
- double opacity_;
- if (node.is_map()) {
- rend_map = node.as_map();
- try {
- rend_set.width_ = rend_map.at("width").as_double();
- rend_set.height_ = rend_map.at("height").as_double();
- rend_set.padding_ = rend_map.at("padding").as_double();
- rend_set.line_width_ = rend_map.at("line_width").as_double();
- rend_set.stop_radius_ = rend_map.at("stop_radius").as_double();
- rend_set.bus_label_font_size_ = rend_map.at("bus_label_font_size").as_int();
- if (rend_map.at("bus_label_offset").is_array()) {
- bus_lab_offset = rend_map.at("bus_label_offset").as_array();
- rend_set.bus_label_offset_ = std::make_pair(bus_lab_offset[0].as_double(),
- bus_lab_offset[1].as_double());
- }
- rend_set.stop_label_font_size_ = rend_map.at("stop_label_font_size").as_int();
- if (rend_map.at("stop_label_offset").is_array()) {
- stop_lab_offset = rend_map.at("stop_label_offset").as_array();
- rend_set.stop_label_offset_ = std::make_pair(stop_lab_offset[0].as_double(),
- stop_lab_offset[1].as_double());
- }
- if (rend_map.at("underlayer_color").is_string()) {
- rend_set.underlayer_color_ = svg::Color(rend_map.at("underlayer_color").as_string());
- } else if (rend_map.at("underlayer_color").is_array()) {
- arr_color = rend_map.at("underlayer_color").as_array();
- red_ = arr_color[0].as_int();
- green_ = arr_color[1].as_int();
- blue_ = arr_color[2].as_int();
- if(arr_color.size() == 4){
- opacity_ = arr_color[3].as_double();
- rend_set.underlayer_color_ = svg::Color(svg::Rgba(red_,
- green_,
- blue_,
- opacity_));
- } else if (arr_color.size() == 3) {
- rend_set.underlayer_color_ = svg::Color(svg::Rgb(red_,
- green_,
- blue_));
- }
- }
- rend_set.underlayer_width_ = rend_map.at("underlayer_width").as_double();
- if (rend_map.at("color_palette").is_array()) {
- arr_palette = rend_map.at("color_palette").as_array();
- for (Node color_palette : arr_palette) {
- if (color_palette.is_string()) {
- rend_set.color_palette_.push_back(svg::Color(color_palette.as_string()));
- } else if (color_palette.is_array()) {
- arr_color = color_palette.as_array();
- red_ = arr_color[0].as_int();
- green_ = arr_color[1].as_int();
- blue_ = arr_color[2].as_int();
- if (arr_color.size() == 4) {
- opacity_ = arr_color[3].as_double();
- rend_set.color_palette_.push_back(svg::Color(svg::Rgba(red_,
- green_,
- blue_,
- opacity_)));
- } else if (arr_color.size() == 3) {
- rend_set.color_palette_.push_back(svg::Color(svg::Rgb(red_,
- green_,
- blue_)));
- }
- }
- }
- }
- } catch(...) {
- std::cout << "unable to parsse init settings";
- }
- } else {
- std::cout << "render_settings is not map";
- }
- }
- void JSONReader::parse_node(const Node& root, TransportCatalogue& catalogue, std::vector<StatRequest>& stat_request, map_renderer::RenderSettings& render_settings){
- Dict root_dictionary;
- if (root.is_map()) {
- root_dictionary = root.as_map();
- try {
- parse_node_base(root_dictionary.at("base_requests"), catalogue);
- } catch(...) {
- std::cout << "base_requests is empty";
- }
- try {
- parse_node_stat(root_dictionary.at("stat_requests"), stat_request);
- } catch(...) {
- std::cout << "stat_requests is empty";
- }
- try {
- parse_node_render(root_dictionary.at("render_settings"), render_settings);
- } catch(...) {
- std::cout << "render_settings is empty";
- }
- } else {
- std::cout << "root is not map";
- }
- }
- void JSONReader::parse(TransportCatalogue& catalogue, std::vector<StatRequest>& stat_request, map_renderer::RenderSettings& render_settings) {
- parse_node(document_.get_root(),
- catalogue,
- stat_request,
- render_settings);
- }
- }//end namespace json
- }//end namespace detail
- }//end namespace transport_catalogue
- -----------------------------------------------------------------------
- main.cpp
- -----------------------------------------------------------------------
- #include "json_reader.h"
- #include "map_renderer.h"
- #include "request_handler.h"
- using namespace std;
- using namespace transport_catalogue;
- using namespace map_renderer;
- using namespace request_handler;
- using namespace transport_catalogue::detail::json;
- int main() {
- vector<StatRequest> stat_request;
- RenderSettings render_settings;
- TransportCatalogue catalogue;
- JSONReader json_reader;
- RequestHandler request_handler;
- json_reader = JSONReader(cin);
- json_reader.parse(catalogue, stat_request, render_settings);
- request_handler = RequestHandler();
- request_handler.execute_queries(catalogue, stat_request, render_settings);
- transport_catalogue::detail::json::print(request_handler.get_document(), cout);
- }
- -----------------------------------------------------------------------
- map_renderer.h
- -----------------------------------------------------------------------
- #pragma once
- #include <iostream>
- #include <optional>
- #include <algorithm>
- #include <cstdlib>
- #include "domain.h"
- #include "geo.h"
- #include "svg.h"
- using namespace domain;
- namespace map_renderer {
- inline const double EPSILON = 1e-6;
- class SphereProjector {
- public:
- SphereProjector() = default;
- template <typename InputIt>
- SphereProjector(InputIt points_begin,
- InputIt points_end,
- double max_width,
- double max_height,
- double padding);
- svg::Point operator()(geo::Coordinates coords) const;
- private:
- double padding_;
- double min_lon_ = 0;
- double max_lat_ = 0;
- double zoom_coeff_ = 0;
- bool is_zero(double value);
- };
- struct RenderSettings {
- double width_;
- double height_;
- double padding_;
- double line_width_;
- double stop_radius_;
- int bus_label_font_size_;
- std::pair<double, double> bus_label_offset_;
- int stop_label_font_size_;
- std::pair<double, double> stop_label_offset_;
- svg::Color underlayer_color_;
- double underlayer_width_;
- std::vector<svg::Color> color_palette_;
- };
- class MapRenderer {
- public:
- MapRenderer(RenderSettings& render_settings);
- SphereProjector get_sphere_projector(const std::vector<geo::Coordinates>& points) const;
- void init_sphere_projector(std::vector<geo::Coordinates> points);
- RenderSettings get_render_settings() const;
- int get_palette_size() const;
- svg::Color get_color(int line_number) const;
- void set_line_properties(svg::Polyline& polyline, int line_number) const;
- void set_route_text_common_properties(svg::Text &text, const std::string& name, svg::Point position) const;
- void set_route_text_additional_properties(svg::Text& text, const std::string& name, svg::Point position) const;
- void set_route_text_color_properties(svg::Text& text, const std::string& name, int palette, svg::Point position) const;
- void set_stops_circles_properties(svg::Circle& circle, svg::Point position) const;
- void set_stops_text_common_properties(svg::Text& text, const std::string& name, svg::Point position) const;
- void set_stops_text_additional_properties(svg::Text& text, const std::string& name, svg::Point position) const;
- void set_stops_text_color_properties(svg::Text& text, const std::string& name, svg::Point position) const;
- void add_line(std::vector<std::pair<Bus*, int>>& buses_palette);
- void add_buses_name(std::vector<std::pair<Bus*, int>>& buses_palette);
- void add_stops_circle(std::vector<Stop*>& stops_name);
- void add_stops_name(std::vector<Stop*>& stops_name);
- void get_stream_map(std::ostream& stream_);
- private:
- SphereProjector sphere_projector;
- RenderSettings& render_settings_;
- svg::Document map_svg;
- };
- template <typename InputIt>
- SphereProjector::SphereProjector(InputIt points_begin,
- InputIt points_end,
- double max_width,
- double max_height,
- double padding) : padding_(padding) {
- if (points_begin == points_end) {
- return;
- }
- const auto [left_it,
- right_it] = std::minmax_element(points_begin,
- points_end,
- [](auto lhs, auto rhs) {
- return lhs.longitude < rhs.longitude;
- });
- min_lon_ = left_it->longitude;
- const double max_lon = right_it->longitude;
- const auto [bottom_it,
- top_it] = std::minmax_element(points_begin,
- points_end,
- [](auto lhs, auto rhs) {
- return lhs.latitude < rhs.latitude;
- });
- const double min_lat = bottom_it->latitude;
- max_lat_ = top_it->latitude;
- std::optional<double> width_zoom;
- if (!is_zero(max_lon - min_lon_)) {
- width_zoom = (max_width - 2 * padding)
- / (max_lon - min_lon_);
- }
- std::optional<double> height_zoom;
- if (!is_zero(max_lat_ - min_lat)) {
- height_zoom = (max_height - 2 * padding)
- / (max_lat_ - min_lat);
- }
- if (width_zoom && height_zoom) {
- zoom_coeff_ = std::min(*width_zoom,
- *height_zoom);
- } else if (width_zoom) {
- zoom_coeff_ = *width_zoom;
- } else if (height_zoom) {
- zoom_coeff_ = *height_zoom;
- }
- }
- }//end namespace map_renderer
- -----------------------------------------------------------------------
- map_renderer.cpp
- -----------------------------------------------------------------------
- #include "map_renderer.h"
- namespace map_renderer {
- bool SphereProjector::is_zero(double value) {
- return std::abs(value) < EPSILON;
- }
- MapRenderer::MapRenderer(RenderSettings& render_settings) : render_settings_(render_settings) {}
- svg::Point SphereProjector::operator()(geo::Coordinates coords) const {
- return {(coords.longitude - min_lon_) * zoom_coeff_ + padding_,
- (max_lat_ - coords.latitude) * zoom_coeff_ + padding_};
- }
- SphereProjector MapRenderer::get_sphere_projector(const std::vector<geo::Coordinates>& points) const {
- return SphereProjector(points.begin(),
- points.end(),
- render_settings_.width_,
- render_settings_.height_,
- render_settings_.padding_);
- }
- void MapRenderer::init_sphere_projector(std::vector<geo::Coordinates> points){
- sphere_projector = SphereProjector(points.begin(),
- points.end(),
- render_settings_.width_,
- render_settings_.height_,
- render_settings_.padding_);
- }
- RenderSettings MapRenderer::get_render_settings() const{
- return render_settings_;
- }
- int MapRenderer::get_palette_size() const{
- return render_settings_.color_palette_.size();
- }
- svg::Color MapRenderer::get_color(int line_number) const {
- return render_settings_.color_palette_[line_number];
- }
- void MapRenderer::set_line_properties(svg::Polyline& polyline,
- [[maybe_unused]] int line_number) const {
- using namespace std::literals;
- polyline.set_stroke_color(get_color(line_number));
- polyline.set_fill_color("none"s);
- polyline.set_stroke_width(render_settings_.line_width_);
- polyline.set_stroke_linecap(svg::StrokeLineCap::ROUND);
- polyline.set_stroke_linejoin(svg::StrokeLineJoin::ROUND);
- }
- void MapRenderer::set_route_text_common_properties(svg::Text& text,
- const std::string& name,
- svg::Point position) const {
- using namespace std::literals;
- text.set_position(position);
- text.set_offset({render_settings_.bus_label_offset_.first,
- render_settings_.bus_label_offset_.second});
- text.set_font_size(render_settings_.bus_label_font_size_);
- text.set_font_family("Verdana");
- text.set_font_weight("bold");
- text.set_data(name);
- }
- void MapRenderer::set_route_text_additional_properties(svg::Text& text,
- const std::string& name,
- svg::Point position) const {
- set_route_text_common_properties(text,
- name,
- position);
- text.set_fill_color(render_settings_.underlayer_color_);
- text.set_stroke_color(render_settings_.underlayer_color_);
- text.set_stroke_width(render_settings_.underlayer_width_);
- text.set_stroke_linejoin(svg::StrokeLineJoin::ROUND);
- text.set_stroke_linecap(svg::StrokeLineCap::ROUND);
- }
- void MapRenderer::set_route_text_color_properties(svg::Text& text,
- const std::string& name,
- int palette,
- svg::Point position) const {
- set_route_text_common_properties(text,
- name,
- position);
- text.set_fill_color(get_color(palette));
- }
- void MapRenderer::set_stops_circles_properties(svg::Circle& circle,
- svg::Point position) const {
- using namespace std::literals;
- circle.set_center(position);
- circle.set_radius(render_settings_.stop_radius_);
- circle.set_fill_color("white");
- }
- void MapRenderer::set_stops_text_common_properties(svg::Text& text,
- const std::string& name,
- svg::Point position) const {
- using namespace std::literals;
- text.set_position(position);
- text.set_offset({render_settings_.stop_label_offset_.first,
- render_settings_.stop_label_offset_.second});
- text.set_font_size(render_settings_.stop_label_font_size_);
- text.set_font_family("Verdana");
- text.set_data(name);
- }
- void MapRenderer::set_stops_text_additional_properties(svg::Text& text,
- const std::string& name,
- svg::Point position) const {
- using namespace std::literals;
- set_stops_text_common_properties(text,
- name,
- position);
- text.set_fill_color(render_settings_.underlayer_color_);
- text.set_stroke_color(render_settings_.underlayer_color_);
- text.set_stroke_width(render_settings_.underlayer_width_);
- text.set_stroke_linejoin(svg::StrokeLineJoin::ROUND);
- text.set_stroke_linecap(svg::StrokeLineCap::ROUND);
- }
- void MapRenderer::set_stops_text_color_properties(svg::Text& text,
- const std::string& name,
- svg::Point position) const {
- using namespace std::literals;
- set_stops_text_common_properties(text,
- name,
- position);
- text.set_fill_color("black");
- }
- void MapRenderer::add_line(std::vector<std::pair<Bus*, int>>& buses_palette) {
- std::vector<geo::Coordinates> stops_geo_coords;
- for (auto [bus, palette] : buses_palette) {
- for (Stop* stop : bus->stops) {
- geo::Coordinates coordinates;
- coordinates.latitude = stop->latitude;
- coordinates.longitude = stop->longitude;
- stops_geo_coords.push_back(coordinates);
- }
- svg::Polyline bus_line;
- bool bus_empty = true;
- for (auto& coord : stops_geo_coords) {
- bus_empty = false;
- bus_line.add_point(sphere_projector(coord));
- }
- if (!bus_empty) {
- set_line_properties(bus_line,
- palette);
- map_svg.add(bus_line);
- }
- stops_geo_coords.clear();
- }
- }
- void MapRenderer::add_buses_name(std::vector<std::pair<Bus*, int>>& buses_palette){
- std::vector<geo::Coordinates> stops_geo_coords;
- bool bus_empty = true;
- for (auto [bus, palette] : buses_palette) {
- for (Stop* stop : bus->stops) {
- geo::Coordinates coordinates;
- coordinates.latitude = stop->latitude;
- coordinates.longitude = stop->longitude;
- stops_geo_coords.push_back(coordinates);
- if(bus_empty) bus_empty = false;
- }
- svg::Text route_name_roundtrip;
- svg::Text route_title_roundtrip;
- svg::Text route_name_notroundtrip;
- svg::Text route_title_notroundtrip;
- if (!bus_empty) {
- if (bus->is_roundtrip) {
- set_route_text_additional_properties(route_name_roundtrip,
- std::string(bus->name),
- sphere_projector(stops_geo_coords[0]));
- map_svg.add(route_name_roundtrip);
- set_route_text_color_properties(route_title_roundtrip,
- std::string(bus->name),
- palette,
- sphere_projector(stops_geo_coords[0]));
- map_svg.add(route_title_roundtrip);
- } else {
- set_route_text_additional_properties(route_name_roundtrip,
- std::string(bus->name),
- sphere_projector(stops_geo_coords[0]));
- map_svg.add(route_name_roundtrip);
- set_route_text_color_properties(route_title_roundtrip,
- std::string(bus->name),
- palette,
- sphere_projector(stops_geo_coords[0]));
- map_svg.add(route_title_roundtrip);
- if (stops_geo_coords[0] != stops_geo_coords[stops_geo_coords.size()/2]) {
- set_route_text_additional_properties(route_name_notroundtrip,
- std::string(bus->name),
- sphere_projector(stops_geo_coords[stops_geo_coords.size()/2]));
- map_svg.add(route_name_notroundtrip);
- set_route_text_color_properties(route_title_notroundtrip,
- std::string(bus->name),
- palette,
- sphere_projector(stops_geo_coords[stops_geo_coords.size()/2]));
- map_svg.add(route_title_notroundtrip);
- }
- }
- }
- bus_empty = false;
- stops_geo_coords.clear();
- }
- }
- void MapRenderer::add_stops_circle(std::vector<Stop*>& stops){
- std::vector<geo::Coordinates> stops_geo_coords;
- svg::Circle icon;
- for (Stop* stop_info : stops) {
- if (stop_info) {
- geo::Coordinates coordinates;
- coordinates.latitude = stop_info->latitude;
- coordinates.longitude = stop_info->longitude;
- set_stops_circles_properties(icon,
- sphere_projector(coordinates));
- map_svg.add(icon);
- }
- }
- }
- void MapRenderer::add_stops_name(std::vector<Stop*>& stops){
- std::vector<geo::Coordinates> stops_geo_coords;
- svg::Text svg_stop_name;
- svg::Text svg_stop_name_title;
- for (Stop* stop_info : stops) {
- if (stop_info) {
- geo::Coordinates coordinates;
- coordinates.latitude = stop_info->latitude;
- coordinates.longitude = stop_info->longitude;
- set_stops_text_additional_properties(svg_stop_name,
- stop_info->name,
- sphere_projector(coordinates));
- map_svg.add(svg_stop_name);
- set_stops_text_color_properties(svg_stop_name_title,
- stop_info->name,
- sphere_projector(coordinates));
- map_svg.add(svg_stop_name_title);
- }
- }
- }
- void MapRenderer::get_stream_map(std::ostream& stream_) {
- map_svg.render(stream_);
- }
- }//end namespace map_renderer
- -----------------------------------------------------------------------
- request_handler.h
- -----------------------------------------------------------------------
- #pragma once
- #include "transport_catalogue.h"
- #include "map_renderer.h"
- #include "json.h"
- using namespace transport_catalogue;
- using namespace map_renderer;
- using namespace transport_catalogue::detail::json;
- namespace request_handler {
- class RequestHandler {
- public:
- std::vector<geo::Coordinates> get_stops_coordinates(TransportCatalogue& catalogue_) const;
- std::vector<std::string_view> get_sort_buses_names(TransportCatalogue& catalogue_) const;
- RequestHandler() = default;
- BusQueryResult bus_query(TransportCatalogue& catalogue, std::string_view str);
- StopQueryResult stop_query(TransportCatalogue& catalogue, std::string_view stop_name);
- Node execute_make_node_stop(int id_request, StopQueryResult query_result);
- Node execute_make_node_bus(int id_request, BusQueryResult query_result);
- Node execute_make_node_map(int id_request, TransportCatalogue& catalogue, RenderSettings render_settings);
- void execute_queries(TransportCatalogue& catalogue, std::vector<StatRequest>& stat_requests, RenderSettings& render_settings);
- void execute_render_map(MapRenderer& map_catalogue, TransportCatalogue& catalogue_) const;
- const Document& get_document();
- private:
- Document doc_out;
- };
- }//end namespace request_handler
- -----------------------------------------------------------------------
- request_handler.cpp
- -----------------------------------------------------------------------
- #include "request_handler.h"
- namespace request_handler {
- Node RequestHandler::execute_make_node_stop(int id_request, StopQueryResult stop_info){
- Dict result;
- Array buses;
- std::string str_not_found = "not found";
- if (stop_info.not_found) {
- result.emplace("request_id", Node(id_request));
- result.emplace("error_message", Node(str_not_found));
- } else {
- result.emplace("request_id", Node(id_request));
- for (std::string bus_name : stop_info.buses_name) {
- buses.push_back(Node(bus_name));
- }
- result.emplace("buses", Node(buses));
- }
- return Node(result);
- }
- Node RequestHandler::execute_make_node_bus(int id_request, BusQueryResult bus_info){
- Dict result;
- std::string str_not_found = "not found";
- if (bus_info.not_found) {
- result.emplace("request_id", Node(id_request));
- result.emplace("error_message", Node(str_not_found));
- } else {
- result.emplace("request_id", Node(id_request));
- result.emplace("curvature", Node(bus_info.curvature));
- result.emplace("route_length", Node(bus_info.route_length));
- result.emplace("stop_count", Node(bus_info.stops_on_route));
- result.emplace("unique_stop_count", Node(bus_info.unique_stops));
- }
- return Node(result);
- }
- Node RequestHandler::execute_make_node_map(int id_request, TransportCatalogue& catalogue_, RenderSettings render_settings){
- Dict result;
- std::ostringstream map_stream;
- std::string map_str;
- MapRenderer map_catalogue(render_settings);
- map_catalogue.init_sphere_projector(get_stops_coordinates(catalogue_));
- execute_render_map(map_catalogue, catalogue_);
- map_catalogue.get_stream_map(map_stream);
- map_str = map_stream.str();
- result.emplace("request_id", Node(id_request));
- result.emplace("map", Node(map_str));
- return Node(result);
- }
- void RequestHandler::execute_queries(TransportCatalogue& catalogue, std::vector<StatRequest>& stat_requests, RenderSettings& render_settings){
- std::vector<Node> result_request;
- for (StatRequest req : stat_requests) {
- if (req.type == "Stop") {
- result_request.push_back(execute_make_node_stop(req.id, stop_query(catalogue, req.name)));
- } else if (req.type == "Bus") {
- result_request.push_back(execute_make_node_bus(req.id, bus_query(catalogue, req.name)));
- } else if(req.type == "Map") {
- result_request.push_back(execute_make_node_map(req.id, catalogue, render_settings));
- }
- }
- doc_out = Document{Node(result_request)};
- }
- void RequestHandler::execute_render_map(MapRenderer& map_catalogue, TransportCatalogue& catalogue) const {
- std::vector<std::pair<Bus*, int>> buses_palette;
- std::vector<Stop*> stops_sort;
- int palette_size = 0;
- int palette_index = 0;
- palette_size = map_catalogue.get_palette_size();
- if (palette_size == 0) {
- std::cout << "color palette is empty";
- return;
- }
- auto buses = catalogue.get_busname_to_bus();
- if (buses.size() > 0) {
- for (std::string_view bus_name : get_sort_buses_names(catalogue)) {
- Bus* bus_info = catalogue.get_bus(bus_name);
- if (bus_info) {
- if (bus_info->stops.size() > 0) {
- buses_palette.push_back(std::make_pair(bus_info, palette_index));
- palette_index++;
- if (palette_index == palette_size) {
- palette_index = 0;
- }
- }
- }
- }
- if (buses_palette.size() > 0) {
- map_catalogue.add_line(buses_palette);
- map_catalogue.add_buses_name(buses_palette);
- }
- }
- auto stops = catalogue.get_stopname_to_stop();
- if (stops.size() > 0) {
- std::vector<std::string_view> stops_name;
- for (auto& [stop_name, stop] : stops) {
- if (stop->buses.size() > 0) {
- stops_name.push_back(stop_name);
- }
- }
- std::sort(stops_name.begin(), stops_name.end());
- for(std::string_view stop_name : stops_name){
- Stop* stop = catalogue.get_stop(stop_name);
- if(stop){
- stops_sort.push_back(stop);
- }
- }
- if (stops_sort.size() > 0) {
- map_catalogue.add_stops_circle(stops_sort);
- map_catalogue.add_stops_name(stops_sort);
- }
- }
- }
- std::vector<geo::Coordinates> RequestHandler::get_stops_coordinates(TransportCatalogue& catalogue_) const {
- std::vector<geo::Coordinates> stops_coordinates;
- auto buses = catalogue_.get_busname_to_bus();
- for (auto& [busname, bus] : buses) {
- for (auto& stop : bus->stops) {
- geo::Coordinates coordinates;
- coordinates.latitude = stop->latitude;
- coordinates.longitude = stop->longitude;
- stops_coordinates.push_back(coordinates);
- }
- }
- return stops_coordinates;
- }
- std::vector<std::string_view> RequestHandler::get_sort_buses_names(TransportCatalogue& catalogue_) const {
- std::vector<std::string_view> buses_names;
- auto buses = catalogue_.get_busname_to_bus();
- if (buses.size() > 0) {
- for (auto& [busname, bus] : buses) {
- buses_names.push_back(busname);
- }
- std::sort(buses_names.begin(), buses_names.end());
- return buses_names;
- } else {
- return {};
- }
- }
- BusQueryResult RequestHandler::bus_query(TransportCatalogue& catalogue, std::string_view bus_name) {
- BusQueryResult bus_info;
- Bus* bus = catalogue.get_bus(bus_name);
- if (bus != nullptr) {
- bus_info.name = bus->name;
- bus_info.not_found = false;
- bus_info.stops_on_route = bus->stops.size();
- bus_info.unique_stops = catalogue.get_uniq_stops(bus).size();
- bus_info.route_length = bus->route_length;
- bus_info.curvature = double(catalogue.get_distance_to_bus(bus)
- /catalogue.get_length(bus));
- } else {
- bus_info.name = bus_name;
- bus_info.not_found = true;
- }
- return bus_info;
- }
- StopQueryResult RequestHandler::stop_query(TransportCatalogue& catalogue, std::string_view stop_name) {
- std::unordered_set<const Bus*> unique_buses;
- StopQueryResult stop_info;
- Stop* stop = catalogue.get_stop(stop_name);
- if (stop != NULL) {
- stop_info.name = stop->name;
- stop_info.not_found = false;
- unique_buses = catalogue.stop_get_uniq_buses(stop);
- if (unique_buses.size() > 0){
- for (const Bus* bus : unique_buses) {
- stop_info.buses_name.push_back(bus->name);
- }
- std::sort(stop_info.buses_name.begin(), stop_info.buses_name.end());
- }
- } else {
- stop_info.name = stop_name;
- stop_info.not_found = true;
- }
- return stop_info;
- }
- const Document& RequestHandler::get_document(){
- return doc_out;
- }
- }//end namespace request_handler
- -----------------------------------------------------------------------
- svg.h
- -----------------------------------------------------------------------
- #pragma once
- #define _USE_MATH_DEFINES
- #include <cstdint>
- #include <iostream>
- #include <memory>
- #include <string>
- #include <vector>
- #include <optional>
- #include <cmath>
- #include <variant>
- namespace svg {
- class Rgb {
- public:
- Rgb() = default;
- Rgb(uint8_t red, uint8_t green, uint8_t blue);
- uint8_t red_ = 0;
- uint8_t green_ = 0;
- uint8_t blue_ = 0;
- };
- inline void print_color(std::ostream& out, Rgb& rgb);
- class Rgba {
- public:
- Rgba() = default;
- Rgba(uint8_t red, uint8_t green, uint8_t blue, double opacity);
- uint8_t red_ = 0;
- uint8_t green_ = 0;
- uint8_t blue_ = 0;
- double opacity_ = 1.0;
- };
- inline void print_color(std::ostream& out, Rgba& rgba);
- using Color = std::variant<std::monostate, std::string, Rgb, Rgba>;
- inline const Color NoneColor{"none"};
- inline void print_color(std::ostream& out, std::monostate);
- inline void print_color(std::ostream& out, std::string& color);
- std::ostream& operator<<(std::ostream& out, const Color& color);
- enum class StrokeLineCap {
- BUTT,
- ROUND,
- SQUARE,
- };
- inline std::ostream &operator<<(std::ostream &out, StrokeLineCap stroke_line_cap) {
- using namespace std::literals;
- if (stroke_line_cap == StrokeLineCap::BUTT) {
- out << "butt"sv;
- } else if (stroke_line_cap == StrokeLineCap::ROUND) {
- out << "round"sv;
- } else if (stroke_line_cap == StrokeLineCap::SQUARE) {
- out << "square"sv;
- }
- return out;
- }
- enum class StrokeLineJoin {
- ARCS,
- BEVEL,
- MITER,
- MITER_CLIP,
- ROUND,
- };
- inline std::ostream &operator<<(std::ostream &out, StrokeLineJoin stroke_line_join) {
- using namespace std::literals;
- if (stroke_line_join == StrokeLineJoin::ARCS) {
- out << "arcs"sv;
- } else if (stroke_line_join == StrokeLineJoin::BEVEL) {
- out << "bevel"sv;
- } else if (stroke_line_join == StrokeLineJoin::MITER) {
- out << "miter"sv;
- } else if (stroke_line_join == StrokeLineJoin::MITER_CLIP) {
- out << "miter-clip"sv;
- } else if (stroke_line_join == StrokeLineJoin::ROUND) {
- out << "round"sv;
- }
- return out;
- }
- template<typename Owner>
- class PathProps {
- public:
- Owner& set_fill_color(const Color& color) {
- fill_color_ = std::move(color);
- return as_owner();
- }
- Owner& set_stroke_color(const Color& color) {
- stroke_color_ = std::move(color);
- return as_owner();
- }
- Owner& set_stroke_width(double width) {
- stroke_width_ = width;
- return as_owner();
- }
- Owner& set_stroke_linecap(StrokeLineCap line_cap) {
- stroke_line_cap_ = line_cap;
- return as_owner();
- }
- Owner& set_stroke_linejoin(StrokeLineJoin line_join) {
- stroke_line_join_ = line_join;
- return as_owner();
- }
- protected:
- ~PathProps() = default;
- void render_attrs(std::ostream &out) const {
- using namespace std::literals;
- if (fill_color_ != std::nullopt) {
- out << "fill=\""sv << *fill_color_ << "\" "sv;
- }
- if (stroke_color_ != std::nullopt) {
- out << "stroke=\""sv << *stroke_color_ << "\" "sv;
- }
- if (stroke_width_ != std::nullopt) {
- out << "stroke-width=\""sv << *stroke_width_ << "\" "sv;
- }
- if (stroke_line_cap_ != std::nullopt) {
- out << "stroke-linecap=\""sv << *stroke_line_cap_ << "\" "sv;
- }
- if (stroke_line_join_ != std::nullopt) {
- out << "stroke-linejoin=\""sv << *stroke_line_join_ << "\" "sv;
- }
- }
- private:
- std::optional<Color> fill_color_;
- std::optional<Color> stroke_color_;
- std::optional<double> stroke_width_;
- std::optional<StrokeLineCap> stroke_line_cap_;
- std::optional<StrokeLineJoin> stroke_line_join_;
- Owner& as_owner() {
- return static_cast<Owner&>(*this);
- }
- };
- struct Point {
- Point() = default;
- Point(double x, double y) : x(x)
- , y(y) {}
- double x = 0;
- double y = 0;
- };
- struct RenderContext {
- RenderContext(std::ostream& out);
- RenderContext(std::ostream& out, int indent_step, int indent = 0) : out_(out)
- , indent_step_(indent_step)
- , indent_(indent) {}
- RenderContext indented() const;
- void render_indent() const;
- std::ostream& out_;
- int indent_step_ = 0;
- int indent_ = 0;
- };
- class Object {
- public:
- void render(const RenderContext& context) const;
- virtual ~Object() = default;
- private:
- virtual void render_object(const RenderContext& context) const = 0;
- };
- class Circle final : public Object, public PathProps<Circle> {
- public:
- Circle& set_center(Point center);
- Circle& set_radius(double radius);
- private:
- Point center_;
- double radius_ = 1.0;
- void render_object(const RenderContext& context) const override;
- };
- class Polyline final : public Object, public PathProps<Polyline> {
- public:
- Polyline& add_point(Point point);
- private:
- std::vector<Point> points_;
- void render_object(const RenderContext& context) const override;
- };
- class Text final : public Object, public PathProps<Text> {
- public:
- Text& set_position(Point pos);
- Text& set_offset(Point offset);
- Text& set_font_size(uint32_t size);
- Text& set_font_family(std::string font_family);
- Text& set_font_weight(std::string font_weight);
- Text& set_data(std::string data);
- private:
- Point position_;
- Point offset_;
- std::string font_family_;
- std::string font_weight_;
- uint32_t font_size_ = 1;
- std::string data_;
- static std::string delete_spaces(const std::string& str);
- static std::string uniq_symbols(const std::string& str);
- void render_object(const RenderContext& context) const override;
- };
- class ObjectContainer {
- public:
- virtual ~ObjectContainer() = default;
- template<typename Obj>
- void add(Obj obj);
- virtual void add_ptr(std::unique_ptr<Object> &&) = 0;
- protected:
- std::vector<std::unique_ptr<Object>> objects_;
- };
- template<typename Obj>
- void ObjectContainer::add(Obj obj) {
- objects_.emplace_back(std::make_unique<Obj>(std::move(obj)));
- }
- class Drawable {
- public:
- virtual void draw(ObjectContainer& container) const = 0;
- virtual ~Drawable() = default;
- };
- class Document : public ObjectContainer {
- public:
- void add_ptr(std::unique_ptr<Object>&& obj) override {
- objects_.emplace_back(std::move(obj));
- }
- void render(std::ostream& out) const;
- };
- }//end namespace svg
- -----------------------------------------------------------------------
- svg.cpp
- -----------------------------------------------------------------------
- #include "svg.h"
- namespace svg {
- using namespace std::literals;
- Rgb::Rgb(uint8_t red, uint8_t green, uint8_t blue) : red_(red)
- , green_(green)
- , blue_(blue) {}
- Rgba::Rgba(uint8_t red, uint8_t green, uint8_t blue, double opacity) : red_(red)
- , green_(green)
- , blue_(blue)
- , opacity_(opacity) {}
- inline void print_color(std::ostream& out, Rgb& rgb) {
- out << "rgb("sv << static_cast<short>(rgb.red_) << ","sv
- << static_cast<short>(rgb.green_) << ","sv
- << static_cast<short>(rgb.blue_) << ")"sv;
- }
- inline void print_color(std::ostream& out, Rgba& rgba) {
- out << "rgba("sv << static_cast<short>(rgba.red_) << ","sv
- << static_cast<short>(rgba.green_) << ","sv
- << static_cast<short>(rgba.blue_) << ","sv
- << (rgba.opacity_) << ")"sv;
- }
- inline void print_color(std::ostream& out, std::monostate) {
- out << "none"sv;
- }
- inline void print_color(std::ostream& out, std::string& color) {
- out << color;
- }
- std::ostream& operator<<(std::ostream& out, const Color& color) {
- std::visit([&out](auto value) {
- print_color(out, value);
- }, color);
- return out;
- }
- RenderContext::RenderContext(std::ostream& out) : out_(out) {}
- RenderContext RenderContext::indented() const {
- return {out_,
- indent_step_,
- indent_ + indent_step_};
- }
- void RenderContext::render_indent() const {
- for (int i = 0; i < indent_; ++i) {
- out_.put(' ');
- }
- }
- void Object::render(const RenderContext& context) const {
- context.render_indent();
- render_object(context);
- context.out_ << std::endl;
- }
- Circle& Circle::set_center(Point center) {
- center_ = center;
- return *this;
- }
- Circle& Circle::set_radius(double radius) {
- radius_ = radius;
- return *this;
- }
- void Circle::render_object(const RenderContext& context) const {
- std::ostream& out = context.out_;
- out << "<circle cx=\""sv << center_.x
- << "\" cy=\""sv << center_.y << "\" "sv;
- out << "r=\""sv << radius_ << "\" "sv;
- render_attrs(context.out_);
- out << "/>"sv;
- }
- Polyline& Polyline::add_point(Point point) {
- points_.emplace_back(point);
- return *this;
- }
- void Polyline::render_object(const RenderContext& context) const {
- std::ostream& out = context.out_;
- out << "<polyline points=\"";
- for (size_t i = 0; i < points_.size(); ++i) {
- out << points_[i].x << ","sv << points_[i].y;
- if (i+1 != points_.size()) {
- out << " "sv;
- }
- }
- out << "\" ";
- render_attrs(context.out_);
- out << "/>";
- }
- Text& Text::set_position(Point pos) {
- position_ = pos;
- return *this;
- }
- Text& Text::set_offset(Point offset) {
- offset_ = offset;
- return *this;
- }
- Text& Text::set_font_size(uint32_t size) {
- font_size_ = size;
- return *this;
- }
- Text& Text::set_font_family(std::string font_family) {
- font_family_ = std::move(font_family);
- return *this;
- }
- Text& Text::set_font_weight(std::string font_weight) {
- font_weight_ = std::move(font_weight);
- return *this;
- }
- Text& Text::set_data(std::string data) {
- data_ = std::move(data);
- return *this;
- }
- std::string Text::delete_spaces(const std::string& str) {
- if (str.empty()) {
- return {};
- } else {
- auto left = str.find_first_not_of(' ');
- auto right = str.find_last_not_of(' ');
- return str.substr(left, right - left + 1);
- }
- }
- std::string Text::uniq_symbols(const std::string& str) {
- std::string out;
- for (char ch : str) {
- if (ch == '"') {
- out += """sv;
- continue;
- } else if (ch == '`' || ch == '\'') {
- out += "'"sv;
- continue;
- } else if (ch == '<') {
- out += "<"sv;
- continue;
- } else if (ch == '>') {
- out += ">"sv;
- continue;
- } else if (ch == '&') {
- out += "&"sv;
- continue;
- } else {
- }
- out += ch;
- }
- return out;
- }
- void Text::render_object(const RenderContext& context) const {
- std::ostream& out = context.out_;
- out << "<text ";
- render_attrs(context.out_);
- out << "x=\""
- << position_.x << "\" y=\""
- << position_.y << "\" "
- << "dx=\""
- << offset_.x << "\" dy=\""
- << offset_.y << "\" "
- << "font-size=\""
- << font_size_ << "\" ";
- if (!font_family_.empty()) {
- out << "font-family=\"" << font_family_ << "\" ";
- }
- if (!font_weight_.empty()) {
- out << "font-weight=\"" << font_weight_ << "\"";
- }
- out << ">"sv << delete_spaces(uniq_symbols(data_)) << "</text>"sv;
- }
- void Document::render(std::ostream& out) const{
- int indent = 2;
- int indent_step = 2;
- RenderContext context(out, indent_step, indent);
- const std::string_view xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"sv;
- const std::string_view svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"sv;
- out << xml << "\n"sv << svg << "\n"sv;
- for (const auto& object : objects_) {
- object->render(context);
- }
- out << "</svg>"sv;
- }
- }//end namespace svg
- -----------------------------------------------------------------------
- transport_catalogue.h
- -----------------------------------------------------------------------
- #pragma once
- #include <deque>
- #include <string>
- #include <vector>
- #include <iomanip>
- #include <iostream>
- #include <unordered_set>
- #include <unordered_map>
- #include "domain.h"
- using namespace domain;
- namespace transport_catalogue {
- struct DistanceHasher {
- std::hash<const void*> hasher;
- std::size_t operator()(const std::pair<const Stop*, const Stop*> pair_stops) const noexcept {
- auto hash_1 = static_cast<const void*>(pair_stops.first);
- auto hash_2 = static_cast<const void*>(pair_stops.second);
- return hasher(hash_1) * 17 + hasher(hash_2);
- }
- };
- typedef std::unordered_map<std::string_view, Stop*> StopMap;
- typedef std::unordered_map<std::string_view, Bus*> BusMap;
- typedef std::unordered_map<std::pair<const Stop*, const Stop*>, int, DistanceHasher> DistanceMap;
- class TransportCatalogue {
- public:
- void add_bus(Bus&& bus);
- void add_stop(Stop&& stop);
- void add_distance(const std::vector<Distance>& distances);
- Bus* get_bus(std::string_view bus_name);
- Stop* get_stop(std::string_view stop_name);
- BusMap get_busname_to_bus() const;
- StopMap get_stopname_to_stop() const;
- std::unordered_set<const Bus*> stop_get_uniq_buses(Stop* stop);
- std::unordered_set<const Stop*> get_uniq_stops(Bus* bus);
- double get_length(Bus* bus);
- size_t get_distance_stop(const Stop* start, const Stop* finish);
- size_t get_distance_to_bus(Bus* bus);
- private:
- std::deque<Stop> stops;
- StopMap stopname_to_stop;
- std::deque<Bus> buses;
- BusMap busname_to_bus;
- DistanceMap distance_to_stop;
- };
- }//end namespace transport_catalogue
- -----------------------------------------------------------------------
- transport_catalogue.cpp
- -----------------------------------------------------------------------
- #include "transport_catalogue.h"
- #include <execution>
- namespace transport_catalogue {
- void TransportCatalogue::add_stop(Stop&& stop) {
- stops.push_back(std::move(stop));
- Stop* stop_buf = &stops.back();
- stopname_to_stop.insert(transport_catalogue::StopMap::value_type(stop_buf->name, stop_buf));
- }
- void TransportCatalogue::add_bus(Bus&& bus) {
- Bus* bus_buf;
- buses.push_back(std::move(bus));
- bus_buf = &buses.back();
- busname_to_bus.insert(BusMap::value_type(bus_buf->name, bus_buf));
- for (Stop* stop : bus_buf->stops) {
- stop->buses.push_back(bus_buf);
- }
- bus_buf->route_length = get_distance_to_bus(bus_buf);
- }
- void TransportCatalogue::add_distance(const std::vector<Distance>& distances) {
- for (auto distance : distances){
- auto dist_pair = std::make_pair(distance.start, distance.end);
- distance_to_stop.insert(DistanceMap::value_type(dist_pair, distance.distance));
- }
- }
- Bus* TransportCatalogue::get_bus(std::string_view bus_name) {
- if(busname_to_bus.empty()){
- return nullptr;
- }
- try{
- return busname_to_bus.at(bus_name);
- }
- catch(const std::out_of_range &e){
- return nullptr;
- }
- }
- Stop* TransportCatalogue::get_stop(std::string_view stop_name) {
- if(stopname_to_stop.empty()){
- return nullptr;
- }
- try {
- return stopname_to_stop.at(stop_name);
- } catch(const std::out_of_range &e) {
- return nullptr;
- }
- }
- BusMap TransportCatalogue::get_busname_to_bus() const {
- return busname_to_bus;
- }
- StopMap TransportCatalogue::get_stopname_to_stop() const {
- return stopname_to_stop;
- }
- std::unordered_set<const Stop*> TransportCatalogue::get_uniq_stops(Bus* bus) {
- std::unordered_set<const Stop*> unique_stops;
- unique_stops.insert(bus->stops.begin(), bus->stops.end());
- return unique_stops;
- }
- double TransportCatalogue::get_length(Bus* bus) {
- return transform_reduce(next(bus->stops.begin()),
- bus->stops.end(),
- bus->stops.begin(),
- 0.0,
- std::plus<>{},
- [](const Stop* lhs, const Stop* rhs) {
- return geo::compute_distance({(*lhs).latitude,
- (*lhs).longitude}, {(*rhs).latitude,
- (*rhs).longitude});
- });
- }
- std::unordered_set<const Bus*> TransportCatalogue::stop_get_uniq_buses(Stop* stop){
- std::unordered_set<const Bus*> unique_stops;
- unique_stops.insert(stop->buses.begin(), stop->buses.end());
- return unique_stops;
- }
- size_t TransportCatalogue::get_distance_stop(const Stop* begin, const Stop* finish) {
- if(distance_to_stop.empty()){
- return 0;
- }
- try {
- auto dist_pair = std::make_pair(begin, finish);
- return distance_to_stop.at(dist_pair);
- } catch(const std::out_of_range &e) {
- try {
- auto dist_pair = std::make_pair(finish, begin);
- return distance_to_stop.at(dist_pair);
- } catch(const std::out_of_range &e) {
- return 0;
- }
- }
- }
- size_t TransportCatalogue::get_distance_to_bus(Bus* bus) {
- size_t distance = 0;
- auto stops_size = bus->stops.size() - 1;
- for (int i = 0; i < static_cast<int>(stops_size); i++) {
- distance += get_distance_stop(bus->stops[i], bus->stops[i+1]);
- }
- return distance;
- }
- }//end namespace transport_catalogue
Advertisement
Add Comment
Please, Sign In to add comment