poserver
Version:
Server for JD Bot
201 lines (169 loc) • 8.03 kB
JavaScript
/**
* Created by tomdaley on 10/8/16.
*/
"use strict";
/**
* ParsedName - Class containing name fields for a person
*
* var myName = "Mr. Thomas J. Daley, Esq.";
* var myParsedName = ParsedName.parse(myName);
*/
class ParsedName {
constructor(nameObject)
{
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;
}
get fullNameWithTitle()
{
var fullname = this.fullName;
if (this.hasOwnProperty("courtesyTitle")) fullname = this.courtesyTitle + ". " + fullname;
return fullname;
}
get fullName()
{
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;
}
get parsedName()
{
var pname = {};
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;
}
toDocument()
{
return this.parsedName;
}
toString()
{
return this.fullNameWithTitle;
}
get inferredGender()
{
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"
*/
static parseName(fullName, nameFromChannel)
{
var parsedName = 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 (parsedName.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"
parsedName.courtesyTitle = nameParts[0];
parsedName.lastName = nameParts[1];
parsedName.salutation = nameParts[0] + ". " + nameParts[1];
return parsedName;
}
else
{
//We have a courtesy title and at least two other words, so assume second word is first name.
//E.G. "Mr. Tom Daley"
parsedName.courtesyTitle = nameParts[0];
parsedName.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.
parsedName.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)
{
parsedName.suffix = nameParts[idx--];
parsedName.lastName = nameParts[idx--];
}
else
{
parsedName.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] + " ";
parsedName.middleName = mname.trim();
}
//What is a polite way to address our user?
if (parsedName.hasOwnProperty("courtesyTitle") && parsedName.hasOwnProperty("lastName"))
parsedName.salutation = parsedName.courtesyTitle + ". " + parsedName.lastName;
else if (parsedName.hasOwnProperty("firstName"))
parsedName.salutation = parsedName.firstName;
else
parsedName.salutation = nameFromChannel;
/*
if (parsedName.hasOwnProperty("courtesyTitle")) this.courtesyTitle = parsedName.courtesyTitle;
if (parsedName.hasOwnProperty("firstName")) this.firstName = parsedName.firstName;
if (parsedName.hasOwnProperty("middleName")) this.middleName = parsedName.middleName;
if (parsedName.hasOwnProperty("lastName")) this.lastName = parsedName.lastName;
if (parsedName.hasOwnProperty("suffix")) this.suffix = parsedName.suffix;
if (parsedName.hasOwnProperty("salutation")) this.salutation = parsedName.salutation;
*/
return parsedName;
}
}
module.exports = ParsedName;