#include "reader.hpp"
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonValue>
#include <functional>
#include <iterator>
namespace advisor {
namespace reader {
namespace {
course::major major(const QJsonObject& m);
course::offering offering(const QJsonObject& o);
timings::timings timings(const QJsonObject& t);
std::set<QDate> days(const QJsonArray& days);
course::set prerequisites(const QJsonArray& ps);
course::requirements requirements(const QJsonArray& reqs);
course::requirements::value_type requirement(const QJsonObject& r);
template<typename Ts, typename Treader>
Ts read(const QJsonArray& a, Treader&& f) {
Ts c;
std::transform(a.constBegin(), a.constEnd(), std::inserter(c, c.begin()),
std::forward<Treader>(f));
return c;
}
} // namespace (anonymous)
std::set<course::major> majors(const QJsonDocument& in) {
return read<std::set<course::major>>(in.array(), [](const QJsonValue& v) {
return major(v.toObject());
});
}
std::set<course::offering> offerings(const QJsonDocument& in) {
return read<std::set<course::offering>>(in.array(), [](const QJsonValue& v) {
return offering(v.toObject());
});
}
course::requirements requirements(const QJsonDocument& in) {
return requirements(in.array());
}
namespace {
course::major major(const QJsonObject& m) {
const auto& name = m.value("name").toString();
const auto& department = m.value("department").toString();
const auto& reqs = requirements(m.value("requirements").toArray());
return {name, department, reqs};
}
course::offering offering(const QJsonObject& o) {
const course::code code{o.value("code").toString().toStdString()};
const auto& section = o.value("section").toString().toInt();
const auto& credits = o.value("credits").toString().toInt();
const auto& timings = reader::timings(o.value("timings").toObject());
return {code, section, credits, timings};
}
timings::timings timings(const QJsonObject& t) {
const auto& time_fmt = "hh:mm";
const auto& start = QTime::fromString(t.value("start").toString(), time_fmt);
const auto& end = QTime::fromString(t.value("end").toString(), time_fmt);
const auto& days = reader::days(t.value("days").toArray());
return {start, end, days};
}
std::set<QDate> days(const QJsonArray& days) {
return read<std::set<QDate>>(days, [](const QJsonValue& day) {
return QDate::fromString(day.toString(), "ddd");
});
}
course::requirements requirements(const QJsonArray& reqs) {
return read<course::requirements>(reqs, [](const QJsonValue& v) {
return requirement(v.toObject());
});
}
course::requirements::value_type requirement(const QJsonObject& r) {
const course::code code{r.value("code").toString().toStdString()};
const auto& prereqs = prerequisites(r.value("prerequisites").toArray());
return {code, prereqs};
}
course::set prerequisites(const QJsonArray& ps) {
return read<course::set>(ps, [](const QJsonValue& v) {
return course::code{v.toString().toStdString()};
});
}
} // namespace (anonymous)
} // namespace reader
} // namespace advisor