poserver
Version:
Server for JD Bot
203 lines (168 loc) • 7.35 kB
JavaScript
/**
* Created by tomdaley on 10/8/16.
*/
;
/**
* ParsedName - Class containing name fields for a person
*
* var myName = "Mr. Thomas J. Daley, Esq.";
* var myParsedName = ParsedName.parse(myName);
*/
var ParsedName = function (nameObject)
{
nameObject = nameObject || {};
if (typeof nameObject === "string") nameObject = this.parseName(nameObject);
var _this = this;
_this.__type = "ParsedName";
if (nameObject.hasOwnProperty("courtesyTitle")) _this.courtesyTitle = nameObject.courtesyTitle;
if (nameObject.hasOwnProperty("firstName")) _this.firstName = nameObject.firstName;
if (nameObject.hasOwnProperty("middleName")) _this.middleName = nameObject.middleName;
if (nameObject.hasOwnProperty("lastName")) _this.lastName = nameObject.lastName;
if (nameObject.hasOwnProperty("suffix")) _this.suffix = nameObject.suffix;
if (nameObject.hasOwnProperty("salutation")) _this.salutation = nameObject.salutation;
if (nameObject.hasOwnProperty("userString")) _this.userString = nameObject.userString;
};
ParsedName.prototype.fullNameWithTitle = function ()
{
var _this = this;
var fullname = _this.fullName();
if (_this.hasOwnProperty("courtesyTitle")) fullname = _this.courtesyTitle + ". " + fullname;
return fullname;
};
ParsedName.prototype.fullName = function ()
{
var _this = this;
var fullname = "";
if (this.hasOwnProperty("firstName")) fullname += _this.firstName;
if (this.hasOwnProperty("middleName"))
{
if (_this.middleName.length === 1)
fullname += " " + _this.middleName + ". ";
else
fullname += " " + _this.middleName;
}
if (this.hasOwnProperty("lastName")) fullname += " " + _this.lastName;
if (this.hasOwnProperty("suffix")) fullname += ", " + _this.suffix;
fullname = fullname.replace(/\s+/, ' ').trim();
return fullname;
};
ParsedName.prototype.parsedName = function ()
{
var _this = this;
var pname = {};
pname.className = _this.__type;
if (_this.suffix) pname.suffix = _this.suffix;
if (_this.firstName) pname.firstName = _this.firstName;
if (_this.middleName) pname.middleName = _this.middleName;
if (_this.lastName) pname.lastName = _this.lastName;
if (_this.suffix) pname.suffix = _this.suffix;
return pname;
};
ParsedName.prototype.toDocument = function ()
{
return this.parsedName;
};
ParsedName.prototype.toString = function ()
{
return this.fullNameWithTitle;
};
ParsedName.prototype.inferredGender = function ()
{
var maleTitles = ["MR"];
var femaleTitles = ["MS", "MX", "MRS"];
if (this.courtesyTitle === false) return -1;
if (maleTitles.indexOf(this.courtesyTitle.toUpperCase()) != -1) return 0;
if (femaleTitles.indexOf(this.courtesyTitle.toUpperCase()) != -1) return 1;
return -1;
};
/**
* Here to break a string apart into various name parts. I will probably use LUIS for this purpose
* in the future. For now, I'm just doing a dumb parse. Here's a trick that no user will ever figure out
* so I don't know what it's worth. For now, an equal sign between words causes them to be parsed as a single
* entity, but then the equal is replaced by a space so that we get the visual appearance of a two-word name.
*
* For example, if the person's last name were "St. Laurent", the user could enter it as "St.=Laurent" and
* it would parse as expected and look nice. Otherwise, with THIS version of the algorithm, the "St." potion
* will parse out as part of the person's middle name.
*
* Input -> First Name Middle Name Last Name
* Tom Daley Tom Daley
* Ludwig Van Beethove Ludwig Van Beethoven
* Ludwig Van=Beethoven Ludwig Van Beethoven
* Ms. C. K. Rowling, PhD C. K. Rowling
*
* TODO: Does not work for multi-word last names, such as "St. Laurent" or "Van Beethoven"
*/
ParsedName.prototype.parseName = function (fullName, nameFromChannel)
{
var pName = new ParsedName({"userString": fullName});
nameFromChannel = nameFromChannel || fullName;
var suffixes = ["JR", "SR", "II", "III", "IV", "V", "PHD", "JD", "ESQ", "MD", "LPC", "RN"];
var courtesyTitles = ["MR", "MS", "MRS", "DR", "HON", "REV", "FR", "GURU", "PANDIT", "ELDER", "WITCH", "LAMANE", "MOBAD", "SEID"];
//Remove commas, periods. Convert all white space to spaces. Compress out consecutive spaces.
var nameParts = fullName.replace(/[.,]/g, '').replace(/\s/g, ' ').replace(/\s+/g, ' ').split(' ');
//For now, if the user puts an equal-sign ("=") in the name, convert it to a space to accommodate multi-word
//names or multiple middle names. This is ugly, but it provides some relief for the "to do" above.
for (var i = 0; i < nameParts.length; i++)
nameParts[i] = (nameParts[i].replace(/=/g, ' ').replace(/\s+/g, ' ')).trim(); //no double space trickery!
//Remember where we found the person's first name
var firstNameIndex;
if (courtesyTitles.indexOf(nameParts[0].toUpperCase()) != -1)
{
if (pName.length === 2)
{
//Strange use case where user provides a courtesy title and a last name, e.g. "Mr. Daley"
//Of course, I can't tell the difference between that and someone saying "Mr. Tom"
pName.courtesyTitle = nameParts[0];
pName.lastName = nameParts[1];
pName.salutation = nameParts[0] + ". " + nameParts[1];
return pName;
}
else
{
//We have a courtesy title and at least two other words, so assume second word is first name.
//E.G. "Mr. Tom Daley"
pName.courtesyTitle = nameParts[0];
pName.firstName = nameParts[1];
firstNameIndex = 1;
}
}
else
{
//No courtesy title. Assume first word is first name.
//E.G. "Tom Daley"
//Note, we have a provincial list of courtesy titles: Common titles from non-Western traditions
//will be missed, e.g. "Guru", "Pandit", as well as less common Western titles, e.g. "Elder".
//OK, I just added those, but you get the picture.
pName.firstName = nameParts[0];
firstNameIndex = 0;
}
//See if we have a suffix. If not, last element is last name
var idx = nameParts.length - 1;
if (suffixes.indexOf(nameParts[idx].toUpperCase()) != -1)
{
pName.suffix = nameParts[idx--];
pName.lastName = nameParts[idx--];
}
else
{
pName.lastName = nameParts[idx--];
}
//Anything left over is the middle name.
if (idx != firstNameIndex)
{
var mname = "";
for (i = firstNameIndex + 1; i <= idx; i++)
mname += nameParts[i] + " ";
pName.middleName = mname.trim();
}
//What is a polite way to address our user?
if (pName.hasOwnProperty("courtesyTitle") && pName.hasOwnProperty("lastName"))
pName.salutation = pName.courtesyTitle + ". " + pName.lastName;
else if (pName.hasOwnProperty("firstName"))
pName.salutation = pName.firstName;
else
pName.salutation = nameFromChannel;
return pName;
};
module.exports = ParsedName;