Timetabler
utils.cpp
1 #include "utils.h"
2 
3 #include <cctype>
4 #include <iomanip>
5 #include <iostream>
6 #include "data.h"
7 
8 namespace Utils {
9 
19 std::string getFieldTypeName(FieldType fieldType) {
20  if (fieldType == FieldType::classroom) return "Classroom";
21  if (fieldType == FieldType::instructor) return "Instructor";
22  if (fieldType == FieldType::isMinor) return "Minor Type";
23  if (fieldType == FieldType::program) return "Programs";
24  if (fieldType == FieldType::segment) return "Segment";
25  if (fieldType == FieldType::slot) return "Slot";
26  assert(false && "Invalid field type!");
27  return "Invalid Type";
28 }
29 
40 std::string getPredefinedConstraintName(const PredefinedClauses clauseType) {
41  if (clauseType == PredefinedClauses::instructorSingleCourseAtATime)
42  return "instructorSingleCourseAtATime";
43  if (clauseType == PredefinedClauses::classroomSingleCourseAtATime)
44  return "classroomSingleCourseAtATime";
45  if (clauseType == PredefinedClauses::programSingleCoreCourseAtATime)
46  return "programSingleCoreCourseAtATime";
47  if (clauseType == PredefinedClauses::minorInMinorTime)
48  return "minorInMinorTime";
49  if (clauseType == PredefinedClauses::exactlyOneSlotPerCourse)
50  return "exactlyOneSlotPerCourse";
51  if (clauseType == PredefinedClauses::exactlyOneInstructorPerCourse)
52  return "exactlyOneInstructorPerCourse";
53  if (clauseType == PredefinedClauses::exactlyOneSegmentPerCourse)
54  return "exactlyOneSegmentPerCourse";
55  if (clauseType == PredefinedClauses::exactlyOneIsMinorPerCourse)
56  return "exactlyOneIsMinorPerCourse";
57  if (clauseType == PredefinedClauses::exactlyOneClassroomPerCourse)
58  return "exactlyOneClassroomPerCourse";
59  if (clauseType == PredefinedClauses::coreInMorningTime)
60  return "coreInMorningTime";
61  if (clauseType == PredefinedClauses::electiveInNonMorningTime)
62  return "electiveInNonMorningTime";
63  if (clauseType == PredefinedClauses::programAtMostOneOfCoreOrElective)
64  return "programAtMostOneOfCoreOrElective";
65  assert(false && "Invalid predefined constraint type!");
66  return "Invalid Type";
67 }
68 
79 std::string getFieldName(FieldType fieldType, int index, Data &data) {
80  if (fieldType == FieldType::classroom)
81  return data.classrooms[index].getName();
82  if (fieldType == FieldType::instructor)
83  return data.instructors[index].getName();
84  if (fieldType == FieldType::isMinor) return data.isMinors[index].getName();
85  if (fieldType == FieldType::program) return data.programs[index].getName();
86  if (fieldType == FieldType::segment) return data.segments[index].getName();
87  if (fieldType == FieldType::slot) return data.slots[index].getName();
88  assert(false && "Invalid field type!");
89  return "Invalid Type";
90 }
91 
100 Log::Log(Severity severity, bool isDebug, int lineWidth, int indentWidth) {
101  this->severity = severity;
102  this->isDebug = isDebug;
103  this->lineWidth = lineWidth - indentWidth;
104  this->indentWidth = indentWidth;
105  this->metaWidth = 10;
106 #ifdef TIMETABLERDEBUG
107  this->metaWidth += 8;
108 #endif
109  if (severity != Severity::EMPTY) {
110  this->lineWidth -= this->metaWidth;
111  }
112 }
113 
118  if (isDebug) {
119 #ifdef TIMETABLERDEBUG
120  displayOutput(std::cerr);
121 #endif
122  } else {
123  displayOutput(std::cout);
124  }
125 }
126 
133 int Log::getSeverityCode() {
134  if (severity == Severity::EMPTY) return DisplayColour::NORMAL;
135  if (severity == Severity::INFO)
136  return DisplayColour::NORMAL;
137  else if (severity == Severity::WARNING)
138  return DisplayColour::YELLOW;
139  else if (severity == Severity::ERROR)
140  return DisplayColour::RED;
141  assert(false && "Severity code not defined!");
142  return -1;
143 }
144 
151 std::string Log::getSeverityIdentifier() {
152  if (severity == Severity::EMPTY) return "";
153  if (severity == Severity::INFO)
154  return "INFO";
155  else if (severity == Severity::WARNING)
156  return "WARNING";
157  else if (severity == Severity::ERROR)
158  return "ERROR";
159  assert(false && "Severity name not defined!");
160  return "Invalid Type";
161 }
162 
169 void Log::displayOutput(std::ostream &out) {
170  if (static_cast<int>(severity) <= verbosity) {
171  if (severity == Severity::EMPTY) {
172  out << std::string(indentWidth, ' ') << formatString(ss.str());
173  return;
174  }
175  out << "\033[" << getSeverityCode() << "m";
176  std::string label = "[" + getSeverityIdentifier() + "]";
177  if (isDebug) label += "[DEBUG]";
178  out << std::setw(metaWidth) << std::left << label;
179  out << std::string(indentWidth, ' ') << formatString(ss.str()) << std::endl;
180  out << "\033[" << 0 << "m";
181  if (severity == Severity::ERROR) {
182  exit(1);
183  }
184  }
185 }
186 
195 std::string Log::formatString(std::string str) {
196  if (lineWidth <= 0) {
197  return str;
198  }
199  int lastSpacePosition;
200  unsigned strPos = 0;
201  while (strPos < str.size()) {
202  if (static_cast<int>(str.size() - strPos) <= lineWidth) break;
203  lastSpacePosition = -1;
204  for (int i = 0; i < lineWidth && strPos < str.size(); i++, strPos++) {
205  if (std::isspace(str[strPos])) {
206  lastSpacePosition = strPos;
207  }
208  }
209  if (lastSpacePosition > 0) {
210  str[lastSpacePosition] = '\n';
211  if (indentWidth > 0) {
212  str = applyIndent(str, lastSpacePosition);
213  strPos = lastSpacePosition + indentWidth + 1;
214  } else {
215  strPos = lastSpacePosition + 1;
216  }
217  } else {
218  while (strPos < str.size() && !std::isspace(str[strPos])) strPos++;
219  if (strPos < str.size()) {
220  str[strPos] = '\n';
221  if (indentWidth > 0) {
222  str = applyIndent(str, strPos);
223  strPos = strPos + indentWidth;
224  }
225  strPos++;
226  }
227  }
228  }
229  return str;
230 }
231 
241 std::string Log::applyIndent(std::string str, int position) {
242  int indentToApply = indentWidth;
243  if (severity != Severity::EMPTY) {
244  indentToApply += metaWidth;
245  }
246  std::string strAfterThisPos = str.substr(position + 1);
247  std::string strBeforeThisPos = str.substr(0, position + 1);
248  return strBeforeThisPos + std::string(indentToApply, ' ') + strAfterThisPos;
249 }
250 
258 void Log::setVerbosity(int verb) { verbosity = verb; }
259 
260 int Log::verbosity = 3;
261 
262 } // namespace Utils
static void setVerbosity(int verb)
Sets the verbosity level for logging. (0 - EMPTY, 1 - ERROR, 2 - WARNING, 3 - INFO). All messages of levels in and below the current verbosity level are displayed in the output.
Definition: utils.cpp:258
std::vector< Segment > segments
Definition: data.h:52
std::vector< Classroom > classrooms
Definition: data.h:44
std::vector< Slot > slots
Definition: data.h:56
Log(Severity severity=Severity::EMPTY, bool isDebug=false, int lineWidth=0, int indentWidth=0)
Constructor for the Logger.
Definition: utils.cpp:100
std::vector< IsMinor > isMinors
Definition: data.h:60
std::string getPredefinedConstraintName(const PredefinedClauses clauseType)
Gets the predefined constraint name as a string.
Definition: utils.cpp:40
std::vector< Instructor > instructors
Definition: data.h:40
PredefinedClauses
Enum that represents all the predefined constraints.
Definition: global.h:14
std::string getFieldName(FieldType fieldType, int index, Data &data)
Gets the field name in the Data of a given FieldType at a given index.
Definition: utils.cpp:79
FieldType
Enum that represents all the field types.
Definition: global.h:9
~Log()
Displays output and destroys object.
Definition: utils.cpp:117
Severity
Specify severity levels for logging.
Definition: utils.h:124
Class for data.
Definition: data.h:31
Definition: utils.h:16
std::string getFieldTypeName(FieldType fieldType)
Gets the field type name as a string.
Definition: utils.cpp:19
std::vector< Program > programs
Definition: data.h:48