1
0
forked from sent/waves
waves/public/assets/g/mario/References/WorldSeedr-0.2.0.ts
2025-04-09 17:11:14 -05:00

1084 lines
41 KiB
TypeScript

declare module WorldSeedr {
export interface IWorldSeedrSettings {
/**
* A very large listing of possibility schemas, keyed by title.
*/
possibilities: IPossibilityContainer;
/**
* Function used to generate a random number, if not Math.random.
*/
random?: () => number;
/**
* Function called in this.generateFull to place a child.
*/
onPlacement?: (commands: ICommand[]) => void;
}
export interface IPossibilityContainer {
[i: string]: IPossibility;
}
export interface IPossibility {
"width": number;
"height": number;
"contents": IPossibilityContents;
}
export interface IPossibilityContents {
"direction": string;
"mode": string;
"snap": string;
"children": IPossibilityChild[];
"spacing"?: number | number[]| IPossibilitySpacing;
"limit"?: number;
"argumentMap"?: IArgumentMap
}
export interface IPercentageOption {
"percent": number;
}
export interface IPossibilityChild extends IPercentageOption {
"title": string;
"type": string;
"arguments"?: IArgumentPossibilities[]| any;
"source"?: string;
"sizing"?: {
"width"?: number;
"height"?: number;
};
"stretch"?: {
"width"?: number;
"height"?: number;
};
}
export interface IPossibilitySpacing {
"min": number;
"max": number;
"units"?: number;
}
export interface IPossibilitySpacingOption extends IPercentageOption {
"value": IPossibilitySpacing;
}
export interface IArgumentPossibilities {
[i: number]: IArgumentPossibility
}
export interface IArgumentPossibility extends IPercentageOption {
values: any[];
}
export interface IArgumentMap {
[i: string]: string;
}
export interface IDirectionsMap {
"top": string;
"right": string;
"bottom": string;
"left": string;
}
export interface IPosition {
"width": number;
"height": number;
"top": number;
"right": number;
"bottom": number;
"left": number;
"type"?: string;
}
export interface ICommand extends IPosition {
"title": string;
"arguments"?: IArgumentPossibilities | any;
}
export interface IChoice extends ICommand {
"contents"?: IChoice;
"children"?: IChoice[];
}
export interface IWorldSeedr {
getPossibilities(): IPossibilityContainer;
setPossibilities(possibilities: IPossibilityContainer): void;
getOnPlacement(): (commands: ICommand[]) => void;
setOnPlacement(onPlacement: (commands: ICommand[]) => void): void;
clearGeneratedCommands(): void;
runGeneratedCommands(): void;
generate(name: string, command: IPosition | ICommand): IChoice;
generateFull(schema: ICommand): void;
}
}
module WorldSeedr {
"use strict";
/**
* A randomization utility to automate random, recursive generation of
* possibilities based on a preset position and probability schema. Each
* "possibility" in the schema contains a width, height, and instructions on
* what type of contents it contains, which are either a preset listing or
* a randomization of other possibilities of certain probabilities. Additional
* functionality is provided to stagger layout of children, such as spacing
* between possibilities.
*/
export class WorldSeedr {
/**
* A very large listing of possibility schemas, keyed by title.
*/
private possibilities: IPossibilityContainer;
/**
* Function used to generate a random number
*/
private random: () => number;
/**
* Function called in generateFull to place a command.
*/
private onPlacement: (commands: ICommand[]) => void;
/**
* Scratch Array of PreThings to be added to during generation.
*/
private generatedCommands: ICommand[];
/**
* A constant listing of direction opposites, like top-bottom.
*/
private directionOpposites: IDirectionsMap = {
"top": "bottom",
"right": "left",
"bottom": "top",
"left": "right"
};
/**
* A constant listing of what direction the sides of areas correspond to.
*/
private directionSizing: IDirectionsMap = {
"top": "height",
"right": "width",
"bottom": "height",
"left": "width"
};
/**
* A constant Array of direction names.
*/
private directionNames: string[] = ["top", "right", "bottom", "left"];
/**
* A constant Array of the dimension descriptors.
*/
private sizingNames: string[] = ["width", "height"];
/**
* @param {IWorldSeedrSettings} settings
*/
constructor(settings: IWorldSeedrSettings) {
if (typeof settings.possibilities === "undefined") {
throw new Error("No possibilities given to WorldSeedr.");
}
this.possibilities = settings.possibilities;
this.random = settings.random || Math.random.bind(Math);
this.onPlacement = settings.onPlacement || console.log.bind(console, "Got:");
this.clearGeneratedCommands();
}
/* Simple gets & sets
*/
/**
* @return {Object} The listing of possibilities that may be generated.
*/
getPossibilities(): IPossibilityContainer {
return this.possibilities;
}
/**
* @param {Object} possibilitiesNew A new Object to list possibilities
* that may be generated.
*/
setPossibilities(possibilities: IPossibilityContainer): void {
this.possibilities = possibilities;
}
/**
* @return {Function} The Function callback for generated possibilities of
* type "known" to be called in runGeneratedCommands.
*/
getOnPlacement(): (commands: ICommand[]) => void {
return this.onPlacement;
}
/**
* @param {Function} onPlacementNew A new Function to be used as the
* onPlacement callback.
*/
setOnPlacement(onPlacement: (commands: ICommand[]) => void): void {
this.onPlacement = onPlacement;
}
/* Generated commands
*/
/**
* Resets the generatedCommands Array so runGeneratedCommands can start.
*/
clearGeneratedCommands(): void {
this.generatedCommands = [];
}
/**
* Runs the onPlacement callback on the generatedCommands Array.
*/
runGeneratedCommands(): void {
this.onPlacement(this.generatedCommands);
}
/* Hardcore generation functions
*/
/**
* Generates a collection of randomly chosen possibilities based on the
* given schema mapping. These does not recursively parse the output; do
* do that, use generateFull.
*
* @param {String} name The name of the possibility schema to start from.
* @param {Object} position An Object that contains .left, .right, .top,
* and .bottom.
* @return {Object} An Object containing a position within the given
* position and some number of children.
*/
generate(name: string, command: IPosition | ICommand): IChoice {
var schema: IPossibility = this.possibilities[name];
if (!schema) {
throw new Error("No possibility exists under '" + name + "'");
}
if (!schema.contents) {
throw new Error("Possibility '" + name + "' has no possibile outcomes.");
}
return this.generateChildren(schema, this.objectCopy(command));
}
/**
* Recursively generates a schema. The schema's title and itself are given
* to this.generate; all outputs of type "Known" are added to the
* generatedCommands Array, while everything else is recursed upon.
*
* @param {Object} schema A simple Object with basic information on the
* chosen possibility.
* @return {Object} An Object containing a position within the given
* position and some number of children.
*/
generateFull(schema: ICommand): void {
var generated: IChoice = this.generate(schema.title, schema),
child: IChoice,
i: number;
if (!generated || !generated.children) {
return;
}
for (i = 0; i < generated.children.length; i += 1) {
child = generated.children[i];
switch (child.type) {
case "Known":
this.generatedCommands.push(child);
break;
case "Random":
this.generateFull(child);
break;
default:
throw new Error("Unknown child type: " + child.type);
}
}
}
/**
* Generates the children for a given schema, position, and direction. This
* is the real hardcore function called by this.generate, which calls the
* differnt subroutines based on whether the contents are in "Certain" or
* "Random" mode.
*
* @param {Object} schema A simple Object with basic information on the
* chosen possibility.
* @param {Object} position The bounding box for where the children may
* be generated.
* @param {String} [direction] A string direction to check the position
* by ("top", "right", "bottom", or "left")
* as a default if contents.direction isn't
* provided.
* @return {Object} An Object containing a position within the given
* position and some number of children.
*/
private generateChildren(schema: IPossibility, position: IPosition, direction: string = undefined): IChoice {
var contents: IPossibilityContents = schema.contents,
spacing: number | number[]| IPossibilitySpacing = contents.spacing || 0,
objectMerged: IPosition = this.objectMerge(schema, position),
children: IChoice[];
direction = contents.direction || direction;
switch (contents.mode) {
case "Random":
children = this.generateChildrenRandom(contents, objectMerged, direction, spacing);
break;
case "Certain":
children = this.generateChildrenCertain(contents, objectMerged, direction, spacing);
break;
case "Repeat":
children = this.generateChildrenRepeat(contents, objectMerged, direction, spacing);
break;
case "Multiple":
children = this.generateChildrenMultiple(contents, objectMerged, direction, spacing);
break;
default:
throw new Error("Unknown contents mode: " + contents.mode);
}
return this.wrapChoicePositionExtremes(children);
}
/**
* Generates a schema's children that are known to follow a set listing of
* sub-schemas.
*
* @param {Object} contents The known possibilities to choose between.
* @param {Object} position The bounding box for where the children may
* be generated.
* @param {String} direction A string direction to check the position by:
* "top", "right", "bottom", or "left".
* @param {Number} spacing How much space there should be between each
* child.
* @return {Object} An Object containing a position within the given
* position and some number of children.
*/
private generateChildrenCertain(
contents: IPossibilityContents,
position: IPosition,
direction: string,
spacing: number | number[]| IPossibilitySpacing): IChoice[] {
var scope: WorldSeedr = this;
return contents.children.map(function (choice: IPossibilityChild): IChoice {
if (choice.type === "Final") {
return scope.parseChoiceFinal(contents, choice, position, direction);
}
var output: IChoice = scope.parseChoice(choice, position, direction);
if (output) {
if (output.type !== "Known") {
output.contents = scope.generate(output.title, position);
}
scope.shrinkPositionByChild(position, output, direction, spacing);
}
return output;
}).filter(function (child: IChoice): boolean {
return child !== undefined;
});
}
/**
* Generates a schema's children that are known to follow a set listing of
* sub-schemas, repeated until there is no space left.
*
* @param {Object} contents The known possibilities to choose between.
* @param {Object} position The bounding box for where the children may
* be generated.
* @param {String} direction A string direction to check the position by:
* "top", "right", "bottom", or "left".
* @param {Number} spacing How much space there should be between each
* child.
* @return {Object} An Object containing a position within the given
* position and some number of children.
*/
private generateChildrenRepeat(
contents: IPossibilityContents,
position: IPosition,
direction: string,
spacing: number | number[]| IPossibilitySpacing): IChoice[] {
var choices: IPossibilityChild[] = contents.children,
children: IChoice[] = [],
choice: IPossibilityChild,
child: IChoice,
i: number = 0;
// Continuously loops through the choices and adds them to the output
// children, so long as there's still room for them
while (this.positionIsNotEmpty(position, direction)) {
choice = choices[i];
if (choice.type === "Final") {
child = this.parseChoiceFinal(contents, choice, position, direction);
} else {
child = this.parseChoice(choice, position, direction);
if (child) {
if (child.type !== "Known") {
child.contents = this.generate(child.title, position);
}
}
}
if (child && this.choiceFitsPosition(child, position)) {
this.shrinkPositionByChild(position, child, direction, spacing);
children.push(child);
} else {
break;
}
i += 1;
if (i >= choices.length) {
i = 0;
}
}
return children;
}
/**
* Generates a schema's children that are known to be randomly chosen from a
* list of possibilities until there is no more room.
*
* @param {Object} contents The Array of known possibilities, with
* probability percentages.
* @param {Object} position An Object that contains .left, .right, .top,
* and .bottom.
* @param {String} direction A string direction to check the position by:
* "top", "right", "bottom", or "left".
* @param {Number} spacing How much space there should be between each
* child.
* @return {Object} An Object containing a position within the given
* position and some number of children.
*/
private generateChildrenRandom(
contents: IPossibilityContents,
position: IPosition,
direction: string,
spacing: number | number[]| IPossibilitySpacing): IChoice[] {
var children: IChoice[] = [],
child: IChoice;
// Continuously add random choices to the output children as long as
// there's room in the position's bounding box
while (this.positionIsNotEmpty(position, direction)) {
child = this.generateChild(contents, position, direction);
if (!child) {
break;
}
this.shrinkPositionByChild(position, child, direction, spacing);
children.push(child);
if (contents.limit && children.length > contents.limit) {
return;
}
}
return children;
}
/**
* Generates a schema's children that are all to be placed within the same
* position. If a direction is provided, each subsequent one is shifted in
* that direction by spacing.
*
* @param {Object} contents The Array of known possibilities, with
* probability percentages.
* @param {Object} position An Object that contains .left, .right, .top,
* and .bottom.
* @param {String} [direction] A string direction to check the position by:
* "top", "right", "bottom", or "left".
* @param {Number} [spacing] How much space there should be between each
* child.
* @return {Object} An Object containing a position within the given
* position and some number of children.
*/
private generateChildrenMultiple(
contents: IPossibilityContents,
position: IPosition,
direction: string,
spacing: number | number[]| IPossibilitySpacing): IChoice[] {
var scope: WorldSeedr = this;
return contents.children.map(function (choice: IPossibilityChild): IChoice {
var output: IChoice = scope.parseChoice(choice, scope.objectCopy(position), direction);
if (direction) {
(<WorldSeedr>scope).movePositionBySpacing(position, direction, spacing);
}
return output;
});
}
/* Choice parsing
*/
/**
* Shortcut function to choose a choice from an allowed set of choices, and
* parse it for positioning and sub-choices.
*
* @param {Object} contents An Array of choice Objects, each of which must
* have a .percentage.
* @param {Object} position An Object that contains .left, .right, .top,
* and .bottom.
* @param {String} direction A string direction to check the position by:
* "top", "right", "bottom", or "left".
* @return {Object} An Object containing the bounding box position of a
* parsed child, with the basic schema (.title) info
* added as well as any optional .arguments.
*/
private generateChild(contents: IPossibilityContents, position: IPosition, direction: string): IChoice {
var choice: IPossibilityChild = this.chooseAmongPosition(contents.children, position);
if (!choice) {
return undefined;
}
return this.parseChoice(choice, position, direction);
}
/**
* Creates a parsed version of a choice given the position and direction.
* This is the function that parses and manipulates the positioning of the
* new choice.
*
* @param {Object} choice The simple definition of the Object chosen from
* a choices array. It should have at least .title,
* and optionally .sizing or .arguments.
* @param {Object} position An Object that contains .left, .right, .top,
* and .bottom.
* @param {String} direction A string direction to shrink the position by:
* "top", "right", "bottom", or "left".
* @return {Object} An Object containing the bounding box position of a
* parsed child, with the basic schema (.title) info
* added as well as any optional .arguments.
*/
private parseChoice(choice: IPossibilityChild, position: IPosition, direction: string): IChoice {
var title: string = choice.title,
schema: IPossibility = this.possibilities[title],
output: IChoice = {
"title": title,
"type": choice.type,
"arguments": choice.arguments instanceof Array
? (<IArgumentPossibility>(this.chooseAmong(choice.arguments))).values
: choice.arguments,
"width": undefined,
"height": undefined,
"top": undefined,
"right": undefined,
"bottom": undefined,
"left": undefined
};
this.ensureSizingOnChoice(output, choice, schema);
this.ensureDirectionBoundsOnChoice(output, position);
output[direction] = output[this.directionOpposites[direction]] + output[this.directionSizing[direction]];
switch (schema.contents.snap) {
case "top":
output.bottom = output.top - output.height;
break;
case "right":
output.left = output.right - output.width;
break;
case "bottom":
output.top = output.bottom + output.height;
break;
case "left":
output.right = output.left + output.width;
break;
default:
break;
}
if (choice.stretch) {
if (!output.arguments) {
output.arguments = {};
}
if (choice.stretch.width) {
output.left = position.left;
output.right = position.right;
output.width = output.right - output.left;
output.arguments.width = output.width;
}
if (choice.stretch.height) {
output.top = position.top;
output.bottom = position.bottom;
output.height = output.top - output.bottom;
output.arguments.height = output.height;
}
}
this.copySchemaArguments(schema, choice, output);
return output;
}
/**
* should conform to parent (contents) via cannonsmall.snap=bottom
*/
private parseChoiceFinal(parent: IPossibilityContents, choice: IPossibilityChild, position: IPosition, direction: string): IChoice {
var schema: IPossibility = this.possibilities[choice.source],
output: IChoice = {
"type": "Known",
"title": choice.title,
"arguments": choice.arguments,
"width": schema.width,
"height": schema.height,
"top": position.top,
"right": position.right,
"bottom": position.bottom,
"left": position.left
};
this.copySchemaArguments(schema, choice, output);
return output;
}
/* Randomization utilities
*/
/**
* From an Array of potential choice objects, returns one chosen at random.
*
* @param {Array} choice An Array of objects with .width and .height.
* @return {Object}
*/
private chooseAmong<t extends IPercentageOption>(choices: t[]): t {
if (!choices.length) {
return undefined;
}
if (choices.length === 1) {
return choices[0];
}
var choice: number = this.randomPercentage(),
sum: number = 0,
i: number;
for (i = 0; i < choices.length; i += 1) {
sum += choices[i].percent;
if (sum >= choice) {
return choices[i];
}
}
}
/**
* From an Array of potential choice objects, filtered to only include those
* within a certain size, returns one chosen at random.
*
* @param {Array} choice An Array of objects with .width and .height.
* @param {Object} position An Object that contains .left, .right, .top,
* and .bottom.
* @return {Object}
* @remarks Functions that use this will have to react to nothing being
* chosen. For example, if only 50 percentage is accumulated
* among fitting ones but 75 is randomly chosen, something should
* still be returned.
*/
private chooseAmongPosition(choices: IPossibilityChild[], position: IPosition): IPossibilityChild {
var width: number = position.right - position.left,
height: number = position.top - position.bottom,
scope: WorldSeedr = this;
return this.chooseAmong(choices.filter(function (choice: IPossibilityChild): boolean {
return scope.choiceFits(scope.possibilities[choice.title], width, height);
}));
}
/**
* Checks whether a choice can fit within a width and height.
*
* @param {Object} choice An Object that contains .width and .height.
* @param {Number} width
* @param {Number} height
* @return {Boolean} Whether the choice fits within the position.
*/
private choiceFits(choice: IPossibility | IChoice, width: number, height: number): boolean {
return choice.width <= width && choice.height <= height;
}
/**
* Checks whether a choice can fit within a position.
*
* @param {Object} choice An Object that contains .width and .height.
* @param {Object} position An Object that contains .left, .right, .top,
* and .bottom.
* @return {Boolean} The boolean equivalent of the choice fits
* within the position.
* @remarks When calling multiple times on a position (such as in
* chooseAmongPosition), it's more efficient to store the width
* and height separately and just use doesChoiceFit.
*/
private choiceFitsPosition(choice: IPossibility | IChoice, position: IPosition): boolean {
return this.choiceFits(choice, position.right - position.left, position.top - position.bottom);
}
/**
* @return {Number} A number in [1, 100] at random.
*/
private randomPercentage(): number {
return Math.floor(this.random() * 100) + 1;
}
/**
* @return {Number} A number in [min, max] at random.
*/
private randomBetween(min: number, max: number): number {
return Math.floor(this.random() * (1 + max - min)) + min;
}
/* Position manipulation utilities
*/
/**
* Creates and returns a copy of a position (really just a shallow copy).
*
* @param {Object} original
* @return {Object}
*/
private objectCopy(original: any): any {
var output: any = {},
i: string;
for (i in original) {
if (original.hasOwnProperty(i)) {
output[i] = original[i];
}
}
return output;
}
/**
* Creates a new position with all required attributes taking from the
* primary source or secondary source, in that order.
*
* @param {Object} primary
* @param {Object} secondary
* @return {Object}
*/
private objectMerge(primary: any, secondary: any): any {
var output: IPosition = this.objectCopy(primary),
i: string;
for (i in secondary) {
if (secondary.hasOwnProperty(i) && !output.hasOwnProperty(i)) {
output[i] = secondary[i];
}
}
return output;
}
/**
* Checks and returns whether a position has open room in a particular
* direction (horizontally for left/right and vertically for top/bottom).
*
* @param {Object} position An Object that contains .left, .right, .top,
* and .bottom.
* @param {String} direction A string direction to check the position in:
* "top", "right", "bottom", or "left".
*/
private positionIsNotEmpty(position: IPosition, direction: string): boolean {
if (direction === "right" || direction === "left") {
return position.left < position.right;
} else {
return position.top > position.bottom;
}
}
/**
* Shrinks a position by the size of a child, in a particular direction.
*
* @param {Object} position An Object that contains .left, .right, .top,
* and .bottom.
* @param {Object} child An Object that contains .left, .right, .top, and
* .bottom.
* @param {String} direction A string direction to shrink the position by:
* "top", "right", "bottom", or "left".
* @param {Mixed} [spacing] How much space there should be between each
* child (by default, 0).
*/
private shrinkPositionByChild(
position: IPosition,
child: IChoice,
direction: string,
spacing: number | number[]| IPossibilitySpacing | IPossibilitySpacingOption[]): void {
switch (direction) {
case "top":
position.bottom = child.top + this.parseSpacing(spacing);
break;
case "right":
position.left = child.right + this.parseSpacing(spacing);
break;
case "bottom":
position.top = child.bottom - this.parseSpacing(spacing);
break;
case "left":
position.right = child.left - this.parseSpacing(spacing);
break;
default:
break;
}
}
/**
* Moves a position by its parsed spacing. This is only useful for content
* of type "Multiple", which are allowed to move themselves via spacing
* between placements.
*
* @param {Object} position An Object that contains .left, .right, .top,
* and .bottom.
* @param {String} direction A string direction to shrink the position by:
* "top", "right", "bottom", or "left".
* @param {Mixed} [spacing] How much space there should be between each
* child (by default, 0).
*/
private movePositionBySpacing(
position: IPosition,
direction: string,
spacing: number | number[]| IPossibilitySpacing | IPossibilitySpacingOption[] = 0): void {
var space: number = this.parseSpacing(spacing);
switch (direction) {
case "top":
position.top += space;
position.bottom += space;
break;
case "right":
position.left += space;
position.right += space;
break;
case "bottom":
position.top -= space;
position.bottom -= space;
break;
case "left":
position.left -= space;
position.right -= space;
break;
default:
throw new Error("Unknown direction: " + direction);
}
}
/**
* Recursively parses a spacing parameter to eventually return a Number,
* which will likely be random.
*
* @param {Mixed} spacing This may be a Number (returned directly), an
* Object[] containing choices for chooseAmong, a
* Number[] containing minimum and maximum values,
* or an Object containing "min", "max", and
* "units" to round to.
* @return {Number}
*/
private parseSpacing(spacing: number | number[]| IPossibilitySpacing | IPossibilitySpacingOption[]): number {
if (!spacing) {
return 0;
}
switch (spacing.constructor) {
case Array:
// Case: [min, max]
if ((<number[]>spacing)[0].constructor === Number) {
return this.parseSpacingObject(this.randomBetween((<number[]>spacing)[0], (<number[]>spacing)[1]));
}
// Case: IPossibilitySpacingOption[]
return this.parseSpacingObject(this.chooseAmong(<IPossibilitySpacingOption[]>spacing).value);
case Object:
// Case: IPossibilitySpacing
return this.parseSpacingObject(<IPossibilitySpacing>spacing);
default:
// Case: Number
return <number>spacing;
}
}
/**
* Helper to parse a spacing Object. The minimum and maximum ("min" and
* "max", respectively) are the range, and an optional "units" parameter
* is what Number it should round to.
*
* @param {Object} spacing
* @return {Number}
*/
private parseSpacingObject(spacing: number | IPossibilitySpacing): number {
if (spacing.constructor === Number) {
return <number>spacing;
}
var min: number = (<IPossibilitySpacing>spacing).min,
max: number = (<IPossibilitySpacing>spacing).max,
units: number = (<IPossibilitySpacing>spacing).units || 1;
return this.randomBetween(min / units, max / units) * units;
}
/**
* Generates the bounding box position Object (think rectangle) for a set of
* children. The top, right, etc. member variables become the most extreme
* out of all the possibilities.
*
* @param {Object} children An Array of Objects with .top, .right,
* .bottom, and .left.
* @return {Object} An Object with .top, .right, .bottom, and .left.
*/
private wrapChoicePositionExtremes(children: IChoice[]): IChoice {
var position: IChoice,
child: IChoice,
i: number;
if (!children || !children.length) {
return undefined;
}
child = children[0];
position = {
"title": undefined,
"top": child.top,
"right": child.right,
"bottom": child.bottom,
"left": child.left,
"width": undefined,
"height": undefined,
"children": children
};
if (children.length === 1) {
return position;
}
for (i = 1; i < children.length; i += 1) {
child = children[i];
if (!Object.keys(child).length) {
return position;
}
position.top = Math.max(position.top, child.top);
position.right = Math.max(position.right, child.right);
position.bottom = Math.min(position.bottom, child.bottom);
position.left = Math.min(position.left, child.left);
}
position.width = position.right - position.left;
position.height = position.top - position.bottom;
return position;
}
/**
* Copies settings from a parsed choice to its arguments. What settings to
* copy over are determined by the schema's content's argumentMap attribute.
*
* @param {Object} schema A simple Object with basic information on the
* chosen possibility.
* @param {Object} choice The simple definition of the Object chosen from
* a choices array.
* @param {Object} output The Object (likely a parsed possibility content)
* having its arguments modified.
*/
private copySchemaArguments(schema: IPossibility, choice: IPossibilityChild, output: IChoice): void {
var map: IArgumentMap = schema.contents.argumentMap,
i: string;
if (!map) {
return;
}
if (!output.arguments) {
output.arguments = {};
}
for (i in map) {
if (map.hasOwnProperty(i)) {
output.arguments[map[i]] = choice[i];
}
}
}
/**
* Ensures an output from parseChoice contains all the necessary size
* measurements, as listed in this.sizingNames.
*
* @param {Object} output The Object (likely a parsed possibility content)
* having its arguments modified.
* @param {Object} choice The simple definition of the Object chosen from
* a choices array.
* @param {Object} schema A simple Object with basic information on the
* chosen possibility.
*/
private ensureSizingOnChoice(output: IChoice, choice: IPossibilityChild, schema: IPossibility): void {
var name: string,
i: string;
for (i in this.sizingNames) {
if (!this.sizingNames.hasOwnProperty(i)) {
continue;
}
name = this.sizingNames[i];
output[name] = (choice.sizing && typeof choice.sizing[name] !== "undefined")
? choice.sizing[name]
: schema[name];
}
}
/**
* Ensures an output from parseChoice contains all the necessary position
* bounding box measurements, as listed in this.directionNames.
*
* @param {Object} output The Object (likely a parsed possibility content)
* having its arguments modified.
* chosen possibility.
* @param {Object} position An Object that contains .left, .right, .top,
* and .bottom.
*/
private ensureDirectionBoundsOnChoice(output: IChoice, position: IPosition): void {
var i: string;
for (i in this.directionNames) {
if (this.directionNames.hasOwnProperty(i)) {
output[this.directionNames[i]] = position[this.directionNames[i]];
}
}
}
}
}