Implement from OpeningHours to TimeTableSet conversion.

This commit is contained in:
Sergey Magidovich 2015-12-22 11:26:12 +03:00 committed by Sergey Yershov
parent db00bcfdee
commit 832abf1f54
8 changed files with 249 additions and 15 deletions

View file

@ -26,7 +26,9 @@
#include "rules_evaluation.hpp"
#include "parse_opening_hours.hpp"
#include <algorithm>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <ios>
#include <ostream>
@ -748,4 +750,28 @@ bool OpeningHours::IsValid() const
{
return m_valid;
}
bool OpeningHours::IsTwentyFourHours() const
{
return m_rule.size() == 1 && m_rule[0].IsTwentyFourHours();
}
bool OpeningHours::HasWeekdaySelector() const
{
return std::any_of(begin(m_rule), end(m_rule), std::mem_fn(&osmoh::RuleSequence::HasWeekdays));
}
bool OpeningHours::HasMonthSelector() const
{
return std::any_of(begin(m_rule), end(m_rule), std::mem_fn(&osmoh::RuleSequence::HasMonths));
}
bool OpeningHours::HasWeekSelector() const
{
return std::any_of(begin(m_rule), end(m_rule), std::mem_fn(&osmoh::RuleSequence::HasWeeks));
}
bool OpeningHours::HasYearSelector() const
{
return std::any_of(begin(m_rule), end(m_rule), std::mem_fn(&osmoh::RuleSequence::HasYears));
}
} // namespace osmoh

View file

@ -69,6 +69,16 @@ private:
HourMinutes operator-(HourMinutes const & hm);
std::ostream & operator<<(std::ostream & ost, HourMinutes const & hm);
inline bool operator<(HourMinutes const & a, HourMinutes const & b)
{
return a.GetDuration() < b.GetDuration();
}
inline bool operator==(HourMinutes const & a, HourMinutes const & b)
{
return a.GetDuration() == b.GetDuration();
}
class Time;
class TimeEvent
@ -661,6 +671,13 @@ public:
bool IsValid() const;
bool IsTwentyFourHours() const;
bool HasWeekdaySelector() const;
bool HasMonthSelector() const;
bool HasWeekSelector() const;
bool HasYearSelector() const;
TRuleSequences const & GetRule() const { return m_rule; }
private:
TRuleSequences m_rule;
bool const m_valid;

View file

@ -196,6 +196,8 @@ std::tm MakeTimetuple(time_t const timestamp)
namespace osmoh
{
using ::operator==;
bool IsActive(Timespan const & span, std::tm const & time)
{
// Timespan with e.h. should be split into parts with no e.h.

View file

@ -16,3 +16,4 @@ SOURCES += \
$$ROOT_DIR/testing/testingmain.cpp \
opening_hours_ui_test.cpp \
xml_feature_test.cpp \
ui2oh_test.cpp \

View file

@ -0,0 +1,113 @@
#include "testing/testing.hpp"
#include "editor/ui2oh.hpp"
using namespace osmoh;
using namespace editor;
using namespace editor::ui;
UNIT_TEST(ConvertOpeningHours)
{
{
OpeningHours oh("Mo-Fr 08:00-22:00");
TEST(oh.IsValid(), ());
TimeTableSet tts;
TEST(ConvertOpeningHours(oh, tts), ());
TEST_EQUAL(tts.Size(), 1, ());
auto const tt = tts.Front();
TEST(!tt.IsTwentyFourHours(), ());
TEST_EQUAL(tt.GetWorkingDays().size(), 5, ());
TEST_EQUAL(tt.GetOpeningTime().GetStart().GetHourMinutes().GetHoursCount(), 8, ());
TEST_EQUAL(tt.GetOpeningTime().GetEnd().GetHourMinutes().GetHoursCount(), 22, ());
}
{
OpeningHours oh("Mo-Fr 08:00-12:00, 13:00-22:00");
TEST(oh.IsValid(), ());
TimeTableSet tts;
TEST(ConvertOpeningHours(oh, tts), ());
TEST_EQUAL(tts.Size(), 1, ());
auto const tt = tts.Front();
TEST(!tt.IsTwentyFourHours(), ());
TEST_EQUAL(tt.GetWorkingDays().size(), 5, ());
TEST_EQUAL(tt.GetOpeningTime().GetStart().GetHourMinutes().GetHoursCount(), 8, ());
TEST_EQUAL(tt.GetOpeningTime().GetEnd().GetHourMinutes().GetHoursCount(), 22, ());
TEST_EQUAL(tt.GetExcludeTime().size(), 1, ());
TEST_EQUAL(tt.GetExcludeTime()[0].GetStart().GetHourMinutes().GetHoursCount(), 12, ());
TEST_EQUAL(tt.GetExcludeTime()[0].GetEnd().GetHourMinutes().GetHoursCount(), 13, ());
}
{
OpeningHours oh("Mo-Fr 08:00-10:00, 11:00-12:30, 13:00-22:00");
TEST(oh.IsValid(), ());
TimeTableSet tts;
TEST(ConvertOpeningHours(oh, tts), ());
TEST_EQUAL(tts.Size(), 1, ());
auto const tt = tts.Front();
TEST(!tt.IsTwentyFourHours(), ());
TEST_EQUAL(tt.GetWorkingDays().size(), 5, ());
TEST_EQUAL(tt.GetOpeningTime().GetStart().GetHourMinutes().GetHoursCount(), 8, ());
TEST_EQUAL(tt.GetOpeningTime().GetEnd().GetHourMinutes().GetHoursCount(), 22, ());
TEST_EQUAL(tt.GetExcludeTime().size(), 2, ());
TEST_EQUAL(tt.GetExcludeTime()[0].GetStart().GetHourMinutes().GetHoursCount(), 10, ());
TEST_EQUAL(tt.GetExcludeTime()[0].GetEnd().GetHourMinutes().GetHoursCount(), 11, ());
TEST_EQUAL(tt.GetExcludeTime()[1].GetStart().GetHourMinutes().GetHoursCount(), 12, ());
TEST_EQUAL(tt.GetExcludeTime()[1].GetEnd().GetHourMinutes().GetHoursCount(), 13, ());
TEST_EQUAL(tt.GetExcludeTime()[1].GetStart().GetHourMinutes().GetMinutesCount(), 30, ());
TEST_EQUAL(tt.GetExcludeTime()[1].GetEnd().GetHourMinutes().GetMinutesCount(), 0, ());
}
{
OpeningHours oh("Mo-Fr 08:00-10:00; Su, Sa 13:00-22:00");
TEST(oh.IsValid(), ());
TimeTableSet tts;
TEST(ConvertOpeningHours(oh, tts), ());
TEST_EQUAL(tts.Size(), 2, ());
{
auto const tt = tts.Get(0);
TEST(!tt.IsTwentyFourHours(), ());
TEST_EQUAL(tt.GetWorkingDays().size(), 5, ());
}
{
auto const tt = tts.Get(1);
TEST(!tt.IsTwentyFourHours(), ());
TEST_EQUAL(tt.GetWorkingDays().size(), 2, ());
}
}
{
OpeningHours oh("Jan Mo-Fr 08:00-10:00");
TEST(oh.IsValid(), ());
TimeTableSet tts;
TEST(!ConvertOpeningHours(oh, tts), ());
}
{
OpeningHours oh("2016 Mo-Fr 08:00-10:00");
TEST(oh.IsValid(), ());
TimeTableSet tts;
TEST(!ConvertOpeningHours(oh, tts), ());
}
{
OpeningHours oh("week 30 Mo-Fr 08:00-10:00");
TEST(oh.IsValid(), ());
TimeTableSet tts;
TEST(!ConvertOpeningHours(oh, tts), ());
}
}

View file

@ -48,18 +48,17 @@ bool FixTimeSpans(osmoh::Timespan openingTime, osmoh::TTimespans & spans)
span.GetEnd().GetHourMinutes().AddDuration(24_h);
}
sort(begin(spans), end(spans),
[](osmoh::Timespan const & s1, osmoh::Timespan const s2)
{
auto const start1 = s1.GetStart().GetHourMinutes().GetDuration();
auto const start2 = s2.GetStart().GetHourMinutes().GetDuration();
sort(begin(spans), end(spans), [](osmoh::Timespan const & s1, osmoh::Timespan const s2)
{
auto const start1 = s1.GetStart().GetHourMinutes();
auto const start2 = s2.GetStart().GetHourMinutes();
// If two spans start at the same point the longest span should be leftmost.
if (start1 == start2)
return SpanLength(s1) > SpanLength(s2);
// If two spans start at the same point the longest span should be leftmost.
if (start1 == start2)
return SpanLength(s1) > SpanLength(s2);
return start1 < start2;
});
return start1 < start2;
});
osmoh::TTimespans result{spans.front()};
for (auto i = 1, j = 0; i < spans.size(); ++i)

View file

@ -1,19 +1,95 @@
#include "editor/ui2oh.hpp"
#include "base/enumerate.hpp"
#include "std/algorithm.hpp"
#include "std/array.hpp"
#include "std/string.hpp"
#include "3party/opening_hours/opening_hours.hpp"
namespace
{
void SetUpWeekdays(osmoh::Weekdays const & wds, editor::ui::TimeTable & tt)
{
set<osmoh::Weekday> workingDays;
for (auto const & wd : wds.GetWeekdayRanges())
{
if (wd.HasSunday())
workingDays.insert(osmoh::Weekday::Sunday);
if (wd.HasMonday())
workingDays.insert(osmoh::Weekday::Monday);
if (wd.HasTuesday())
workingDays.insert(osmoh::Weekday::Tuesday);
if (wd.HasWednesday())
workingDays.insert(osmoh::Weekday::Wednesday);
if (wd.HasThursday())
workingDays.insert(osmoh::Weekday::Thursday);
if (wd.HasFriday())
workingDays.insert(osmoh::Weekday::Friday);
if (wd.HasSaturday())
workingDays.insert(osmoh::Weekday::Saturday);
}
tt.SetWorkingDays(workingDays);
}
void SetUpTimeTable(osmoh::TTimespans spans, editor::ui::TimeTable & tt)
{
using namespace osmoh;
sort(begin(spans), end(spans), [](Timespan const & a, Timespan const & b)
{
auto const start1 = a.GetStart().GetHourMinutes().GetDuration();
auto const start2 = b.GetStart().GetHourMinutes().GetDuration();
return start1 < start2;
});
// Take first start and last end as opening time span.
tt.SetOpeningTime({spans.front().GetStart(), spans.back().GetEnd()});
// Add an end of a span of index i and start of following span
// as exclude time.
for (auto i = 0; i + 1 < spans.size(); ++i)
tt.AddExcludeTime({spans[i].GetEnd(), spans[i + 1].GetStart()});
}
} // namespace
namespace editor
{
osmoh::OpeningHours ConvertOpeningHours(ui::TimeTableSet const & tt)
{
return string(); // TODO(mgsergio): // Just a dummy.
return string(); // TODO(mgsergio): Implement me.
}
ui::TimeTableSet ConvertOpeningHours(osmoh::OpeningHours const & oh)
bool ConvertOpeningHours(osmoh::OpeningHours const & oh, ui::TimeTableSet & tts)
{
return {};
if (oh.HasYearSelector() || oh.HasWeekSelector() || oh.HasMonthSelector())
return false;
tts = ui::TimeTableSet();
if (oh.IsTwentyFourHours())
return true;
for (auto const & p : my::enumerate(oh.GetRule()))
{
auto const & rulePart = p.item;
ui::TimeTable tt;
if (rulePart.HasWeekdays())
SetUpWeekdays(rulePart.GetWeekdays(), tt);
if (rulePart.HasTimes())
{
tt.SetTwentyFourHours(false);
SetUpTimeTable(rulePart.GetTimes(), tt);
}
bool const appended = p.index == 0 ? tts.Replace(tt, 0) : tts.Append(tt);
if (!appended)
return false;
}
return true;
}
} // namespace editor

View file

@ -9,6 +9,6 @@ class OpeningHours;
namespace editor
{
osmoh::OpeningHours ConvertOpeningHours(ui::TimeTableSet const & tt);
ui::TimeTableSet ConvertOpeningHours(osmoh::OpeningHours const & oh);
osmoh::OpeningHours ConvertOpeningHours(ui::TimeTableSet const & tts);
bool ConvertOpeningHours(osmoh::OpeningHours const & oh, ui::TimeTableSet & tts);
} // namespace editor