package engine import "gitea.maximumdirect.net/eric/ConfigKit/internal/document" // projectTierHistoryApplications composes each strict source's local projection // with the tier operation. The retained source values stay in authored coordinates. func projectTierHistoryApplications(applications []historyApplication, operations []sequenceHistoryContribution) []historyApplication { mapped := false for _, operation := range operations { mapped = mapped || operation.mode == sequenceHistoryMapped } if !mapped { return applications } projections := indexSequenceHistoryContributions(operations) projected := cloneHistoryApplications(applications) for index, original := range applications { application := &projected[index] if path, found := projectSequenceHistoryPath(original.path, projections); found { application.path = path } for sequenceIndex, source := range original.sequences { container := appendDestination(original.path, source.path) operation, active := projections[container.String()] if !active || operation.mode != sequenceHistoryMapped { continue } value, found := documentAtPath(original.value, source.path) if !found || value.Kind != document.Sequence { continue } sourceIndex := application.sequencesByPath[source.path.String()] contribution := sequenceHistoryContribution{path: source.path.clone(), mode: sequenceHistoryMapped} for inputIndex := range value.Sequence { tierIndex := source.offset + inputIndex if source.mode == sequenceHistoryMapped { tierIndex = sourceIndex.outputForInput(inputIndex) } outputIndex, present := operation.projection.outputForInput(tierIndex) if !present { continue } contribution.items = append(contribution.items, sequenceItemProjection{inputIndex: inputIndex, outputIndex: outputIndex}) if _, replaced := operation.replacedOutputs[outputIndex]; replaced { // Upsert replacements retain their lower-list position. contribution.replacements = append(contribution.replacements, sequenceItemReplacement{ lowerIndex: outputIndex, higherIndex: inputIndex, outputIndex: outputIndex, }) } } application.sequences[sequenceIndex] = contribution } application.sequencesByPath = indexSequenceHistoryContributions(application.sequences) } return projected } func projectSequenceHistoryPath(path Path, projections map[string]sequenceHistoryContributionIndex) (Path, bool) { projected := path.clone() for index, segment := range path.segments { if segment.kind != pathSegmentIndex { continue } prefix := Path{segments: path.segments[:index]} operation, found := projections[prefix.String()] if !found || operation.mode != sequenceHistoryMapped { continue } outputIndex, found := operation.projection.outputForInput(segment.index) if !found { return Path{}, false } projected.segments[index].index = outputIndex } return projected, true }