Processing a Square Dance Call
Every square dance call is represented by an instance of a subtype of SquareDanceCall
. Every instance has a role
field (or a method on [
restricted_to](@ref)) which can be used to restrict the call to only some dancers, for example
OriginalHeadsor
Centers. Some calls might have additional fields that inform a handedness (e.g. [
PullBy](@ref)) or a count ([
SquareThru`](@ref)).
The function do_call
is the entry point for performing a square dance call. It is passed the current knowledge base (a SDRKnowledgeBase
) and the call to be performed. The knowledge base already knows the current location and facing direction of each dancer, and has concluded all of the formations they are in.
do_call
creates a CallSchedule
and schedules the call to that schedule. do_call
then calls do_schedule
, passing it the schedule and the knowledge base.
do_schedule
dequeues calls from the schedule. It calls [get_call_options
] to identify formations in the knowledge base that match the call's role and the result of calling can_do_from
. do_schedule
calls expand_parts
with the call and the appropriate formation. If there is an expansion, those parts are placed in the schedule. Otherwise perform
is called to perform the call.
There is a method of can_do_from
for each combination of square dance call and formation. can_do_from
returns a preference number that imposes a preference order on each combination of call and formation. A preference value of 0
indicates that the call can not be performed from that formation (or that it is not yet implemented). A positive preference value is returned if the call can be performed from that formation. A higher preference value is preferred over a lower one. For example, UTurnBack
from Couple
is preferable to UTurnBack
from a single dancer (represented as a DancerState
) because Couple
further informs correct turning direction. A call like AndRoll
need only be implemented for a single dancer (DancerState
) because the dancer's rotational flow can be determined from there (via the previous
field chain).
get_call_options
is pretty complicated. Consider a right handed tidal wave (RHWaveOfEight
). it includes 7
two dancer formations: four RHMiniWave
s and three LHMiniWave
s. If there is only one CanDoCall
concerning a dancer after the preference sorting, then that CanDoCall
will be included in the results of get_call_options
. Any CanDoCall
whose formation includes a dancer that is already included in the result set is discarded. get_call_options
loops over these two operations: adding to the result set and eliminating overlaps, until all CanDoCall
objects have been considered. get_call_options
finally returns those results – a vector of CanDoCall
objects that concern disjoint formations.
Once do_schedule
has processed all of the schedule entries for a given time value, it calls `breatheto spread dancers apart if any overlap.
doschedulethen makes sure the dancers are all synchronized and updates the knowledge base (actually, it creates and populates a new one because the Rete package doesn't support retraction). If the schedule is not yet empty then
doschedule` continues as above.