Timeline: work out a scheme of Invariants and Normalisation for the ZoomWindow

Getting all those requirements translated into code turns out to be a challenging task;
and the usual ascent to handle such a situation is to define **Invariants**
in conjunction with a normalisation scheme; each manipulation will then be
translated into invocation of one of the three fundamental mutators,
and these in turn always lead into the common normalisation sequence.

__Invariants__
- oriented and non-empty windows
- never alter given pxWidth
- zoom metric factor < max zoom
- visibleWindow ⊂ Canvas
This commit is contained in:
Fischlurch 2022-11-05 23:45:33 +01:00
parent f2ef893adb
commit 5ed5905d7f
3 changed files with 763 additions and 109 deletions

View file

@ -82,9 +82,11 @@
#include "lib/rational.hpp"
#include "lib/time/timevalue.hpp"
#include "lib/nocopy.hpp"
#include "lib/util.hpp"
//#include "lib/idi/entry-id.hpp"
//#include "lib/symbol.hpp"
#include <limits>
//#include <utility>
//#include <string>
@ -105,11 +107,39 @@ namespace model {
using util::Rat;
using util::rational_cast;
namespace {
/** the deepest zoom is to use 2px per micro-tick */
const uint ZOOM_MAX_RESOLUTION = 2 * TimeValue::SCALE;
using util::min;
using util::max;
namespace { ///////////////////////////////////////////////////////////////////////////////////////////////TICKET #1259 : reorganise raw time base datatypes : need conversion path into FSecs
/**
* @todo preliminary helper to enter into fractional integer calculations
* - FSecs (maybe better called `RSec`) should be a light-weight wrapper
* on top of util::Rat = `boost::rational<int64_t>`
* - a conversion function like in TimeVar should be in the base type
* - however, cross conversion from raw int64_t should be prohibited
* to avoid ill-guided automatic conversions from µ-tick to seconds
*/
inline FSecs
_FSecs (TimeValue const& timeVal)
{
return FSecs{_raw(timeVal), TimeValue::SCALE};
}
}
/** the deepest zoom is to use 2px per micro-tick */
const uint ZOOM_MAX_RESOLUTION = 2 * TimeValue::SCALE;
namespace {// initial values (rather arbitrary)
const FSecs DEFAULT_CANVAS{23};
const Rat DEFAULT_METRIC{25};
const uint MAX_PX_WIDTH{1000000};
const FSecs MAX_TIMESPAN{_FSecs(Time::MAX-Time::MIN)};
const FSecs MICRO_TICK{1_r/Time::SCALE};
const Rat FRACT_ULP{1_r/std::numeric_limits<int64_t>::max()};
}
/**
* A component to ensure uniform handling of zoom scale
* and visible interval on the timeline. Changes through
@ -129,23 +159,21 @@ namespace model {
{
TimeVar startAll_, afterAll_,
startWin_, afterWin_;
uint px_per_sec_; ///////////////////TODO use rational
Rat px_per_sec_;
public:
ZoomWindow (TimeSpan timeline =TimeSpan{Time::ZERO, FSecs(23)})
ZoomWindow (uint pxWidth, TimeSpan timeline =TimeSpan{Time::ZERO, DEFAULT_CANVAS})
: startAll_{timeline.start()}
, afterAll_{nonEmpty(timeline.end())}
, afterAll_{ensureNonEmpty(startAll_, timeline.end())}
, startWin_{startAll_}
, afterWin_{afterAll_}
, px_per_sec_{25}
{ }
, px_per_sec_{establishMetric (pxWidth, startWin_, afterWin_)}
{
ensureInvariants();
}
ZoomWindow (uint pxWidth, TimeSpan timeline =TimeSpan{Time::ZERO, FSecs(23)})
: startAll_{timeline.start()}
, afterAll_{nonEmpty(timeline.end())}
, startWin_{startAll_}
, afterWin_{afterAll_}
, px_per_sec_{25}
ZoomWindow (TimeSpan timeline =TimeSpan{Time::ZERO, DEFAULT_CANVAS})
: ZoomWindow{0, timeline} //see ensureConsistent()
{ }
TimeSpan
@ -169,11 +197,12 @@ namespace model {
uint
pxWidth() const
{
REQUIRE (0 < _raw(afterWin_ - startWin_));
return rational_cast<uint> (px_per_sec() / FSecs(afterWin_-startWin_));
REQUIRE (startWin_ < afterWin_);
return rational_cast<uint> (px_per_sec() * FSecs(afterWin_-startWin_));
}
/* === Mutators === */
void
@ -185,7 +214,7 @@ namespace model {
void
setMetric (Rat px_per_sec)
{
UNIMPLEMENTED ("setMetric");
mutateScale (px_per_sec);
}
/**
@ -201,12 +230,11 @@ namespace model {
void
nudgeMetric (int steps)
{
uint changedScale =
steps > 0 ? px_per_sec_ << steps
: px_per_sec_ >> -steps;
if (0 < changedScale
and changedScale <= ZOOM_MAX_RESOLUTION)
mutateScale (changedScale);
mutateScale(
steps > 0 ? Rat{px_per_sec_.numerator() << steps
,px_per_sec_.denominator()}
: Rat{px_per_sec_.numerator()
,px_per_sec_.denominator() << -steps});
}
void
@ -283,104 +311,203 @@ namespace model {
UNIMPLEMENTED ("navigate Zoom History");
}
private:
/* === adjust and coordinate === */
TimeValue
nonEmpty (TimeValue endPoint)
private:
/* === establish and maintain invariants === */
/*
* - oriented and non-empty windows
* - never alter given pxWidth
* - zoom metric factor < max zoom
* - visibleWindow Canvas
*/
static TimeValue
ensureNonEmpty (TimeVar& startRef, TimeValue endPoint)
{
if (startAll_ < endPoint)
if (startRef < endPoint)
return endPoint;
if (startAll_ < Time::MAX)
return TimeValue{startAll_ + 1};
startAll_ = Time::MAX - TimeValue(1);
if (startRef <= Time::MAX - Time{DEFAULT_CANVAS})
return startRef + Time{DEFAULT_CANVAS};
startRef = Time::MAX - Time{DEFAULT_CANVAS};
return Time::MAX;
}
static Rat
establishMetric (uint pxWidth, Time startWin, Time afterWin)
{
REQUIRE (startWin < afterWin);
FSecs dur = _FSecs(afterWin-startWin);
if (pxWidth == 0 or pxWidth > MAX_PX_WIDTH) // default to sane pixel width
pxWidth = max<uint> (1, rational_cast<uint> (DEFAULT_METRIC * dur));
Rat metric = Rat(pxWidth) / dur;
// rational arithmetic ensures we can always reproduce the pxWidth
ENSURE (pxWidth == rational_cast<uint> (metric*dur));
ENSURE (0 < metric);
return metric;
}
Rat
conformMetricToWindow (uint pxWidth)
{
REQUIRE (pxWidth > 0);
REQUIRE (afterWin_> startWin_);
FSecs dur{afterWin_-startWin_};
Rat adjMetric = Rat(pxWidth) / dur;
ENSURE (pxWidth == rational_cast<uint> (adjMetric*dur));
return adjMetric;
}
void
conformWindowToMetric (Rat changedMetric)
{
REQUIRE (changedMetric > 0);
REQUIRE (afterWin_> startWin_);
FSecs dur{afterWin_-startWin_};
uint pxWidth = rational_cast<uint> (px_per_sec_*dur);
dur = Rat(pxWidth) / changedMetric;
dur += MICRO_TICK - FRACT_ULP; // prefer bias towards increased window instead of increased metric
dur = min (dur, MAX_TIMESPAN);
dur = max (dur, MICRO_TICK); // prevent window going void
if (startWin_<= Time::MAX - Time{dur})
afterWin_ = startWin_ + Time{dur};
else
{
startWin_ = Time::MAX - Time{dur};
afterWin_ = Time::MAX;
}
// re-check metric to maintain precise pxWidth
px_per_sec_ = conformMetricToWindow (pxWidth);
ENSURE (_FSecs(afterWin_-startWin_) < MAX_TIMESPAN);
ENSURE (px_per_sec_<= changedMetric); // bias towards increased window
}
void
conformWindowToCanvas()
{
FSecs dur{afterWin_-startWin_};
REQUIRE (dur < MAX_TIMESPAN);
REQUIRE (Time::MIN <= startWin_);
REQUIRE (afterWin_ <= Time::MAX);
if (dur <= _FSecs(afterAll_-startAll_))
{//possibly shift into current canvas
if (afterWin_ > afterAll_)
{
Offset shift{afterWin_ - afterAll_};
startWin_ -= shift;
afterWin_ -= shift;
}
else
if (startWin_ < startAll_)
{
Offset shift{startAll_ - startWin_};
startWin_ += shift;
afterWin_ += shift;
}
}
else
{//need to cap window to fit into canvas
startWin_ = startAll_;
afterWin_ = afterAll_;
}
ENSURE (startAll_ <= startWin_);
ENSURE (afterWin_ <= afterAll_);
}
void
conformToBounds (Rat changedMetric)
{
if (changedMetric > ZOOM_MAX_RESOLUTION)
{
changedMetric = ZOOM_MAX_RESOLUTION;
conformWindowToMetric (changedMetric);
}
startAll_ = min (startAll_, startWin_);
afterAll_ = max (afterAll_, afterWin_);
ENSURE (Time::MIN <= startWin_);
ENSURE (afterWin_ <= Time::MAX);
ENSURE (startAll_ <= startWin_);
ENSURE (afterWin_ <= afterAll_);
ENSURE (px_per_sec_ <= ZOOM_MAX_RESOLUTION);
ENSURE (px_per_sec_ <= changedMetric); // bias
}
/**
* Procedure to (re)establish the invariants.
* Adjustments should be done first to windows,
* then to the metric, using #conformWindowToMetric().
* Then this function shall be called and will first
* shift and possibly cap the window, then reestablish
* the metric and possibly increase the canvas to keep
* ensure the ZOOM_MAX_RESOLUTION is not exceeded.
* These steps ensure overall pixel size remains stable.
*/
void
ensureInvariants(uint px =0)
{
if (px==0) px = pxWidth();
conformWindowToCanvas();
px_per_sec_ = conformMetricToWindow (px);
conformToBounds (px_per_sec_);
}
/* === adjust and coordinate window parameters === */
/** @internal change Window TimeSpan, validate and adjust all params */
void
mutateWindow (TimeVar start, TimeVar after)
{
if (not (start < after))
{
if (after == Time::MAX)
start = Time::MAX - TimeValue(1);
else
after = start + TimeValue(1);
}
FSecs dur{after - start};
if (dur > FSecs{afterAll_ - startAll_})
{
start = startAll_;
after = afterAll_;
}
else
if (start < startAll_)
{
start = startAll_;
after = start + dur;
}
else
if (after > afterAll_)
{
after = afterAll_;
start = after - dur;
}
ASSERT (after-start <= afterAll_-startAll_);
px_per_sec_ = adjustedScale (start,after, startWin_,afterWin_);
uint px{pxWidth()};
startWin_ = start;
afterWin_ = after;
afterWin_ = ensureNonEmpty (startWin_, after);
px_per_sec_ = conformMetricToWindow (px);
ensureInvariants (px);
fireChangeNotification();
}
/**
/**
* @internal adjust Window to match given scale,
* validate and adjust all params */
void
mutateScale (uint px_per_sec)
mutateScale (Rat changedMetric)
{
if (px_per_sec == 0) px_per_sec = 1;
if (px_per_sec == px_per_sec_) return;
changedMetric = min (changedMetric, ZOOM_MAX_RESOLUTION);
if (changedMetric == px_per_sec_) return;
FSecs changeFactor{px_per_sec, px_per_sec_};
Rat changeFactor{changedMetric / px_per_sec_};
FSecs dur{afterWin_ - startWin_};
dur /= changeFactor;
if (dur > FSecs{afterAll_ - startAll_})
{// limit to the overall timespan...
px_per_sec_ = adjustedScale (startAll_,afterAll_, startWin_,afterWin_);
uint px{pxWidth()};
startWin_ = startAll_;
afterWin_ = afterAll_;
px_per_sec_ = conformMetricToWindow(px);
ensureInvariants (px);
fireChangeNotification();
}
else
{
TimeVar start{anchorPoint() - dur*relativeAnchor()};
if (start < startAll_)
start = startAll_;
TimeVar after{start + dur};
if (after > afterAll_)
{
after = afterAll_;
start = afterAll_ - dur;
}
ASSERT (after-start <= afterAll_-startAll_);
if (start == startWin_ and after == afterWin_)
return; // nothing changed effectively
px_per_sec_ = adjustedScale (start,after, startWin_,afterWin_);
startWin_ = start;
afterWin_ = after;
}
fireChangeNotification();
mutateDuration (dur);
}
/** @internal change visible duration centred around anchor point,
* validate and adjust all params */
void
mutateDuration (Duration duration)
mutateDuration (FSecs duration)
{
UNIMPLEMENTED ("change visible duration, validate and adjust all params");
if (duration <= 0)
duration = DEFAULT_CANVAS;
uint px{pxWidth()};
TimeVar start{anchorPoint() - duration*relativeAnchor()};
TimeVar after{start + duration};
if (start == startWin_ and after == afterWin_)
return; // nothing changed effectively
Rat changedMetric = adjustedScale (start,after, startWin_,afterWin_);
conformWindowToMetric (changedMetric);
ensureInvariants(px);
fireChangeNotification();
}
@ -392,12 +519,12 @@ namespace model {
* @param afterOld previous end point
* @return adapted scale factor in pixel per second, rounded half up to the next pixel.
*/
uint
Rat
adjustedScale (TimeVar startNew, TimeVar afterNew, TimeVar startOld, TimeVar afterOld)
{
REQUIRE (startOld < afterOld);
FSecs factor = FSecs{afterNew - startNew} / FSecs{afterOld - startOld};
return boost::rational_cast<uint>(px_per_sec_ / factor + 1/2); // rounding half pixels
REQUIRE (startNew < afterNew and startOld < afterOld);
Rat change{_raw(afterNew - startNew), _raw(afterOld - startOld)};
return px_per_sec_ / change;
}
/**
@ -413,7 +540,7 @@ namespace model {
FSecs
anchorPoint() const
{
return startWin_ + FSecs{afterWin_-startWin_} * relativeAnchor();
return startWin_ + FSecs{afterWin_-startWin_} * relativeAnchor();
}
/**
@ -423,13 +550,13 @@ namespace model {
* to the current visible window's position within the overall timeline; if it's
* close to the beginning, the anchor point is also rather to the beginning...
*/
FSecs
Rat
relativeAnchor() const
{
// the visible window itself has to fit in, which reduces the action range
FSecs possibleRange = (afterAll_-startAll_) - (afterWin_-startWin_);
if (possibleRange == 0) // if there is no room for scrolling...
return FSecs{1,2}; // then anchor zooming in the middle
if (possibleRange <= 0) // if there is no room for scrolling...
return 1_r/2; // then anchor zooming in the middle
// use a 3rd degree parabola to favour positions in the middle
FSecs posFactor = FSecs{startWin_-startAll_} / possibleRange;

View file

@ -66,9 +66,9 @@ namespace test {
CHECK (_t(10,3) == Time{FSecs(10,3)}); // Time point at t = 10/3sec (fractional number)
CHECK (FSecs(10,3) == FSecs(10)/3); // fractional number arithmetics
CHECK (FSecs(10)/3 == 10_r/3); // _r is a user defined literal to denote 64-bit fractional
CHECK (10_r/3 == Rat(10,3));
CHECK (Rat(10/3) == boost::rational<int64_t>(10,3)); // using Rat = boost::rational<int64_t>
CHECK (rational_cast<float> (10_r/3) == 3.33333f); // rational_cast performs the division with indicated type
CHECK (Rat(10,3) == 10_r/3);
CHECK (Rat(10,3) == boost::rational<int64_t>(10,3)); // using Rat = boost::rational<int64_t>
CHECK (rational_cast<float> (10_r/3) == 3.33333f); // rational_cast calculates division after type conversion
verify_simpleUsage();
verify_setup();
@ -101,10 +101,11 @@ namespace test {
/** @test verify the possible variations for initial setup of the zoom window
* - can be defined either the canvas duration, or an explicit extension
* given in pixels, or both
* - window extension, when given, defines the visible span
* - otherwise the whole canvas is visible, thereby defining the metric
* - can be defined either the canvas duration,
* or an explicit extension given in pixels, or both
* - after construction, visible window always covers whole canvas
* - window extension, when given, defines the initial metric
* - otherwise pixel extension is derived from default metric
*/
void
verify_setup()
@ -112,26 +113,26 @@ namespace test {
ZoomWindow win1;
CHECK (win1.overallSpan() == TimeSpan(_t(0), FSecs(23)));
CHECK (win1.visible() == win1.overallSpan());
CHECK (win1.pxWidth() == 25*23);
CHECK (win1.px_per_sec() == 25);
CHECK (win1.pxWidth() == 23*25);
ZoomWindow win2{TimeSpan{_t(-1), _t(+1)}};
CHECK (win2.overallSpan() == TimeSpan(_t(-1), FSecs(2)));
CHECK (win2.visible() == win2.overallSpan());
CHECK (win2.pxWidth() == 25*2);
CHECK (win2.px_per_sec() == 25);
CHECK (win2.pxWidth() == 2*25);
ZoomWindow win3{555};
CHECK (win3.overallSpan() == TimeSpan(_t(0), FSecs(23)));
CHECK (win3.visible() == win3.overallSpan());
CHECK (win3.pxWidth() == 555);
CHECK (win3.px_per_sec() == 555_r/23);
CHECK (win3.visible() == win3.overallSpan());
ZoomWindow win4{555, TimeSpan{_t(-10), _t(-5)}};
CHECK (win4.overallSpan() == TimeSpan(_t(10), FSecs(5)));
CHECK (win4.visible() == win4.overallSpan());
CHECK (win4.pxWidth() == 555);
CHECK (win4.px_per_sec() == 111);
CHECK (win4.visible() == win4.overallSpan());
}

View file

@ -38638,9 +38638,24 @@
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592413859" ID="ID_745987096" MODIFIED="1667592507648" TEXT="brauche dazu einen offiziellen Zugang zu einer fraktionalen Repr&#xe4;sentation">
<icon BUILTIN="yes"/>
<node CREATED="1667592510702" ID="ID_669892678" MODIFIED="1667592532079" TEXT="Duration &#x27f6; FSec"/>
<node CREATED="1667592539018" ID="ID_1283310585" MODIFIED="1667592544568" TEXT="Offset &#x27f6; FSec"/>
<node CREATED="1667592532973" ID="ID_31952265" MODIFIED="1667592538214" TEXT="Time &#x27f6; FSec"/>
</node>
<node COLOR="#338800" CREATED="1667593654463" ID="ID_1694088540" MODIFIED="1667593677324" TEXT="vorl&#xe4;ufige Zwischenl&#xf6;sung: _FSecs() direkt in ZoomWindow-Header">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1667488158059" ID="ID_898168096" MODIFIED="1667491200716" TEXT="neue Zielvorgabe: Pixel-Angaben sind stets pr&#xe4;zise">
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593710047" ID="ID_920638973" MODIFIED="1667593745244" TEXT="kein Runden mehr, sondern nur noch truncate">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593719313" ID="ID_317494909" MODIFIED="1667593745245" TEXT="daf&#xfc;r die Toleranz senken auf der Metrik">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
</node>
@ -38660,6 +38675,378 @@
</html></richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1667603662334" ID="ID_162164091" MODIFIED="1667603891148" TEXT="drehe mich mit den geforderten Randbedingungen im Kreis">
<arrowlink COLOR="#ec1941" DESTINATION="ID_1507636517" ENDARROW="Default" ENDINCLINATION="27;-47;" ID="Arrow_ID_49426086" STARTARROW="None" STARTINCLINATION="-122;6;"/>
<icon BUILTIN="stop-sign"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1667603756089" ID="ID_1802881683" MODIFIED="1667603844726" TEXT="m&#xf6;chte einen maximal-Zoom-Faktor vorgeben">
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1667603784445" ID="ID_1006588421" MODIFIED="1667603844726" TEXT="Fenster soll immer im Canvas bleiben">
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1667603813378" ID="ID_1979403390" MODIFIED="1667603844727" TEXT="Pixel-Vorgaben stets einzuhalten">
<icon BUILTIN="yes"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667603646312" ID="ID_1507636517" MODIFIED="1667603891148" TEXT="mu&#xdf; Invarianten sicherstellen">
<linktarget COLOR="#ec1941" DESTINATION="ID_1507636517" ENDARROW="Default" ENDINCLINATION="27;-47;" ID="Arrow_ID_49426086" SOURCE="ID_162164091" STARTARROW="None" STARTINCLINATION="-122;6;"/>
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1667603900358" ID="ID_353785530" MODIFIED="1667603950298" TEXT="das gew&#xe4;hlte Implementierungs-Schema ist nicht beherrschbar">
<icon BUILTIN="broken-line"/>
<node CREATED="1667603974758" ID="ID_1895105732" MODIFIED="1667603997149" TEXT="Konstuktor legt sichere Startwerte fest"/>
<node CREATED="1667603997785" ID="ID_1559828104" MODIFIED="1667604014827" TEXT="von dort weiter, mit Einzelfall-bezogenen Regeln"/>
</node>
<node CREATED="1667604115641" ID="ID_340228791" MODIFIED="1667604155428">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
mein Anspruch ist, hier eine <b>absolut fehlerfrei</b>&#160;arbeitende Komponente zu schreiben
</p>
</body>
</html></richcontent>
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1667604025125" ID="ID_573471794" MODIFIED="1667604225117" TEXT="die Korrektur-Regeln zum Einhalten der Constraints sind komplex (im Allgemeinen)">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...und zwar, wenn man <i>wirklich alle</i>&#160;Eingangswerte zul&#228;&#223;t, und sich eben nicht nur auf <i>vern&#252;nftige </i>Eingaben <i>verl&#228;&#223;t.</i>
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1667604082603" ID="ID_1966401065" MODIFIED="1667604109981" TEXT="ich mu&#xdf; letztlich Verg&#xf6;&#xdf;erung des Canvas zulassen (oder beliebig starken Zoom)">
<node CREATED="1667604258315" ID="ID_539837281" MODIFIED="1667604273064" TEXT="Canvas-Vergr&#xf6;&#xdf;erung erscheint mir pragmatischer"/>
<node CREATED="1667604319406" ID="ID_169844915" MODIFIED="1667604346784" TEXT="ich m&#xf6;chte den Zoom-Faktor auf eine technisch realisierbare Spanne beschr&#xe4;nken"/>
<node CREATED="1667604407474" ID="ID_1964908869" MODIFIED="1667609918926" TEXT="diese Spanne kann in der logarithmischen Skala vergleichsweise rasch durchschritten werden.">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
so &#177;15 2er-Potenz-Schritte gen&#252;gen, um von der maximalen Aufl&#246;sung in den Minuten-Bereich zu kommen
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1667610042409" ID="ID_1645790878" MODIFIED="1667610212422" TEXT="es kann nicht die Aufgabe des ZoomWindow sein, sinnvolle Speicher-Limits einzuhalten">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
insofern mu&#223; es dann aber auch mit maximal gro&#223;en Integer-Zahlen noch sauber funktionieren
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1667610216018" ID="ID_399148751" MODIFIED="1667610253025" TEXT="insofern ist das hier auch eine sportliche Herausforderung">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...einmal wirklich sicheren Code schreiben...
</p>
</body>
</html></richcontent>
<icon BUILTIN="ksmiletris"/>
</node>
</node>
<node CREATED="1667610259517" ID="ID_738196107" MODIFIED="1667610281605" TEXT="andere Code-Struktur als L&#xf6;sung?">
<node CREATED="1667610283233" ID="ID_1965026515" MODIFIED="1667610294374" TEXT="Konstruktur initialisiert nur"/>
<node CREATED="1667610295059" ID="ID_15303386" MODIFIED="1667610302622" TEXT="es gibt eine Invarianten-Funktion"/>
<node CREATED="1667610303406" ID="ID_268951847" MODIFIED="1667610331180" TEXT="diese f&#xfc;hrt eine feste Folge von Pr&#xfc;f- und Korrekturschritten aus"/>
<node CREATED="1667610416991" ID="ID_1022295277" MODIFIED="1667610430339" TEXT="und die gleiche Funktion wird nach jeder &#xc4;nderung gleicherma&#xdf;en angewendet"/>
</node>
<node CREATED="1667610443917" ID="ID_156996069" MODIFIED="1667610464053" TEXT="Invariante(n)">
<node CREATED="1667610465437" ID="ID_1890704401" MODIFIED="1667660026181" TEXT="pxWidth konstant erhalten">
<icon BUILTIN="full-1"/>
</node>
<node CREATED="1667610496460" ID="ID_1598935964" MODIFIED="1667660029149" TEXT="Metrik &lt; Maximal-Faktor">
<icon BUILTIN="full-2"/>
</node>
<node CREATED="1667610522737" ID="ID_870501024" MODIFIED="1667660034107" TEXT="visibleWindow &#x2282; Canvas">
<icon BUILTIN="full-3"/>
</node>
</node>
<node CREATED="1667610617421" ID="ID_1255567216" MODIFIED="1667659859838" TEXT="Ausgleichs-Regeln">
<icon BUILTIN="idea"/>
<node COLOR="#338800" CREATED="1667610965654" ID="ID_1822123568" MODIFIED="1667667095016" TEXT="Canvas und Fenster orientieren">
<icon BUILTIN="button_ok"/>
<node CREATED="1667667099807" ID="ID_313293093" MODIFIED="1667667110754" TEXT="kann relativ brachial erfolgen">
<icon BUILTIN="yes"/>
</node>
<node CREATED="1667667111845" ID="ID_240814651" MODIFIED="1667667131096" TEXT="Input kann nur leer sein, nicht negativ"/>
<node CREATED="1667667143969" ID="ID_971076298" MODIFIED="1667667564598" TEXT="falls leer, weite aus auf DEFAULT_CANVAS (&#x2259; 23sec)">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...zun&#228;chst habe ich hier immer nur das Minimale getan, n&#228;mlich 1 &#181;Tick aufgeweitet; dies w&#252;rde zwar funktionieren, aber in der Regel nicht zu einem praktikablen Verhalten f&#252;hren &#8212; wohingegen der <i>DEFAULT_CANVAS</i>&#160; so gew&#228;hlt ist, da&#223; er klein und handlich ist
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1667667185251" ID="ID_396603353" MODIFIED="1667667316295" TEXT="extrem gro&#xdf;e Canvas oder Fenster sind nicht gef&#xe4;hrlich">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
sofern wir den Speicher haben...
</p>
<p>
Will sagen, sie sind nicht gef&#228;hrlich f&#252;r den Invarianten-Mechanismus, denn f&#252;r diesen wird es ehr bei sehr kleinen Zeitspannen kniffelig; wohingegen beliebig starkes zoom-out stets repr&#228;sentierbar ist als fraktionaler Integer
</p>
</body>
</html></richcontent>
</node>
</node>
<node COLOR="#338800" CREATED="1667611339595" ID="ID_1035209313" MODIFIED="1667668297039" TEXT="pxWidth errechnen / festsetzen">
<icon BUILTIN="button_ok"/>
<node CREATED="1667667900172" ID="ID_638983817" MODIFIED="1667667999509" TEXT="hier nun doch eine Maximal-Pixelzahl eingef&#xfc;hrt">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...auch das basiert auf einer pragmatischen &#220;berlegung; theoretisch k&#246;nnten wir beliebig gro&#223;e Pixelanzahl unterst&#252;tzen, dies w&#252;rde aber auf allen Ebenen zu unerwartetem Verhalten f&#252;hren, dessen Konsequenzen ich nicht &#252;berblicke &#10233; dann besser eine willk&#252;rliche und hinreichend gro&#223;e Grenze
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1667668184215" ID="ID_364715169" MODIFIED="1667668292358" TEXT="und fall-back auf das visibleWin in default-Metrik">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
dies ist ein reiner Platzhalter f&#252;r Tests, denn in der Praxis erwarte ich stets da&#223; sofort zu Beginn eine Breite in Pixeln gesetzt wird &#8212; kann ja gar nicht anders sein...
</p>
</body>
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
</node>
<node CREATED="1667610653277" ID="ID_1224205751" MODIFIED="1667611359311" TEXT="neue Metrik &#x27f6; visibleWin">
<node CREATED="1667659377837" ID="ID_634768326" MODIFIED="1667659613008" TEXT="&#xbb;conformWindowToMetric&#xab;"/>
</node>
<node CREATED="1667610682228" ID="ID_154285310" MODIFIED="1667610688031" TEXT="Fenster in Canvas schieben">
<node CREATED="1667659486321" ID="ID_897577157" MODIFIED="1667659616368" TEXT="&#xbb;conformWindowToCanvas&#xab;"/>
</node>
<node CREATED="1667610688715" ID="ID_11883276" MODIFIED="1667610699053" TEXT="Fenster auf Canvas beschneiden"/>
<node CREATED="1667610653277" ID="ID_831514693" MODIFIED="1667611449269" TEXT="neue Metrik &#x27f5; visibleWin">
<node CREATED="1667659622859" ID="ID_828891167" MODIFIED="1667659633949" TEXT="&#xbb;conformMetricToWindow&#xab;"/>
</node>
<node CREATED="1667611135215" ID="ID_1783825207" MODIFIED="1667611444146" TEXT="neue Metrik beschneiden">
<node CREATED="1667659689795" ID="ID_1515577475" MODIFIED="1667659703886" TEXT="&#xbb;conformBounds&#xab;"/>
<node CREATED="1667672310513" ID="ID_1440027403" MODIFIED="1667672328162" TEXT="Metric &lt; MAX_ZOOM"/>
<node CREATED="1667610653277" ID="ID_761246682" MODIFIED="1667682138815" TEXT="Metrik &#x27f6; visibleWin">
<linktarget COLOR="#9e7367" DESTINATION="ID_761246682" ENDARROW="Default" ENDINCLINATION="145;-11;" ID="Arrow_ID_702546557" SOURCE="ID_1067254564" STARTARROW="None" STARTINCLINATION="-54;-36;"/>
</node>
<node CREATED="1667611247456" ID="ID_1658100193" MODIFIED="1667611265274" TEXT="visibleWin &#x27f6; Canvas"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1667673574471" ID="ID_1973274504" MODIFIED="1667673591693" TEXT="neue Metrik &lt; MAX_ZOOM">
<icon BUILTIN="help"/>
<node CREATED="1667673606578" ID="ID_1067254564" MODIFIED="1667682151865" TEXT="potentiell gef&#xe4;hrlich: Metrik &#x27f6; visibleWin">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
denn dabei wird gerundet, um die exakte Pixel-Zahl zu erhalten
</p>
</body>
</html></richcontent>
<arrowlink COLOR="#9e7367" DESTINATION="ID_761246682" ENDARROW="Default" ENDINCLINATION="145;-11;" ID="Arrow_ID_702546557" STARTARROW="None" STARTINCLINATION="-54;-36;"/>
</node>
<node CREATED="1667682713949" ID="ID_425310807" MODIFIED="1667682719231" TEXT="Grenzfall-Analyse">
<node CREATED="1667682721338" ID="ID_842333816" MODIFIED="1667682794317" TEXT="Fenster kann verk&#xfc;rzt werden durch Rundung">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
<font face="Monospaced">afterWin_ = startWin_ + Time{dur};</font>
</p>
<p>
wobei dur einen fraktionalen Anteil &lt; 1 &#181;Tick enthalten k&#246;nnte
</p>
</body>
</html></richcontent>
</node>
<node COLOR="#338800" CREATED="1667683782783" ID="ID_1842670966" MODIFIED="1667683907910" TEXT="MAX_TIMESPAN: Begrenzung hier nicht relevant">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Der Grenzfall ist ja changedMetric = MAX_ZOOM
</p>
<p>
Wenn ich das durch eine irgendwie geartete pxWidth teile, wird es niemals gr&#246;&#223;er, und zudem ist MAX_ZOOM &lt; MAX_TIMESPAN
</p>
</body>
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
<node CREATED="1667683116532" ID="ID_895916326" MODIFIED="1667683126786" TEXT="ruft auf: conformMetricToWindow">
<node COLOR="#435e98" CREATED="1667683149810" ID="ID_872183002" MODIFIED="1667683633595" TEXT="Bug: errechnet pxWidth neu mit schon ge&#xe4;nderter L&#xe4;nge">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
das bedeutet: genau durch diese Abrundung auf den n&#228;chst kleineren &#181;Tick k&#246;nnten wir u.U einen Pixel verlieren
</p>
<p>
&#10233; Abhilfe: originale pxWidth als Paremeter mitgeben
</p>
</body>
</html></richcontent>
<icon BUILTIN="broken-line"/>
</node>
<node CREATED="1667683634701" ID="ID_1449451873" MODIFIED="1667685735423" TEXT="Metrik kann minimal gr&#xf6;&#xdf;er geworden sein (durch Rundung)">
<richcontent TYPE="NOTE">&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;
&lt;u&gt;Konkretes Rechenbeispiel:&lt;/u&gt;
&lt;/p&gt;
&lt;p&gt;
pxWidth = 99999&amp;#160;&amp;#160;(ein Pixel weniger als maximal m&amp;#246;glich)
&lt;/p&gt;
&lt;p&gt;
changedMetric = MAX_ZOOM = 2000000
&lt;/p&gt;
&lt;p&gt;
&amp;#10233; conformWindowToMetric() errechnet
&lt;/p&gt;
&lt;p&gt;
dur = 49999+1/2 &amp;#181;Tick
&lt;/p&gt;
&lt;p style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; text-indent: 0px&quot;&gt;
&amp;#55358;&amp;#56370; das wird abgerundet auf 49999 &amp;#181;Tick
&lt;/p&gt;
&lt;p&gt;
&amp;#10233; conformMetricToWindow() errechnet
&lt;/p&gt;
&lt;p&gt;
adjMetric = 99999 / (49999/1000000) = 2000020,0004000080001600032
&lt;/p&gt;
&lt;p style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; text-indent: 0px&quot;&gt;
&amp;#10233; das ist &lt;b&gt;definitiv gr&amp;#246;&amp;#223;er&lt;/b&gt;&amp;#160;als MAX_ZOOM
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</richcontent>
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1667688476525" ID="ID_226096711" MODIFIED="1667688576067" TEXT="&#x27f9; Konsequenz: Bias in Richtung vergr&#xf6;&#xdf;erter Zoom / verkleinertes Fenster">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1667688579306" ID="ID_486622183" MODIFIED="1667688586268" TEXT="allerdings ein sehr kleiner Effekt"/>
<node CREATED="1667688595090" ID="ID_1458378798" MODIFIED="1667688601683" TEXT="&#xe4;quivalent +1 &#xb5;Tick"/>
<node CREATED="1667688946763" ID="ID_376119418" MODIFIED="1667689144112" TEXT="trotzdem unerw&#xfc;nscht &#x27f9; man kommt nicht zum Anfrang zur&#xfc;ck">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
einmal stark reinzoomen, und dann wieder zur&#252;ck &#10233; Bereich ist beschnitten und kleiner geworden; das ist l&#228;stig, weil die n&#228;chst gr&#246;&#223;ere Stufe deutlich gr&#246;&#223;er ist; meiner Einsch&#228;tzung nach w&#228;re es weniger l&#228;stig, wenn man ein kleines bischen zu viel sieht, zumal sich das auf der n&#228;chsten Zweierpotenz einpendeln d&#252;rfte
</p>
</body>
</html></richcontent>
</node>
</node>
<node CREATED="1667687800139" ID="ID_1785911993" MODIFIED="1667687809137" TEXT="Abhilfe">
<node CREATED="1667687810116" ID="ID_1519072103" MODIFIED="1667689196961" TEXT="L&#xf6;sung-1">
<icon BUILTIN="smily_bad"/>
<node CREATED="1667688228377" ID="ID_1083352192" MODIFIED="1667688446311" TEXT="den Fall MAX_ZOOM + Rundungsfehler explizit abtesten"/>
<node CREATED="1667688234896" ID="ID_1025502092" MODIFIED="1667688423306" TEXT="und dann das visibleWin um 1 &#xb5;Tick vergr&#xf6;&#xdf;ern">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...vergr&#246;&#223;ern, weil damit die Metrik kleiner wird und unter der Schwelle MAX_ZOOM gehalten wird
</p>
</body>
</html></richcontent>
</node>
</node>
<node CREATED="1667688257381" ID="ID_1551466069" MODIFIED="1667689187817" TEXT="L&#xf6;sung-2">
<icon BUILTIN="button_cancel"/>
<node CREATED="1667688279379" ID="ID_873793356" MODIFIED="1667688288165" TEXT="stets pauschal 1&#xb5;Tick aufschlagen"/>
<node CREATED="1667688305031" ID="ID_950638301" MODIFIED="1667688330439" TEXT="keine gute Idee: behandelt exakte Verh&#xe4;ltnisse falsch"/>
</node>
<node CREATED="1667688337402" ID="ID_124934014" MODIFIED="1667689201165" TEXT="L&#xf6;sung-3">
<icon BUILTIN="forward"/>
<node CREATED="1667688343137" ID="ID_1666323585" MODIFIED="1667688353420" TEXT="explizit auf Rundungsfehler testen"/>
<node CREATED="1667688354104" ID="ID_1203966035" MODIFIED="1667688377833" TEXT="und in diesem Fall visibleWin um 1 &#xb5;Tick vergr&#xf6;&#xdf;ern"/>
<node CREATED="1667689836161" ID="ID_1356615492" MODIFIED="1667690176127" TEXT="besser: Aufrundungs-Konstante addieren">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...nach grober Absch&#228;tzung sind das weniger Operationen, als die Konvertierung auszuf&#252;hren und zur&#252;ck zu konvertieren und dann zu testen; zwar k&#246;nnte der Optimiser den Test per common subexpression noch vereinfachen &#8212; aber letztlich empfinde ich das Addieren einer ULP-Konstante als deklarativer
</p>
</body>
</html></richcontent>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667690184889" ID="ID_1410341897" MODIFIED="1667690193752" TEXT="Vorsicht: experimentell pr&#xfc;fen">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1667659852956" ID="ID_1802836695" MODIFIED="1667659962798" TEXT="Implementierung">
<icon BUILTIN="pencil"/>
<node CREATED="1667659867147" ID="ID_1797487380" MODIFIED="1667659882100" TEXT="jeweils den beweglichen Teil als Argument"/>
<node CREATED="1667659890055" ID="ID_1728452596" MODIFIED="1667659897292" TEXT="immer nur einen Aspekt justieren"/>
<node CREATED="1667659931146" ID="ID_1567516385" MODIFIED="1667659944676" TEXT="die jeweilige Ziel-Invariante per Assertion dokumentieren"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1667698387387" ID="ID_1173911153" MODIFIED="1667698425495" TEXT="Normalisierungs-Sequenz auf Basis der einzel-Normalisierungen definieren">
<icon BUILTIN="pencil"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1667260366701" ID="ID_1895903283" MODIFIED="1667528268261" TEXT="n&#xe4;chste F&#xe4;lle">
<icon BUILTIN="pencil"/>
@ -55560,7 +55947,7 @@
<node CREATED="1667336818154" ID="ID_228764070" MODIFIED="1667336839107" TEXT="TimeValue + symbolische Grid-Referenz"/>
<node CREATED="1667336841967" ID="ID_1852849270" MODIFIED="1667336856426" TEXT="Grid &#xfc;ber das Advice-System publiziert"/>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1667476797049" FOLDED="true" ID="ID_767502481" MODIFIED="1667487664229" TEXT="Diskussion: interne Zeitbasis">
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1667476797049" FOLDED="true" ID="ID_767502481" MODIFIED="1667593632385" TEXT="Diskussion: interne Zeitbasis">
<linktarget COLOR="#af1a4c" DESTINATION="ID_767502481" ENDARROW="Default" ENDINCLINATION="96;-430;" ID="Arrow_ID_1672039685" SOURCE="ID_1838246834" STARTARROW="None" STARTINCLINATION="-670;38;"/>
<icon BUILTIN="hourglass"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667486621881" ID="ID_566152244" MODIFIED="1667486629636" TEXT="#1258 clarify internal time base">
@ -55572,6 +55959,7 @@
<node CREATED="1667486681289" ID="ID_1245609548" MODIFIED="1667486715504" TEXT="egal ob man nun floating-point nimmt, oder eine feste integrale Basis (&#xb5;-Ticks)"/>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1667486847011" ID="ID_1394182591" MODIFIED="1667486860346" TEXT="sehe folgende L&#xf6;sungen">
<linktarget COLOR="#b3a5d6" DESTINATION="ID_1394182591" ENDARROW="Default" ENDINCLINATION="-42;135;" ID="Arrow_ID_1017363931" SOURCE="ID_945218071" STARTARROW="None" STARTINCLINATION="-118;6;"/>
<icon BUILTIN="hourglass"/>
<node CREATED="1667486862210" ID="ID_860525476" MODIFIED="1667487583167" TEXT="Umstellen auf Bruch-Darstellung">
<icon BUILTIN="full-1"/>
@ -55638,6 +56026,144 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592184752" ID="ID_1933332619" MODIFIED="1667592189752" TEXT="Aufr&#xe4;um-Arbeiten">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592193783" ID="ID_1808934689" MODIFIED="1667592204255" TEXT="#1259 organise raw time base implementation">
<icon BUILTIN="flag-yellow"/>
</node>
<node CREATED="1667592218952" ID="ID_1463501252" MODIFIED="1667592230199" TEXT="Einsichten">
<icon BUILTIN="idea"/>
<node CREATED="1667592232354" ID="ID_1809679126" MODIFIED="1667592268849" TEXT="die unterliegende Roh-Implementierung wird stets &#x201e;durchscheinen&#x201c;"/>
<node CREATED="1667592285128" ID="ID_945218071" MODIFIED="1667592349554">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
im Besonderen bei den <i>pragmatischen L&#246;sungen</i>
</p>
</body>
</html></richcontent>
<arrowlink COLOR="#b3a5d6" DESTINATION="ID_1394182591" ENDARROW="Default" ENDINCLINATION="-42;135;" ID="Arrow_ID_1017363931" STARTARROW="None" STARTINCLINATION="-118;6;"/>
<icon BUILTIN="full-2"/>
<icon BUILTIN="full-3"/>
</node>
<node CREATED="1667592366001" ID="ID_170684768" LINK="#ID_745987096" MODIFIED="1667592483713" TEXT="Zeit-Berechnungen brauchen einen validen Zugang">
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1667592593027" ID="ID_1398816169" MODIFIED="1667592611842" TEXT="Aufgaben">
<icon BUILTIN="yes"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592613824" ID="ID_1877249067" MODIFIED="1667593560997" TEXT="keine externen Library-Typen mehr im normalen Implementierungs code">
<icon BUILTIN="yes"/>
<node CREATED="1667592632302" ID="ID_1344505411" MODIFIED="1667592635745" TEXT="boost::rational"/>
<node CREATED="1667592636666" ID="ID_392219650" MODIFIED="1667592641529" TEXT="gavl_time_t"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592643724" ID="ID_504422240" MODIFIED="1667592665218" TEXT="LibGavl-Dependency hier entfernen">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1667592666825" ID="ID_1632149108" MODIFIED="1667592677380" TEXT="so sehr ich Gavl im allgemeinen gut finde"/>
<node CREATED="1667592677944" ID="ID_130946855" MODIFIED="1667592698682" TEXT="wir brauchen keine Lib um einen int64_t zu deklarieren">
<icon BUILTIN="yes"/>
</node>
<node CREATED="1667592700101" ID="ID_942374659" MODIFIED="1667592737240" TEXT="ansonsten wird Gavl nicht / noch nicht verwendet">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
und ganz im Besonderen: wir st&#252;tzen uns f&#252;r die Zeitbehandlung nicht auf libGavl ab
</p>
</body>
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593471839" ID="ID_1651396499" MODIFIED="1667593549109" TEXT="gavl_time_t ersetzen durch einen Typedef RawTicks">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593606149" ID="ID_1259605001" MODIFIED="1667593625459" TEXT="_raw() &#x27f6; _rawTicks()">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592743130" ID="ID_675688540" MODIFIED="1667593547383">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
FSecs durch einen neuen Wrapper <font face="Monospaced" color="#1e178c"><b>RSec</b></font>&#160;ersetzen
</p>
</body>
</html></richcontent>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1667592790281" ID="ID_1680785799" MODIFIED="1667592800092" TEXT="au&#xdf;erdem den neuen lib/rational.hpp hier einbinden"/>
<node CREATED="1667592805748" ID="ID_290360900" MODIFIED="1667592820329" TEXT="explizit als Typ RSec verwenden f&#xfc;r alle Konvertierungen"/>
<node CREATED="1667592821013" ID="ID_289952678" MODIFIED="1667592916791" TEXT="RSec">
<icon BUILTIN="info"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592825916" ID="ID_66335543" MODIFIED="1667592941549" TEXT="implizit konstruierbar aus Rat">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592930415" ID="ID_569654636" MODIFIED="1667592944318" TEXT="implizit konstruierbar aus TimeVal">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592835795" ID="ID_1955597942" MODIFIED="1667592942626">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<b>nicht</b>&#160;implizit konstruierbar aus int64_t
</p>
</body>
</html></richcontent>
<icon BUILTIN="messagebox_warning"/>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1667592866911" ID="ID_416309268" MODIFIED="1667592869523" TEXT="ganz wichtig"/>
<node CREATED="1667592870151" ID="ID_1316405427" MODIFIED="1667592884425" TEXT="denn int64_t impliziert &#xb5;-Ticks"/>
<node CREATED="1667592895059" ID="ID_556517411" MODIFIED="1667592912143" TEXT="sollte explizit konstruierbar sein, mit Skalen-Transformation"/>
</node>
<node CREATED="1667592989079" ID="ID_531764150" MODIFIED="1667593020006" TEXT="minimale Arithmetik-Integration mit Time und Duration"/>
<node CREATED="1667593029266" ID="ID_1518807557" MODIFIED="1667593045317" TEXT="aber Zeit-Gr&#xf6;&#xdf;en nur explizit konstruierbar (= Status quo)"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593084541" ID="ID_737389227" MODIFIED="1667593105376" TEXT="C-Library effektiv entfernen">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1667593106935" ID="ID_1453484901" MODIFIED="1667593139782" TEXT="ich will keine C-Implementierungen mehr">
<icon BUILTIN="yes"/>
</node>
<node CREATED="1667593146938" ID="ID_572582896" MODIFIED="1667593420308" TEXT="die C-Library verf&#xfc;hrt dazu, das Time-Framework zu umgehen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...seinerzeit fand ich diese Art &#187;Offenheit&#171; noch gut; auch weil ich mir erhoffte, damit mehr Contributors zu bekommen. Die Erfahrungen sprechen dagegen; klar, die Leute m&#246;gen erst einmal gerne &#8222;move fast and break things&#8220; &#8212; aber wenn dann Aufr&#228;umen oder anstrengende Konzeptions-Arbeit notwendig w&#252;rde, bleibt alles liegen und man verschwindet aus dem Projekt.
</p>
</body>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593164461" ID="ID_1585303440" MODIFIED="1667593241126" TEXT="Umbau">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593169047" ID="ID_377190169" MODIFIED="1667593239462" TEXT="Header umbenennen">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593179870" ID="ID_1823116307" MODIFIED="1667593239462" TEXT="Header und Implementierung in C++">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593196675" ID="ID_530670970" MODIFIED="1667593239463" TEXT="plain-C-Tests in C++-Tests umziehen">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593209815" ID="ID_1675418151" MODIFIED="1667593239463" TEXT="Hinweise aus Dokumentation entfernen">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1667336859796" ID="ID_1810244902" MODIFIED="1667337099718" TEXT="Timecode">
<icon BUILTIN="hourglass"/>