contra-renderer/www/js/libfigureMapper.ts

601 lines
16 KiB
TypeScript

import libfigure from "./libfigure/libfigure.js";
export interface LibFigureMove {
move: string,
parameter_values: any[],
progression?: 1,
note?: string,
}
export type LibFigureDance = LibFigureMove[];
type chooser_text = string;
type chooser_revolutions = number;
type chooser_places = number;
type chooser_boolean = true | false;
type chooser_spin = true | false;
type chooser_left_right_spin = true | false;
type chooser_right_left_hand = false | true;
type chooser_right_left_shoulder = false | true;
type chooser_slide = true | false;
type chooser_slice_increment = "couple" | "dancer";
type chooser_go_back = true | false;
type chooser_give = true | false;
type chooser_half_or_full = 0.5 | 1;
type chooser_star_grip = "" | "wrist grip" | "hands across";
type chooser_march_facing = "forward" | "backward" | "forward then backward";
type chooser_set_direction = "along" | "across" | "right diagonal" | "left diagonal";
type chooser_set_direction_acrossish = "across" | "right diagonal" | "left diagonal";
type chooser_set_direction_grid = "along" | "across";
type chooser_set_direction_figure_8 = "" | "above" | "below" | "across";
type chooser_gate_direction = "up" | "down" | "in" | "out";
type chooser_slice_return = "straight" | "diagonal" | "none";
type chooser_all_or_center_or_outsides = "all" | "center" | "outsides";
type chooser_down_the_hall_ender = "turn-alone" | "turn-couple" | "circle" | "cozy" | "cloverleaf" | "thread-needle" | "right-high" | "sliding-doors" | "";
type chooser_zig_zag_ender = "" | "ring" | "allemande";
type chooser_hey_length = "full" | "half" | "less than half" | "between half and full" | { dancer: chooser_pairz, time: 1 | 2};
type chooser_swing_prefix = "none" | "balance" | "meltdown";
type chooser_dancers = "everyone" | "gentlespoon" | "gentlespoons" | "ladle" | "ladles" | "partners" | "neighbors" | "ones" | "twos" | "same roles" | "first corners" | "second corners" | "first gentlespoon" | "first ladle" | "second gentlespoon" | "second ladle" | "shadows";
type chooser_pair = "gentlespoons" | "ladles" | "ones" | "twos" | "first corners" | "second corners";
type chooser_pair_or_everyone = "everyone" | "gentlespoons" | "ladles" | "ones" | "twos" | "first corners" | "second corners";
type chooser_pairc_or_everyone = "everyone" | "gentlespoons" | "ladles" | "centers" | "ones" | "twos";
export type chooser_pairz = "gentlespoons" | "ladles" | "partners" | "neighbors" | "next neighbors" | "3rd neighbors" | "ones" | "twos" | "same roles" | "first corners" | "second corners" | "shadows";
type chooser_pairz_or_unspecified = "" | "gentlespoons" | "ladles" | "partners" | "neighbors" | "ones" | "twos" | "same roles" | "first corners" | "second corners" | "shadows";
type chooser_pairs = "partners" | "neighbors" | "same roles" | "shadows";
type chooser_pairs_or_ones_or_twos = "partners" | "neighbors" | "same roles" | "ones" | "twos" | "shadows";
type chooser_pairs_or_everyone = "everyone" | "partners" | "neighbors" | "same roles" | "shadows";
type chooser_dancer = "first gentlespoon" | "first ladle" | "second gentlespoon" | "second ladle";
type chooser_role = "gentlespoons" | "ladles";
type chooser_hetero = "partners" | "neighbors" | "shadows";
export type Move = {
beats: number,
note?: string,
progression: boolean,
} & ({
move: "allemande",
parameters: {
who: chooser_pairz,
hand: chooser_right_left_hand,
circling: chooser_revolutions,
},
} | {
move: "allemande orbit",
parameters: {
who: chooser_pair,
hand: chooser_right_left_hand,
circling1: chooser_revolutions, // for allemande
circling2: chooser_revolutions, // for orbit
},
} | {
move: "arch & dive",
parameters: {
who: chooser_pair,
},
} | {
move: "balance",
parameters: {
who: chooser_pairs_or_everyone,
},
} | {
move: "balance the ring",
parameters: {
},
} | {
move: "box circulate",
parameters: {
who: chooser_pair,
bal: chooser_boolean,
hand: chooser_right_left_hand,
},
} | {
move: "box the gnat",
parameters: {
who: chooser_pairz,
bal: chooser_boolean,
hand: chooser_right_left_hand,
},
} | {
move: "swat the flea",
parameters: {
who: chooser_pairz,
bal: chooser_boolean,
hand: chooser_right_left_hand,
},
} | {
move: "butterfly whirl",
parameters: {
},
} | {
move: "California twirl",
parameters: {
who: chooser_pairz,
},
} | {
move: "chain",
parameters: {
who: chooser_role,
hand: chooser_right_left_hand,
dir: chooser_set_direction,
},
} | {
move: "circle",
parameters: {
turn: chooser_left_right_spin,
places: chooser_places,
},
} | {
move: "contra corners",
parameters: {
who: chooser_pair,
custom: chooser_text,
},
} | {
move: "cross trails",
parameters: {
who: chooser_pairs,
dir: chooser_set_direction_grid,
shoulder: chooser_right_left_shoulder,
who2: chooser_pairs,
},
} | {
move: "custom",
parameters: {
custom: chooser_text,
},
} | {
move: "do si do",
parameters: {
who: chooser_pairz,
shoulder: chooser_right_left_shoulder,
circling: chooser_revolutions,
},
} | {
move: "see saw",
parameters: {
who: chooser_pairz,
shoulder: chooser_right_left_shoulder,
circling: chooser_revolutions,
},
} | {
move: "dolphin hey",
parameters: {
who: chooser_pair,
whom: chooser_dancer,
shoulder: chooser_right_left_shoulder,
},
} | {
move: "down the hall",
parameters: {
who: chooser_pair_or_everyone,
moving: chooser_all_or_center_or_outsides,
facing: chooser_march_facing,
ender: chooser_down_the_hall_ender,
},
} | {
move: "up the hall",
parameters: {
who: chooser_pair_or_everyone,
moving: chooser_all_or_center_or_outsides,
facing: chooser_march_facing,
ender: chooser_down_the_hall_ender,
},
} | {
move: "figure 8",
parameters: {
who: chooser_pair,
dir: chooser_set_direction_figure_8,
lead: chooser_dancer,
half: chooser_half_or_full,
},
} | {
move: "form long waves",
parameters: {
who: chooser_pair,
},
} | {
move: "form a long wave",
parameters: {
who: chooser_pair,
in: chooser_boolean,
out: chooser_boolean,
bal: chooser_boolean,
},
} | {
move: "form an ocean wave",
parameters: {
"pass thru": chooser_boolean,
dir: chooser_set_direction_acrossish,
bal: chooser_boolean,
center: chooser_pair,
"c.hand": chooser_right_left_hand,
sides: chooser_pairs,
},
} | {
move: "gate",
parameters: {
who: chooser_pair,
whom: chooser_pairs_or_ones_or_twos,
face: chooser_gate_direction,
},
} | {
move: "give & take",
parameters: {
who: chooser_role,
whom: chooser_hetero,
give: chooser_give,
},
} | {
move: "facing star",
parameters: {
who: chooser_pair,
turn: chooser_spin,
places: chooser_places,
},
} | {
move: "gyre",
parameters: {
who: chooser_pairz,
shoulder: chooser_right_left_shoulder,
circling: chooser_revolutions,
},
} | {
move: "hey",
parameters: {
who: chooser_pairz,
who2: chooser_pairz_or_unspecified,
shoulder: chooser_right_left_shoulder,
until: chooser_hey_length,
dir: chooser_set_direction,
rico1: chooser_boolean,
rico2: chooser_boolean,
rico3: chooser_boolean,
rico4: chooser_boolean,
},
} | {
move: "long lines",
parameters: {
go: chooser_go_back,
},
} | {
move: "mad robin",
parameters: {
who: chooser_pair,
circling: chooser_revolutions,
},
} | {
move: "pass by",
parameters: {
who: chooser_pairz,
shoulder: chooser_right_left_shoulder,
},
} | {
move: "pass through",
parameters: {
dir: chooser_set_direction,
shoulder: chooser_right_left_shoulder,
},
} | {
move: "petronella",
parameters: {
bal: chooser_boolean,
},
} | {
move: "poussette",
parameters: {
half: chooser_half_or_full,
who: chooser_pair,
whom: chooser_pairs_or_ones_or_twos,
turn: chooser_spin,
},
} | {
move: "promenade",
parameters: {
who: chooser_pairs,
dir: chooser_set_direction,
turn: chooser_left_right_spin,
},
} | {
move: "pull by dancers",
parameters: {
who: chooser_pairz,
bal: chooser_boolean,
hand: chooser_right_left_hand,
},
} | {
move: "pull by direction",
parameters: {
bal: chooser_boolean,
dir: chooser_set_direction,
hand: chooser_right_left_hand,
},
} | {
move: "revolving door",
parameters: {
who: chooser_pair,
hand: chooser_right_left_hand,
whom: chooser_pairs,
},
} | {
move: "right left through",
parameters: {
dir: chooser_set_direction,
},
} | {
move: "roll away",
parameters: {
who: chooser_pair,
whom: chooser_pairs_or_ones_or_twos,
"½sash": chooser_boolean,
},
} | {
move: "Rory O'More",
parameters: {
who: chooser_pairc_or_everyone,
bal: chooser_boolean,
slide: chooser_slide,
},
} | {
move: "slice",
parameters: {
slide: chooser_slide,
"slice increment": chooser_slice_increment,
"slice return": chooser_slice_return,
},
} | {
move: "slide along set",
parameters: {
slide: chooser_slide,
},
} | {
move: "square through",
parameters: {
who: chooser_pairs,
who2: chooser_pairs,
bal: chooser_boolean,
hand: chooser_right_left_hand,
places: chooser_places,
},
} | {
move: "stand still",
parameters: {
},
} | {
move: "star",
parameters: {
hand: chooser_right_left_hand,
places: chooser_places,
grip: chooser_star_grip,
},
} | {
move: "star promenade",
parameters: {
who: chooser_pair,
hand: chooser_right_left_hand,
circling: chooser_revolutions,
},
} | {
move: "swing",
parameters: {
who: chooser_pairz,
prefix: chooser_swing_prefix,
},
} | {
move: "meltdown swing",
parameters: {
who: chooser_pairz,
prefix: chooser_swing_prefix,
},
} | {
move: "turn alone",
parameters: {
who: chooser_pair_or_everyone,
custom: chooser_text,
},
} | {
move: "zig zag",
parameters: {
who: chooser_pairs,
turn: chooser_left_right_spin,
ender: chooser_zig_zag_ender,
},
});
export function nameLibFigureParameters(move: LibFigureMove): Move {
const libfigureParameters: { name: string }[] = libfigure.formalParameters(move.move);
const parameterNames: string[] = libfigureParameters.map(p => p.name)
// Some moves have repeat parameter names, rename them to name1, name2, etc.
.map((v, i, a) => a.indexOf(v) === i && a.lastIndexOf(v) === i ? v : v + (a.slice(0, i).filter(el => el === v).length + 1));
const parameters = {};
for (let i = 0; i < parameterNames.length; i++) {
if (parameterNames[i] === "until") {
// parse chooser_hey_length
const hey_length: string = move.parameter_values[i];
if (hey_length.includes('%%')) {
parameters[parameterNames[i]] = {
dancer: hey_length.slice(0, -3),
time: parseInt(hey_length.at(-1)!),
};
} else {
parameters[parameterNames[i]] = hey_length;
}
} else {
parameters[parameterNames[i]] = move.parameter_values[i];
}
}
const beats: number = parameters["beats"];
parameters["beats"] = undefined;
return {
move: move.move,
beats,
progression: move.progression === 1,
note: move.note,
parameters,
} as Move;
}
// Helper for building the types above.
export function asTypeDefinitions(): string {
type Dialect = any;
const choosers: { [key: string]: (string | [any, string])[] } = {
chooser_boolean: [["*", "*"], [true, "yes"], [false, "no"]],
chooser_spin: [["*", "*"], [true, "clockwise"], [false, "ccw"]],
chooser_left_right_spin: [["*", "*"], [true, "left"], [false, "right"]],
chooser_right_left_hand: [["*", "*"], [false, "left"], [true, "right"]],
chooser_right_left_shoulder: [["*", "*"], [false, "left"], [true, "right"]],
chooser_slide: [["*", "*"], [true, "left"], [false, "right"]],
chooser_slice_increment: [
["*", "*"],
["couple", "couple"],
["dancer", "dancer"],
],
chooser_go_back: [["*", "*"], [true, "forward & back"], [false, "forward"]],
chooser_give: [["*", "*"], [true, "give & take"], [false, "take"]],
chooser_half_or_full: [["*", "*"], [0.5, "half"], [1.0, "full"]],
chooser_beats: [
"*",
8,
16,
0,
1,
2,
3,
4,
6,
8,
10,
12,
14,
16,
20,
24,
32,
48,
64,
],
chooser_star_grip:
["*"].concat(
libfigure.wristGrips.map(function (grip: any) {
return grip === "" ? ["", "unspecified"] : grip
})
),
chooser_march_facing: [
"*",
"forward",
"backward",
"forward then backward",
],
chooser_set_direction: [
"*",
["along", "along the set"],
["across", "across the set"],
"right diagonal",
"left diagonal",
],
chooser_set_direction_acrossish: [
"*",
["across", "across the set"],
"right diagonal",
"left diagonal",
],
chooser_set_direction_grid: [
"*",
["along", "along the set"],
["across", "across the set"],
],
chooser_set_direction_figure_8: [
"*",
"",
"above",
"below",
"across",
],
chooser_gate_direction: [
"*",
["up", "up the set"],
["down", "down the set"],
["in", "into the set"],
["out", "out of the set"],
],
chooser_slice_return: [
"*",
["straight", "straight back"],
["diagonal", "diagonal back"],
"none",
],
chooser_all_or_center_or_outsides: [
"*",
"all",
"center",
"outsides",
],
chooser_down_the_hall_ender: [
"*",
["turn-alone", "turn alone"],
["turn-couple", "turn as a couple"],
["circle", "bend into a ring"],
["cozy", "form a cozy line"],
["cloverleaf", "bend into a cloverleaf"],
["thread-needle", "thread the needle"],
["right-high", "right hand high, left hand low"],
["sliding-doors", "sliding doors"],
["", "unspecified"],
],
chooser_zig_zag_ender: [
"*",
["", "none"],
["ring", "into a ring"],
["allemande", "training two catch hands"],
],
chooser_hey_length: [
"*",
"full",
"half",
"less than half",
"between half and full",
],
chooser_swing_prefix: [
"*",
"none",
"balance",
"meltdown",
],
...libfigure.dancerChooserNames().reduce(
(acc: any, chooserName: string) => {
acc[chooserName] =
["*"].concat(
libfigure.dancerCategoryMenuForChooser(
libfigure.chooser(chooserName)
).map((dancers: string) => [
dancers,
libfigure.dancerMenuLabel(dancers, libfigure.defaultDialect),
])
)
return acc
},
{}
),
}
const chooserDefs = Object.keys(choosers).map(name => {
let c = choosers[name];
if (c instanceof Function) c = c(name);
function onlyUnique(value, index, array) {
return array.indexOf(value) === index;
}
c = c.map(el => (el instanceof String || typeof el === 'string') ? el : el[0]).filter(el => el != "*").filter(onlyUnique);
return "type " + name + " = " + c.map(el => JSON.stringify(el)).join(" | ") + ";"
}).join("\n");
const moveDefs = libfigure.moves().map(m => {
const params = libfigure.formalParameters(m);
return "{\n move: " + JSON.stringify(m)
+ ",\n parameters: {\n"
+ params.map(p => " " + p.name + ": " + p.ui.name + ",").join("\n")
+ "\n },\n }";
}).join(" | ");
return chooserDefs + "\n\n" + moveDefs;
}