getPlayerCharacterFrom(name) Dependencies: None Given a string name, this function returns an appropriate value for the first parameter of sendChat . function getPlayerCharacterFrom(name) {
var character = findObjs({
type: 'character',
name: name
})[0],
player = findObjs({
type: 'player',
displayname: name.lastIndexOf(' (GM)') === name.length - 5 ? name.substring(0, name.length - 5) : name
})[0];
if (player) {
return 'player|' + player.id;
}
if (character) {
return 'character|' + character.id;
}
return name;
} // example use: // sendChat(getPlayerCharacterFrom(msg.who), 'What\'s up, doc?'); getWhisperTarget(options) Dependencies: levenshteinDistance (see below) Given a set of options, this function tries to construct the "/w name " portion of a whisper for a call to sendChat . The options parameter should contain either player: true or character: true and a value for either id or name . Players are preferred over characters if both are true, and ids are preferred over names if both have a valid value. If a name is supplied, the player or character with the name closest to the supplied string will be sent the whisper. options is technically optional, but if you omit it (or don't supply a combination of player/character + id/name), the function will return an empty string. function getWhisperTarget(options) {
var nameProperty, targets, type;
options = options || {};
if (options.player) {
nameProperty = 'displayname';
type = 'player';
} else if (options.character) {
nameProperty = 'name';
type = 'character';
} else {
return '';
}
if (options.id) {
targets = [getObj(type, options.id)];
if (targets[0]) {
return '/w ' + targets[0].get(nameProperty).split(' ')[0] + ' ';
}
}
if (options.name) { // Gets all players or characters (as appropriate) whose name *contains* the supplied name, // then sorts them by how close they are to the supplied name.
targets = _.sortBy(filterObjs(function(obj) {
if (obj.get('type') !== type) return false;
return obj.get(nameProperty).indexOf(options.name) >= 0;
}), function(obj) {
return Math.abs(levenshteinDistance(obj.get(nameProperty), options.name));
});
if (targets[0]) {
return '/w ' + targets[0].get(nameProperty).split(' ')[0] + ' ';
}
}
return '';
} // example use: // sendChat('', getWhisperTarget({ player: true, id: msg.playerid }) + 'You shouldn\'t do that'); // sendChat('', getWhisperTarget({ player: true, name: msg.who }) + 'You\'ll go blind'); // sendChat('', getWhisperTarget({ character: true, id: myCharacter.id }) + 'That\'s illegal'); // sendChat('', getwhisperTarget({ character: true, name: myCharacter.get('name') }) + 'And dangerous'); splitArgs(input, separator) Source: <a href="https://github.com/elgs/splitargs" rel="nofollow">https://github.com/elgs/splitargs</a> While msg.content.split(' ') is often sufficient, sometimes you want a little more control over how you split up parameters to your API command. This function lets you split up a string while maintaining quoted sections using either single or double quotes. separator is optional, and if omitted the function will default to splitting around whitespace. If supplied, separator should be a regular expression object, not a string. function splitArgs(input, separator) {
var singleQuoteOpen = false,
doubleQuoteOpen = false,
tokenBuffer = [],
ret = [],
arr = input.split(''),
element, i, matches;
separator = separator || /\s/g;
for (i = 0; i < arr.length; i++) {
element = arr[i];
matches = element.match(separator);
if (element === '\'') {
if (!doubleQuoteOpen) {
singleQuoteOpen = !singleQuoteOpen;
continue;
}
} else if (element === '"') {
if (!singleQuoteOpen) {
doubleQuoteOpen = !doubleQuoteOpen;
continue;
}
}
if (!singleQuoteOpen && !doubleQuoteOpen) {
if (matches) {
if (tokenBuffer && tokenBuffer.length > 0) {
ret.push(tokenBuffer.join(''));
tokenBuffer = [];
}
} else {
tokenBuffer.push(element);
}
} else if (singleQuoteOpen || doubleQuoteOpen) {
tokenBuffer.push(element);
}
}
if (tokenBuffer && tokenBuffer.length > 0) {
ret.push(tokenBuffer.join(''));
}
return ret;
} // example use: // parameters = splitArgs(msg.content); levenshteinDistance(a, b) Source: <a href="http://en.wikibooks.org/wiki/Algorithm_Implementat" rel="nofollow">http://en.wikibooks.org/wiki/Algorithm_Implementat</a>... Computes the number of transformations required to get from string a to string b . A transformation can be substitution (ABC -> ADC), insertion (ABC -> ABDC), or deletion (ABC -> AC). function levenshteinDistance(a, b) {
var i, j,
matrix = [];
if (a.length === 0) {
return b.length;
}
if (b.length === 0) {
return a.length;
}
// Increment along the first column of each row
for (i = 0; i <= b.length; i++) {
matrix[i] = [i];
}
// Increment each column in the first row
for (j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}
// Fill in the rest of the matrix
for (i = 1; i <= b.length; i++) {
for (j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) === a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // Substitution
Math.min(matrix[i][j - 1] + 1, // Insertion
matrix[i - 1][j] + 1)); // Deletion
}
}
}
return matrix[b.length][a.length];
} // example use (see getWhisperTarget(options), above): // Math.abs(levenshteinDistance(obj.get(nameProperty), options.name))
How about the rest of you? Any awesome utility functions that could be used in most any script? Preferably things with limited or no dependencies on other functions, other than Underscore.js, native JavaScript, or built-in Roll20 library functions.