0 votes
by (1.1k points)
edited by

I'm starting to get more into complex information manipulation... I guess it will not be long before I need the javascript.
But anyway... The question is based on an array of objects, each person is an object, the question is, how to select a person from this array or a group of people based on a conditional.

E.g.

Imagine a nursery school...

<<set $myArray = []>>

<<set $myArray.push( {
		name: 'Edward',
		age: 5
} )>>

<<set $myArray.push( {
		name: 'Elizabeth',
		age: 3
} )>>

<<set $myArray.push( {
		name: 'Carlos',
		age: 5
} )>>

You create an event for children of 5 years but the array has children of different ages, you must select a children with this conditional age of 5 (randomly among all 5-year-olds) years for the event.

I'd like to know this in JS too, I know that Twine has limitations and complex things look better on JS, maybe that's one of them.

2 Answers

+1 vote
by (44.7k points)

The answer to this is actually pretty similar to the answer to your "How to modify all objects in an array" question.  You just loop through the array, check the age of each object in the array (instead of adding to it), and if it satisfies your critera, store that index in an array to track which indexes have relevant data.  For example:

<<nobr>>
	<<set _matches = []>>
	<<for _idx, _child range $myArray>>
		<<if _child.age == 5>>
			<<set _matches.push(_idx)>>
		<</if>>
	<</for>>
	<<if _matches.length == 0>>
		No matches found.<br>
	<<else>>
		Matches:
		<<for _n, _idx range _matches>>
			<<if _n < _matches.length - 1>>
				<<print " " + $myArray[_idx].name>>,
			<<else>>
				<<print " " + $myArray[_idx].name>>
			<</if>>
		<</for>>
		<br>
	<</if>>
<</nobr>>

So that will create an array of indexes, and you can then use that array to use or display the data however you want.  The above also shows an example of how you might display that data.

The method to get the array of indexes in JavaScript is quite similar:

State.temporary.matches = [];
for (var idx = 0; idx < State.variables.myArray.length; idx++) {
	if (State.variables.myArray[idx].age == 5) {
		State.temporary.matches.push(idx)>>
	}
}

That will do basically the same thing as lines 2 through 7 of the earlier SugarCube code.

Once you have the _matches array filled in, you can use "_matches.random()" to get the index of a random 5-year-old, assuming that there are any in $myArray.  (See the .random() method documentation for arrays in SugarCube.)  Or, you can use the .pluck() method to not only get a random index, but also remove that index from the array so you don't pick it again if you're picking multiple children.

Hope that helps!  :-)

+1 vote
by (68.6k points)
edited by

Here are three examples of how you could do it.  One using mostly macros, another mostly JavaScript, and the last full JavaScript.

 

Using mostly macros:

<<set _children to []>>
<<for _child range $myArray>>
	<<if _child.age is 5>><<run _children.push(_child)>><</if>>
<</for>>
<<set $selectedChild to _children.random()>>

 

Using mostly JavaScript:

<<set $selectedChild to $myArray.filter(function (child) {
	return child.age === 5;
}).random()>>

 

Using full JavaScript:

var sv = State.variables;
sv.selectedChild = sv.myArray.filter(function (child) {
	return child.age === 5;
}).random();

 

PS: Links to the documentation for Array methods you may not have seen yet.

...