Coming from previous design of having all deltas be bidirectional
Current format for operations is
tuple[ name, data]
this isnt enforced its just what ive been doing
they are stored in a list as
tuple[ type| None, list[ tuple[ transformOperationId, transformData]]]
version types can currently either be INIT| FULL| DELTA| FULL_WITH_DELTA
if we had unidirectional deltas| we would have INIT| FULL| FORWARDS_DELTA| BIDIRECTIONAL_DELTA| FULL_WITH_BACKWARDS_DELTA
So calculateDeltaData needs to know the desired direction
if we wish for a FULL_WITH_BACKWARDS_DELTA save then we desire a backwards delta
otherwise we want a normal delta save and so
so the save function takes a desired: FORWARDS_DELTA| BIDIRECTIONAL_DELTA| FULL_WITH_BACKWARDS_DELTA
and calls calculateDeltaData with a desired TransformType of FORWARDS| BIDIRECTIONAL| BACKWARDS
calculateDeltaData does some initial checks and returns and then finds a ConstructionSet for the type
the ConstructionSet.deltaConstruction takes the two instances and returns ( TransformType, data)
they could take a preferred TransformType which is None by default
one way they could implement this is that when detaConstruction encounters a situation which could result in branching types
of TransformType it uses the preferred
Every operation needs to support bidirectional, ( forwards, backwards) but some may store the data in the same manner
In this case, deltaConstruction can return bidirecitonal as this signals that the most traversible option is available
deconstructVersionDataChain and applyDataTransform need to change
deconstructVersionDataChain will still return a valid sequence but it will possibly be made of uni and bidirectional deltas
when applying data changes in a line now, we will encounter unidirectional deltas
class Directionality( IntFlag):
BIDIRECTIONAL= auto()
UNIDIRECTIONAL= auto()
the ConstructionSet s can now have a function called applyDeltas which takes a group of delta transforms of a specific directionality
applyDataTransform currently takes typeAndTransforms: deltaTransforms it only needs to take the type once, as it should only ever be passed operations from a singular type
so it should take ( object: Any, typez: type, operations: Sequence[ Sequence[ Directionality, Sequence[ Sequence[ transformOperationId, transformData]]]], direction: OperationDirection)
and within it should call ConstructionSet.applyDeltas for each Directionality block
so ConstructionSet.applyDeltas should take ( object: Any, directionality: , operations: Sequence[ Sequence[ transformOperationId, transformData]])
The design of preferred type passing seems a little weak
We can specify either a transform type or a commit type
Transform type delta s are BIDIRECTIONAL| UNIDIRECTIONAL| NONE| FULL
Commit types are those specified above, INIT| FULL| FORWARDS_DELTA| BIDIRECTIONAL_DELTA| FULL_WITH_BACKWARDS_DELTA
constructed bidirectional transforms
when specifying the preferred do we specify q to w? or w to q if no preferred and only bidirectional like before it is implied q to w forwards and w to q backwards so maybe bidirectional needs an application direction of q to w or w to q unidirectional are constructed with a specific direction
i think in some circumstances if the preferred isnt available then we want to fallback to a full change in others we could accept bidirectional in place of unidirectional, unidirectional in place of bidirectional, maybe these desires could be fully specified using a sequence of acceptable outcomes, and if none can be fulfilled then it falls to a full change there is fallback behaviour for no sequence specified
the issue with running it once, determining the output and then rerunning is that the conversion set may have to run extra processes whereas if the order of desired outcomes was known to the conversion function then it could quickly decide on the outcome. maybe then a preference can be specified as well as a fallback value which either falls back to the other directionality than the prefferred and then to full or it directly falls back to a full transform so
class TransformFallback( IntFlag):
OPPOSITE_DIRECTIONALITY_THEN_FULL= auto()
FULL= auto()
So LTSD.save can take a preffered version type from these specific CommitType s: FORWARDS_DELTA| BIDIRECTIONAL_DELTA| FULL_WITH_BACKWARDS_DELTA
if forwards then we desire a unidirectional delta, if none can be found then we could fall back to bidirectional or full, either one really
save could take a fallback value it is currently relativelty unknown where it will be called from to initiate the different commit types, i envision an optimisation process which could reduce load times by constructing FULL_WITH_BACKWARDS_DELTA commits on data that has a large amount of subsequent deltas, bidirectional or forward could be discerned between by a software aspect seeking to optimise each individual version, maybe one that doesnt care about backwards traversing on the data could only use FORWARDS_DELTA
calculateDeltaData can take a preffered delta transform type form these TransformType s: UNIDIRECTIONAL| BIDIRECTIONAL
as well as a fallback of any from TransformFallback
DeltaTransformSet.deltaConstruction can take a preffered delta transform type form these TransformType s: UNIDIRECTIONAL| BIDIRECTIONAL
as well as a fallback of any from TransformFallback
UNIDIRECTIONAL s are calculated as q to w BIDIRECTIONAL s can be applied as ( q to w)| ( w to q)
So now need to redesign save, calculateDeltaData, DeltaTransformSet.deltaConstruction
save needs to call calculateDeltaData with UNIDIRECTIONAL if FORWARDS_DELTA
needs to call calculateDeltaData with BIDIRECTIONAL if BIDIRECTIONAL_DELTA
needs to call calculateDeltaData with UNIDIRECTIONAL if FULL_WITH_BACKWARDS_DELTA
How the output is managed is dependant on the transform type of the output as well as the preferred CommitType passed to save
FULL, NONE, BIDIRECTIONAL is the same result regardless
if the resultant TransformType is UNIDIRECTIONAL then:
if the preffered CommitType is FORWARDS then we are just using the returned data as a forwards delta
if the preffered CommitType is FULL_WITH_BACKWARDS then we need to use the full data and the returned data
calculateDeltaData is mostly a passthrough to either basic returns or DeltaTransformSet.deltaConstruction
DeltaTransformSet.deltaConstruction can return:
tuple[ TransformType, tuple[ type| None, list[ tuple[ transformOperationId, transformData]]]| None| Any]
This doesnt need to change
delta transforms of both directionalities can return list[ tuple[ transformOperationId, transformData]]]
all elements of the sequence should be of the same directionality
this includes any recursively contained delta lists
Due to this recursive requirement, if the passed fallback to the containing level is FULL then that also must be the case for the called contained
If the contained cannot match the prefference of the container then
if FULL is active then the contained must not default to the opposite of the preferred delta type
if OPPOSITE_DIRECTIONALITY_THEN_FULL is active then the containd should fallback to the opposite of the preffered and then full
i think this means that the contained fallback should match the fallback of the container
the preffered of the contained should match the preferred of the container
if this is enforced by calculateDeltaData then we should be fine with just specifying the input prefferred and fallback for the contained
in the future it could also be made so that individual transforms in the delta list are either uni or bi directional