//////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2018 Leo Tenenbaum // This file is part of GraphColoring. // // GraphColoring is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // GraphColoring is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with GraphColoring. If not, see . //////////////////////////////////////////////////////////////////////////////// #include "boundrule.hpp" #include "graphcoloring/level.hpp" #include "utils/errors.hpp" namespace graphcoloring { namespace rules { BoundRule::BoundRule(gui::Color color_, int bound_, bool bound_type_, bool rule_type_) : color(color_), bound(bound_), bound_type(bound_type_), rule_type(rule_type_) {} BoundRule::BoundRule(pugi::xml_node node, const ColorLoader& color_loader) { LoadFromNode(node, color_loader); } void BoundRule::LoadFromNode(pugi::xml_node node, const ColorLoader& color_loader) { std::string name(node.name()); if (name.substr(name.length()-7) == std::string("minimum")) bound_type = MINIMUM; else bound_type = MAXIMUM; if (name.substr(0,name.length()-8) == std::string("vertex")) rule_type = VERTEX_RULE; else rule_type = EDGE_RULE; color = ColorFromAttribute(node.attribute("color"), color_loader); bound = node.attribute(bound_type == MINIMUM ? "min" : "max").as_int(0); } bool BoundRule::CheckAllCounts(const Graph& graph) const { std::map counts; for (gui::Color color : Level::colors) counts[color] = 0; if (rule_type == VERTEX_RULE) { for (const Vertex* v : graph.vertices) { if (counts.count(v->Color())) counts[v->Color()]++; } } else { for (const Edge* e : graph.edges) { if (counts.count(e->Color())) counts[e->Color()]++; else counts[e->Color()] = 1; } } for (std::pair count : counts) { if (bound_type == MINIMUM && count.second < bound) return false; if (bound_type == MAXIMUM && count.second > bound) return false; } return true; } bool BoundRule::ObeysRule(const Graph& graph) const { if (color == SAME_COLOR) // For same, check if any color is out of bounds. return CheckAllCounts(graph); int count = 0; if (rule_type == VERTEX_RULE) { for (const Vertex* v : graph.vertices) if (IsSameColor(v->Color(), color)) count++; } else { for (const Edge* e : graph.edges) if (IsSameColor(e->Color(), color)) count++; } return bound_type == MINIMUM ? (count >= bound) : (count <= bound); } int BoundRule::Render(gui::Window* window, int x, int y, int width) const { int r = Vertex::VERTEX_RADIUS; window->SetDrawColor(RenderColor(color)); if (rule_type == VERTEX_RULE) { window->DrawCircle(x+r, y+r, r, false); } else { window->DrawLine(x, y+r, x+width/4, y+r); } window->SetTextSize(r*2); window->DrawText(std::to_string(bound), gui::Position(x+width, y+r), gui::Alignment::RIGHT, gui::Alignment::CENTER); window->DrawText(bound_type == MAXIMUM ? ">" : "<", gui::Position(x+width/2, y+r), gui::Alignment::CENTER, gui::Alignment::CENTER); window->SetDrawColor(0xFF0000FF); window->DrawLine(x+3*width/8, y, x+5*width/8, y+2*r); return r*2; } } // namespace rules } // namespace graphcoloring