sdr 0.7

net.cscott.sdr.calls
Class Formation

java.lang.Object
  extended by net.cscott.sdr.calls.Formation
Direct Known Subclasses:
TaggedFormation

public class Formation
extends Object

A Formation is a set of dancers and positions for them. Certain dancers in the formation can be selected. In addition, all dancers can be tagged with modifiers such as 'BEAU', 'BELLE', 'LEADER', 'TRAILER', etc.


Field Summary
static Map<Dancer,String> dancerNames
          Map from StandardDancers to 2-character dancer representations.
static Formation FOUR_SQUARE
          Starting formation for 2-couple dancing.
protected  Map<Dancer,Position> location
           
protected  Set<Dancer> selected
           
static Formation SQUARED_SET
          Starting formation for 8-couple dancing.
 
Constructor Summary
protected Formation(Formation f, Map<Dancer,Dancer> map)
           
  Formation(Map<Dancer,Position> location)
           
protected Formation(Map<Dancer,Position> location, Set<Dancer> selected)
           
 
Method Summary
 Box bounds()
          Return the bounds of this formation, which is the bounding box around all the dancers' bounding boxes.
 Box bounds(Dancer d)
          Return the bounds of the given dancer -- always its position plus or minus 1 unit on the x and y axes.
 Comparator<Dancer> dancerComparator()
          Return a Dancer Comparator that compares dancers based on their positions within this Formation.
 Set<Dancer> dancers()
           
 boolean equals(Object o)
           
 int hashCode()
           
 boolean isCentered()
          Return true if the given formation is centered at the origin.
 boolean isSelected(Dancer d)
          Return true iff the given dancer is selected.
 Position location(Dancer d)
           
 Formation map(Dancer... dancers)
          Replace the dancers in this formation with the given dancers, specified in the "sorted dancers" order (left-to-right, top-to-bottom).
 Formation map(Map<Dancer,Dancer> map)
           
 Formation mapStd(StandardDancer... dancers)
          Special case of map(Dancer...) which allows you to specify half the dancers, and fills in the rest with their opposites to result in a symmetric formation.
 Formation mirror(boolean mirrorShoulderPass)
          Return a formation like this one, except with all positions mirrored.
 Formation move(Dancer d, Position p)
          Return a formation like this one, except that the given dancer is moved to the specified position.
 Formation onlySelected()
          Create a new formation containing only the selected dancers from this formation.
 Formation recenter()
          Build a new formation, centered on 0,0.
 Formation rotate(ExactRotation rotation)
          Build a new formation, like this one except rotated around 0,0.
 Formation select(Collection<Dancer> d)
          Build a new formation with only the given dancers selected.
 Formation select(Dancer... d)
          Convenience method for select(Collection).
 Set<Dancer> selectedDancers()
           
 List<Dancer> sortedDancers()
          Return the dancers of dancers(), in the order given by dancerComparator().
 String toString()
           
 String toStringDiagram()
          Return an ascii-art diagram of this formation.
 String toStringDiagram(String prefix)
          Return an ascii-art diagram of this formation with the specified prefix on each line.
 String toStringDiagram(String prefix, Map<Dancer,String> dancerNames)
          Return an ascii-art diagram of this formation, using a custom mapping from Dancers to 2-character strings.
 String toStringDiagramWithDetails()
           
 String toStringDiagramWithDetails(String prefix)
           
 String toStringDiagramWithDetails(String prefix, Map<Dancer,String> dancerNames)
           
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

location

protected final Map<Dancer,Position> location

selected

protected final Set<Dancer> selected

dancerNames

public static final Map<Dancer,String> dancerNames
Map from StandardDancers to 2-character dancer representations.

Tests:
js> Formation.dancerNames.get(StandardDancer.COUPLE_1_BOY)
1B
js> Formation.dancerNames.get(StandardDancer.COUPLE_4_GIRL)
4G

SQUARED_SET

public static final Formation SQUARED_SET
Starting formation for 8-couple dancing.

Tests:
Check the diagram for this formation:
js> Formation.SQUARED_SET.toStringDiagram()
     3Gv  3Bv

4B>            2G<

4G>            2B<

     1B^  1G^

FOUR_SQUARE

public static final Formation FOUR_SQUARE
Starting formation for 2-couple dancing.

Tests:
Check the diagram for this formation:
js> Formation.FOUR_SQUARE.toStringDiagram()
3Gv  3Bv

1B^  1G^
Constructor Detail

Formation

protected Formation(Map<Dancer,Position> location,
                    Set<Dancer> selected)

Formation

public Formation(Map<Dancer,Position> location)

Formation

protected Formation(Formation f,
                    Map<Dancer,Dancer> map)
Method Detail

onlySelected

public Formation onlySelected()
Create a new formation containing only the selected dancers from this formation.

Tests:
Create a formation containing only the sides from a squared set:
js> importPackage(java.util)
js> f = Formation.SQUARED_SET ; undefined
js> sides = [d for each (d in Iterator(f.sortedDancers())) if (d.isSide())]
COUPLE 4 BOY,COUPLE 2 GIRL,COUPLE 4 GIRL,COUPLE 2 BOY
js> f2 = f.select(Arrays.asList(sides)).onlySelected()
net.cscott.sdr.calls.Formation[
  location={COUPLE 4 BOY=-3,1,e, COUPLE 2 GIRL=3,1,w, COUPLE 4 GIRL=-3,-1,e, COUPLE 2 BOY=3,-1,w}
  selected=[COUPLE 4 BOY, COUPLE 2 GIRL, COUPLE 4 GIRL, COUPLE 2 BOY]
]
js> f2.toStringDiagram()
4B>            2G<

4G>            2B<

isSelected

public boolean isSelected(Dancer d)
Return true iff the given dancer is selected.

Tests:
Select the sides, and verify that isSelected() returns the expected results:
js> importPackage(java.util)
js> f = Formation.SQUARED_SET ; undefined
js> heads = [d for each (d in Iterator(f.sortedDancers())) if (d.isHead())]
COUPLE 3 GIRL,COUPLE 3 BOY,COUPLE 1 BOY,COUPLE 1 GIRL
js> sides = [d for each (d in Iterator(f.sortedDancers())) if (d.isSide())]
COUPLE 4 BOY,COUPLE 2 GIRL,COUPLE 4 GIRL,COUPLE 2 BOY
js> f2 = f.select(Arrays.asList(sides)); undefined
js> [f2.isSelected(d) for each (d in sides)]
true,true,true,true
js> [f2.selectedDancers().contains(d) for each (d in sides)]
true,true,true,true
js> [f2.isSelected(d) for each (d in heads)]
false,false,false,false
js> [f2.selectedDancers().contains(d) for each (d in heads)]
false,false,false,false

selectedDancers

public Set<Dancer> selectedDancers()

dancers

public Set<Dancer> dancers()

location

public Position location(Dancer d)

bounds

public Box bounds()
Return the bounds of this formation, which is the bounding box around all the dancers' bounding boxes. This means that the 1 unit border from bounds(Dancer) applies here as well. If there are no dancers, returns a zero-width, zero-height box centered at the origin.

Tests:
js> Formation.SQUARED_SET.bounds()
(-4,-4;4,4)
js> Formation.SQUARED_SET.select(java.util.Collections.EMPTY_SET).onlySelected().bounds()
(0,0;0,0)

bounds

public Box bounds(Dancer d)
Return the bounds of the given dancer -- always its position plus or minus 1 unit on the x and y axes.


select

public Formation select(Collection<Dancer> d)
Build a new formation with only the given dancers selected.

Tests:
js> importPackage(java.util)
js> f = Formation.SQUARED_SET ; undefined
js> heads = [d for each (d in Iterator(f.sortedDancers())) if (d.isHead())]
COUPLE 3 GIRL,COUPLE 3 BOY,COUPLE 1 BOY,COUPLE 1 GIRL
js> f2 = f.select(Arrays.asList(heads))
net.cscott.sdr.calls.Formation[
  location={COUPLE 3 GIRL=-1,3,s, COUPLE 3 BOY=1,3,s, COUPLE 4 BOY=-3,1,e, COUPLE 2 GIRL=3,1,w, COUPLE 4 GIRL=-3,-1,e, COUPLE 2 BOY=3,-1,w, COUPLE 1 BOY=-1,-3,n, COUPLE 1 GIRL=1,-3,n}
  selected=[COUPLE 3 GIRL, COUPLE 3 BOY, COUPLE 1 BOY, COUPLE 1 GIRL]
]

select

public Formation select(Dancer... d)
Convenience method for select(Collection).


recenter

public Formation recenter()
Build a new formation, centered on 0,0.

Tests:
Isolate the #1 couple, then recenter:
js> importPackage(java.util)
js> couple1 = [StandardDancer.COUPLE_1_BOY, StandardDancer.COUPLE_1_GIRL]
COUPLE 1 BOY,COUPLE 1 GIRL
js> f = Formation.SQUARED_SET.select(Arrays.asList(couple1)).onlySelected()
net.cscott.sdr.calls.Formation[
  location={COUPLE 1 BOY=-1,-3,n, COUPLE 1 GIRL=1,-3,n}
  selected=[COUPLE 1 BOY, COUPLE 1 GIRL]
]
js> f.isCentered()
false
js> f1 = f.recenter()
net.cscott.sdr.calls.Formation[
  location={COUPLE 1 BOY=-1,0,n, COUPLE 1 GIRL=1,0,n}
  selected=[COUPLE 1 BOY, COUPLE 1 GIRL]
]
js> f1.isCentered()
true
js> // preserves position flags, too
js> f2=f.move(StandardDancer.COUPLE_1_BOY, f.location(StandardDancer.COUPLE_1_BOY)
  >        .addFlags(Position.Flag.PASS_LEFT, Position.Flag.ROLL_RIGHT))
net.cscott.sdr.calls.Formation[
  location={COUPLE 1 BOY=-1,-3,n,[PASS_LEFT, ROLL_RIGHT], COUPLE 1 GIRL=1,-3,n}
  selected=[COUPLE 1 BOY, COUPLE 1 GIRL]
]
js> f2.isCentered()
false
js> f2 = f2.recenter()
net.cscott.sdr.calls.Formation[
  location={COUPLE 1 BOY=-1,0,n,[PASS_LEFT, ROLL_RIGHT], COUPLE 1 GIRL=1,0,n}
  selected=[COUPLE 1 BOY, COUPLE 1 GIRL]
]
js> f2.isCentered()
true

rotate

public Formation rotate(ExactRotation rotation)
Build a new formation, like this one except rotated around 0,0. We rotate CW by the amount given in the rotation parameter; "north" corresponds to no rotation.

Tests:
Rotate the squared set 90 degrees CW:
js> Formation.SQUARED_SET.rotate(ExactRotation.ONE_QUARTER).toStringDiagram()
     4Gv  4Bv

1B>            3G<

1G>            3B<

     2B^  2G^
Non-orthogonal rotation:
js> Formation.SQUARED_SET.rotate(ExactRotation.ONE_EIGHTH).toStringDiagram()
     4BQ       3GL

4GQ                 3BL



1B7                 2G`

     1G7       2B`

isCentered

public boolean isCentered()
Return true if the given formation is centered at the origin.

Tests:
js> Formation.SQUARED_SET.isCentered()
true

dancerComparator

public Comparator<Dancer> dancerComparator()
Return a Dancer Comparator that compares dancers based on their positions within this Formation.


sortedDancers

public List<Dancer> sortedDancers()
Return the dancers of dancers(), in the order given by dancerComparator().


equals

public boolean equals(Object o)
Overrides:
equals in class Object

hashCode

public int hashCode()
Overrides:
hashCode in class Object

toString

public String toString()
Overrides:
toString in class Object

toStringDiagram

public String toStringDiagram()
Return an ascii-art diagram of this formation. Each 2x2 dancer becomes a 5x2 char array, with facing direction indicator centered in the 5 unit width. ie, a box (bounds -2,-2 to 2,2) is:
 "1B^  1Gv  \n"
 "          \n"
 "3B^  3Gv  "
 
Note that the return value has no trailing \n. js> Formation.SQUARED_SET.toStringDiagram() 3Gv 3Bv 4B> 2G< 4G> 2B< 1B^ 1G^


toStringDiagram

public String toStringDiagram(String prefix)
Return an ascii-art diagram of this formation with the specified prefix on each line. Note that the return value has no trailing \n.

See Also:
js> Formation.SQUARED_SET.toStringDiagram("!") ! 3Gv 3Bv ! !4B> 2G< ! !4G> 2B< ! ! 1B^ 1G^

toStringDiagram

public String toStringDiagram(String prefix,
                              Map<Dancer,String> dancerNames)
Return an ascii-art diagram of this formation, using a custom mapping from Dancers to 2-character strings. Each line of the diagram is preceded with the specified prefix. Note that the return value has no trailing \n.

See Also:
toStringDiagram()
Tests:
Use AA through HH to represent dancers
js> m = java.util.LinkedHashMap()
{}
js> for (i in Iterator(StandardDancer.values())) {
  >   m.put(i[1], String.fromCharCode(65+i[0],65+i[0]))
  > }
null
js> Formation.SQUARED_SET.toStringDiagram("|", m)
|     FFv  EEv
|
|GG>            DD<
|
|HH>            CC<
|
|     AA^  BB^

toStringDiagramWithDetails

public String toStringDiagramWithDetails()

toStringDiagramWithDetails

public String toStringDiagramWithDetails(String prefix)

toStringDiagramWithDetails

public String toStringDiagramWithDetails(String prefix,
                                         Map<Dancer,String> dancerNames)

map

public Formation map(Map<Dancer,Dancer> map)

map

public Formation map(Dancer... dancers)
Replace the dancers in this formation with the given dancers, specified in the "sorted dancers" order (left-to-right, top-to-bottom).


mapStd

public Formation mapStd(StandardDancer... dancers)
Special case of map(Dancer...) which allows you to specify half the dancers, and fills in the rest with their opposites to result in a symmetric formation.


move

public Formation move(Dancer d,
                      Position p)
Return a formation like this one, except that the given dancer is moved to the specified position. js> f = Formation.SQUARED_SET; f.toStringDiagram("|") | 3Gv 3Bv | |4B> 2G< | |4G> 2B< | | 1B^ 1G^ js> f.move(StandardDancer.COUPLE_1_BOY, Position.getGrid(-1,0,"e")).toStringDiagram("|") | 3Gv 3Bv | |4B> 2G< | 1B> |4G> 2B< | | 1G^


mirror

public Formation mirror(boolean mirrorShoulderPass)
Return a formation like this one, except with all positions mirrored.

Tests:
js> f = Formation.SQUARED_SET; f.toStringDiagram("|");
|     3Gv  3Bv
|
|4B>            2G<
|
|4G>            2B<
|
|     1B^  1G^
js> f.mirror(false).toStringDiagram("|")
|     3Bv  3Gv
|
|2G>            4B<
|
|2B>            4G<
|
|     1G^  1B^
js> f.mirror(false).location(StandardDancer.COUPLE_1_BOY)
1,-3,n
js> f.mirror(true).toStringDiagram("|")
|     3Bv  3Gv
|
|2G>            4B<
|
|2B>            4G<
|
|     1G^  1B^
js> f.mirror(true).location(StandardDancer.COUPLE_1_BOY)
1,-3,n,[PASS_LEFT]

sdr 0.7

Copyright © 2006-2009 C. Scott Ananian