mirror of
https://github.com/GothenburgBitFactory/timewarrior.git
synced 2025-06-26 10:54:28 +02:00
data: Migrated and renamed funcitons
This commit is contained in:
parent
796efa6773
commit
39855f8006
3 changed files with 167 additions and 439 deletions
144
src/data.cpp
144
src/data.cpp
|
@ -29,6 +29,7 @@
|
|||
#include <Datetime.h>
|
||||
#include <Duration.h>
|
||||
#include <timew.h>
|
||||
#include <iostream> // TODO Remove.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// A filter is just another interval, containing start, end and tags.
|
||||
|
@ -192,6 +193,8 @@ Interval getFilter (const CLI& cli)
|
|||
}
|
||||
|
||||
filter.range = range;
|
||||
std::cout << "# getFilter:\n";
|
||||
std::cout << "# " << filter.dump () << "\n";
|
||||
return filter;
|
||||
}
|
||||
|
||||
|
@ -215,6 +218,9 @@ std::vector <Range> getHolidays (const Rules& rules)
|
|||
}
|
||||
}
|
||||
|
||||
std::cout << "# getHolidays:\n";
|
||||
for (auto& h : results)
|
||||
std::cout << "# " << h.dump () << "\n";
|
||||
return results;
|
||||
}
|
||||
|
||||
|
@ -231,8 +237,8 @@ std::vector <Range> getHolidays (const Rules& rules)
|
|||
// The result is the complete set of untrackable time that lies within the
|
||||
// input range. This will be a set of nights, weekends, holidays and lunchtimes.
|
||||
std::vector <Range> getAllExclusions (
|
||||
const Range& range,
|
||||
const Rules& rules)
|
||||
const Rules& rules,
|
||||
const Range& range)
|
||||
{
|
||||
// Start with the set of all holidays, intersected with range.
|
||||
std::vector <Range> results;
|
||||
|
@ -271,7 +277,12 @@ std::vector <Range> getAllExclusions (
|
|||
for (auto& r : exclusion.ranges (range))
|
||||
exclusionRanges.push_back (r);
|
||||
|
||||
return addRanges (range, results, exclusionRanges);
|
||||
auto all = addRanges (range, results, exclusionRanges);
|
||||
std::cout << "# getAllExclusions:\n";
|
||||
for (auto& r : all)
|
||||
std::cout << "# " << r.dump () << "\n";
|
||||
return all;
|
||||
// return addRanges (range, results, exclusionRanges);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -282,11 +293,14 @@ std::vector <Exclusion> getExclusions (const Rules& rules)
|
|||
for (auto& name : rules.all ("exclusions."))
|
||||
all.push_back (Exclusion (lowerCase (name), rules.get (name)));
|
||||
|
||||
std::cout << "# getExclusions:\n";
|
||||
for (auto& e : all)
|
||||
std::cout << "# " << e.dump () << "\n";
|
||||
return all;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::vector <Interval> getInclusions (Database& database)
|
||||
std::vector <Interval> getAllInclusions (Database& database)
|
||||
{
|
||||
std::vector <Interval> all;
|
||||
for (auto& line : database.allLines ())
|
||||
|
@ -296,6 +310,9 @@ std::vector <Interval> getInclusions (Database& database)
|
|||
all.push_back (i);
|
||||
}
|
||||
|
||||
std::cout << "# getAllInclusions:\n";
|
||||
for (auto& i : all)
|
||||
std::cout << "# " << i.dump () << "\n";
|
||||
return all;
|
||||
}
|
||||
|
||||
|
@ -306,9 +323,12 @@ std::vector <Interval> subset (
|
|||
{
|
||||
std::vector <Interval> all;
|
||||
for (auto& interval : intervals)
|
||||
if (intervalMatchesFilter (interval, filter))
|
||||
if (matchesFilter (interval, filter))
|
||||
all.push_back (interval);
|
||||
|
||||
std::cout << "# subset (filter intervals):\n";
|
||||
for (auto& i : all)
|
||||
std::cout << "# " << i.dump () << "\n";
|
||||
return all;
|
||||
}
|
||||
|
||||
|
@ -322,6 +342,9 @@ std::vector <Range> subset (
|
|||
if (range.overlap (r))
|
||||
all.push_back (r);
|
||||
|
||||
std::cout << "# subset (ranges):\n";
|
||||
for (auto& r : all)
|
||||
std::cout << "# " << r.dump () << "\n";
|
||||
return all;
|
||||
}
|
||||
|
||||
|
@ -335,11 +358,14 @@ std::vector <Interval> subset (
|
|||
if (range.overlap (interval.range))
|
||||
all.push_back (interval);
|
||||
|
||||
std::cout << "# subset (intervals):\n";
|
||||
for (auto& i : all)
|
||||
std::cout << "# " << i.dump () << "\n";
|
||||
return all;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::vector <Interval> realize (
|
||||
std::vector <Interval> collapse (
|
||||
const Interval& interval,
|
||||
const std::vector <Range>& exclusions)
|
||||
{
|
||||
|
@ -357,15 +383,13 @@ std::vector <Interval> realize (
|
|||
pieces = split_pieces;
|
||||
}
|
||||
|
||||
// Return all the fragments as intervals.
|
||||
// Return all the fragments as clipped intervals.
|
||||
for (auto& piece : pieces)
|
||||
{
|
||||
// Clone the interval, override the range.
|
||||
Interval clipped {interval};
|
||||
clipped.range = piece;
|
||||
all.push_back (clipped);
|
||||
}
|
||||
all.push_back (clip (interval, piece));
|
||||
|
||||
std::cout << "# collapse:\n";
|
||||
for (auto& i : all)
|
||||
std::cout << "# " << i.dump () << "\n";
|
||||
return all;
|
||||
}
|
||||
|
||||
|
@ -386,6 +410,9 @@ std::vector <Range> addRanges (
|
|||
if (limits.overlap (addition))
|
||||
results.push_back (addition);
|
||||
|
||||
std::cout << "# addRange:\n";
|
||||
for (auto& result : results)
|
||||
std::cout << "# " << result.dump () << "\n";
|
||||
return results;
|
||||
}
|
||||
|
||||
|
@ -406,6 +433,9 @@ std::vector <Range> subtractRanges (
|
|||
for (auto& r3 : r1.subtract (r2))
|
||||
results.push_back (limits.intersect (r3));
|
||||
|
||||
std::cout << "# addRange:\n";
|
||||
for (auto& result : results)
|
||||
std::cout << "# " << result.dump () << "\n";
|
||||
return results;
|
||||
}
|
||||
|
||||
|
@ -414,22 +444,92 @@ std::vector <Range> subtractRanges (
|
|||
// return these in a Range.
|
||||
Range outerRange (const std::vector <Interval>& intervals)
|
||||
{
|
||||
Range overall;
|
||||
|
||||
Range outer;
|
||||
for (auto& interval : intervals)
|
||||
{
|
||||
if (interval.range.start < overall.start || overall.start.toEpoch () == 0)
|
||||
overall.start = interval.range.start;
|
||||
if (interval.range.start < outer.start || outer.start.toEpoch () == 0)
|
||||
outer.start = interval.range.start;
|
||||
|
||||
// Deliberately mixed start/end.
|
||||
if (interval.range.start > overall.end)
|
||||
overall.end = interval.range.start;
|
||||
if (interval.range.start > outer.end)
|
||||
outer.end = interval.range.start;
|
||||
|
||||
if (interval.range.end > overall.end)
|
||||
overall.end = interval.range.end;
|
||||
if (interval.range.end > outer.end)
|
||||
outer.end = interval.range.end;
|
||||
|
||||
if (! interval.range.ended ())
|
||||
outer.end = Datetime ();
|
||||
}
|
||||
|
||||
return overall;
|
||||
std::cout << "# outerRange " << outer.dump () << "\n";
|
||||
return outer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// An interval matches a filter interval if the start/end overlaps, and all
|
||||
// filter interval tags are found in the interval.
|
||||
bool matchesFilter (const Interval& interval, const Interval& filter)
|
||||
{
|
||||
if ((filter.range.start.toEpoch () == 0 &&
|
||||
filter.range.end.toEpoch () == 0)
|
||||
|
||||
||
|
||||
|
||||
((interval.range.end.toEpoch () == 0 ||
|
||||
interval.range.end > filter.range.start) &&
|
||||
interval.range.start < filter.range.end))
|
||||
{
|
||||
for (auto& tag : filter.tags ())
|
||||
if (! interval.hasTag (tag))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Take an interval and clip it to the range.
|
||||
Interval clip (const Interval& interval, const Range& range)
|
||||
{
|
||||
Interval clipped {interval};
|
||||
clipped.range = clipped.range.intersect (range);
|
||||
return clipped;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::vector <Interval> getTrackedIntervals (
|
||||
Database& database,
|
||||
const Rules& rules,
|
||||
Interval& filter)
|
||||
{
|
||||
auto inclusions = getAllInclusions (database);
|
||||
|
||||
if (! filter.range.started ())
|
||||
filter.range = outerRange (inclusions);
|
||||
|
||||
// Get the set of expanded exclusions that overlap the range defined by the
|
||||
// timeline. If no range is defined, derive it from the set of all data.
|
||||
auto exclusions = getAllExclusions (rules, filter.range);
|
||||
|
||||
std::vector <Interval> intervals;
|
||||
for (auto& inclusion : subset (filter, inclusions))
|
||||
for (auto& interval : collapse (clip (inclusion, filter.range), exclusions))
|
||||
intervals.push_back (interval);
|
||||
|
||||
return intervals;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Interval getLatestInterval (Database& database)
|
||||
{
|
||||
Interval i;
|
||||
auto lastLine = database.lastLine ();
|
||||
if (lastLine != "")
|
||||
i.initialize (lastLine);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
430
src/helper.cpp
430
src/helper.cpp
|
@ -31,6 +31,7 @@
|
|||
#include <Duration.h>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <iostream> // TODO Remove.
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
|
@ -117,248 +118,37 @@ bool expandIntervalHint (
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// A filter is just another interval, containing start, end and tags.
|
||||
//
|
||||
// Supported interval forms:
|
||||
// ["from"] <date> ["to"|"-" <date>]
|
||||
// ["from"] <date> "for" <duration>
|
||||
// <duration> ["before"|"after" <date>]
|
||||
//
|
||||
Interval getFilter (const CLI& cli)
|
||||
// Excluded time is that which is not available for work.
|
||||
/*
|
||||
std::vector <Range> getExcludedRanges (Rules& rules, Range& range)
|
||||
{
|
||||
Interval filter;
|
||||
std::string start;
|
||||
std::string end;
|
||||
std::string duration;
|
||||
// Create a range representing the whole timeline.
|
||||
// If no range is defined, then assume the full range of all the inclusions.
|
||||
Range overallRange {range};
|
||||
if (! overallRange.started () &&
|
||||
! overallRange.ended ())
|
||||
overallRange = outerRange (getInclusions (database));
|
||||
|
||||
std::vector <std::string> args;
|
||||
for (auto& arg : cli._args)
|
||||
{
|
||||
if (arg.hasTag ("BINARY") ||
|
||||
arg.hasTag ("CMD") ||
|
||||
arg.hasTag ("EXT"))
|
||||
continue;
|
||||
|
||||
if (arg.hasTag ("FILTER"))
|
||||
{
|
||||
auto canonical = arg.attribute ("canonical");
|
||||
auto raw = arg.attribute ("raw");
|
||||
|
||||
if (arg.hasTag ("HINT"))
|
||||
{
|
||||
if (expandIntervalHint (canonical, start, end))
|
||||
{
|
||||
args.push_back ("<date>");
|
||||
args.push_back ("-");
|
||||
args.push_back ("<date>");
|
||||
}
|
||||
|
||||
// Hints that are not expandable to a date range are ignored.
|
||||
}
|
||||
else if (arg._lextype == Lexer::Type::date)
|
||||
{
|
||||
if (start == "")
|
||||
start = raw;
|
||||
else if (end == "")
|
||||
end = raw;
|
||||
|
||||
args.push_back ("<date>");
|
||||
}
|
||||
else if (arg._lextype == Lexer::Type::duration)
|
||||
{
|
||||
if (duration == "")
|
||||
duration = raw;
|
||||
|
||||
args.push_back ("<duration>");
|
||||
}
|
||||
else if (arg.hasTag ("KEYWORD"))
|
||||
{
|
||||
args.push_back (raw);
|
||||
}
|
||||
else
|
||||
{
|
||||
filter.tag (raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Range range;
|
||||
|
||||
// <date>
|
||||
if (args.size () == 1 &&
|
||||
args[0] == "<date>")
|
||||
{
|
||||
range.start = Datetime (start);
|
||||
range.end = Datetime ("now");
|
||||
}
|
||||
|
||||
// from <date>
|
||||
else if (args.size () == 2 &&
|
||||
args[0] == "from" &&
|
||||
args[1] == "<date>")
|
||||
{
|
||||
range.start = Datetime (start);
|
||||
range.end = Datetime ("now");
|
||||
}
|
||||
|
||||
// <date> to/- <date>
|
||||
else if (args.size () == 3 &&
|
||||
args[0] == "<date>" &&
|
||||
(args[1] == "to" || args[1] == "-") &&
|
||||
args[2] == "<date>")
|
||||
{
|
||||
range.start = Datetime (start);
|
||||
range.end = Datetime (end);
|
||||
}
|
||||
|
||||
// from/since <date> to/- <date>
|
||||
else if (args.size () == 4 &&
|
||||
args[0] == "from" &&
|
||||
args[1] == "<date>" &&
|
||||
(args[2] == "to" || args[2] == "-") &&
|
||||
args[3] == "<date>")
|
||||
{
|
||||
range.start = Datetime (start);
|
||||
range.end = Datetime (end);
|
||||
}
|
||||
|
||||
// <date> for <duration>
|
||||
else if (args.size () == 3 &&
|
||||
args[0] == "<date>" &&
|
||||
args[1] == "for" &&
|
||||
args[2] == "<duration>")
|
||||
{
|
||||
range.start = Datetime (start);
|
||||
range.end = Datetime (start) + Duration (duration).toTime_t ();
|
||||
}
|
||||
|
||||
// from/since <date> for <duration>
|
||||
else if (args.size () == 4 &&
|
||||
(args[0] == "from" || args[0] == "since") &&
|
||||
args[1] == "<date>" &&
|
||||
args[2] == "for" &&
|
||||
args[3] == "<duration>")
|
||||
{
|
||||
range.start = Datetime (start);
|
||||
range.end = Datetime (start) + Duration (duration).toTime_t ();
|
||||
}
|
||||
|
||||
// <duration> before <date>
|
||||
else if (args.size () == 3 &&
|
||||
args[0] == "<duration>" &&
|
||||
args[1] == "before" &&
|
||||
args[2] == "<date>")
|
||||
{
|
||||
range.start = Datetime (start) - Duration (duration).toTime_t ();
|
||||
range.end = Datetime (start);
|
||||
}
|
||||
|
||||
// <duration> after <date>
|
||||
else if (args.size () == 3 &&
|
||||
args[0] == "<duration>" &&
|
||||
args[1] == "after" &&
|
||||
args[2] == "<date>")
|
||||
{
|
||||
range.start = Datetime (start);
|
||||
range.end = Datetime (start) + Duration (duration).toTime_t ();
|
||||
}
|
||||
|
||||
// <duration>
|
||||
else if (args.size () == 1 &&
|
||||
args[0] == "<duration>")
|
||||
{
|
||||
range.start = Datetime ("now") - Duration (duration).toTime_t ();
|
||||
range.end = Datetime ("now");
|
||||
}
|
||||
|
||||
// Unrecognized date range construct.
|
||||
else if (args.size ())
|
||||
{
|
||||
throw std::string ("Unrecognized date range: '") + join (" ", args) + "'.";
|
||||
}
|
||||
|
||||
filter.range = range;
|
||||
return filter;
|
||||
// Cobmine all the non-trackable time.
|
||||
return getAllExclusions (rules, overallRange);
|
||||
}
|
||||
|
||||
*/
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The five different overlap possibilities:
|
||||
//
|
||||
// timeline.start timeline.end
|
||||
// | |
|
||||
// A [--------) | |
|
||||
// B [----|----) |
|
||||
// C | [------------) |
|
||||
// D | [----|----)
|
||||
// E | | [--------)
|
||||
// F [----|-------------------|----)
|
||||
// | |
|
||||
//
|
||||
// We really only need to eliminate A and F.
|
||||
//
|
||||
Timeline createTimelineFromData (
|
||||
const Rules& rules,
|
||||
Database& database,
|
||||
const Interval& filter)
|
||||
// Untracked time is that which is not excluded, and not filled. Gaps.
|
||||
std::vector <Range> getUntrackedRanges (Rules& rules)
|
||||
{
|
||||
Timeline t;
|
||||
t.range = filter.range;
|
||||
std::vector <Range> gaps;
|
||||
|
||||
// Add filtered intervals.
|
||||
for (auto& line : database.allLines ())
|
||||
{
|
||||
Interval i;
|
||||
i.initialize (line);
|
||||
if (intervalMatchesFilterInterval (i, filter))
|
||||
t.include (i);
|
||||
}
|
||||
// Get the set of expanded exclusions that overlap the range defined by the
|
||||
// timeline. If no range is defined, derive it from the set of all data.
|
||||
/*
|
||||
auto exclusions = getExcludedRanges (rules);
|
||||
*/
|
||||
|
||||
// Add exclusions from configuration.
|
||||
for (auto& name : rules.all ("exclusions."))
|
||||
t.exclude (Exclusion (lowerCase (name), rules.get (name)));
|
||||
// TODO subtract all exclusions
|
||||
// TODO subtract all inclusions
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Interval getLatestInterval (Database& database)
|
||||
{
|
||||
Interval i;
|
||||
auto lastLine = database.lastLine ();
|
||||
if (lastLine != "")
|
||||
{
|
||||
i.initialize (lastLine);
|
||||
if (! i.range.ended ())
|
||||
{
|
||||
// TODO An open interval needs to be split against all exclusions.
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// An interval matches a filter interval if the start/end overlaps, and all
|
||||
// filter interval tags are found in the interval.
|
||||
bool intervalMatchesFilterInterval (const Interval& interval, const Interval& filter)
|
||||
{
|
||||
if ((filter.range.start.toEpoch () == 0 &&
|
||||
filter.range.end.toEpoch () == 0)
|
||||
|
||||
||
|
||||
|
||||
((interval.range.end.toEpoch () == 0 ||
|
||||
interval.range.end > filter.range.start) &&
|
||||
interval.range.start < filter.range.end))
|
||||
{
|
||||
for (auto& tag : filter.tags ())
|
||||
if (! interval.hasTag (tag))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return gaps;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -394,147 +184,6 @@ std::string jsonFromIntervals (const std::vector <Interval>& intervals)
|
|||
return out.str ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Read rules and extract all holiday definitions. Create a Range for each
|
||||
// one that spans from midnight to midnight.
|
||||
std::vector <Range> rangesFromHolidays (const Rules& rules)
|
||||
{
|
||||
std::vector <Range> results;
|
||||
for (auto& holiday : rules.all ("holidays."))
|
||||
{
|
||||
auto lastDot = holiday.rfind ('.');
|
||||
if (lastDot != std::string::npos)
|
||||
{
|
||||
Range r;
|
||||
Datetime d (holiday.substr (lastDot + 1), "Y_M_D");
|
||||
r.start = d;
|
||||
++d;
|
||||
r.end = d;
|
||||
results.push_back (r);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Subset both ranges and additions by limits, and combine.
|
||||
std::vector <Range> addRanges (
|
||||
const Range& limits,
|
||||
const std::vector <Range>& ranges,
|
||||
const std::vector <Range>& additions)
|
||||
{
|
||||
std::vector <Range> results;
|
||||
|
||||
for (auto& range : ranges)
|
||||
if (limits.overlap (range))
|
||||
results.push_back (range);
|
||||
|
||||
for (auto& addition : additions)
|
||||
if (limits.overlap (addition))
|
||||
results.push_back (addition);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Subtract a set of Range from another set of Range, all within a defined
|
||||
// range.
|
||||
std::vector <Range> subtractRanges (
|
||||
const Range& limits,
|
||||
const std::vector <Range>& ranges,
|
||||
const std::vector <Range>& subtractions)
|
||||
{
|
||||
if (! subtractions.size ())
|
||||
return ranges;
|
||||
|
||||
std::vector <Range> results;
|
||||
for (auto& r1 : ranges)
|
||||
for (auto& r2 : subtractions)
|
||||
for (auto& r3 : r1.subtract (r2))
|
||||
results.push_back (limits.intersect (r3));
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// From a set of intervals, find the earliest start and the latest end, and
|
||||
// return these in a Range.
|
||||
Range overallRangeFromIntervals (const std::vector <Interval>& intervals)
|
||||
{
|
||||
Range overall;
|
||||
|
||||
for (auto& interval : intervals)
|
||||
{
|
||||
if (interval.range.start < overall.start || overall.start.toEpoch () == 0)
|
||||
overall.start = interval.range.start;
|
||||
|
||||
// Deliberately mixed start/end.
|
||||
if (interval.range.start > overall.end)
|
||||
overall.end = interval.range.start;
|
||||
|
||||
if (interval.range.end > overall.end)
|
||||
overall.end = interval.range.end;
|
||||
}
|
||||
|
||||
return overall;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// [1] Read holiday definitions from the rules, extract their dates and create
|
||||
// a set of Range from them.
|
||||
// [2] For 'exc day ...' exclusions, separate into daysOn and daysOff sets,
|
||||
// based on whether the exclusion is additive.
|
||||
// [3] Treat daysOff as additional holidays.
|
||||
// [4] Subtract daysOn from the set of holidays.
|
||||
// [5] Take all the 'exc <dayOfWeek> ...' exclusions and expand them into
|
||||
// concrete ranges within the overall range, adding them to the results.
|
||||
//
|
||||
// The result is the complete set of untrackable time that lies within the
|
||||
// input range. This will be a set of nights, weekends, holidays and lunchtimes.
|
||||
std::vector <Range> combineHolidaysAndExclusions (
|
||||
const Range& range,
|
||||
const Rules& rules,
|
||||
const std::vector <Exclusion>& exclusions)
|
||||
{
|
||||
// Start with the set of all holidays, intersected with range.
|
||||
std::vector <Range> results;
|
||||
results = addRanges (range, results, rangesFromHolidays (rules));
|
||||
|
||||
// Find exclusions 'exc day on <date>' and remove from holidays.
|
||||
// Find exlcusions 'exc day off <date>' and add to holidays.
|
||||
std::vector <Range> daysOn;
|
||||
std::vector <Range> daysOff;
|
||||
for (auto& exclusion : exclusions)
|
||||
{
|
||||
if (exclusion.tokens ()[1] == "day")
|
||||
{
|
||||
if (exclusion.additive ())
|
||||
for (auto& r : exclusion.ranges (range))
|
||||
daysOn.push_back (r);
|
||||
else
|
||||
for (auto& r : exclusion.ranges (range))
|
||||
daysOff.push_back (r);
|
||||
}
|
||||
}
|
||||
|
||||
// daysOff are combined with existing holidays.
|
||||
results = addRanges (range, results, daysOff);
|
||||
|
||||
// daysOn are subtracted from the existing holidays.
|
||||
results = subtractRanges (range, results, daysOn);
|
||||
|
||||
// Expand all exclusions that are not 'exc day ...' into excluded ranges that
|
||||
// overlage with range.
|
||||
std::vector <Range> exclusionRanges;
|
||||
for (auto& exclusion : exclusions)
|
||||
if (exclusion.tokens ()[1] != "day")
|
||||
for (auto& r : exclusion.ranges (range))
|
||||
exclusionRanges.push_back (r);
|
||||
|
||||
return addRanges (range, results, exclusionRanges);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Palette createPalette (const Rules& rules)
|
||||
{
|
||||
|
@ -587,34 +236,3 @@ int quantizeTo15Minutes (const int minutes)
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::vector <Interval> splitInterval (
|
||||
const Interval& interval,
|
||||
const std::vector <Range>& exclusions)
|
||||
{
|
||||
std::vector <Interval> all;
|
||||
|
||||
// Start with a single range from the interval, from which to subtract.
|
||||
std::vector <Range> intervalFragments {interval.range};
|
||||
for (auto& exclusion : exclusions)
|
||||
{
|
||||
std::vector <Range> brokenFragments;
|
||||
for (auto& fragment : intervalFragments)
|
||||
for (auto& broken : fragment.subtract (exclusion))
|
||||
brokenFragments.push_back (broken);
|
||||
|
||||
intervalFragments = brokenFragments;
|
||||
}
|
||||
|
||||
// Return all the fragments as intervals.
|
||||
for (auto& fragment : intervalFragments)
|
||||
{
|
||||
// Clone the interval, set the new range.
|
||||
Interval clipped {interval};
|
||||
clipped.range = fragment;
|
||||
all.push_back (clipped);
|
||||
}
|
||||
|
||||
return all;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
32
src/timew.h
32
src/timew.h
|
@ -32,10 +32,28 @@
|
|||
#include <Rules.h>
|
||||
#include <Extensions.h>
|
||||
#include <Interval.h>
|
||||
#include <Timeline.h>
|
||||
#include <Exclusion.h>
|
||||
#include <Palette.h>
|
||||
#include <Color.h>
|
||||
|
||||
// data.cpp
|
||||
Interval getFilter (const CLI&);
|
||||
std::vector <Range> getHolidays (const Rules&);
|
||||
std::vector <Exclusion> getExclusions (const Rules&);
|
||||
std::vector <Range> getAllExclusions (const Rules&, const Range&);
|
||||
std::vector <Interval> getAllInclusions (Database&);
|
||||
std::vector <Interval> subset (const Interval&, const std::vector <Interval>&);
|
||||
std::vector <Range> subset (const Range&, const std::vector <Range>&);
|
||||
std::vector <Interval> subset (const Range&, const std::vector <Interval>&);
|
||||
std::vector <Interval> collapse (const Interval&, const std::vector <Range>&);
|
||||
std::vector <Range> addRanges (const Range&, const std::vector <Range>&, const std::vector <Range>&);
|
||||
std::vector <Range> subtractRanges (const Range&, const std::vector <Range>&, const std::vector <Range>&);
|
||||
Range outerRange (const std::vector <Interval>&);
|
||||
bool matchesFilter (const Interval&, const Interval&);
|
||||
Interval clip (const Interval&, const Range&);
|
||||
std::vector <Interval> getTrackedIntervals (Database&, const Rules&, Interval&);
|
||||
Interval getLatestInterval (Database&);
|
||||
|
||||
// init.cpp
|
||||
bool lightweightVersionCheck (int, const char**);
|
||||
void initializeEntities (CLI&);
|
||||
|
@ -47,20 +65,12 @@ int dispatchCommand (const CLI&, Database&, Rules&, const Extensions&);
|
|||
Color tagColor (const Rules&, const std::string&);
|
||||
std::string intervalSummarize (const Rules&, const Interval&);
|
||||
bool expandIntervalHint (const std::string&, std::string&, std::string&);
|
||||
Timeline createTimelineFromData (const Rules&, Database&, const Interval&);
|
||||
Interval getFilter (const CLI&);
|
||||
Interval getLatestInterval (Database&);
|
||||
bool intervalMatchesFilterInterval (const Interval&, const Interval&);
|
||||
std::vector <Range> getExcludedRanges (Rules&, Range&);
|
||||
std::vector <Range> getUntrackedRanges (Rules&);
|
||||
std::string jsonFromIntervals (const std::vector <Interval>&);
|
||||
std::vector <Range> rangesFromHolidays (const Rules&);
|
||||
std::vector <Range> addRanges (const Range&, const std::vector <Range>&, const std::vector <Range>&);
|
||||
std::vector <Range> subtractRanges (const Range&, const std::vector <Range>&, const std::vector <Range>&);
|
||||
Range overallRangeFromIntervals (const std::vector <Interval>&);
|
||||
std::vector <Range> combineHolidaysAndExclusions (const Range&, const Rules&, const std::vector <Exclusion>&);
|
||||
Palette createPalette (const Rules&);
|
||||
std::map <std::string, Color> createTagColorMap (const Rules&, Palette&, const std::vector <Interval>&);
|
||||
int quantizeTo15Minutes (const int);
|
||||
std::vector <Interval> splitInterval (const Interval&, const std::vector <Range>&);
|
||||
|
||||
// utiŀ.cpp
|
||||
std::string osName ();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue