Files
alda-mirror/client/model/repeat.go
2025-05-20 11:10:01 +02:00

87 lines
2.2 KiB
Go

package model
import (
"alda.io/client/json"
"github.com/mohae/deepcopy"
)
// A Repeat expression repeats an event a number of times.
type Repeat struct {
SourceContext AldaSourceContext
Event ScoreUpdate
Times int32
}
// GetSourceContext implements HasSourceContext.GetSourceContext.
func (repeat Repeat) GetSourceContext() AldaSourceContext {
return repeat.SourceContext
}
// JSON implements RepresentableAsJSON.JSON.
func (repeat Repeat) JSON() *json.Container {
return json.Object(
"type", "repeat",
"value", json.Object(
"event", repeat.Event.JSON(),
"times", repeat.Times,
),
)
}
// UpdateScore implements ScoreUpdate.UpdateScore by repeatedly updating the
// score with an event a specified number of times.
func (repeat Repeat) UpdateScore(score *Score) error {
previousRepetitions := make([]int32, len(score.CurrentParts))
for i, part := range score.CurrentParts {
previousRepetitions[i] = part.currentRepetition
}
for repetition := int32(1); repetition <= repeat.Times; repetition++ {
for _, part := range score.CurrentParts {
part.currentRepetition = repetition
}
if err := score.Update(repeat.Event); err != nil {
return err
}
}
for i, part := range score.CurrentParts {
part.currentRepetition = previousRepetitions[i]
}
return nil
}
// DurationMs implements ScoreUpdate.DurationMs by returning the total duration
// of the event being repeated the specified number of times.
func (repeat Repeat) DurationMs(part *Part) float64 {
durationMs := 0.0
previousRepetition := part.currentRepetition
for repetition := int32(1); repetition <= repeat.Times; repetition++ {
part.currentRepetition = repetition
durationMs += repeat.Event.DurationMs(part)
}
part.currentRepetition = previousRepetition
return durationMs
}
// VariableValue implements ScoreUpdate.VariableValue by returning a version of
// the repeat where the value of the event to be repeated is captured.
func (repeat Repeat) VariableValue(score *Score) (ScoreUpdate, error) {
result := deepcopy.Copy(repeat).(Repeat)
eventValue, err := repeat.Event.VariableValue(score)
if err != nil {
return nil, err
}
result.Event = eventValue
return result, nil
}