You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
4.3 KiB
169 lines
4.3 KiB
### |
|
oneOf.js |
|
|
|
Copyright (c) 2015 Bruno Dias |
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
|
of this software and associated documentation files (the "Software"), to deal |
|
in the Software without restriction, including without limitation the rights |
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
copies of the Software, and to permit persons to whom the Software is |
|
furnished to do so, subject to the following conditions: |
|
|
|
The above copyright notice and this permission notice shall be included in |
|
all copies or substantial portions of the Software. |
|
### |
|
|
|
### |
|
Undularity Tools |
|
|
|
Those functions are not a core part of Undularity, but provide some |
|
general functionality that relates to adaptive text generation. |
|
|
|
This is provided partly as a helper to less technical users, and as |
|
a convenience for authors. |
|
### |
|
|
|
# Monkey patching |
|
|
|
### |
|
Shuffles an array. It can use Undum's random number generator implementation, |
|
so it expects a System.rnd object to be passed into it. If one isn't |
|
supplied, it will use Math.Random instead. |
|
|
|
This is an implementation of the Fischer-Yates (Knuth) shuffle. |
|
|
|
Returns the shuffled array. |
|
### |
|
|
|
Array.prototype.shuffle = () -> |
|
# slice() clones the array. Object members are copied by reference, beware. |
|
newArr = this.slice() |
|
m = newArr.length |
|
|
|
while (m) |
|
i = Math.floor(salet.rnd.randf() * m--) |
|
t = newArr[m] |
|
newArr[m] = newArr[i] |
|
newArr[i] = t |
|
|
|
return newArr |
|
|
|
### |
|
oneOf() |
|
|
|
Takes an array and returns an object with several methods. Each method |
|
returns an iterator which iterates over the array in a specific way: |
|
|
|
inOrder() |
|
Returns the array items in order. |
|
|
|
cycling() |
|
Returns the array items in order, cycling back to the first item when |
|
it runs out. |
|
|
|
stopping() |
|
Returns the array items in order, then repeats the last item when it |
|
runs out. |
|
|
|
randomly() |
|
Returns the array items at random. Takes a system object, for consistent |
|
randomness. Will never return the same item twice in a row. |
|
|
|
trulyAtRandom() |
|
Returns the array items purely at random. Takes a system object, for |
|
consistent randomness. |
|
|
|
inRandomOrder() |
|
Returns the array items in a random order. Takes a system object, for |
|
consistent randomness. |
|
### |
|
|
|
### |
|
Takes a function and gives it a toString() property that calls itself and |
|
returns its value, allowing for ambiguous use of the closure object |
|
as a text snippet. |
|
|
|
Returns the modified function. |
|
### |
|
stringish = (callback) -> |
|
callback.toString = () -> |
|
return '' + this.call() |
|
return callback |
|
|
|
oneOf = (ary...) -> |
|
if ary.length == 0 |
|
throw new Error( |
|
"tried to create a oneOf iterator with a 0-length array"); |
|
|
|
return { |
|
inOrder: () -> |
|
i = 0 |
|
return stringish(() -> |
|
if i >= ary.length |
|
return null |
|
return ary[i++] |
|
) |
|
|
|
cycling: () -> |
|
i = 0 |
|
return stringish(() -> |
|
if (i >= ary.length) |
|
i = 0 |
|
return ary[i++] |
|
) |
|
|
|
stopping: () -> |
|
i = 0 |
|
return stringish(() -> |
|
if (i >= ary.length) |
|
i = ary.length - 1 |
|
return ary[i++] |
|
) |
|
|
|
randomly: (system) -> |
|
last = null |
|
|
|
if (ary.length<2) |
|
throw new Error("attempted to make randomly() iterator with a 1-length array") |
|
return stringish( () -> |
|
i = null |
|
offset = null |
|
if not last? |
|
i = Math.floor(salet.rnd.randf() * ary.length) |
|
else |
|
### |
|
Let offset be a random number between 1 and the length of the |
|
array, minus one. We jump offset items ahead on the array, |
|
wrapping around to the beginning. This gives us a random item |
|
other than the one we just chose. |
|
### |
|
|
|
offset = Math.floor(salet.rnd.randf() * (ary.length -1) + 1) |
|
i = (last + offset) % ary.length |
|
|
|
last = i |
|
return ary[i] |
|
) |
|
|
|
trulyAtRandom: (system) -> |
|
return stringish(() -> |
|
return ary[Math.floor(salet.rnd.randf() * ary.length)]; |
|
) |
|
|
|
inRandomOrder: (system) -> |
|
shuffled = ary.shuffle(system) |
|
i = 0 |
|
return stringish(() -> |
|
if (i >= ary.length) |
|
i = 0 |
|
return shuffled[i++] |
|
) |
|
} |
|
|
|
Array.prototype.oneOf = () -> |
|
oneOf.apply(null, this) |
|
String.prototype.oneOf = () -> |
|
return this |
|
|
|
module.exports = oneOf
|
|
|