6080 lines
257 KiB
JavaScript
6080 lines
257 KiB
JavaScript
|
|
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.jiboEmbodiedDialog = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
|||
|
|
module.exports={
|
|||
|
|
"partial": [
|
|||
|
|
"4r5e",
|
|||
|
|
"5h1t",
|
|||
|
|
"5hit",
|
|||
|
|
"a55",
|
|||
|
|
"ar5e",
|
|||
|
|
"arrse",
|
|||
|
|
"assfukka",
|
|||
|
|
"asshole",
|
|||
|
|
"assholes",
|
|||
|
|
"asswhole",
|
|||
|
|
"a_s_s",
|
|||
|
|
"b!tch",
|
|||
|
|
"b00bs",
|
|||
|
|
"b17ch",
|
|||
|
|
"b1tch",
|
|||
|
|
"ballbag",
|
|||
|
|
"ballsack",
|
|||
|
|
"beastiality",
|
|||
|
|
"bellend",
|
|||
|
|
"bestiality",
|
|||
|
|
"bi\\+ch",
|
|||
|
|
"biatch",
|
|||
|
|
"bitcher",
|
|||
|
|
"bitchers",
|
|||
|
|
"bitchin",
|
|||
|
|
"bitching",
|
|||
|
|
"blow job",
|
|||
|
|
"blowjob",
|
|||
|
|
"boiolas",
|
|||
|
|
"bollock",
|
|||
|
|
"bollok",
|
|||
|
|
"boner",
|
|||
|
|
"buceta",
|
|||
|
|
"bugger",
|
|||
|
|
"butthole",
|
|||
|
|
"buttmuch",
|
|||
|
|
"buttplug",
|
|||
|
|
"c0ck",
|
|||
|
|
"carpet muncher",
|
|||
|
|
"cawk",
|
|||
|
|
"cl1t",
|
|||
|
|
"clits",
|
|||
|
|
"cnut",
|
|||
|
|
"cock-sucker",
|
|||
|
|
"cockface",
|
|||
|
|
"cockhead",
|
|||
|
|
"cockmunch",
|
|||
|
|
"cockmuncher",
|
|||
|
|
"cocksuck",
|
|||
|
|
"cocksuka",
|
|||
|
|
"cocksukka",
|
|||
|
|
"cok",
|
|||
|
|
"cummer",
|
|||
|
|
"cumming",
|
|||
|
|
"cumshot",
|
|||
|
|
"cunilingus",
|
|||
|
|
"cunillingus",
|
|||
|
|
"cunnilingus",
|
|||
|
|
"cuntlick",
|
|||
|
|
"cyberfuc",
|
|||
|
|
"d1ck",
|
|||
|
|
"dickhead",
|
|||
|
|
"dildo",
|
|||
|
|
"dlck",
|
|||
|
|
"donkeyribber",
|
|||
|
|
"doosh",
|
|||
|
|
"ejakulate",
|
|||
|
|
"f u c k",
|
|||
|
|
"f4nny",
|
|||
|
|
"fagging",
|
|||
|
|
"faggitt",
|
|||
|
|
"faggot",
|
|||
|
|
"faggs",
|
|||
|
|
"fagot",
|
|||
|
|
"fags",
|
|||
|
|
"fannyflaps",
|
|||
|
|
"fannyfucker",
|
|||
|
|
"fanyy",
|
|||
|
|
"fatass",
|
|||
|
|
"fcuk",
|
|||
|
|
"fecker",
|
|||
|
|
"felching",
|
|||
|
|
"fellate",
|
|||
|
|
"fellatio",
|
|||
|
|
"fook",
|
|||
|
|
"fuck",
|
|||
|
|
"fudge packer",
|
|||
|
|
"fudgepacker",
|
|||
|
|
"fuk",
|
|||
|
|
"fux",
|
|||
|
|
"f_u_c_k",
|
|||
|
|
"gangbang",
|
|||
|
|
"gaylord",
|
|||
|
|
"gaysex",
|
|||
|
|
"goatse",
|
|||
|
|
"god-dam",
|
|||
|
|
"goddamn",
|
|||
|
|
"hardcoresex",
|
|||
|
|
"hoare",
|
|||
|
|
"hotsex",
|
|||
|
|
"jack-off",
|
|||
|
|
"jackoff",
|
|||
|
|
"jerk-off",
|
|||
|
|
"jism",
|
|||
|
|
"jiz",
|
|||
|
|
"jizm",
|
|||
|
|
"kawk",
|
|||
|
|
"knobead",
|
|||
|
|
"knobed",
|
|||
|
|
"knobend",
|
|||
|
|
"knobhead",
|
|||
|
|
"knobjocky",
|
|||
|
|
"knobjokey",
|
|||
|
|
"kock",
|
|||
|
|
"kondum",
|
|||
|
|
"kondums",
|
|||
|
|
"kummer",
|
|||
|
|
"kumming",
|
|||
|
|
"kums",
|
|||
|
|
"kunilingus",
|
|||
|
|
"l3i\\+ch",
|
|||
|
|
"l3itch",
|
|||
|
|
"m0f0",
|
|||
|
|
"m0fo",
|
|||
|
|
"m45terbate",
|
|||
|
|
"ma5terb8",
|
|||
|
|
"ma5terbate",
|
|||
|
|
"master-bate",
|
|||
|
|
"masterb8",
|
|||
|
|
"masterbat*",
|
|||
|
|
"masterbat3",
|
|||
|
|
"masterbate",
|
|||
|
|
"masterbation",
|
|||
|
|
"masterbations",
|
|||
|
|
"masturbate",
|
|||
|
|
"mo-fo",
|
|||
|
|
"mof0",
|
|||
|
|
"n1gga",
|
|||
|
|
"n1gger",
|
|||
|
|
"nigg3r",
|
|||
|
|
"nigg4h",
|
|||
|
|
"nigga",
|
|||
|
|
"nigger",
|
|||
|
|
"nob jokey",
|
|||
|
|
"nobhead",
|
|||
|
|
"nobjocky",
|
|||
|
|
"nobjokey",
|
|||
|
|
"numbnuts",
|
|||
|
|
"nutsack",
|
|||
|
|
"p0rn",
|
|||
|
|
"penisfucker",
|
|||
|
|
"phonesex",
|
|||
|
|
"phuck",
|
|||
|
|
"phuked",
|
|||
|
|
"phuking",
|
|||
|
|
"phukked",
|
|||
|
|
"phukking",
|
|||
|
|
"phuks",
|
|||
|
|
"phuq",
|
|||
|
|
"pigfucker",
|
|||
|
|
"pimpis",
|
|||
|
|
"pisser",
|
|||
|
|
"pisses",
|
|||
|
|
"pissflaps",
|
|||
|
|
"pissin",
|
|||
|
|
"pissoff",
|
|||
|
|
"pusse",
|
|||
|
|
"pussi",
|
|||
|
|
"pussys",
|
|||
|
|
"rimjaw",
|
|||
|
|
"schlong",
|
|||
|
|
"scroat",
|
|||
|
|
"scrote",
|
|||
|
|
"sh!\\+",
|
|||
|
|
"sh!t",
|
|||
|
|
"sh1t",
|
|||
|
|
"shagger",
|
|||
|
|
"shaggin",
|
|||
|
|
"shagging",
|
|||
|
|
"shemale",
|
|||
|
|
"shit",
|
|||
|
|
"shi\\+",
|
|||
|
|
"skank",
|
|||
|
|
"slut",
|
|||
|
|
"smegma",
|
|||
|
|
"son-of-a-bitch",
|
|||
|
|
"s_h_i_t",
|
|||
|
|
"t1tt1e5",
|
|||
|
|
"t1tties",
|
|||
|
|
"titfuck",
|
|||
|
|
"tittie5",
|
|||
|
|
"tittiefucker",
|
|||
|
|
"titties",
|
|||
|
|
"tittyfuck",
|
|||
|
|
"tittywank",
|
|||
|
|
"titwank",
|
|||
|
|
"tw4t",
|
|||
|
|
"twathead",
|
|||
|
|
"twatty",
|
|||
|
|
"twunt",
|
|||
|
|
"twunter",
|
|||
|
|
"v14gra",
|
|||
|
|
"v1gra",
|
|||
|
|
"w00se",
|
|||
|
|
"wanker",
|
|||
|
|
"whoar",
|
|||
|
|
"whore"
|
|||
|
|
],
|
|||
|
|
"whole": [
|
|||
|
|
"arse",
|
|||
|
|
"boo+bi*e*s*",
|
|||
|
|
"cipa",
|
|||
|
|
"clit",
|
|||
|
|
"coon",
|
|||
|
|
"cox",
|
|||
|
|
"cum",
|
|||
|
|
"cums",
|
|||
|
|
"cunt",
|
|||
|
|
"cunts",
|
|||
|
|
"doggin",
|
|||
|
|
"duche",
|
|||
|
|
"fag",
|
|||
|
|
"feck",
|
|||
|
|
"heshe",
|
|||
|
|
"hoar",
|
|||
|
|
"hoer",
|
|||
|
|
"hore",
|
|||
|
|
"jap",
|
|||
|
|
"kum",
|
|||
|
|
"mofo",
|
|||
|
|
"muff",
|
|||
|
|
"pecker",
|
|||
|
|
"phuk",
|
|||
|
|
"pron",
|
|||
|
|
"pube",
|
|||
|
|
"teez",
|
|||
|
|
"tits",
|
|||
|
|
"titt",
|
|||
|
|
"twat",
|
|||
|
|
"wank",
|
|||
|
|
"wanky"
|
|||
|
|
],
|
|||
|
|
"whitelist": [
|
|||
|
|
"alan cumming",
|
|||
|
|
"bycoket",
|
|||
|
|
"bycokets",
|
|||
|
|
"coke",
|
|||
|
|
"cokes",
|
|||
|
|
"cokernut",
|
|||
|
|
"cokernuts",
|
|||
|
|
"cokuloris",
|
|||
|
|
"cokulorises",
|
|||
|
|
"contrafagotto",
|
|||
|
|
"contrafagottos",
|
|||
|
|
"cummerbund",
|
|||
|
|
"cummerbunds",
|
|||
|
|
"cummington",
|
|||
|
|
"cummingtonite",
|
|||
|
|
"deboner",
|
|||
|
|
"deboners",
|
|||
|
|
"debugger",
|
|||
|
|
"debuggers",
|
|||
|
|
"decoke",
|
|||
|
|
"decoked",
|
|||
|
|
"decokes",
|
|||
|
|
"decoking",
|
|||
|
|
"fagotto",
|
|||
|
|
"fagotti",
|
|||
|
|
"fagottist",
|
|||
|
|
"fagottists",
|
|||
|
|
"glucokinase",
|
|||
|
|
"glucokinases",
|
|||
|
|
"hokums",
|
|||
|
|
"humbugger",
|
|||
|
|
"humbuggeries",
|
|||
|
|
"humbuggers",
|
|||
|
|
"humbuggery",
|
|||
|
|
"kokum",
|
|||
|
|
"kokums",
|
|||
|
|
"kummerbund",
|
|||
|
|
"kummerbunds",
|
|||
|
|
"mishit",
|
|||
|
|
"mishits",
|
|||
|
|
"mishitting",
|
|||
|
|
"noncoking",
|
|||
|
|
"oakums",
|
|||
|
|
"pharmacokinetic",
|
|||
|
|
"pharmacokinetics",
|
|||
|
|
"scummer",
|
|||
|
|
"scummers",
|
|||
|
|
"scumming",
|
|||
|
|
"shaginess",
|
|||
|
|
"shaginesses",
|
|||
|
|
"shittah",
|
|||
|
|
"shittim",
|
|||
|
|
"shittimwood",
|
|||
|
|
"shittimwoods",
|
|||
|
|
"shitzu",
|
|||
|
|
"shitzus",
|
|||
|
|
"sourpuss",
|
|||
|
|
"stickums",
|
|||
|
|
"swarajism",
|
|||
|
|
"trankums",
|
|||
|
|
"trinkum",
|
|||
|
|
"trinkums"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
},{}],2:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|||
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|||
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|||
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|||
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|||
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const EmbodiedSpeech_1 = require("./speech/EmbodiedSpeech");
|
|||
|
|
const EmbodiedListen_1 = require("./listen/EmbodiedListen");
|
|||
|
|
const jibo_cai_utils_1 = require("jibo-cai-utils");
|
|||
|
|
var EmbodiedState;
|
|||
|
|
(function (EmbodiedState) {
|
|||
|
|
EmbodiedState["IDLE"] = "IDLE";
|
|||
|
|
EmbodiedState["SPEAKING"] = "SPEAKING";
|
|||
|
|
EmbodiedState["LISTENING"] = "LISTENING";
|
|||
|
|
EmbodiedState["MIXED"] = "MIXED";
|
|||
|
|
})(EmbodiedState = exports.EmbodiedState || (exports.EmbodiedState = {}));
|
|||
|
|
class EmbodiedDialog {
|
|||
|
|
constructor() {
|
|||
|
|
this.speech = new EmbodiedSpeech_1.EmbodiedSpeech(this);
|
|||
|
|
this.listen = new EmbodiedListen_1.EmbodiedListen(this);
|
|||
|
|
}
|
|||
|
|
init(jibo, options, esConfig) {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
jibo_cai_utils_1.CacheUtils.initGlobalCache(jibo);
|
|||
|
|
const debug = options ? !!options.debugMode : false;
|
|||
|
|
yield this.speech.init(jibo, debug, options, esConfig);
|
|||
|
|
yield this.listen.init(jibo, debug);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
getState() {
|
|||
|
|
const esActive = this.speech.isActive();
|
|||
|
|
const elState = this.listen.getCurrentState();
|
|||
|
|
if (!esActive && elState === this.listen._idle) {
|
|||
|
|
return EmbodiedState.IDLE;
|
|||
|
|
}
|
|||
|
|
else if (esActive && elState === this.listen._idle) {
|
|||
|
|
return EmbodiedState.SPEAKING;
|
|||
|
|
}
|
|||
|
|
else if (!esActive && elState !== this.listen._idle) {
|
|||
|
|
return EmbodiedState.LISTENING;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
return EmbodiedState.MIXED;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.EmbodiedDialog = EmbodiedDialog;
|
|||
|
|
|
|||
|
|
},{"./listen/EmbodiedListen":6,"./speech/EmbodiedSpeech":12,"jibo-cai-utils":undefined}],3:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
let tunable = null;
|
|||
|
|
try {
|
|||
|
|
tunable = require('jibo-tunable');
|
|||
|
|
}
|
|||
|
|
catch (e) {
|
|||
|
|
}
|
|||
|
|
const WIN = 'Jibo Embodied Dialog';
|
|||
|
|
class TunableDebug {
|
|||
|
|
static setup(embodied) {
|
|||
|
|
if (tunable) {
|
|||
|
|
const Tunable = tunable.Tunable;
|
|||
|
|
Tunable.getCheckboxField('Use Debug perceptual eye', false, WIN)
|
|||
|
|
.events.change.on((value) => embodied.listen.debugPerceptualEye = value);
|
|||
|
|
Tunable.getButtonField('Person found', WIN).events.change.on(() => {
|
|||
|
|
embodied.listen.eventsIn.personFound.emit();
|
|||
|
|
});
|
|||
|
|
Tunable.getButtonField('Person lost', WIN).events.change.on(() => {
|
|||
|
|
embodied.listen.eventsIn.personLost.emit();
|
|||
|
|
});
|
|||
|
|
Tunable.getButtonField('Demo engaged ON', WIN).events.change.on(() => {
|
|||
|
|
embodied.listen.demoEngaged(true);
|
|||
|
|
});
|
|||
|
|
Tunable.getButtonField('Demo engaged OFF', WIN).events.change.on(() => {
|
|||
|
|
embodied.listen.demoEngaged(false);
|
|||
|
|
});
|
|||
|
|
Tunable.getButtonField('Disable once', WIN).events.change.on(() => {
|
|||
|
|
embodied.listen.disableOnce();
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.TunableDebug = TunableDebug;
|
|||
|
|
|
|||
|
|
},{"jibo-tunable":undefined}],4:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|||
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|||
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|||
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|||
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|||
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const EmbodiedDialog_1 = require("./EmbodiedDialog");
|
|||
|
|
exports.EmbodiedState = EmbodiedDialog_1.EmbodiedState;
|
|||
|
|
const speech_ns = require("./speech");
|
|||
|
|
const listen_ns = require("./listen");
|
|||
|
|
const TunableDebug_1 = require("./TunableDebug");
|
|||
|
|
const logs = require("./log");
|
|||
|
|
const log = logs.dialogLog;
|
|||
|
|
let _jibo;
|
|||
|
|
function init(jibo, options, autoRuleConfig) {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
_jibo = jibo;
|
|||
|
|
exports._embodied = new EmbodiedDialog_1.EmbodiedDialog();
|
|||
|
|
yield exports._embodied.init(_jibo, options, autoRuleConfig);
|
|||
|
|
_jibo.jetstream.events.hjHeard.on(() => {
|
|||
|
|
exports._embodied.listen.eventsIn.hjHeard.emit();
|
|||
|
|
process.nextTick(() => exports._embodied.listen.eventsIn.oriented.emit());
|
|||
|
|
});
|
|||
|
|
_jibo.jetstream.events.localTurnStarted.on(() => {
|
|||
|
|
exports._embodied.listen.eventsIn.startListen.emit();
|
|||
|
|
});
|
|||
|
|
_jibo.jetstream.events.globalTurnResult.on(() => {
|
|||
|
|
exports._embodied.listen.eventsIn.cloudFinished.emit();
|
|||
|
|
});
|
|||
|
|
_jibo.globalEvents.shared.hjOnly.on(() => {
|
|||
|
|
exports._embodied.listen.eventsIn.cloudFinished.emit();
|
|||
|
|
});
|
|||
|
|
_jibo.jetstream.events.localTurnResult.on(() => {
|
|||
|
|
exports._embodied.listen.eventsIn.cloudFinished.emit();
|
|||
|
|
});
|
|||
|
|
_jibo.jetstream.events.eos.on(() => {
|
|||
|
|
exports._embodied.listen.eventsIn.eos.emit();
|
|||
|
|
});
|
|||
|
|
_jibo.jetstream.events.sos.on(() => {
|
|||
|
|
exports._embodied.listen.eventsIn.sos.emit();
|
|||
|
|
});
|
|||
|
|
let personVisible;
|
|||
|
|
if (_jibo.lps.identity.getVisibleFaces().size === 0) {
|
|||
|
|
personVisible = false;
|
|||
|
|
exports._embodied.listen.eventsIn.personLost.emit();
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
personVisible = true;
|
|||
|
|
exports._embodied.listen.eventsIn.personFound.emit();
|
|||
|
|
}
|
|||
|
|
_jibo.lps.identity.events.visibleFaceStarted.on(data => {
|
|||
|
|
if (!personVisible) {
|
|||
|
|
personVisible = true;
|
|||
|
|
exports._embodied.listen.eventsIn.personFound.emit();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
_jibo.lps.identity.events.visibleFaceStopped.on(data => {
|
|||
|
|
const visible = _jibo.lps.identity.getVisibleFaces();
|
|||
|
|
if (visible.size === 0 ||
|
|||
|
|
(visible.size === 1 && visible.has(data.id))) {
|
|||
|
|
personVisible = false;
|
|||
|
|
exports._embodied.listen.eventsIn.personLost.emit();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
TunableDebug_1.TunableDebug.setup(exports._embodied);
|
|||
|
|
exports._embodied.listen.start();
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
exports.init = init;
|
|||
|
|
function isInitialized() {
|
|||
|
|
return !!exports._embodied;
|
|||
|
|
}
|
|||
|
|
exports.isInitialized = isInitialized;
|
|||
|
|
function getState() {
|
|||
|
|
return exports._embodied.getState();
|
|||
|
|
}
|
|||
|
|
exports.getState = getState;
|
|||
|
|
var speech;
|
|||
|
|
(function (speech) {
|
|||
|
|
speech.RequestStatus = speech_ns.common.RequestStatus;
|
|||
|
|
function speak(textToSpeak, speakOptions, autoRuleConfig) {
|
|||
|
|
return exports._embodied.speech.speak(textToSpeak, speakOptions, autoRuleConfig);
|
|||
|
|
}
|
|||
|
|
speech.speak = speak;
|
|||
|
|
function stop() {
|
|||
|
|
return exports._embodied.speech.stop();
|
|||
|
|
}
|
|||
|
|
speech.stop = stop;
|
|||
|
|
function setPaths(assetPack) {
|
|||
|
|
let resourceRoot = null;
|
|||
|
|
if (assetPack) {
|
|||
|
|
try {
|
|||
|
|
resourceRoot = _jibo.utils.PathUtils.getAssetUri('', assetPack);
|
|||
|
|
}
|
|||
|
|
catch (e) {
|
|||
|
|
log.warn('Unable to set resourceRoot, path-based assets will be unavailable: ', e);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports._embodied.speech.setResourceRoots(resourceRoot);
|
|||
|
|
}
|
|||
|
|
speech.setPaths = setPaths;
|
|||
|
|
function isActive() {
|
|||
|
|
return !!exports._embodied.speech.isActive();
|
|||
|
|
}
|
|||
|
|
speech.isActive = isActive;
|
|||
|
|
function waitForAnimDispatch() {
|
|||
|
|
return exports._embodied.speech.waitForAnimDispatch();
|
|||
|
|
}
|
|||
|
|
speech.waitForAnimDispatch = waitForAnimDispatch;
|
|||
|
|
})(speech = exports.speech || (exports.speech = {}));
|
|||
|
|
var listen;
|
|||
|
|
(function (listen) {
|
|||
|
|
listen.AmbientListenMode = listen_ns.AmbientListenMode;
|
|||
|
|
listen.ActiveListenMode = listen_ns.ActiveListenMode;
|
|||
|
|
listen.RequestStatus = listen_ns.RequestStatus;
|
|||
|
|
function getAmbientMode() {
|
|||
|
|
return exports._embodied.listen.getAmbientMode();
|
|||
|
|
}
|
|||
|
|
listen.getAmbientMode = getAmbientMode;
|
|||
|
|
function getActiveMode() {
|
|||
|
|
return exports._embodied.listen.getActiveMode();
|
|||
|
|
}
|
|||
|
|
listen.getActiveMode = getActiveMode;
|
|||
|
|
function setAmbientMode(mode) {
|
|||
|
|
exports._embodied.listen.setAmbientMode(mode);
|
|||
|
|
}
|
|||
|
|
listen.setAmbientMode = setAmbientMode;
|
|||
|
|
function enterActiveMode(mode, options) {
|
|||
|
|
return exports._embodied.listen.enterActiveMode(mode, options);
|
|||
|
|
}
|
|||
|
|
listen.enterActiveMode = enterActiveMode;
|
|||
|
|
function exitActiveMode(fastForward) {
|
|||
|
|
return exports._embodied.listen.exitActiveMode(fastForward);
|
|||
|
|
}
|
|||
|
|
listen.exitActiveMode = exitActiveMode;
|
|||
|
|
function dispose() {
|
|||
|
|
exports._embodied.listen.dispose();
|
|||
|
|
}
|
|||
|
|
listen.dispose = dispose;
|
|||
|
|
function waitForIdle(fastForward) {
|
|||
|
|
return exports._embodied.listen.waitForIdle(fastForward);
|
|||
|
|
}
|
|||
|
|
listen.waitForIdle = waitForIdle;
|
|||
|
|
function disableOnce() {
|
|||
|
|
exports._embodied.listen.disableOnce();
|
|||
|
|
}
|
|||
|
|
listen.disableOnce = disableOnce;
|
|||
|
|
function demoEngaged(turnOn) {
|
|||
|
|
exports._embodied.listen.demoEngaged(turnOn);
|
|||
|
|
}
|
|||
|
|
listen.demoEngaged = demoEngaged;
|
|||
|
|
})(listen = exports.listen || (exports.listen = {}));
|
|||
|
|
|
|||
|
|
},{"./EmbodiedDialog":2,"./TunableDebug":3,"./listen":10,"./log":11,"./speech":15}],5:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const findRoot = require('find-root');
|
|||
|
|
const ROOT = findRoot(__filename);
|
|||
|
|
const SOUNDS_ROOT = ROOT + '/resources/audio/';
|
|||
|
|
exports.Anims = {
|
|||
|
|
ENGAGE: `User_Speak_Begin_01`,
|
|||
|
|
DISENGAGE: `User_Speak_End_01`,
|
|||
|
|
THINKING: `Thinking_Short_01`,
|
|||
|
|
BLINK: `Eye_Quick_Blink_01`,
|
|||
|
|
HEAD_BOB: [
|
|||
|
|
`Listen_Head_Bob_01`,
|
|||
|
|
`Speak_Posture_Shift_01`,
|
|||
|
|
],
|
|||
|
|
};
|
|||
|
|
var EyeTransitionStyle;
|
|||
|
|
(function (EyeTransitionStyle) {
|
|||
|
|
EyeTransitionStyle[EyeTransitionStyle["POP"] = 0] = "POP";
|
|||
|
|
EyeTransitionStyle[EyeTransitionStyle["BLINK"] = 1] = "BLINK";
|
|||
|
|
})(EyeTransitionStyle = exports.EyeTransitionStyle || (exports.EyeTransitionStyle = {}));
|
|||
|
|
var EyeTransitionDirection;
|
|||
|
|
(function (EyeTransitionDirection) {
|
|||
|
|
EyeTransitionDirection[EyeTransitionDirection["TO"] = 0] = "TO";
|
|||
|
|
EyeTransitionDirection[EyeTransitionDirection["FROM"] = 1] = "FROM";
|
|||
|
|
})(EyeTransitionDirection = exports.EyeTransitionDirection || (exports.EyeTransitionDirection = {}));
|
|||
|
|
class AnimSelector {
|
|||
|
|
static getPerceptualEyeTransition(seePerson, style, direction, sound = true) {
|
|||
|
|
let nameComps = [];
|
|||
|
|
nameComps.push(seePerson ? 'hj-sp-transition-' : 'hj-dsp-transition-');
|
|||
|
|
nameComps.push(direction === EyeTransitionDirection.FROM ? 'from-' : 'to-');
|
|||
|
|
nameComps.push(style === EyeTransitionStyle.POP ? 'pop' : 'blink');
|
|||
|
|
if (direction === EyeTransitionDirection.TO) {
|
|||
|
|
nameComps.push(sound ? '' : '-ns');
|
|||
|
|
}
|
|||
|
|
return nameComps.join('');
|
|||
|
|
}
|
|||
|
|
static getPerceptualEyePose(seePerson, listening) {
|
|||
|
|
let nameComps = [];
|
|||
|
|
nameComps.push(listening ? 'l-' : 'nl-');
|
|||
|
|
nameComps.push(seePerson ? 'sp' : 'dsp');
|
|||
|
|
return nameComps.join('');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.AnimSelector = AnimSelector;
|
|||
|
|
exports.AnimConfigs = {
|
|||
|
|
'NO_BODY': {
|
|||
|
|
layers: {
|
|||
|
|
'Body': false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
const LISTENING = [0.05, 0.73, 0.94];
|
|||
|
|
exports.Led = {
|
|||
|
|
LISTENING: LISTENING,
|
|||
|
|
LISTENING_OR: LISTENING,
|
|||
|
|
OFF: [0, 0, 0],
|
|||
|
|
};
|
|||
|
|
exports.Sound = {
|
|||
|
|
ON: SOUNDS_ROOT + `speak-cue.mp3`
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{"find-root":undefined}],6:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|||
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|||
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|||
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|||
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|||
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const jibo_cai_utils_1 = require("jibo-cai-utils");
|
|||
|
|
const jibo_state_machine_1 = require("jibo-state-machine");
|
|||
|
|
const Types_1 = require("./Types");
|
|||
|
|
const Events_1 = require("./Events");
|
|||
|
|
const Utils_1 = require("./Utils");
|
|||
|
|
const Utils_2 = require("../utils/Utils");
|
|||
|
|
const Assets_1 = require("./Assets");
|
|||
|
|
const logs = require("../log");
|
|||
|
|
const log = logs.listenLog;
|
|||
|
|
const HJ_BLINK_INTERVAL = 25 * 1000;
|
|||
|
|
const USE_CENTER_ROBOT = false;
|
|||
|
|
const TIMEOUT = 3000;
|
|||
|
|
const ANIM_CLEAR_TIMEOUT = 'ANIM_CLEAR_TIMEOUT';
|
|||
|
|
class EmbodiedListen extends jibo_state_machine_1.StateMachine {
|
|||
|
|
constructor(_ed) {
|
|||
|
|
super();
|
|||
|
|
this._ed = _ed;
|
|||
|
|
this._queue = new jibo_cai_utils_1.PromiseQueue();
|
|||
|
|
this._idle = new jibo_state_machine_1.State(this, 'Idle');
|
|||
|
|
this._reset = new jibo_state_machine_1.State(this, 'Reset');
|
|||
|
|
this._hjExpression = new jibo_state_machine_1.State(this, 'HJ Expression');
|
|||
|
|
this._nonHjExpression = new jibo_state_machine_1.State(this, 'NonHJ Expression');
|
|||
|
|
this._offExpression = new jibo_state_machine_1.State(this, 'Off Expression');
|
|||
|
|
this._engage = new jibo_state_machine_1.State(this, 'Engage');
|
|||
|
|
this._listening = new jibo_state_machine_1.State(this, 'Listen');
|
|||
|
|
this._thinking = new jibo_state_machine_1.State(this, 'Off Expression + Thinking');
|
|||
|
|
this._waitForAnimFinish = new jibo_state_machine_1.State(this, 'Wait for anim finish');
|
|||
|
|
this._active = new jibo_state_machine_1.State(this, 'Active Mode');
|
|||
|
|
this.listenState = Types_1.ListeningState.NOT_LISTENING;
|
|||
|
|
this.debugPerceptualEye = false;
|
|||
|
|
this.eventsIn = new Events_1.IncomingEvents();
|
|||
|
|
this.eventsOut = new Events_1.OutgoingEvents();
|
|||
|
|
this.eventsInternal = new Events_1.InternalEvents();
|
|||
|
|
this._disableOnce = false;
|
|||
|
|
this._lastHeadBob = -1;
|
|||
|
|
this._nextHeadBob = 0;
|
|||
|
|
this._ambientMode = Types_1.AmbientListenMode.NORMAL;
|
|||
|
|
this._activeMode = null;
|
|||
|
|
this._lastHJBlinkTime = -1;
|
|||
|
|
}
|
|||
|
|
init(jibo, debug = false) {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
if (jibo) {
|
|||
|
|
this._jibo = jibo;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw new Error('Cannot instantiate without Jibo instances!');
|
|||
|
|
}
|
|||
|
|
const dofs = this._jibo.expression.dofs;
|
|||
|
|
this.DOFS_ALL_MINUS_EYE_TRANSLATE = dofs.ALL.minus(dofs.EYE_TRANSLATE);
|
|||
|
|
this.DOFS_EYE_AND_OVERLAY_MINUS_EYE_TRANSLATE = (dofs.EYE.plus(dofs.OVERLAY)).minus(dofs.EYE_TRANSLATE);
|
|||
|
|
this.DOFS_TO_CENTER = dofs.ALL.minus(dofs.LED).minus(dofs.BODY).minus(dofs.EYE_TRANSLATE);
|
|||
|
|
this._debug = debug;
|
|||
|
|
jibo.timer.once('update', () => {
|
|||
|
|
log.debug('Caching core Embodied Listen animations.');
|
|||
|
|
const seePerson = true;
|
|||
|
|
const eyeStyles = [Assets_1.EyeTransitionStyle.POP, Assets_1.EyeTransitionStyle.BLINK];
|
|||
|
|
const dir = Assets_1.EyeTransitionDirection.TO;
|
|||
|
|
const listening = true;
|
|||
|
|
const useSound = false;
|
|||
|
|
eyeStyles.forEach((styleKey) => __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
let anim;
|
|||
|
|
try {
|
|||
|
|
anim = Assets_1.AnimSelector.getPerceptualEyeTransition(seePerson, styleKey, dir, useSound);
|
|||
|
|
yield Utils_2.Utils.loadAnimationIntoCache(jibo, anim, jibo_cai_utils_1.CacheUtils.GlobalCacheName);
|
|||
|
|
anim = Assets_1.AnimSelector.getPerceptualEyePose(seePerson, listening);
|
|||
|
|
yield Utils_2.Utils.loadAnimationIntoCache(jibo, anim, jibo_cai_utils_1.CacheUtils.GlobalCacheName);
|
|||
|
|
}
|
|||
|
|
catch (err) {
|
|||
|
|
log.warn(`Unable to load animation ${anim} into cache ${jibo_cai_utils_1.CacheUtils.GlobalCacheName}`);
|
|||
|
|
}
|
|||
|
|
}));
|
|||
|
|
});
|
|||
|
|
[
|
|||
|
|
this._hjExpression,
|
|||
|
|
this._nonHjExpression,
|
|||
|
|
this._offExpression,
|
|||
|
|
this._engage,
|
|||
|
|
this._listening,
|
|||
|
|
this._thinking,
|
|||
|
|
this._waitForAnimFinish,
|
|||
|
|
].forEach(state => {
|
|||
|
|
state.addTypedEventTransition(this.eventsInternal.reset, this._reset);
|
|||
|
|
});
|
|||
|
|
this._reset.addDoneTransition(this._idle);
|
|||
|
|
this._reset.onEntry = () => __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
log.debug('Entering Reset');
|
|||
|
|
this._queue.clear();
|
|||
|
|
const waitResult = yield Utils_2.timeout(this._queue.waitUntilEmpty(), TIMEOUT, {
|
|||
|
|
log: log,
|
|||
|
|
logMessage: 'embodiedListen.animQueue.waitUntilEmpty',
|
|||
|
|
timeoutValue: ANIM_CLEAR_TIMEOUT
|
|||
|
|
});
|
|||
|
|
if (typeof waitResult === 'string') {
|
|||
|
|
if (waitResult === ANIM_CLEAR_TIMEOUT) {
|
|||
|
|
this._queue = new jibo_cai_utils_1.PromiseQueue();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (this._reset.isCurrent()) {
|
|||
|
|
Utils_1.Utils.setLED(this._jibo, Assets_1.Led.OFF);
|
|||
|
|
yield this.stopListeningEye();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
const updateBind = this.update.bind(this);
|
|||
|
|
updateBind.isGlobalTimer = true;
|
|||
|
|
this._idle.addTypedEventTransition(this.eventsIn.hjHeard, this._hjExpression);
|
|||
|
|
this._idle.addTypedEventTransition(this.eventsIn.startListen, this._nonHjExpression);
|
|||
|
|
this._idle.addTypedEventTransition(this.eventsInternal.enterActiveMode, this._active);
|
|||
|
|
this._idle.onEntry = () => {
|
|||
|
|
log.debug('Entering Idle');
|
|||
|
|
this._jibo.performance.log('EmbodiedListenReturnedToIdleSkill');
|
|||
|
|
this.eventsOut.finished.emit();
|
|||
|
|
this._jibo.timer.removeListener('update', updateBind);
|
|||
|
|
if (this._pendingActiveMode) {
|
|||
|
|
this.eventsInternal.enterActiveMode.emit();
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
this._idle.onExit = () => {
|
|||
|
|
log.debug('Exiting Idle');
|
|||
|
|
this._jibo.timer.on('update', updateBind);
|
|||
|
|
};
|
|||
|
|
this._active.addTypedEventTransition(this.eventsInternal.exitActiveMode, this._idle);
|
|||
|
|
this._active.addTypedEventTransition(this.eventsInternal.enterActiveMode, this._active);
|
|||
|
|
this._active.onEntry = () => {
|
|||
|
|
this._activeMode = this._pendingActiveMode;
|
|||
|
|
this._pendingActiveModeExtPr.resolve(Types_1.RequestStatus.SUCCEEDED);
|
|||
|
|
this._pendingActiveMode = null;
|
|||
|
|
log.debug(`Entering Active Mode: ${this._activeMode}`);
|
|||
|
|
switch (this._activeMode) {
|
|||
|
|
case Types_1.ActiveListenMode.UI:
|
|||
|
|
Utils_1.Utils.setLED(this._jibo, Assets_1.Led.LISTENING);
|
|||
|
|
break;
|
|||
|
|
case Types_1.ActiveListenMode.OPTIONAL_RESPONSE:
|
|||
|
|
Utils_1.Utils.setLED(this._jibo, Assets_1.Led.LISTENING_OR);
|
|||
|
|
this.startListeningEye(true);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
this._active.onExit = () => __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
log.debug(`Exiting Active Mode: ${this._activeMode}`);
|
|||
|
|
switch (this._activeMode) {
|
|||
|
|
case Types_1.ActiveListenMode.UI:
|
|||
|
|
Utils_1.Utils.setLED(this._jibo, Assets_1.Led.OFF);
|
|||
|
|
break;
|
|||
|
|
case Types_1.ActiveListenMode.OPTIONAL_RESPONSE:
|
|||
|
|
Utils_1.Utils.setLED(this._jibo, Assets_1.Led.OFF);
|
|||
|
|
yield this.stopListeningEye();
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
this._activeMode = null;
|
|||
|
|
});
|
|||
|
|
this._waitForAnimFinish.addInternalTransition('Finished', this._idle);
|
|||
|
|
this._waitForAnimFinish.onEntry = () => {
|
|||
|
|
log.debug('Entering Wait for Anim Finished');
|
|||
|
|
this._jibo.performance.log('EmbodiedListenWaitForAnimFinishSkill');
|
|||
|
|
if (USE_CENTER_ROBOT) {
|
|||
|
|
this._addAnimToQueue(() => {
|
|||
|
|
return this._jibo.expression.centerRobot({
|
|||
|
|
requestor: EmbodiedListen.NONHJ_OWNER_INFORMATION,
|
|||
|
|
dofs: this.DOFS_TO_CENTER,
|
|||
|
|
centerGlobally: false
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
this._queue.waitUntilEmpty()
|
|||
|
|
.then(() => {
|
|||
|
|
if (this._waitForAnimFinish._isCurrent) {
|
|||
|
|
this._waitForAnimFinish.transitionTo(this._idle);
|
|||
|
|
}
|
|||
|
|
}).catch(e => {
|
|||
|
|
log.error(e);
|
|||
|
|
if (this._waitForAnimFinish._isCurrent) {
|
|||
|
|
this._waitForAnimFinish.transitionTo(this._idle);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
this._offExpression.addDoneTransition(this._waitForAnimFinish);
|
|||
|
|
this._offExpression.addTypedEventTransition(this.eventsIn.hjHeard, this._hjExpression);
|
|||
|
|
this._offExpression.onEntry = () => __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
log.debug('Entering Off Expression');
|
|||
|
|
Utils_1.Utils.setLED(jibo, Assets_1.Led.OFF);
|
|||
|
|
yield this.stopListeningEye();
|
|||
|
|
});
|
|||
|
|
this._hjExpression.addTypedEventTransition(this.eventsIn.oriented, this._engage);
|
|||
|
|
this._hjExpression.addTypedEventTransition(this.eventsIn.cloudFinished, this._offExpression);
|
|||
|
|
this._hjExpression.addInternalTransition('Disable once', this._idle);
|
|||
|
|
this._hjExpression.onEntry = () => {
|
|||
|
|
log.debug('Entering HJ Expression (Eye+LED)');
|
|||
|
|
this._jibo.performance.log('EmbodiedListenStartingHJHeardSkill');
|
|||
|
|
if (this._disableOnce) {
|
|||
|
|
this._disableOnce = false;
|
|||
|
|
this._hjExpression.transitionTo(this._idle);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
switch (this._ambientMode) {
|
|||
|
|
case Types_1.AmbientListenMode.NORMAL:
|
|||
|
|
case Types_1.AmbientListenMode.NO_BODY:
|
|||
|
|
Utils_1.Utils.setLED(this._jibo, Assets_1.Led.LISTENING);
|
|||
|
|
this.startListeningEye(true);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
this._nonHjExpression.addInternalTransition('ES Dispatch Done', this._engage);
|
|||
|
|
this._nonHjExpression.addInternalTransition('Disable once', this._idle);
|
|||
|
|
this._nonHjExpression.addTypedEventTransition(this.eventsIn.cloudFinished, this._offExpression);
|
|||
|
|
this._nonHjExpression.addTypedEventTransition(this.eventsIn.hjHeard, this._hjExpression);
|
|||
|
|
this._nonHjExpression.onEntry = () => {
|
|||
|
|
log.debug('Entering non-HJ Expression (Eye+LED)');
|
|||
|
|
this._jibo.performance.log('EmbodiedListenStartingNonHJSkill');
|
|||
|
|
if (this._disableOnce) {
|
|||
|
|
this._disableOnce = false;
|
|||
|
|
this._nonHjExpression.transitionTo(this._idle);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
switch (this._ambientMode) {
|
|||
|
|
case Types_1.AmbientListenMode.NORMAL:
|
|||
|
|
case Types_1.AmbientListenMode.NO_BODY:
|
|||
|
|
Utils_1.Utils.setLED(this._jibo, Assets_1.Led.LISTENING);
|
|||
|
|
this.startListeningEye(true);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
this._ed.speech.waitForAnimDispatch().then(() => {
|
|||
|
|
if (this.current === this._nonHjExpression) {
|
|||
|
|
this._nonHjExpression.transitionTo(this._engage);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
this._engage.addTypedEventTransition(this.eventsIn.sos, this._listening);
|
|||
|
|
this._engage.addTypedEventTransition(this.eventsIn.eos, this._thinking);
|
|||
|
|
this._engage.addTypedEventTransition(this.eventsIn.cloudFinished, this._offExpression);
|
|||
|
|
this._engage.addTypedEventTransition(this.eventsIn.hjHeard, this._hjExpression);
|
|||
|
|
let nextBlinkTime = -1;
|
|||
|
|
this._engage.onEntry = () => {
|
|||
|
|
log.debug('Entering Engage');
|
|||
|
|
nextBlinkTime = Date.now() + 2000;
|
|||
|
|
switch (this._ambientMode) {
|
|||
|
|
case Types_1.AmbientListenMode.NORMAL:
|
|||
|
|
break;
|
|||
|
|
case Types_1.AmbientListenMode.NO_BODY:
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
this._engage.onUpdate = () => {
|
|||
|
|
let now = Date.now();
|
|||
|
|
if (now >= nextBlinkTime) {
|
|||
|
|
nextBlinkTime = now + Math.floor(2500 + Math.random() * 1000);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
this._engage.onExit = () => {
|
|||
|
|
switch (this._ambientMode) {
|
|||
|
|
case Types_1.AmbientListenMode.NORMAL:
|
|||
|
|
break;
|
|||
|
|
case Types_1.AmbientListenMode.NO_BODY:
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
this._listening.addTypedEventTransition(this.eventsIn.eos, this._thinking);
|
|||
|
|
this._listening.addTypedEventTransition(this.eventsIn.cloudFinished, this._offExpression);
|
|||
|
|
this._listening.addTypedEventTransition(this.eventsIn.hjHeard, this._hjExpression);
|
|||
|
|
let incrementalHandler = this._handleIncremental.bind(this);
|
|||
|
|
this._listening.onEntry = () => {
|
|||
|
|
log.debug('Entering Listening');
|
|||
|
|
this.eventsIn.sos.on(incrementalHandler);
|
|||
|
|
};
|
|||
|
|
this._listening.onExit = () => {
|
|||
|
|
this.eventsIn.sos.removeListener(incrementalHandler);
|
|||
|
|
};
|
|||
|
|
this._thinking.addTypedEventTransition(this.eventsIn.cloudFinished, this._waitForAnimFinish);
|
|||
|
|
this._thinking.addTypedEventTransition(this.eventsIn.hjHeard, this._hjExpression);
|
|||
|
|
this._thinking.onEntry = () => __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
log.debug('Entering Thinking (+ Off Expression)');
|
|||
|
|
Utils_1.Utils.setLED(jibo, Assets_1.Led.OFF);
|
|||
|
|
yield this.stopListeningEye();
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
dispose() {
|
|||
|
|
}
|
|||
|
|
waitForIdle(fastForward = false) {
|
|||
|
|
if (this.current === this._idle) {
|
|||
|
|
return Promise.resolve();
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
return new Promise(resolve => {
|
|||
|
|
this.eventsOut.finished.once(resolve);
|
|||
|
|
if (fastForward) {
|
|||
|
|
this.eventsInternal.reset.emit();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
demoEngaged(turnOn) {
|
|||
|
|
if (turnOn) {
|
|||
|
|
Utils_1.Utils.setLED(this._jibo, Assets_1.Led.LISTENING);
|
|||
|
|
return Promise.all([this.startListeningEye(true)]);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
Utils_1.Utils.setLED(this._jibo, Assets_1.Led.OFF);
|
|||
|
|
return Promise.all([this.stopListeningEye()]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
disableOnce() {
|
|||
|
|
this._disableOnce = true;
|
|||
|
|
}
|
|||
|
|
getAmbientMode() {
|
|||
|
|
return this._ambientMode;
|
|||
|
|
}
|
|||
|
|
getActiveMode() {
|
|||
|
|
return this._activeMode;
|
|||
|
|
}
|
|||
|
|
setAmbientMode(mode) {
|
|||
|
|
const newMode = Types_1.AmbientListenMode[mode];
|
|||
|
|
if (!newMode) {
|
|||
|
|
log.warn(`Requested invalid Ambient Listen Mode '${mode}'`);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
this._ambientMode = newMode;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
enterActiveMode(mode, options) {
|
|||
|
|
const newMode = Types_1.ActiveListenMode[mode];
|
|||
|
|
if (!newMode) {
|
|||
|
|
log.warn(`Requested invalid Active Listen Mode '${mode}'`);
|
|||
|
|
return Promise.resolve(Types_1.RequestStatus.REJECTED);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
if (this._activeMode) {
|
|||
|
|
if (newMode !== this._activeMode) {
|
|||
|
|
this._pendingActiveMode = newMode;
|
|||
|
|
this._pendingActiveModeExtPr = new Utils_2.ExtPromise();
|
|||
|
|
this.eventsInternal.enterActiveMode.emit();
|
|||
|
|
return this._pendingActiveModeExtPr.promise;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
return Promise.resolve(Types_1.RequestStatus.SUCCEEDED);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
if (this._pendingActiveMode) {
|
|||
|
|
this._pendingActiveMode = null;
|
|||
|
|
this._pendingActiveModeExtPr.resolve(Types_1.RequestStatus.INTERRUPTED);
|
|||
|
|
}
|
|||
|
|
this._pendingActiveMode = newMode;
|
|||
|
|
this._pendingActiveModeExtPr = new Utils_2.ExtPromise();
|
|||
|
|
this.waitForIdle(true);
|
|||
|
|
this.eventsInternal.enterActiveMode.emit();
|
|||
|
|
return this._pendingActiveModeExtPr.promise;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exitActiveMode(fastforward = true) {
|
|||
|
|
if (this._activeMode) {
|
|||
|
|
if (this._pendingActiveMode) {
|
|||
|
|
this._pendingActiveMode = null;
|
|||
|
|
this._pendingActiveModeExtPr.resolve(Types_1.RequestStatus.CANCELLED);
|
|||
|
|
}
|
|||
|
|
this.eventsInternal.exitActiveMode.emit();
|
|||
|
|
return this.waitForIdle(fastforward);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
return Promise.resolve();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
startListeningEye(heyJibo) {
|
|||
|
|
const seePerson = true;
|
|||
|
|
const dir = Assets_1.EyeTransitionDirection.TO;
|
|||
|
|
const useSound = false;
|
|||
|
|
const now = Date.now();
|
|||
|
|
if (this.listenState !== Types_1.ListeningState.LISTENING) {
|
|||
|
|
this.listenState = Types_1.ListeningState.LISTENING;
|
|||
|
|
if (heyJibo && ((now - this._lastHJBlinkTime) > HJ_BLINK_INTERVAL)) {
|
|||
|
|
this._lastHJBlinkTime = now;
|
|||
|
|
this.addEyeAnimationToQueue(Assets_1.AnimSelector.getPerceptualEyeTransition(seePerson, Assets_1.EyeTransitionStyle.BLINK, dir, useSound), heyJibo);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
this.addEyeAnimationToQueue(Assets_1.AnimSelector.getPerceptualEyeTransition(seePerson, Assets_1.EyeTransitionStyle.POP, dir, useSound), heyJibo);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
stopListeningEye() {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
if (this.listenState !== Types_1.ListeningState.NOT_LISTENING) {
|
|||
|
|
this.listenState = Types_1.ListeningState.NOT_LISTENING;
|
|||
|
|
yield this._jibo.expression.cleanup({
|
|||
|
|
requestor: EmbodiedListen.HJ_OWNER_INFORMATION,
|
|||
|
|
dofs: this.DOFS_TO_CENTER
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
_handleIncremental() {
|
|||
|
|
if (this._ambientMode !== Types_1.AmbientListenMode.NO_BODY) {
|
|||
|
|
const now = Date.now();
|
|||
|
|
if (now - this._lastHeadBob > this._nextHeadBob) {
|
|||
|
|
this._nextHeadBob = Math.floor(1000 + Math.random() * 1000);
|
|||
|
|
this._lastHeadBob = now;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
addEyeAnimationToQueue(name, heyJibo = false) {
|
|||
|
|
const baseConfig = {
|
|||
|
|
cache: jibo_cai_utils_1.CacheUtils.GlobalCacheName,
|
|||
|
|
dofs: this.DOFS_EYE_AND_OVERLAY_MINUS_EYE_TRANSLATE,
|
|||
|
|
};
|
|||
|
|
const nonhjConfig = Object.assign({}, baseConfig, { layer: "beat" });
|
|||
|
|
const config = heyJibo ? baseConfig : nonhjConfig;
|
|||
|
|
const baseOptions = {
|
|||
|
|
screenCenterOverride: true,
|
|||
|
|
disableSetFaceAnim: true
|
|||
|
|
};
|
|||
|
|
const hjOptions = Object.assign({}, baseOptions, {
|
|||
|
|
ownerInformation: EmbodiedListen.HJ_OWNER_INFORMATION,
|
|||
|
|
disableSetFaceAnim: false,
|
|||
|
|
});
|
|||
|
|
const options = heyJibo ? hjOptions : baseOptions;
|
|||
|
|
this._addAnimToQueue(name, config, options);
|
|||
|
|
}
|
|||
|
|
_addAnimToQueue(anim, config, options) {
|
|||
|
|
if (typeof anim === 'function') {
|
|||
|
|
this._queue.add(anim);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
this._queue.add(() => __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
const playbackResult = Utils_1.Utils.playAnimation({
|
|||
|
|
jibo: this._jibo,
|
|||
|
|
animName: anim,
|
|||
|
|
config: config,
|
|||
|
|
options: options,
|
|||
|
|
});
|
|||
|
|
this._lastAnimInstance = playbackResult.playback;
|
|||
|
|
return playbackResult.result;
|
|||
|
|
}));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
EmbodiedListen.NONHJ_OWNER_INFORMATION = 'EmbodiedListen';
|
|||
|
|
EmbodiedListen.HJ_OWNER_INFORMATION = 'BargeIn';
|
|||
|
|
exports.EmbodiedListen = EmbodiedListen;
|
|||
|
|
|
|||
|
|
},{"../log":11,"../utils/Utils":65,"./Assets":5,"./Events":7,"./Types":8,"./Utils":9,"jibo-cai-utils":undefined,"jibo-state-machine":undefined}],7:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const jibo_typed_events_1 = require("jibo-typed-events");
|
|||
|
|
class IncomingEvents extends jibo_typed_events_1.EventContainer {
|
|||
|
|
constructor() {
|
|||
|
|
super();
|
|||
|
|
this.hjHeard = new jibo_typed_events_1.Event('Hey Jibo heard');
|
|||
|
|
this.startListen = new jibo_typed_events_1.Event('Started listening');
|
|||
|
|
this.oriented = new jibo_typed_events_1.Event('Oriented');
|
|||
|
|
this.sos = new jibo_typed_events_1.Event('Start of speech');
|
|||
|
|
this.cloudFinished = new jibo_typed_events_1.Event('Cloud finished');
|
|||
|
|
this.eos = new jibo_typed_events_1.Event('End of speech');
|
|||
|
|
this.personFound = new jibo_typed_events_1.Event('Person visually found');
|
|||
|
|
this.personLost = new jibo_typed_events_1.Event('Person visually lost');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.IncomingEvents = IncomingEvents;
|
|||
|
|
class OutgoingEvents extends jibo_typed_events_1.EventContainer {
|
|||
|
|
constructor() {
|
|||
|
|
super();
|
|||
|
|
this.finished = new jibo_typed_events_1.Event('Embodied Listen finished');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.OutgoingEvents = OutgoingEvents;
|
|||
|
|
class InternalEvents extends jibo_typed_events_1.EventContainer {
|
|||
|
|
constructor() {
|
|||
|
|
super();
|
|||
|
|
this.reset = new jibo_typed_events_1.Event(`Reset`);
|
|||
|
|
this.enterActiveMode = new jibo_typed_events_1.Event(`Enter Active Mode`);
|
|||
|
|
this.exitActiveMode = new jibo_typed_events_1.Event(`Exit Active Mode`);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.InternalEvents = InternalEvents;
|
|||
|
|
|
|||
|
|
},{"jibo-typed-events":undefined}],8:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
var RequestStatus;
|
|||
|
|
(function (RequestStatus) {
|
|||
|
|
RequestStatus["SUCCEEDED"] = "SUCCEEDED";
|
|||
|
|
RequestStatus["INTERRUPTED"] = "INTERRUPTED";
|
|||
|
|
RequestStatus["CANCELLED"] = "CANCELLED";
|
|||
|
|
RequestStatus["REJECTED"] = "REJECTED";
|
|||
|
|
})(RequestStatus = exports.RequestStatus || (exports.RequestStatus = {}));
|
|||
|
|
var VisualPerceptionState;
|
|||
|
|
(function (VisualPerceptionState) {
|
|||
|
|
VisualPerceptionState["PERSON"] = "PERSON";
|
|||
|
|
VisualPerceptionState["NO_PERSON"] = "NO_PERSON";
|
|||
|
|
})(VisualPerceptionState = exports.VisualPerceptionState || (exports.VisualPerceptionState = {}));
|
|||
|
|
var ListeningState;
|
|||
|
|
(function (ListeningState) {
|
|||
|
|
ListeningState["LISTENING"] = "LISTENING";
|
|||
|
|
ListeningState["NOT_LISTENING"] = "NOT_LISTENING";
|
|||
|
|
})(ListeningState = exports.ListeningState || (exports.ListeningState = {}));
|
|||
|
|
var FadeDirection;
|
|||
|
|
(function (FadeDirection) {
|
|||
|
|
FadeDirection["IN"] = "IN";
|
|||
|
|
FadeDirection["OUT"] = "OUT";
|
|||
|
|
})(FadeDirection = exports.FadeDirection || (exports.FadeDirection = {}));
|
|||
|
|
var AmbientListenMode;
|
|||
|
|
(function (AmbientListenMode) {
|
|||
|
|
AmbientListenMode["NORMAL"] = "NORMAL";
|
|||
|
|
AmbientListenMode["NO_BODY"] = "NO_BODY";
|
|||
|
|
})(AmbientListenMode = exports.AmbientListenMode || (exports.AmbientListenMode = {}));
|
|||
|
|
var ActiveListenMode;
|
|||
|
|
(function (ActiveListenMode) {
|
|||
|
|
ActiveListenMode["OPTIONAL_RESPONSE"] = "OPTIONAL_RESPONSE";
|
|||
|
|
ActiveListenMode["UI"] = "UI";
|
|||
|
|
})(ActiveListenMode = exports.ActiveListenMode || (exports.ActiveListenMode = {}));
|
|||
|
|
|
|||
|
|
},{}],9:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const EmbodiedListen_1 = require("./EmbodiedListen");
|
|||
|
|
const jibo_cai_utils_1 = require("jibo-cai-utils");
|
|||
|
|
exports.WIN_NAME = 'Embodied Listen';
|
|||
|
|
let ALL_MINUS_BASE;
|
|||
|
|
class Utils {
|
|||
|
|
static playAnimation(options) {
|
|||
|
|
const jibo = options.jibo;
|
|||
|
|
if (!ALL_MINUS_BASE) {
|
|||
|
|
ALL_MINUS_BASE = jibo.expression.dofs.ALL.minus(jibo.expression.dofs.BASE);
|
|||
|
|
}
|
|||
|
|
const asset = jibo.animDB.getAnimByName(options.animName);
|
|||
|
|
if (!asset) {
|
|||
|
|
throw new Error(`No animation of name '${options.animName}' found in animDB`);
|
|||
|
|
}
|
|||
|
|
const hasDOFs = !!(options.config && options.config.dofs);
|
|||
|
|
const config = hasDOFs ? options.config : Object.assign(options.config || { cache: jibo_cai_utils_1.CacheUtils.GlobalCacheName }, {
|
|||
|
|
dofs: ALL_MINUS_BASE
|
|||
|
|
});
|
|||
|
|
const hasOwner = !!(options.options && options.options.ownerInformation);
|
|||
|
|
const playbackOptions = hasOwner ? options.options : Object.assign(options.options || {}, {
|
|||
|
|
ownerInformation: EmbodiedListen_1.EmbodiedListen.NONHJ_OWNER_INFORMATION,
|
|||
|
|
});
|
|||
|
|
return asset.play(config, playbackOptions);
|
|||
|
|
}
|
|||
|
|
static setLED(jibo, color) {
|
|||
|
|
jibo.performance.log('EmbodiedListenSettingLEDSkill', (color[0] !== 0) ? 'ON' : 'OFF');
|
|||
|
|
jibo.expression.setLEDColor(color);
|
|||
|
|
}
|
|||
|
|
static playSound(jibo, path) {
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
jibo.performance.log('EmbodiedListenLoadSoundSkill');
|
|||
|
|
const sound = jibo.loader.cached(path, jibo_cai_utils_1.CacheUtils.GlobalCacheName);
|
|||
|
|
if (sound) {
|
|||
|
|
jibo.performance.log('EmbodiedListenPlaySoundSkill', path);
|
|||
|
|
sound.play(() => resolve());
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
jibo.loader.load({
|
|||
|
|
type: 'sound',
|
|||
|
|
id: path,
|
|||
|
|
cache: jibo_cai_utils_1.CacheUtils.GlobalCacheName,
|
|||
|
|
src: path,
|
|||
|
|
complete: (err, sound) => {
|
|||
|
|
if (err) {
|
|||
|
|
return reject(err);
|
|||
|
|
}
|
|||
|
|
jibo.performance.log('EmbodiedListenPlaySoundSkill', path);
|
|||
|
|
sound.play(() => resolve());
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
static packRGB(rbgArray) {
|
|||
|
|
return (rbgArray[0] & 0xff) << 16 |
|
|||
|
|
(rbgArray[1] & 0xff) << 8 |
|
|||
|
|
(rbgArray[2] & 0xff);
|
|||
|
|
}
|
|||
|
|
static unpackRGB(rgbPacked) {
|
|||
|
|
const r = (rgbPacked >>> 16) & 0xff;
|
|||
|
|
const g = (rgbPacked >>> 8) & 0xff;
|
|||
|
|
const b = (rgbPacked) & 0xff;
|
|||
|
|
return [r, g, b];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.Utils = Utils;
|
|||
|
|
|
|||
|
|
},{"./EmbodiedListen":6,"jibo-cai-utils":undefined}],10:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const EmbodiedListen_1 = require("./EmbodiedListen");
|
|||
|
|
exports.EmbodiedListen = EmbodiedListen_1.EmbodiedListen;
|
|||
|
|
const Types_1 = require("./Types");
|
|||
|
|
exports.AmbientListenMode = Types_1.AmbientListenMode;
|
|||
|
|
exports.ActiveListenMode = Types_1.ActiveListenMode;
|
|||
|
|
exports.RequestStatus = Types_1.RequestStatus;
|
|||
|
|
|
|||
|
|
},{"./EmbodiedListen":6,"./Types":8}],11:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const jibo_log_1 = require("jibo-log");
|
|||
|
|
const dialogLog = new jibo_log_1.Log('Jibo.Embodied');
|
|||
|
|
exports.dialogLog = dialogLog;
|
|||
|
|
const speechLog = dialogLog.createChild('Speech');
|
|||
|
|
exports.speechLog = speechLog;
|
|||
|
|
const listenLog = dialogLog.createChild('Listen');
|
|||
|
|
exports.listenLog = listenLog;
|
|||
|
|
|
|||
|
|
},{"jibo-log":undefined}],12:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|||
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|||
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|||
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|||
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|||
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const uuid = require("uuid");
|
|||
|
|
const path = require("path");
|
|||
|
|
const jibo_cai_utils_1 = require("jibo-cai-utils");
|
|||
|
|
const jibo_state_machine_1 = require("jibo-state-machine");
|
|||
|
|
const Types_1 = require("./common/Types");
|
|||
|
|
const InputProcessor_1 = require("./processing/InputProcessor");
|
|||
|
|
const NLParser_1 = require("./processing/parsers/NLParser");
|
|||
|
|
const AutoRuleManager_1 = require("./processing/auto_rules/AutoRuleManager");
|
|||
|
|
const TimelineManager_1 = require("./timelines/TimelineManager");
|
|||
|
|
const Utils_1 = require("../utils/Utils");
|
|||
|
|
const Validation_1 = require("./utils/Validation");
|
|||
|
|
const states_1 = require("./states");
|
|||
|
|
const logs = require("../log");
|
|||
|
|
const log = logs.speechLog;
|
|||
|
|
const DEFAULT_FRAME_BUFFER_MS = 0;
|
|||
|
|
class EmbodiedSpeech {
|
|||
|
|
constructor(_ed) {
|
|||
|
|
this.log = log;
|
|||
|
|
this.ownerInformation = 'EmbodiedSpeech';
|
|||
|
|
this.playingKeys = [];
|
|||
|
|
this.animationDispatchPr = Promise.resolve();
|
|||
|
|
this.active = null;
|
|||
|
|
this.sm = new jibo_state_machine_1.StateMachine();
|
|||
|
|
this.createTimelineState = new states_1.CreateTimelineState(this.sm, this, 'Create Timeline');
|
|||
|
|
this.buildDispatchableState = new states_1.BuildDispatchableState(this.sm, this, 'Build Dispatchable');
|
|||
|
|
this.dispatchState = new states_1.DispatchState(this.sm, this, 'Dispatch');
|
|||
|
|
this.completeState = new states_1.CompleteState(this.sm, this, 'Complete');
|
|||
|
|
this.queue = new jibo_cai_utils_1.PromiseQueue();
|
|||
|
|
this.unresolved = new Set();
|
|||
|
|
this.isStopping = false;
|
|||
|
|
this.ed = _ed;
|
|||
|
|
this.sm.setInitial(this.createTimelineState);
|
|||
|
|
this.createTimelineState.addDoneTransition(this.buildDispatchableState);
|
|||
|
|
this.buildDispatchableState.addDoneTransition(this.dispatchState);
|
|||
|
|
this.dispatchState.addDoneTransition(this.completeState);
|
|||
|
|
}
|
|||
|
|
init(jibo, debug = false, options, autoRuleConfig) {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
if (jibo) {
|
|||
|
|
this.jibo = jibo;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw new Error('Cannot instantiate without Jibo instances!');
|
|||
|
|
}
|
|||
|
|
jibo.timer.once('update', () => {
|
|||
|
|
log.debug('Caching common Embodied Speech AutoRule animations.');
|
|||
|
|
const blinksQuery = {
|
|||
|
|
categories: ['blinks'],
|
|||
|
|
includeSomeMeta: ['single', 'double'],
|
|||
|
|
excludeMeta: ['sfx-only', 'ssa-only']
|
|||
|
|
};
|
|||
|
|
const beatQuery = {
|
|||
|
|
categories: ['poses'],
|
|||
|
|
includeMeta: ['initiation'],
|
|||
|
|
excludeMeta: ['sfx-only', 'ssa-only']
|
|||
|
|
};
|
|||
|
|
const commaQuery = {
|
|||
|
|
categories: ['comma'],
|
|||
|
|
excludeMeta: ['sfx-only', 'ssa-only']
|
|||
|
|
};
|
|||
|
|
const questionQuery = {
|
|||
|
|
categories: ['question'],
|
|||
|
|
excludeMeta: ['eye-only', 'sfx-only', 'ssa-only']
|
|||
|
|
};
|
|||
|
|
[blinksQuery, beatQuery, commaQuery, questionQuery].forEach((query) => __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
try {
|
|||
|
|
yield Utils_1.Utils.loadAnimationIntoCache(jibo, query, jibo_cai_utils_1.CacheUtils.GlobalCacheName);
|
|||
|
|
}
|
|||
|
|
catch (err) {
|
|||
|
|
log.warn(`Unable to load animations from query ${JSON.stringify(query)} into cache ${jibo_cai_utils_1.CacheUtils.GlobalCacheName}`);
|
|||
|
|
}
|
|||
|
|
}));
|
|||
|
|
});
|
|||
|
|
const dofsAll = this.jibo.expression.dofs.ALL;
|
|||
|
|
this.dofsToCenter = dofsAll.minus(this.jibo.expression.dofs.LED)
|
|||
|
|
.minus(this.jibo.expression.dofs.BODY).minus(this.jibo.expression.dofs.EYE_TRANSLATE);
|
|||
|
|
const defaultSpeakOptions = {
|
|||
|
|
disableAutoRules: false,
|
|||
|
|
dispatchComplete: Types_1.DispatchType.ALL,
|
|||
|
|
enableLayerMerging: true,
|
|||
|
|
frameBuffer: Utils_1.Utils.millisecToSec(DEFAULT_FRAME_BUFFER_MS),
|
|||
|
|
followedByListen: false,
|
|||
|
|
debugMode: debug
|
|||
|
|
};
|
|||
|
|
this._speakOptions = Validation_1.Validation.validateSpeakOptions(defaultSpeakOptions, options);
|
|||
|
|
const allowAutoRule = !this._speakOptions.disableAutoRules;
|
|||
|
|
const defaultAutoRuleConfig = {
|
|||
|
|
interSentenceTiming: false,
|
|||
|
|
intraSentenceTiming: false,
|
|||
|
|
hotWords: allowAutoRule,
|
|||
|
|
punctuation: allowAutoRule,
|
|||
|
|
structure: false,
|
|||
|
|
voice: allowAutoRule,
|
|||
|
|
beat: allowAutoRule,
|
|||
|
|
themeRheme: false
|
|||
|
|
};
|
|||
|
|
this._autoRuleConfig = Validation_1.Validation.validateAutoRuleConfig(defaultAutoRuleConfig, autoRuleConfig);
|
|||
|
|
this.inputProcessor = new InputProcessor_1.InputProcessor(this.jibo);
|
|||
|
|
this.nlParser = new NLParser_1.NLParser(this.jibo);
|
|||
|
|
this.autoRuleManager = new AutoRuleManager_1.AutoRuleManager(this.jibo);
|
|||
|
|
let resourceRoot;
|
|||
|
|
if (options && options.resourceRoot) {
|
|||
|
|
resourceRoot = options.resourceRoot;
|
|||
|
|
}
|
|||
|
|
this.setResourceRoots(resourceRoot);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
speak(textToSpeak, speakOptions, autoRuleConfig) {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
log.info("Speak request received");
|
|||
|
|
this.jibo.performance.log('EmbodiedSpeechStartSkill', 'When ES is called');
|
|||
|
|
if (this.active) {
|
|||
|
|
this.stop();
|
|||
|
|
}
|
|||
|
|
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
const session = {
|
|||
|
|
resolve,
|
|||
|
|
reject,
|
|||
|
|
id: uuid.v4(),
|
|||
|
|
wasStopped: false
|
|||
|
|
};
|
|||
|
|
this.unresolved.add(session);
|
|||
|
|
this.queue.add(() => __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
this.active = session;
|
|||
|
|
this.unresolved.delete(session);
|
|||
|
|
try {
|
|||
|
|
yield this._speak(textToSpeak, session, speakOptions, autoRuleConfig);
|
|||
|
|
}
|
|||
|
|
catch (error) {
|
|||
|
|
reject(error);
|
|||
|
|
}
|
|||
|
|
finally {
|
|||
|
|
this.active = null;
|
|||
|
|
log.info("Ready for next speak request");
|
|||
|
|
if (session.wasStopped) {
|
|||
|
|
this.isStopping = false;
|
|||
|
|
resolve(Types_1.RequestStatus.STOPPED);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
resolve(Types_1.RequestStatus.SUCCEEDED);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}));
|
|||
|
|
}));
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
_speak(textToSpeak, session, speakOptions, autoRuleConfig) {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
log.info("Processing speak request");
|
|||
|
|
const validatedOptions = Validation_1.Validation.validateSpeakOptions(this._speakOptions, speakOptions);
|
|||
|
|
log.debug("Validated Speak Options: ", validatedOptions);
|
|||
|
|
const validatedConfig = Validation_1.Validation.validateAutoRuleConfig(this._autoRuleConfig, autoRuleConfig);
|
|||
|
|
log.debug("Validated AutoRule Config: ", validatedConfig);
|
|||
|
|
const data = {
|
|||
|
|
session: session.id,
|
|||
|
|
textToSpeak: textToSpeak,
|
|||
|
|
speakOptions: validatedOptions,
|
|||
|
|
autoRuleConfig: validatedConfig,
|
|||
|
|
centeringEnabled: false
|
|||
|
|
};
|
|||
|
|
log.info("Starting new speak session: ", session.id);
|
|||
|
|
return this.sm.start(data);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
stop() {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
log.info("Stop request received");
|
|||
|
|
if (this.active && !this.isStopping) {
|
|||
|
|
this.isStopping = true;
|
|||
|
|
this.active.wasStopped = true;
|
|||
|
|
this._stop();
|
|||
|
|
}
|
|||
|
|
this.queue.clear();
|
|||
|
|
const temp = this.unresolved;
|
|||
|
|
this.unresolved = new Set();
|
|||
|
|
temp.forEach(session => {
|
|||
|
|
log.info("Stopping queued session: ", session.id);
|
|||
|
|
session.resolve(Types_1.RequestStatus.STOPPED);
|
|||
|
|
});
|
|||
|
|
return this.queue.waitUntilEmpty()
|
|||
|
|
.then(() => null);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
_stop() {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
if (this.active) {
|
|||
|
|
log.info("Processing stop request on active session: ", this.active.id);
|
|||
|
|
return this.sm.stop();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
setResourceRoots(root) {
|
|||
|
|
const resourceRoot = root;
|
|||
|
|
let animResourceRoot;
|
|||
|
|
let audioResourceRoot;
|
|||
|
|
if (resourceRoot) {
|
|||
|
|
log.debug(`Setting new resource roots based off of: ${root}`);
|
|||
|
|
animResourceRoot = path.join(resourceRoot, 'animations');
|
|||
|
|
audioResourceRoot = path.join(resourceRoot, 'audio');
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
log.debug(`Clearing resource roots`);
|
|||
|
|
}
|
|||
|
|
this.timelineManager = new TimelineManager_1.TimelineManager(this.jibo, resourceRoot, animResourceRoot, audioResourceRoot);
|
|||
|
|
}
|
|||
|
|
isActive() {
|
|||
|
|
return !!this.active;
|
|||
|
|
}
|
|||
|
|
waitForAnimDispatch() {
|
|||
|
|
return this.animationDispatchPr;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.EmbodiedSpeech = EmbodiedSpeech;
|
|||
|
|
|
|||
|
|
},{"../log":11,"../utils/Utils":65,"./common/Types":13,"./processing/InputProcessor":19,"./processing/auto_rules/AutoRuleManager":23,"./processing/parsers/NLParser":51,"./states":58,"./timelines/TimelineManager":60,"./utils/Validation":63,"jibo-cai-utils":undefined,"jibo-state-machine":undefined,"path":undefined,"uuid":undefined}],13:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
var RequestStatus;
|
|||
|
|
(function (RequestStatus) {
|
|||
|
|
RequestStatus["SUCCEEDED"] = "SUCCEEDED";
|
|||
|
|
RequestStatus["STOPPED"] = "STOPPED";
|
|||
|
|
})(RequestStatus = exports.RequestStatus || (exports.RequestStatus = {}));
|
|||
|
|
var SSMLNodeType;
|
|||
|
|
(function (SSMLNodeType) {
|
|||
|
|
SSMLNodeType["BREAK"] = "BREAK";
|
|||
|
|
SSMLNodeType["AUDIO_BREAK"] = "AUDIO_BREAK";
|
|||
|
|
SSMLNodeType["PHONEME"] = "PHONEME";
|
|||
|
|
SSMLNodeType["PITCH"] = "PITCH";
|
|||
|
|
SSMLNodeType["DURATION"] = "DURATION";
|
|||
|
|
SSMLNodeType["SAY_AS"] = "SAY-AS";
|
|||
|
|
SSMLNodeType["STYLE"] = "STYLE";
|
|||
|
|
SSMLNodeType["ENGINE"] = "ENGINE";
|
|||
|
|
})(SSMLNodeType = exports.SSMLNodeType || (exports.SSMLNodeType = {}));
|
|||
|
|
var SSMLStyleTagType;
|
|||
|
|
(function (SSMLStyleTagType) {
|
|||
|
|
SSMLStyleTagType["NEUTRAL"] = "NEUTRAL";
|
|||
|
|
SSMLStyleTagType["SHEEPISH"] = "SHEEPISH";
|
|||
|
|
SSMLStyleTagType["CONFUSED"] = "CONFUSED";
|
|||
|
|
SSMLStyleTagType["CONFIDENT"] = "CONFIDENT";
|
|||
|
|
SSMLStyleTagType["ENTHUSIASTIC"] = "ENTHUSIASTIC";
|
|||
|
|
SSMLStyleTagType["NEWS"] = "NEWS";
|
|||
|
|
})(SSMLStyleTagType = exports.SSMLStyleTagType || (exports.SSMLStyleTagType = {}));
|
|||
|
|
var AssetNodeType;
|
|||
|
|
(function (AssetNodeType) {
|
|||
|
|
AssetNodeType["ES"] = "ES";
|
|||
|
|
AssetNodeType["ANIM"] = "ANIM";
|
|||
|
|
AssetNodeType["SSA"] = "SSA";
|
|||
|
|
AssetNodeType["SFX"] = "SFX";
|
|||
|
|
AssetNodeType["AUDIO"] = "AUDIO";
|
|||
|
|
})(AssetNodeType = exports.AssetNodeType || (exports.AssetNodeType = {}));
|
|||
|
|
var RequestType;
|
|||
|
|
(function (RequestType) {
|
|||
|
|
RequestType["NAME"] = "NAME";
|
|||
|
|
RequestType["PATH"] = "PATH";
|
|||
|
|
RequestType["QUERY"] = "QUERY";
|
|||
|
|
RequestType["UNKNOWN"] = "UNKNOWN";
|
|||
|
|
})(RequestType = exports.RequestType || (exports.RequestType = {}));
|
|||
|
|
var ESTreeType;
|
|||
|
|
(function (ESTreeType) {
|
|||
|
|
ESTreeType["TAG_TREE"] = "TAG_TREE";
|
|||
|
|
ESTreeType["NLP_TREE"] = "NLP_TREE";
|
|||
|
|
})(ESTreeType = exports.ESTreeType || (exports.ESTreeType = {}));
|
|||
|
|
var DispatchType;
|
|||
|
|
(function (DispatchType) {
|
|||
|
|
DispatchType["TTS"] = "TTS";
|
|||
|
|
DispatchType["ALL"] = "ALL";
|
|||
|
|
})(DispatchType = exports.DispatchType || (exports.DispatchType = {}));
|
|||
|
|
var TTSNodeType;
|
|||
|
|
(function (TTSNodeType) {
|
|||
|
|
TTSNodeType["TTS"] = "TTS";
|
|||
|
|
})(TTSNodeType = exports.TTSNodeType || (exports.TTSNodeType = {}));
|
|||
|
|
var NLPNodeType;
|
|||
|
|
(function (NLPNodeType) {
|
|||
|
|
NLPNodeType["WORD"] = "WORD";
|
|||
|
|
NLPNodeType["SENTENCE"] = "SENTENCE";
|
|||
|
|
NLPNodeType["PART"] = "PART";
|
|||
|
|
})(NLPNodeType = exports.NLPNodeType || (exports.NLPNodeType = {}));
|
|||
|
|
var WordType;
|
|||
|
|
(function (WordType) {
|
|||
|
|
WordType["NOUN"] = "NOUN";
|
|||
|
|
WordType["VERB"] = "VERB";
|
|||
|
|
WordType["END"] = "END";
|
|||
|
|
WordType["CONN"] = "CONN";
|
|||
|
|
WordType["PREP"] = "PREP";
|
|||
|
|
WordType["UNKN"] = "UNKN";
|
|||
|
|
})(WordType = exports.WordType || (exports.WordType = {}));
|
|||
|
|
var SentenceType;
|
|||
|
|
(function (SentenceType) {
|
|||
|
|
SentenceType["QUESTION"] = "QUESTION";
|
|||
|
|
SentenceType["EXCLAMATION"] = "EXCLAMATION";
|
|||
|
|
SentenceType["REGULAR"] = "REGULAR";
|
|||
|
|
})(SentenceType = exports.SentenceType || (exports.SentenceType = {}));
|
|||
|
|
|
|||
|
|
},{}],14:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
function __export(m) {
|
|||
|
|
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|||
|
|
}
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
__export(require("./Types"));
|
|||
|
|
|
|||
|
|
},{"./Types":13}],15:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
function __export(m) {
|
|||
|
|
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|||
|
|
}
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const timelines = require("./timelines");
|
|||
|
|
exports.timelines = timelines;
|
|||
|
|
const processing = require("./processing");
|
|||
|
|
exports.processing = processing;
|
|||
|
|
const common = require("./common");
|
|||
|
|
exports.common = common;
|
|||
|
|
const utils = require("./utils");
|
|||
|
|
exports.utils = utils;
|
|||
|
|
const states = require("./states");
|
|||
|
|
exports.states = states;
|
|||
|
|
__export(require("./EmbodiedSpeech"));
|
|||
|
|
|
|||
|
|
},{"./EmbodiedSpeech":12,"./common":14,"./processing":49,"./states":58,"./timelines":61,"./utils":64}],16:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const jibo_node_xml_1 = require("jibo-node-xml");
|
|||
|
|
const Types_1 = require("../common/Types");
|
|||
|
|
const log_1 = require("../../log");
|
|||
|
|
const log = log_1.speechLog.createChild("AssetNode");
|
|||
|
|
exports.MetaLayerMap = {
|
|||
|
|
body: 'Body',
|
|||
|
|
screen: 'Screen',
|
|||
|
|
audio: 'Audio'
|
|||
|
|
};
|
|||
|
|
const ESAliasToFilter = {
|
|||
|
|
ANIM: '!ssa-only, !sfx-only',
|
|||
|
|
SSA: 'ssa-only',
|
|||
|
|
SFX: 'sfx-only'
|
|||
|
|
};
|
|||
|
|
const ALL_LAYERS = 'all';
|
|||
|
|
class AssetNode extends jibo_node_xml_1.default {
|
|||
|
|
constructor(type, att, timeSyncNode, playbackData) {
|
|||
|
|
super(type);
|
|||
|
|
this.timeSyncNode = timeSyncNode;
|
|||
|
|
this.playbackData = playbackData;
|
|||
|
|
let defaultFilterIntent;
|
|||
|
|
if (type !== Types_1.AssetNodeType.AUDIO) {
|
|||
|
|
this.type = Types_1.AssetNodeType.ES;
|
|||
|
|
defaultFilterIntent = ESAliasToFilter[type];
|
|||
|
|
this.metaFilter = {
|
|||
|
|
allOf: [],
|
|||
|
|
someOf: [],
|
|||
|
|
noneOf: [],
|
|||
|
|
addAll: []
|
|||
|
|
};
|
|||
|
|
this.categoryFilter = {
|
|||
|
|
allOf: [],
|
|||
|
|
someOf: [],
|
|||
|
|
noneOf: [],
|
|||
|
|
addAll: []
|
|||
|
|
};
|
|||
|
|
AssetNode.addFilterAttributes(defaultFilterIntent, this.metaFilter);
|
|||
|
|
}
|
|||
|
|
if (att) {
|
|||
|
|
this.att = att;
|
|||
|
|
this.requestInfo = AssetNode.getRequestInfo(att);
|
|||
|
|
const requestedCategoryIntent = this.att.get('cat') || this.att.get('cats');
|
|||
|
|
if (requestedCategoryIntent) {
|
|||
|
|
AssetNode.addCategories(requestedCategoryIntent, this.categoryFilter);
|
|||
|
|
}
|
|||
|
|
const requestedFilterIntent = this.att.get('filter') || this.att.get('filters') || this.att.get('meta') || this.att.get('metas');
|
|||
|
|
if (requestedFilterIntent) {
|
|||
|
|
AssetNode.addMeta(requestedFilterIntent, this.metaFilter);
|
|||
|
|
}
|
|||
|
|
this.layers = {};
|
|||
|
|
this.layersToAdd = {};
|
|||
|
|
const reqLayers = this.att.get('layers') || this.att.get('layer');
|
|||
|
|
if (reqLayers) {
|
|||
|
|
AssetNode.addLayers(reqLayers, this.layers, this.layersToAdd);
|
|||
|
|
}
|
|||
|
|
const reqLoop = this.att.get('loop') || this.att.get('loops');
|
|||
|
|
if (reqLoop) {
|
|||
|
|
this.loops = parseInt(reqLoop);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
static getRequestInfo(att) {
|
|||
|
|
let info = {
|
|||
|
|
type: Types_1.RequestType.UNKNOWN,
|
|||
|
|
description: Types_1.RequestType.UNKNOWN
|
|||
|
|
};
|
|||
|
|
if (att.has('name')) {
|
|||
|
|
info.type = Types_1.RequestType.NAME;
|
|||
|
|
info.description = `${info.type}[ ${att.get('name')} ]`;
|
|||
|
|
}
|
|||
|
|
else if (att.has('cat') || att.has('cats') || att.has('filter') || att.has('filters') || att.has('meta') || att.has('metas')) {
|
|||
|
|
info.type = Types_1.RequestType.QUERY;
|
|||
|
|
const cat = `CAT[ ${att.get('cat') || att.get('cats')} ]`;
|
|||
|
|
const meta = `META[ ${att.get('filter') || att.get('filters') || att.get('meta') || att.get('metas')} ]`;
|
|||
|
|
info.description = `${info.type}[ ${cat} ${meta} ]`;
|
|||
|
|
}
|
|||
|
|
else if (att.has('path')) {
|
|||
|
|
info.type = Types_1.RequestType.PATH;
|
|||
|
|
info.description = `${info.type}[ ${att.get('path')} ]`;
|
|||
|
|
}
|
|||
|
|
return info;
|
|||
|
|
}
|
|||
|
|
static addCategories(reqestedCategoriesIntent, categoryFilter) {
|
|||
|
|
AssetNode.addFilterAttributes(reqestedCategoriesIntent, categoryFilter);
|
|||
|
|
}
|
|||
|
|
static addFilterAttributes(filterAttr, metaFilter) {
|
|||
|
|
if (filterAttr) {
|
|||
|
|
const terms = filterAttr.split(/[;,](?![^(]*\))/g);
|
|||
|
|
terms.forEach(term => {
|
|||
|
|
const [op, attrs] = AssetNode.parseTerm(term);
|
|||
|
|
if (attrs.length > 0) {
|
|||
|
|
if (!op || op === '&') {
|
|||
|
|
metaFilter.allOf.push(...attrs);
|
|||
|
|
}
|
|||
|
|
else if (op === '?') {
|
|||
|
|
metaFilter.someOf.push(...attrs);
|
|||
|
|
}
|
|||
|
|
else if (op === '!') {
|
|||
|
|
metaFilter.noneOf.push(...attrs);
|
|||
|
|
}
|
|||
|
|
else if (op === '+') {
|
|||
|
|
metaFilter.addAll.push(...attrs);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
static parseTerm(term) {
|
|||
|
|
const trimmed = term.trim().toLowerCase();
|
|||
|
|
let op;
|
|||
|
|
let attrs = [];
|
|||
|
|
const groupedMatches = /^([!\?\+&]?)\(([\w\s-,;]+)\)/.exec(trimmed);
|
|||
|
|
if (groupedMatches) {
|
|||
|
|
op = groupedMatches[1];
|
|||
|
|
const subterms = groupedMatches[2].split(',');
|
|||
|
|
attrs.push(...subterms.map(subterm => subterm.trim()));
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
const indMatches = /^([!\?\+&]?)([\w-]+)/.exec(trimmed);
|
|||
|
|
if (indMatches) {
|
|||
|
|
op = indMatches[1];
|
|||
|
|
attrs.push(indMatches[2]);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
log.warn('ESML Query contains un-parseable elements. No or unexpected results likely.');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return [op, attrs];
|
|||
|
|
}
|
|||
|
|
static addMeta(reqFiltered, metaFilter) {
|
|||
|
|
AssetNode.addFilterAttributes(reqFiltered, metaFilter);
|
|||
|
|
if (metaFilter.allOf.length > 0) {
|
|||
|
|
metaFilter.allOf = Array.from(new Set(metaFilter.allOf));
|
|||
|
|
}
|
|||
|
|
if (metaFilter.someOf.length > 0) {
|
|||
|
|
metaFilter.someOf = Array.from(new Set(metaFilter.someOf));
|
|||
|
|
}
|
|||
|
|
if (metaFilter.noneOf.length > 0) {
|
|||
|
|
metaFilter.noneOf = Array.from(new Set(metaFilter.noneOf));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
static addLayers(reqestedLayersIntent, layers, layersToAdd) {
|
|||
|
|
let layerFilter = {
|
|||
|
|
allOf: [],
|
|||
|
|
someOf: [],
|
|||
|
|
noneOf: [],
|
|||
|
|
addAll: []
|
|||
|
|
};
|
|||
|
|
AssetNode.addFilterAttributes(reqestedLayersIntent, layerFilter);
|
|||
|
|
if (layerFilter.addAll.length > 0) {
|
|||
|
|
if (layerFilter.allOf.length > 0 || layerFilter.noneOf.length > 0) {
|
|||
|
|
log.warn('Cannot both add layers and filter inclusively or exclusively at the same time.' +
|
|||
|
|
' Modify layers filter to be one approach or the other.');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (layerFilter.addAll.length === 1 && layerFilter.addAll[0] === ALL_LAYERS) {
|
|||
|
|
layers.Body = true;
|
|||
|
|
layers.Screen = true;
|
|||
|
|
layers.Audio = true;
|
|||
|
|
layersToAdd.Body = true;
|
|||
|
|
layersToAdd.Screen = true;
|
|||
|
|
layersToAdd.Audio = true;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
layerFilter.addAll.forEach(layer => {
|
|||
|
|
const metaLayerName = exports.MetaLayerMap[layer];
|
|||
|
|
if (metaLayerName === undefined) {
|
|||
|
|
log.warn(`Layer ${layer} is not a valid layers filter.`);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
layers[metaLayerName] = true;
|
|||
|
|
layersToAdd[metaLayerName] = true;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
if (layerFilter.allOf.length > 0 && layerFilter.noneOf.length > 0) {
|
|||
|
|
log.warn('Cannot filter layers in both an inclusive and exclusive manner at the same time.' +
|
|||
|
|
' Modify layers filter to be one or the other.');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (layerFilter.allOf.length > 0) {
|
|||
|
|
layers.Body = false;
|
|||
|
|
layers.Screen = false;
|
|||
|
|
layers.Audio = false;
|
|||
|
|
layerFilter.allOf.forEach(layer => {
|
|||
|
|
const metaLayerName = exports.MetaLayerMap[layer];
|
|||
|
|
if (metaLayerName === undefined) {
|
|||
|
|
log.warn(`Layer ${layer} is not a valid layers filter.`);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
layers[metaLayerName] = true;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
layerFilter.noneOf.forEach(layer => {
|
|||
|
|
const metaLayerName = exports.MetaLayerMap[layer];
|
|||
|
|
if (metaLayerName === undefined) {
|
|||
|
|
log.warn(`Layer ${layer} is not a valid layers filter.`);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
layers[metaLayerName] = false;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.AssetNode = AssetNode;
|
|||
|
|
|
|||
|
|
},{"../../log":11,"../common/Types":13,"jibo-node-xml":undefined}],17:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const ContentLists = require('../../../resources/swears.json');
|
|||
|
|
class ContentValidator {
|
|||
|
|
constructor() {
|
|||
|
|
const reWholeMatch = `\\b(${ContentLists.whole.join('|')})+\\b`;
|
|||
|
|
const rePartialMatch = `(\\w*(${ContentLists.partial.join('|')})\\w*)`;
|
|||
|
|
const reBlackList = `${reWholeMatch}|${rePartialMatch}`;
|
|||
|
|
const reWhitelist = `(\\b(${ContentLists.whitelist.join('|')})\\b)`;
|
|||
|
|
this.blacklist = new RegExp(reBlackList, 'ig');
|
|||
|
|
this.whitelist = new RegExp(reWhitelist, 'ig');
|
|||
|
|
}
|
|||
|
|
replaceRestricted(sentence, replacement) {
|
|||
|
|
this.blacklist.lastIndex = 0;
|
|||
|
|
this.whitelist.lastIndex = 0;
|
|||
|
|
let saved = {};
|
|||
|
|
let count = 0;
|
|||
|
|
let ids = [];
|
|||
|
|
const hider = (match) => {
|
|||
|
|
const id = `<wl id=${count++}\/>`;
|
|||
|
|
ids.push(id);
|
|||
|
|
saved[id] = match;
|
|||
|
|
return id;
|
|||
|
|
};
|
|||
|
|
const seeker = (match) => {
|
|||
|
|
return saved[match];
|
|||
|
|
};
|
|||
|
|
const hidden = sentence.replace(this.whitelist, hider);
|
|||
|
|
const replaced = hidden.replace(this.blacklist, replacement);
|
|||
|
|
if (ids.length) {
|
|||
|
|
const reSavelist = `(${ids.join('|')})`;
|
|||
|
|
const savelist = new RegExp(reSavelist, 'g');
|
|||
|
|
return replaced.replace(savelist, seeker);
|
|||
|
|
}
|
|||
|
|
return replaced;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.ContentValidator = ContentValidator;
|
|||
|
|
|
|||
|
|
},{"../../../resources/swears.json":1}],18:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
class AudioAnimTemplate {
|
|||
|
|
constructor(duration, path) {
|
|||
|
|
this.duration = duration;
|
|||
|
|
this.version = '0.7.0';
|
|||
|
|
this.framerate = 30;
|
|||
|
|
this.scale = 1;
|
|||
|
|
this.animdb = {
|
|||
|
|
name: 'audio_path_tag',
|
|||
|
|
metaTerms: ["audio-only"],
|
|||
|
|
scaleMax: 1,
|
|||
|
|
scaleMin: 1,
|
|||
|
|
speedMax: 1,
|
|||
|
|
speedMin: 1
|
|||
|
|
};
|
|||
|
|
this.pathless = true;
|
|||
|
|
let audioEvent = {};
|
|||
|
|
audioEvent.AudioEvent = {
|
|||
|
|
file: path
|
|||
|
|
};
|
|||
|
|
let keyframe = {};
|
|||
|
|
keyframe.time = 0;
|
|||
|
|
keyframe.value = audioEvent;
|
|||
|
|
let layer = {};
|
|||
|
|
layer.id = '96ca2c12e2f4459589c8dd99387ab59e';
|
|||
|
|
layer.name = 'Audio Event';
|
|||
|
|
layer.type = 'Audio Event';
|
|||
|
|
layer.visible = true;
|
|||
|
|
layer.locked = false;
|
|||
|
|
layer.keyframes = [keyframe];
|
|||
|
|
this.layers = [layer];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.AudioAnimTemplate = AudioAnimTemplate;
|
|||
|
|
|
|||
|
|
},{}],19:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|||
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|||
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|||
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|||
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|||
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const jibo_node_xml_1 = require("jibo-node-xml");
|
|||
|
|
const jibo_node_xml_2 = require("jibo-node-xml");
|
|||
|
|
const AssetNode_1 = require("./AssetNode");
|
|||
|
|
const ContentValidator_1 = require("./ContentValidator");
|
|||
|
|
const Types_1 = require("../common/Types");
|
|||
|
|
const SSMLNode_1 = require("./SSMLNode");
|
|||
|
|
const NLPTools_1 = require("../utils/NLPTools");
|
|||
|
|
const Lexer_1 = require("./parsers/Lexer");
|
|||
|
|
const TimelineModUtils_1 = require("./auto_rules/timeline_mod/TimelineModUtils");
|
|||
|
|
const log_1 = require("../../log");
|
|||
|
|
const log = log_1.speechLog.createChild("InputProcessor");
|
|||
|
|
exports.TagAttributes = {
|
|||
|
|
NON_BLOCKING: 'nonBlocking',
|
|||
|
|
END_NEUTRAL: 'endNeutral'
|
|||
|
|
};
|
|||
|
|
class InputProcessor {
|
|||
|
|
constructor(jibo) {
|
|||
|
|
this.swearToTags = {
|
|||
|
|
ALL: `<break size='0.1'/> <pitch band='0.0'> <pitch add="4000"> <duration set="0.5"> e </duration> </pitch> </pitch> <break size='0.1'/>`
|
|||
|
|
};
|
|||
|
|
this._lexer = new Lexer_1.Lexer(jibo);
|
|||
|
|
this.contentValidator = new ContentValidator_1.ContentValidator();
|
|||
|
|
}
|
|||
|
|
generatePreInputTree(sentence, censorSwears = true) {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
if (censorSwears) {
|
|||
|
|
const replaced = this.contentValidator.replaceRestricted(sentence, this.swearToTags.ALL);
|
|||
|
|
if (sentence !== replaced) {
|
|||
|
|
log.warn('Requested TTS contains restricted content! It has been censored.');
|
|||
|
|
}
|
|||
|
|
sentence = replaced;
|
|||
|
|
}
|
|||
|
|
let xmlTree = jibo_node_xml_2.Parser.parseXML(sentence);
|
|||
|
|
xmlTree.forEachDescendant(node => {
|
|||
|
|
node.type = node.type.toUpperCase();
|
|||
|
|
});
|
|||
|
|
xmlTree.forEachDescendantType(Types_1.SSMLNodeType.BREAK, node => {
|
|||
|
|
if (node.parents.length === 1) {
|
|||
|
|
const parent = node.parents[0];
|
|||
|
|
const selfIndex = parent.children.indexOf(node);
|
|||
|
|
const size = node.getNumberAtt('size');
|
|||
|
|
let properSSMLNode = new SSMLNode_1.SSMLNode(Types_1.SSMLNodeType.BREAK);
|
|||
|
|
properSSMLNode.setAttribute('size', size);
|
|||
|
|
parent.children.splice(selfIndex, 1, properSSMLNode);
|
|||
|
|
properSSMLNode.parents.push(parent);
|
|||
|
|
node.clearParents();
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw new Error('Unexpected number of parents to SSML Break Node.');
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
let textNodes = xmlTree.gatherDescendantsType(jibo_node_xml_2.NodeType.TEXT);
|
|||
|
|
xmlTree.expansions = [];
|
|||
|
|
xmlTree.contractions = [];
|
|||
|
|
for (let textNode of textNodes) {
|
|||
|
|
let sanitizedText = NLPTools_1.NLPTools.cleanInput(textNode.value);
|
|||
|
|
let preExpanded = yield this._lexer.lex(sanitizedText);
|
|||
|
|
let newNodes = [];
|
|||
|
|
preExpanded.forEach(token => {
|
|||
|
|
let [localExp, localContr] = NLPTools_1.NLPTools.getExpansionsAndContractions(token);
|
|||
|
|
xmlTree.expansions.push(...localExp);
|
|||
|
|
xmlTree.contractions.push(...localContr);
|
|||
|
|
localExp.forEach(exp => {
|
|||
|
|
let node = new jibo_node_xml_1.default(jibo_node_xml_2.NodeType.TEXT, exp);
|
|||
|
|
newNodes.push(node);
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
textNode.parents.forEach(parent => {
|
|||
|
|
let positionIndex = parent.children.indexOf(textNode);
|
|||
|
|
if (positionIndex === -1) {
|
|||
|
|
throw new Error('Parent node missing reference to child.');
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
parent.children.splice(positionIndex, 1);
|
|||
|
|
for (let newNode of newNodes) {
|
|||
|
|
newNode.parents = textNode.parents.slice();
|
|||
|
|
parent.children.splice(positionIndex, 0, newNode);
|
|||
|
|
positionIndex++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
xmlTree.value = sentence;
|
|||
|
|
xmlTree.treeType = Types_1.ESTreeType.TAG_TREE;
|
|||
|
|
xmlTree.textValue = InputProcessor.getPlainTextFromTree(xmlTree);
|
|||
|
|
return xmlTree;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
insertTimelineAutoRules(xmlTree, timelineAutoRuleData) {
|
|||
|
|
const timefulMatches = timelineAutoRuleData.filter(ruleData => {
|
|||
|
|
return ruleData.type === TimelineModUtils_1.TimelineAutoRuleType.TIMEFUL;
|
|||
|
|
});
|
|||
|
|
const timelessMatches = timelineAutoRuleData.filter(ruleData => {
|
|||
|
|
return ruleData.type === TimelineModUtils_1.TimelineAutoRuleType.TIMELESS;
|
|||
|
|
});
|
|||
|
|
let parentMerged = new Map();
|
|||
|
|
timefulMatches.forEach(ruleData => {
|
|||
|
|
ruleData.matches.forEach((matchInfo, parent) => {
|
|||
|
|
let childrenToInsert = parentMerged.get(parent);
|
|||
|
|
if (!childrenToInsert) {
|
|||
|
|
childrenToInsert = [];
|
|||
|
|
parentMerged.set(parent, childrenToInsert);
|
|||
|
|
}
|
|||
|
|
childrenToInsert.push(...matchInfo);
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
parentMerged.forEach((matchInfo, parent) => {
|
|||
|
|
matchInfo.sort((a, b) => {
|
|||
|
|
return a.offset - b.offset;
|
|||
|
|
});
|
|||
|
|
let insertedNodeCount = 0;
|
|||
|
|
matchInfo.forEach(content => {
|
|||
|
|
content.nodes.forEach(node => {
|
|||
|
|
parent.children.splice((content.offset + insertedNodeCount), 0, node);
|
|||
|
|
insertedNodeCount++;
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
timelessMatches.forEach(ruleData => {
|
|||
|
|
ruleData.matches.forEach((matchInfo, parent) => {
|
|||
|
|
matchInfo.forEach(content => {
|
|||
|
|
let workingChild;
|
|||
|
|
let shouldBeInsertedCount = 0;
|
|||
|
|
while (content.nodes.length > 0) {
|
|||
|
|
const innermost = content.nodes.pop();
|
|||
|
|
if (!workingChild && shouldBeInsertedCount < 1) {
|
|||
|
|
const parentCheck = content.children.every(child => child.parents[0] === parent);
|
|||
|
|
const firstChildIdx = parent.children.indexOf(content.children[0]);
|
|||
|
|
if (parentCheck && (firstChildIdx > -1)) {
|
|||
|
|
parent.children.splice(firstChildIdx, 0, innermost);
|
|||
|
|
content.children.forEach(child => {
|
|||
|
|
child.clearParents();
|
|||
|
|
innermost.addChild(child);
|
|||
|
|
});
|
|||
|
|
innermost.parents.push(parent);
|
|||
|
|
parent.children.splice(firstChildIdx + 1, content.children.length);
|
|||
|
|
workingChild = innermost;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (workingChild && shouldBeInsertedCount > 0) {
|
|||
|
|
const workingChildIdx = parent.children.indexOf(workingChild);
|
|||
|
|
parent.children.splice(workingChildIdx, 0, innermost);
|
|||
|
|
workingChild.clearParents();
|
|||
|
|
innermost.addChild(workingChild);
|
|||
|
|
parent.children.splice(workingChildIdx + 1, 1);
|
|||
|
|
innermost.parents.push(parent);
|
|||
|
|
workingChild = innermost;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
shouldBeInsertedCount++;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
return xmlTree;
|
|||
|
|
}
|
|||
|
|
static generateInputTree(inputTree, nlpTree) {
|
|||
|
|
InputProcessor.replaceTreeTextNodes(nlpTree, inputTree, true);
|
|||
|
|
let assetNodes = inputTree.gatherDescendants(node => {
|
|||
|
|
return InputProcessor.isAsset(node);
|
|||
|
|
});
|
|||
|
|
assetNodes.forEach((assetNode) => {
|
|||
|
|
if (assetNode.metaFilter === undefined) {
|
|||
|
|
let newAssetNode = new AssetNode_1.AssetNode(assetNode.type, assetNode.att);
|
|||
|
|
InputProcessor._createSubTree(newAssetNode, assetNode.children);
|
|||
|
|
for (let parent of assetNode.parents) {
|
|||
|
|
let positionIndex = parent.children.indexOf(assetNode);
|
|||
|
|
if (positionIndex === -1) {
|
|||
|
|
throw new Error('Parent doesn\'t not recognize child.');
|
|||
|
|
}
|
|||
|
|
parent.children.splice(positionIndex, 1, newAssetNode);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
const words = inputTree.gatherDescendantsType(Types_1.NLPNodeType.WORD);
|
|||
|
|
for (let idx = (words.length - 1); idx >= 0; idx--) {
|
|||
|
|
const word = words[idx];
|
|||
|
|
let isContraction = word.getAttribute('contraction');
|
|||
|
|
if (isContraction) {
|
|||
|
|
word.value = isContraction;
|
|||
|
|
}
|
|||
|
|
else if (word.contractionBase) {
|
|||
|
|
for (let parent of word.parents) {
|
|||
|
|
let positionIndex = parent.children.indexOf(word);
|
|||
|
|
if (positionIndex !== -1) {
|
|||
|
|
parent.children.splice(positionIndex, 1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
word.clearParents();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return inputTree;
|
|||
|
|
}
|
|||
|
|
static _createSubTree(root, nodesToAdd) {
|
|||
|
|
nodesToAdd.forEach((node) => {
|
|||
|
|
node.clearParents();
|
|||
|
|
root.addChild(node);
|
|||
|
|
});
|
|||
|
|
return root;
|
|||
|
|
}
|
|||
|
|
static isAsset(node) {
|
|||
|
|
return Types_1.AssetNodeType.hasOwnProperty(node.type);
|
|||
|
|
}
|
|||
|
|
static isEmpty(node) {
|
|||
|
|
return (node.children.length === 0);
|
|||
|
|
}
|
|||
|
|
static isBlocking(node) {
|
|||
|
|
return (InputProcessor.isAsset(node)) &&
|
|||
|
|
((InputProcessor.isEmpty(node)) &&
|
|||
|
|
((node.getAttribute(exports.TagAttributes.NON_BLOCKING) !== 'true') ||
|
|||
|
|
(node.getAttribute(exports.TagAttributes.NON_BLOCKING) === undefined)));
|
|||
|
|
}
|
|||
|
|
static isUnboundedNonBlocking(node) {
|
|||
|
|
return (InputProcessor.isAsset(node)) &&
|
|||
|
|
(InputProcessor.isEmpty(node)) &&
|
|||
|
|
(InputProcessor.isExplicitlyNonBlocking(node));
|
|||
|
|
}
|
|||
|
|
static isExplicitlyNonBlocking(node) {
|
|||
|
|
return (node.getAttribute(exports.TagAttributes.NON_BLOCKING) === 'true');
|
|||
|
|
}
|
|||
|
|
static isSSML(node) {
|
|||
|
|
return InputProcessor.isTimefulSSML(node) ||
|
|||
|
|
InputProcessor.isTimelessSSML(node);
|
|||
|
|
}
|
|||
|
|
static isTimefulSSML(node) {
|
|||
|
|
return InputProcessor.isBreak(node) ||
|
|||
|
|
InputProcessor.isSayAs(node);
|
|||
|
|
}
|
|||
|
|
static isTimelessSSML(node) {
|
|||
|
|
return InputProcessor.isPhoneme(node) ||
|
|||
|
|
InputProcessor.isPitch(node) ||
|
|||
|
|
InputProcessor.isDuration(node) ||
|
|||
|
|
InputProcessor.isStyle(node) ||
|
|||
|
|
InputProcessor.isEngine(node);
|
|||
|
|
}
|
|||
|
|
static isBreak(node) {
|
|||
|
|
return node.type === Types_1.SSMLNodeType.BREAK;
|
|||
|
|
}
|
|||
|
|
static isPhoneme(node) {
|
|||
|
|
return node.type === Types_1.SSMLNodeType.PHONEME;
|
|||
|
|
}
|
|||
|
|
static isPitch(node) {
|
|||
|
|
return node.type === Types_1.SSMLNodeType.PITCH;
|
|||
|
|
}
|
|||
|
|
static isDuration(node) {
|
|||
|
|
return node.type === Types_1.SSMLNodeType.DURATION;
|
|||
|
|
}
|
|||
|
|
static isSayAs(node) {
|
|||
|
|
return node.type === Types_1.SSMLNodeType.SAY_AS;
|
|||
|
|
}
|
|||
|
|
static isStyle(node) {
|
|||
|
|
return node.type === Types_1.SSMLNodeType.STYLE;
|
|||
|
|
}
|
|||
|
|
static isEngine(node) {
|
|||
|
|
return node.type === Types_1.SSMLNodeType.ENGINE;
|
|||
|
|
}
|
|||
|
|
static getPlainTextArrayFromTree(tree) {
|
|||
|
|
const textNodes = tree.gatherDescendantsType(jibo_node_xml_2.NodeType.TEXT);
|
|||
|
|
return textNodes.map(node => node.value);
|
|||
|
|
}
|
|||
|
|
static getPlainTextFromTree(tree) {
|
|||
|
|
const wordArray = InputProcessor.getPlainTextArrayFromTree(tree);
|
|||
|
|
return NLPTools_1.NLPTools.joinWordsIntoSentence(wordArray);
|
|||
|
|
}
|
|||
|
|
static getSSMLTextFromTree(tree) {
|
|||
|
|
let textNodes = tree.gatherDescendants(node => {
|
|||
|
|
return (node.type === jibo_node_xml_2.NodeType.TEXT) || (node.type === Types_1.NLPNodeType.WORD) || (InputProcessor.isSSML(node));
|
|||
|
|
});
|
|||
|
|
return InputProcessor.getSSMLTextFromArray(textNodes);
|
|||
|
|
}
|
|||
|
|
static getSSMLTextFromArray(textNodes, prune = false) {
|
|||
|
|
let stringifiedSSML = [];
|
|||
|
|
for (let idx = 0; idx < textNodes.length; idx++) {
|
|||
|
|
const terminal = InputProcessor._getSSMLTextRecursive(textNodes[idx], stringifiedSSML);
|
|||
|
|
const nextIdx = textNodes.indexOf(terminal);
|
|||
|
|
if (nextIdx < 0) {
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
else if (nextIdx > idx) {
|
|||
|
|
idx = nextIdx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return NLPTools_1.NLPTools.joinWordsIntoSentence(stringifiedSSML);
|
|||
|
|
}
|
|||
|
|
static _getSSMLTextRecursive(node, stringified) {
|
|||
|
|
let terminal;
|
|||
|
|
if (node.children.length) {
|
|||
|
|
let stringifiedRecur = [];
|
|||
|
|
if (!InputProcessor.isAsset(node)) {
|
|||
|
|
stringifiedRecur.push(node.toStringTagOnly());
|
|||
|
|
}
|
|||
|
|
for (let idx = 0; idx < node.children.length; idx++) {
|
|||
|
|
terminal = InputProcessor._getSSMLTextRecursive(node.children[idx], stringifiedRecur);
|
|||
|
|
}
|
|||
|
|
if (!InputProcessor.isAsset(node)) {
|
|||
|
|
stringifiedRecur.push(node.toStringClosingTag());
|
|||
|
|
}
|
|||
|
|
stringified.push(...stringifiedRecur);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
if (InputProcessor.isAsset(node)) {
|
|||
|
|
if (InputProcessor.isBlocking(node) && node.timeSyncNode) {
|
|||
|
|
node = node.timeSyncNode;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
return node;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (node.type === jibo_node_xml_2.NodeType.TEXT || node.type === Types_1.NLPNodeType.WORD) {
|
|||
|
|
stringified.push(node.value);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
stringified.push(node.toStringTagOnly());
|
|||
|
|
}
|
|||
|
|
terminal = node;
|
|||
|
|
}
|
|||
|
|
return terminal;
|
|||
|
|
}
|
|||
|
|
static replaceTreeTextNodes(sourceTree, destinationTree, optMatchWords) {
|
|||
|
|
let srcTxtNodes = sourceTree.gatherDescendants(n => {
|
|||
|
|
return n.type === Types_1.NLPNodeType.WORD || n.type === jibo_node_xml_2.NodeType.TEXT;
|
|||
|
|
});
|
|||
|
|
let destTxtNodes = destinationTree.gatherDescendants(n => {
|
|||
|
|
return n.type === Types_1.NLPNodeType.WORD || n.type === jibo_node_xml_2.NodeType.TEXT;
|
|||
|
|
});
|
|||
|
|
if (optMatchWords) {
|
|||
|
|
let srcValues = srcTxtNodes.map(n => n.value).join(' ');
|
|||
|
|
let destValues = destTxtNodes.map(n => n.value).join(' ');
|
|||
|
|
if (srcValues !== destValues) {
|
|||
|
|
throw new TypeError(`Both trees must have the same words. ` +
|
|||
|
|
`SrcValues: ${srcValues}, DstValues: ${destValues}`);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (srcTxtNodes.length !== destTxtNodes.length) {
|
|||
|
|
throw new TypeError(`Must have same # of nodes in both trees. ` +
|
|||
|
|
`SrcValues: ${srcTxtNodes}, DstValues: ${destTxtNodes}`);
|
|||
|
|
}
|
|||
|
|
destTxtNodes.forEach((destNode, index) => {
|
|||
|
|
for (let parent of destNode.parents) {
|
|||
|
|
let positionIndex = parent.children.indexOf(destNode);
|
|||
|
|
if (positionIndex === -1) {
|
|||
|
|
throw new Error('Parent doesn\'t not recognize child.');
|
|||
|
|
}
|
|||
|
|
parent.children.splice(positionIndex, 1, srcTxtNodes[index]);
|
|||
|
|
let parentIndex = destNode.parents.indexOf(parent);
|
|||
|
|
if (parentIndex === -1) {
|
|||
|
|
throw new Error('Node does not recognize parent');
|
|||
|
|
}
|
|||
|
|
destNode.parents.splice(parentIndex, 1);
|
|||
|
|
srcTxtNodes[index].parents.push(parent);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return destinationTree;
|
|||
|
|
}
|
|||
|
|
static generateWordList(annotationTree, ssml) {
|
|||
|
|
if (ssml) {
|
|||
|
|
annotationTree.forEachDescendant((node) => {
|
|||
|
|
if (InputProcessor.isSSML(node)) {
|
|||
|
|
node.value = node.toString();
|
|||
|
|
node.type = Types_1.NLPNodeType.WORD;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
return annotationTree.gatherDescendants((node) => {
|
|||
|
|
return node.type === Types_1.NLPNodeType.WORD ||
|
|||
|
|
node.type === jibo_node_xml_2.NodeType.TEXT;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.InputProcessor = InputProcessor;
|
|||
|
|
|
|||
|
|
},{"../../log":11,"../common/Types":13,"../utils/NLPTools":62,"./AssetNode":16,"./ContentValidator":17,"./SSMLNode":20,"./auto_rules/timeline_mod/TimelineModUtils":47,"./parsers/Lexer":50,"jibo-node-xml":undefined}],20:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const jibo_node_xml_1 = require("jibo-node-xml");
|
|||
|
|
class SSMLNode extends jibo_node_xml_1.default {
|
|||
|
|
constructor(type) {
|
|||
|
|
super(type);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.SSMLNode = SSMLNode;
|
|||
|
|
|
|||
|
|
},{"jibo-node-xml":undefined}],21:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const jibo_node_xml_1 = require("jibo-node-xml");
|
|||
|
|
class TagTreeNode extends jibo_node_xml_1.default {
|
|||
|
|
constructor(type, value) {
|
|||
|
|
super(type, value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.TagTreeNode = TagTreeNode;
|
|||
|
|
|
|||
|
|
},{"jibo-node-xml":undefined}],22:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const jibo_node_xml_1 = require("jibo-node-xml");
|
|||
|
|
const jibo_node_xml_2 = require("jibo-node-xml");
|
|||
|
|
class AutoRule {
|
|||
|
|
constructor(ruleName, priority, probability = 1) {
|
|||
|
|
this.ruleName = ruleName;
|
|||
|
|
this.priority = priority;
|
|||
|
|
this.probability = probability;
|
|||
|
|
}
|
|||
|
|
_applyInternal(nlpTreeRoot, otherRoots) {
|
|||
|
|
throw new Error('Should be implemented by subclass');
|
|||
|
|
}
|
|||
|
|
_createNode(children, subRule) {
|
|||
|
|
throw new Error('Should be implemented by subclass');
|
|||
|
|
}
|
|||
|
|
applyRule(nlpTreeRoot, otherRoots) {
|
|||
|
|
let wordSequences = this._applyInternal(nlpTreeRoot, otherRoots);
|
|||
|
|
let root = new jibo_node_xml_1.default(jibo_node_xml_2.NodeType.ROOT);
|
|||
|
|
root.setAttribute('autoRule', this.ruleName);
|
|||
|
|
root.setAttribute('priority', this.priority);
|
|||
|
|
wordSequences.forEach(sequence => {
|
|||
|
|
if (Math.random() < this.probability) {
|
|||
|
|
const newNode = this._createNode(sequence);
|
|||
|
|
if (newNode) {
|
|||
|
|
sequence.forEach(wordNode => newNode.addChild(wordNode));
|
|||
|
|
root.addChild(newNode);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return root;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.AutoRule = AutoRule;
|
|||
|
|
|
|||
|
|
},{"jibo-node-xml":undefined}],23:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const path = require("path");
|
|||
|
|
const fs = require("fs");
|
|||
|
|
const QuestionRule_1 = require("./QuestionRule");
|
|||
|
|
const CommaRule_1 = require("./CommaRule");
|
|||
|
|
const InitiateRule_1 = require("./InitiateRule");
|
|||
|
|
const BlinkRule_1 = require("./BlinkRule");
|
|||
|
|
const DoubleBlinkRule_1 = require("./DoubleBlinkRule");
|
|||
|
|
const BeatBlinkRule_1 = require("./BeatBlinkRule");
|
|||
|
|
const HotWordsRule_1 = require("./HotWordsRule");
|
|||
|
|
const OrRule_1 = require("./OrRule");
|
|||
|
|
const ButRule_1 = require("./ButRule");
|
|||
|
|
const NounRule_1 = require("./NounRule");
|
|||
|
|
const ListRule_1 = require("./ListRule");
|
|||
|
|
const InterSentenceTimingRule_1 = require("./timeline_mod/InterSentenceTimingRule");
|
|||
|
|
const IntraSentenceTimingRule_1 = require("./timeline_mod/IntraSentenceTimingRule");
|
|||
|
|
const EllipsisRule_1 = require("./timeline_mod/EllipsisRule");
|
|||
|
|
const EmotionalVoiceRule_1 = require("./timeline_mod/EmotionalVoiceRule");
|
|||
|
|
const log_1 = require("../../../log");
|
|||
|
|
const log = log_1.speechLog.createChild("AutoRuleManager");
|
|||
|
|
exports.AutoRuleNames = {
|
|||
|
|
Exclamation: 'Exclamation',
|
|||
|
|
Question: 'Question',
|
|||
|
|
Blink: 'Blink',
|
|||
|
|
DoubleBlink: 'DoubleBlink',
|
|||
|
|
BeatBlink: 'BeatBlink',
|
|||
|
|
Comma: 'Comma',
|
|||
|
|
Or: 'Or',
|
|||
|
|
But: 'But',
|
|||
|
|
List: 'List',
|
|||
|
|
Noun: 'Noun',
|
|||
|
|
BeatFirstWordPart: 'BeatFirstWordPart',
|
|||
|
|
BeatNewWord: 'BeatNewWord',
|
|||
|
|
Initiate: "Initiate",
|
|||
|
|
Settle: "Settle",
|
|||
|
|
HotWords: 'HotWords',
|
|||
|
|
ThemeRhemeGaze: 'ThemeRhemeGaze'
|
|||
|
|
};
|
|||
|
|
exports.TimelineModifyingRuleNames = {
|
|||
|
|
InterSentenceTiming: 'InterSentenceTiming',
|
|||
|
|
IntraSentenceTiming: 'IntraSentenceTiming',
|
|||
|
|
Ellipsis: 'Ellipsis',
|
|||
|
|
ExclamationVoice: 'ExclamationVoice',
|
|||
|
|
EmotionalVoice: 'EmotionalVoice'
|
|||
|
|
};
|
|||
|
|
class AutoRuleManager {
|
|||
|
|
constructor(_jibo) {
|
|||
|
|
this._jibo = _jibo;
|
|||
|
|
this.hotWordMap = new Map();
|
|||
|
|
this.rejectWordMap = new Map();
|
|||
|
|
this.descendingPhraseLengths = [];
|
|||
|
|
this.rules = [
|
|||
|
|
new QuestionRule_1.QuestionRule(2),
|
|||
|
|
new CommaRule_1.CommaRule(this._jibo, 5),
|
|||
|
|
new BlinkRule_1.BlinkRule(3),
|
|||
|
|
new DoubleBlinkRule_1.DoubleBlinkRule(3),
|
|||
|
|
new BeatBlinkRule_1.BeatBlinkRule(4),
|
|||
|
|
new ListRule_1.ListRule(this._jibo, 10),
|
|||
|
|
new OrRule_1.OrRule(this._jibo, 10),
|
|||
|
|
new ButRule_1.ButRule(this._jibo, 10),
|
|||
|
|
new NounRule_1.NounRule(10),
|
|||
|
|
new HotWordsRule_1.HotWordsRule(0, 1, this.hotWordMap, this.rejectWordMap, this.descendingPhraseLengths),
|
|||
|
|
new InitiateRule_1.InitiateRule(this._jibo, 1),
|
|||
|
|
];
|
|||
|
|
this.timelineModRules = [
|
|||
|
|
new InterSentenceTimingRule_1.InterSentenceTimingRule(1),
|
|||
|
|
new IntraSentenceTimingRule_1.IntraSentenceTimingRule(1),
|
|||
|
|
new EllipsisRule_1.EllipsisRule(1),
|
|||
|
|
new EmotionalVoiceRule_1.EmotionalVoiceRule(this._jibo, 1)
|
|||
|
|
];
|
|||
|
|
const hotWordsDir = this.retreiveHotWordsDir();
|
|||
|
|
if (hotWordsDir) {
|
|||
|
|
const hotWordCategoryFiles = fs.readdirSync(hotWordsDir);
|
|||
|
|
let hotWordCategories = [];
|
|||
|
|
log.debug(`Generating HotWords Match and Reject Maps`);
|
|||
|
|
hotWordCategoryFiles.forEach(hotWordCategoryFile => {
|
|||
|
|
const hotWordCategoryFilePath = path.join(hotWordsDir, hotWordCategoryFile);
|
|||
|
|
if (!fs.statSync(hotWordCategoryFilePath).isDirectory()) {
|
|||
|
|
try {
|
|||
|
|
hotWordCategories.push(JSON.parse(fs.readFileSync(hotWordCategoryFilePath, 'utf8')));
|
|||
|
|
}
|
|||
|
|
catch (err) {
|
|||
|
|
log.warn(`Unable to load/parse HotWord JSON '${hotWordCategoryFile}'; skipping...`, err);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
hotWordCategories.forEach(hotWordMappings => {
|
|||
|
|
hotWordMappings.forEach(([hotWordMatchReject, weightedMatches]) => {
|
|||
|
|
hotWordMatchReject.forEach(matchRejectPair => {
|
|||
|
|
const match = matchRejectPair.match;
|
|||
|
|
const reject = matchRejectPair.reject;
|
|||
|
|
const length = match.trim().split(' ').length;
|
|||
|
|
let subMap = this.hotWordMap.get(length);
|
|||
|
|
if (!subMap) {
|
|||
|
|
subMap = new Map();
|
|||
|
|
this.hotWordMap.set(length, subMap);
|
|||
|
|
this.descendingPhraseLengths.push(length);
|
|||
|
|
}
|
|||
|
|
const keyName = match.toLowerCase();
|
|||
|
|
subMap.set(keyName, weightedMatches);
|
|||
|
|
if (reject.length > 0) {
|
|||
|
|
this.rejectWordMap.set(keyName, reject.map(word => word.toLowerCase()));
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
this.descendingPhraseLengths.sort((a, b) => { return b - a; });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
retreiveHotWordsDir() {
|
|||
|
|
const resolvedPath = this._jibo.animDB.resolveAnimDB(this._jibo);
|
|||
|
|
let hotWordsDir;
|
|||
|
|
if (resolvedPath) {
|
|||
|
|
const rootPath = path.dirname(resolvedPath);
|
|||
|
|
hotWordsDir = path.join(rootPath, 'hot');
|
|||
|
|
if (!fs.existsSync(hotWordsDir)) {
|
|||
|
|
log.warn(`Module 'jibo-anim-db-animations' not found. HotWords will not work.`);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return hotWordsDir;
|
|||
|
|
}
|
|||
|
|
applyRules(nlpTreeRoot, autoRuleConfig) {
|
|||
|
|
let out = [];
|
|||
|
|
this.rules.forEach(rule => {
|
|||
|
|
switch (rule.ruleName) {
|
|||
|
|
case exports.AutoRuleNames.Question:
|
|||
|
|
case exports.AutoRuleNames.Comma:
|
|||
|
|
if (autoRuleConfig.punctuation) {
|
|||
|
|
out.push(rule.applyRule(nlpTreeRoot));
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case exports.AutoRuleNames.Or:
|
|||
|
|
case exports.AutoRuleNames.But:
|
|||
|
|
case exports.AutoRuleNames.List:
|
|||
|
|
case exports.AutoRuleNames.Noun:
|
|||
|
|
if (autoRuleConfig.structure) {
|
|||
|
|
out.push(rule.applyRule(nlpTreeRoot));
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case exports.AutoRuleNames.Initiate:
|
|||
|
|
case exports.AutoRuleNames.Blink:
|
|||
|
|
case exports.AutoRuleNames.DoubleBlink:
|
|||
|
|
case exports.AutoRuleNames.BeatBlink:
|
|||
|
|
if (autoRuleConfig.beat) {
|
|||
|
|
out.push(rule.applyRule(nlpTreeRoot));
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case exports.AutoRuleNames.HotWords:
|
|||
|
|
if (autoRuleConfig.hotWords) {
|
|||
|
|
out.push(rule.applyRule(nlpTreeRoot));
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
log.warn(`Unable to apply AutoRule: ${rule.ruleName}.`);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return out;
|
|||
|
|
}
|
|||
|
|
applyTimelineModifyingRules(xmlTree, autoRuleConfig) {
|
|||
|
|
let out = [];
|
|||
|
|
this.timelineModRules.forEach(rule => {
|
|||
|
|
switch (rule.ruleName) {
|
|||
|
|
case exports.TimelineModifyingRuleNames.InterSentenceTiming:
|
|||
|
|
if (autoRuleConfig.interSentenceTiming) {
|
|||
|
|
out.push(rule.applyRule(xmlTree, autoRuleConfig.punctuation));
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case exports.TimelineModifyingRuleNames.IntraSentenceTiming:
|
|||
|
|
if (autoRuleConfig.intraSentenceTiming) {
|
|||
|
|
out.push(rule.applyRule(xmlTree));
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case exports.TimelineModifyingRuleNames.Ellipsis:
|
|||
|
|
if (autoRuleConfig.interSentenceTiming && autoRuleConfig.punctuation) {
|
|||
|
|
out.push(rule.applyRule(xmlTree));
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case exports.TimelineModifyingRuleNames.EmotionalVoice:
|
|||
|
|
case exports.TimelineModifyingRuleNames.ExclamationVoice:
|
|||
|
|
if (autoRuleConfig.voice) {
|
|||
|
|
out.push(rule.applyRule(xmlTree));
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
log.warn(`Unable to apply AutoRule: ${rule.ruleName}.`);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return out;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.AutoRuleManager = AutoRuleManager;
|
|||
|
|
|
|||
|
|
},{"../../../log":11,"./BeatBlinkRule":25,"./BlinkRule":28,"./ButRule":29,"./CommaRule":30,"./DoubleBlinkRule":31,"./HotWordsRule":33,"./InitiateRule":34,"./ListRule":35,"./NounRule":36,"./OrRule":37,"./QuestionRule":38,"./timeline_mod/EllipsisRule":41,"./timeline_mod/EmotionalVoiceRule":42,"./timeline_mod/InterSentenceTimingRule":44,"./timeline_mod/IntraSentenceTimingRule":45,"fs":undefined,"path":undefined}],24:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const NLPTools_1 = require("../../utils/NLPTools");
|
|||
|
|
exports.AR_SUBRULE = {
|
|||
|
|
PERIOD: '.',
|
|||
|
|
QUESTION: '?',
|
|||
|
|
EXCLAMATION: '!',
|
|||
|
|
COMMA: ',',
|
|||
|
|
ELLIPSIS: '...',
|
|||
|
|
OR: 'or',
|
|||
|
|
BUT: 'but',
|
|||
|
|
BLINK: 'single',
|
|||
|
|
DOUBLE_BLINK: 'double'
|
|||
|
|
};
|
|||
|
|
class AutoRuleUtils {
|
|||
|
|
static getLastWordNodesInSentence(sentenceNode) {
|
|||
|
|
let parts = sentenceNode.gatherChildrenType(Types_1.NLPNodeType.PART);
|
|||
|
|
let lastPart = parts[parts.length - 1];
|
|||
|
|
let out = [];
|
|||
|
|
if (!lastPart.getAttribute('verbCount')) {
|
|||
|
|
out = lastPart.gatherDescendantsType(Types_1.NLPNodeType.WORD);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
let words = lastPart.gatherDescendantsType(Types_1.NLPNodeType.WORD);
|
|||
|
|
words.forEach((word) => {
|
|||
|
|
if (word.wordType === Types_1.WordType.VERB) {
|
|||
|
|
out.push(word);
|
|||
|
|
}
|
|||
|
|
else if (out.length > 0) {
|
|||
|
|
out.push(word);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
return AutoRuleUtils.removeExpandedContractionWords(out);
|
|||
|
|
}
|
|||
|
|
static getWordsFromSentenceSegmentedBy(segmenters, sentenceNode, keepPunct = false) {
|
|||
|
|
let segments = [];
|
|||
|
|
let words = sentenceNode.gatherDescendantsType(Types_1.NLPNodeType.WORD);
|
|||
|
|
words = AutoRuleUtils.removeExpandedContractionWords(words);
|
|||
|
|
let segmenterCount = 0;
|
|||
|
|
segments[segmenterCount] = [];
|
|||
|
|
words.forEach((word) => {
|
|||
|
|
if (segmenters.indexOf(word.value) !== -1) {
|
|||
|
|
if (segments[segmenterCount].length > 0) {
|
|||
|
|
segmenterCount++;
|
|||
|
|
segments[segmenterCount] = [];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (keepPunct || !NLPTools_1.NLPTools.isPunctuation(word.value)) {
|
|||
|
|
segments[segmenterCount].push(word);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return (segmenterCount > 0) ? segments : [];
|
|||
|
|
}
|
|||
|
|
static removeExpandedContractionWords(words) {
|
|||
|
|
for (let idx = 0; idx < words.length; idx++) {
|
|||
|
|
if (words[idx].contractionBase) {
|
|||
|
|
words.splice(idx, 1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return words;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.AutoRuleUtils = AutoRuleUtils;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"../../utils/NLPTools":62}],25:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const AutoRule_1 = require("./AutoRule");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const AutoRuleManager_1 = require("./AutoRuleManager");
|
|||
|
|
const TimelineModUtils_1 = require("./timeline_mod/TimelineModUtils");
|
|||
|
|
const AutoRuleUtils_1 = require("./AutoRuleUtils");
|
|||
|
|
const BEAT_BLINK_PERIOD = 7;
|
|||
|
|
class BeatBlinkRule extends AutoRule_1.AutoRule {
|
|||
|
|
constructor(priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.AutoRuleNames.Blink, priority, probability);
|
|||
|
|
}
|
|||
|
|
_createNode(children) {
|
|||
|
|
let n = TimelineModUtils_1.TimelineModUtils.blinkNodeBuilder(TimelineModUtils_1.BlinkNodeType.SINGLE);
|
|||
|
|
n.setAttribute('nonBlocking', 'true');
|
|||
|
|
n.setAttribute('rule', AutoRuleManager_1.AutoRuleNames.Blink);
|
|||
|
|
n.timeSyncNode = children[0];
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
_applyInternal(nlpTreeRoot, otherRoots) {
|
|||
|
|
let sequences = [];
|
|||
|
|
nlpTreeRoot.forEachChildType(Types_1.NLPNodeType.SENTENCE, sentence => {
|
|||
|
|
const rawWords = sentence.gatherDescendantsType(Types_1.NLPNodeType.WORD);
|
|||
|
|
const words = AutoRuleUtils_1.AutoRuleUtils.removeExpandedContractionWords(rawWords);
|
|||
|
|
if (words.length > 0) {
|
|||
|
|
for (let idx = 0; idx < Math.max(1, words.length - BEAT_BLINK_PERIOD); idx += BEAT_BLINK_PERIOD) {
|
|||
|
|
sequences.push([words[idx]]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return sequences;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.BeatBlinkRule = BeatBlinkRule;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"./AutoRule":22,"./AutoRuleManager":23,"./AutoRuleUtils":24,"./timeline_mod/TimelineModUtils":47}],26:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const AutoRule_1 = require("./AutoRule");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const AssetNode_1 = require("../AssetNode");
|
|||
|
|
const AutoRuleManager_1 = require("./AutoRuleManager");
|
|||
|
|
class BeatFirstWordPartRule extends AutoRule_1.AutoRule {
|
|||
|
|
constructor(priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.AutoRuleNames.BeatFirstWordPart, priority, probability);
|
|||
|
|
}
|
|||
|
|
_createNode() {
|
|||
|
|
let n = new AssetNode_1.AssetNode(Types_1.AssetNodeType.ANIM);
|
|||
|
|
n.setAttribute('cat', 'beat');
|
|||
|
|
n.setAttribute('rule', AutoRuleManager_1.AutoRuleNames.BeatFirstWordPart);
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
_applyInternal(nlpTreeRoot, otherRoots) {
|
|||
|
|
let sequences = [];
|
|||
|
|
nlpTreeRoot.forEachChildType(Types_1.NLPNodeType.SENTENCE, sentence => {
|
|||
|
|
sentence.forEachChildType(Types_1.NLPNodeType.PART, part => {
|
|||
|
|
let firstWord = part.findFirstDescendantType(Types_1.NLPNodeType.WORD);
|
|||
|
|
if (firstWord) {
|
|||
|
|
if (firstWord.contractionBase) {
|
|||
|
|
if (!sequences || sequences.indexOf(firstWord.contractionBase) !== -1) {
|
|||
|
|
sequences.push([firstWord.contractionBase]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
sequences.push([firstWord]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
return sequences;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.BeatFirstWordPartRule = BeatFirstWordPartRule;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"../AssetNode":16,"./AutoRule":22,"./AutoRuleManager":23}],27:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const AutoRule_1 = require("./AutoRule");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const AssetNode_1 = require("../AssetNode");
|
|||
|
|
const AutoRuleManager_1 = require("./AutoRuleManager");
|
|||
|
|
class BeatNewWordRule extends AutoRule_1.AutoRule {
|
|||
|
|
constructor(priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.AutoRuleNames.BeatNewWord, priority, probability);
|
|||
|
|
}
|
|||
|
|
_createNode() {
|
|||
|
|
let n = new AssetNode_1.AssetNode(Types_1.AssetNodeType.ANIM);
|
|||
|
|
n.setAttribute('cat', 'beat');
|
|||
|
|
n.setAttribute('rule', AutoRuleManager_1.AutoRuleNames.BeatNewWord);
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
_applyInternal(nlpTreeRoot, otherRoots) {
|
|||
|
|
let sequences = [];
|
|||
|
|
nlpTreeRoot.forEachDescendantType(Types_1.NLPNodeType.WORD, _word => {
|
|||
|
|
const word = _word;
|
|||
|
|
if (word.getAttribute('new')) {
|
|||
|
|
if (word.contractionBase) {
|
|||
|
|
if (!sequences || sequences.indexOf(word.contractionBase) !== -1) {
|
|||
|
|
sequences.push([word.contractionBase]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
sequences.push([word]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return sequences;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.BeatNewWordRule = BeatNewWordRule;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"../AssetNode":16,"./AutoRule":22,"./AutoRuleManager":23}],28:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const AutoRule_1 = require("./AutoRule");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const AutoRuleManager_1 = require("./AutoRuleManager");
|
|||
|
|
const TimelineModUtils_1 = require("./timeline_mod/TimelineModUtils");
|
|||
|
|
const AutoRuleUtils_1 = require("./AutoRuleUtils");
|
|||
|
|
class BlinkRule extends AutoRule_1.AutoRule {
|
|||
|
|
constructor(priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.AutoRuleNames.Blink, priority, probability);
|
|||
|
|
}
|
|||
|
|
_createNode(children) {
|
|||
|
|
let n = TimelineModUtils_1.TimelineModUtils.blinkNodeBuilder(TimelineModUtils_1.BlinkNodeType.SINGLE);
|
|||
|
|
n.setAttribute('nonBlocking', 'true');
|
|||
|
|
n.setAttribute('position', 'after');
|
|||
|
|
n.setAttribute('rule', AutoRuleManager_1.AutoRuleNames.Blink);
|
|||
|
|
n.timeSyncNode = children[0];
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
_applyInternal(nlpTreeRoot, otherRoots) {
|
|||
|
|
let sequences = [];
|
|||
|
|
nlpTreeRoot.forEachChildType(Types_1.NLPNodeType.SENTENCE, sentence => {
|
|||
|
|
const sentenceType = sentence.getAttribute('sentenceType');
|
|||
|
|
if (sentenceType === Types_1.SentenceType.REGULAR || sentenceType === Types_1.SentenceType.EXCLAMATION) {
|
|||
|
|
let words = sentence.gatherDescendantsType(Types_1.NLPNodeType.WORD);
|
|||
|
|
words = AutoRuleUtils_1.AutoRuleUtils.removeExpandedContractionWords(words);
|
|||
|
|
if (words) {
|
|||
|
|
sequences.push(words.slice(-1));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return sequences;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.BlinkRule = BlinkRule;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"./AutoRule":22,"./AutoRuleManager":23,"./AutoRuleUtils":24,"./timeline_mod/TimelineModUtils":47}],29:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const _ = require("lodash/lodash.min");
|
|||
|
|
const AutoRule_1 = require("./AutoRule");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const AssetNode_1 = require("../AssetNode");
|
|||
|
|
const AutoRuleUtils_1 = require("./AutoRuleUtils");
|
|||
|
|
const AutoRuleManager_1 = require("./AutoRuleManager");
|
|||
|
|
const AR_BUT_SEGMENT_START_KEY = 'ar-but-segment-start';
|
|||
|
|
const AR_BUT_SEGMENT_STOP_KEY = 'ar-but-segment-stop';
|
|||
|
|
exports.BUT_KEYS = [
|
|||
|
|
'But_01',
|
|||
|
|
'But_02'
|
|||
|
|
];
|
|||
|
|
const NUM_WORDS_TO_WRAP = 5;
|
|||
|
|
class ButRule extends AutoRule_1.AutoRule {
|
|||
|
|
constructor(jibo, priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.AutoRuleNames.But, priority, probability);
|
|||
|
|
this.jibo = jibo;
|
|||
|
|
this.Orientation = this.jibo.animDB.Orientation;
|
|||
|
|
this.lastOrientation = (Math.random() > 0.5) ? this.Orientation.LEFT : this.Orientation.RIGHT;
|
|||
|
|
}
|
|||
|
|
_createNode(children) {
|
|||
|
|
const newSegment = children[0].getAttribute(AR_BUT_SEGMENT_START_KEY);
|
|||
|
|
const endSegment = children[0].getAttribute(AR_BUT_SEGMENT_STOP_KEY);
|
|||
|
|
if (newSegment) {
|
|||
|
|
this.currentSegmentAnim = _.sample(exports.BUT_KEYS);
|
|||
|
|
}
|
|||
|
|
this.lastOrientation = this.lastOrientation === this.Orientation.LEFT ? this.Orientation.RIGHT : this.Orientation.LEFT;
|
|||
|
|
let atts = new Map();
|
|||
|
|
let n = new AssetNode_1.AssetNode(Types_1.AssetNodeType.ANIM, atts);
|
|||
|
|
n.setAttribute('name', this.currentSegmentAnim);
|
|||
|
|
n.setAttribute('orientation', this.lastOrientation);
|
|||
|
|
n.setAttribute('rule', AutoRuleManager_1.AutoRuleNames.But);
|
|||
|
|
n.setAttribute('endNeutral', 'false');
|
|||
|
|
if (endSegment) {
|
|||
|
|
n.setAttribute('endNeutral', 'true');
|
|||
|
|
}
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
_applyInternal(nlpTreeRoot, otherRoots) {
|
|||
|
|
let sequences = [];
|
|||
|
|
nlpTreeRoot.forEachChildType(Types_1.NLPNodeType.SENTENCE, (sentence) => {
|
|||
|
|
let wordSegments = AutoRuleUtils_1.AutoRuleUtils.getWordsFromSentenceSegmentedBy(['but'], sentence);
|
|||
|
|
if (wordSegments.length > 0) {
|
|||
|
|
let segmentIdx = 0;
|
|||
|
|
let endSegment;
|
|||
|
|
wordSegments.forEach(wordSegment => {
|
|||
|
|
let choppedWordSegment;
|
|||
|
|
if (wordSegment.length > 0) {
|
|||
|
|
if (segmentIdx === 0) {
|
|||
|
|
choppedWordSegment = wordSegment.slice(-NUM_WORDS_TO_WRAP);
|
|||
|
|
choppedWordSegment[0].setAttribute(AR_BUT_SEGMENT_START_KEY, true);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
choppedWordSegment = wordSegment.slice(0, NUM_WORDS_TO_WRAP);
|
|||
|
|
endSegment = choppedWordSegment;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
sequences.push(choppedWordSegment);
|
|||
|
|
segmentIdx++;
|
|||
|
|
});
|
|||
|
|
if (endSegment) {
|
|||
|
|
endSegment[0].setAttribute(AR_BUT_SEGMENT_STOP_KEY, true);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return sequences;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.ButRule = ButRule;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"../AssetNode":16,"./AutoRule":22,"./AutoRuleManager":23,"./AutoRuleUtils":24,"lodash/lodash.min":undefined}],30:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const AutoRule_1 = require("./AutoRule");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const AssetNode_1 = require("../AssetNode");
|
|||
|
|
const AutoRuleUtils_1 = require("./AutoRuleUtils");
|
|||
|
|
const AutoRuleManager_1 = require("./AutoRuleManager");
|
|||
|
|
class CommaRule extends AutoRule_1.AutoRule {
|
|||
|
|
constructor(jibo, priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.AutoRuleNames.Comma, priority, probability);
|
|||
|
|
this.jibo = jibo;
|
|||
|
|
this.Orientation = this.jibo.animDB.Orientation;
|
|||
|
|
this.lastOrientation = (Math.random() > 0.5) ? this.Orientation.LEFT : this.Orientation.RIGHT;
|
|||
|
|
}
|
|||
|
|
_createNode(children) {
|
|||
|
|
this.lastOrientation = this.lastOrientation === this.Orientation.LEFT ? this.Orientation.RIGHT : this.Orientation.LEFT;
|
|||
|
|
let atts = new Map();
|
|||
|
|
atts.set('layers', 'body');
|
|||
|
|
atts.set('cat', 'comma');
|
|||
|
|
let n = new AssetNode_1.AssetNode(Types_1.AssetNodeType.ANIM, atts);
|
|||
|
|
n.setAttribute('orientation', this.lastOrientation);
|
|||
|
|
n.setAttribute('rule', AutoRuleManager_1.AutoRuleNames.Comma);
|
|||
|
|
n.setAttribute('endNeutral', 'false');
|
|||
|
|
if (children.length < 3) {
|
|||
|
|
n.setAttribute('nonBlocking', 'true');
|
|||
|
|
n.timeSyncNode = children[0];
|
|||
|
|
}
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
_applyInternal(nlpTreeRoot, otherRoots) {
|
|||
|
|
let sequences = [];
|
|||
|
|
nlpTreeRoot.forEachChildType(Types_1.NLPNodeType.SENTENCE, (sentence) => {
|
|||
|
|
const wordSegments = AutoRuleUtils_1.AutoRuleUtils.getWordsFromSentenceSegmentedBy([','], sentence);
|
|||
|
|
if (wordSegments.length < 3) {
|
|||
|
|
const leftSegments = wordSegments.slice(0, -1);
|
|||
|
|
sequences.push(...leftSegments);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return sequences;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.CommaRule = CommaRule;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"../AssetNode":16,"./AutoRule":22,"./AutoRuleManager":23,"./AutoRuleUtils":24}],31:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const AutoRule_1 = require("./AutoRule");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const AutoRuleManager_1 = require("./AutoRuleManager");
|
|||
|
|
const TimelineModUtils_1 = require("./timeline_mod/TimelineModUtils");
|
|||
|
|
const AutoRuleUtils_1 = require("./AutoRuleUtils");
|
|||
|
|
class DoubleBlinkRule extends AutoRule_1.AutoRule {
|
|||
|
|
constructor(priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.AutoRuleNames.DoubleBlink, priority, probability);
|
|||
|
|
}
|
|||
|
|
_createNode(children) {
|
|||
|
|
let n = TimelineModUtils_1.TimelineModUtils.blinkNodeBuilder(TimelineModUtils_1.BlinkNodeType.DOUBLE);
|
|||
|
|
n.setAttribute('nonBlocking', 'true');
|
|||
|
|
n.setAttribute('position', 'after');
|
|||
|
|
n.setAttribute('rule', AutoRuleManager_1.AutoRuleNames.DoubleBlink);
|
|||
|
|
n.timeSyncNode = children[0];
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
_applyInternal(nlpTreeRoot, otherRoots) {
|
|||
|
|
let sequences = [];
|
|||
|
|
nlpTreeRoot.forEachChildType(Types_1.NLPNodeType.SENTENCE, sentence => {
|
|||
|
|
const sentenceType = sentence.getAttribute('sentenceType');
|
|||
|
|
if (sentenceType === Types_1.SentenceType.QUESTION) {
|
|||
|
|
let words = sentence.gatherDescendantsType(Types_1.NLPNodeType.WORD);
|
|||
|
|
words = AutoRuleUtils_1.AutoRuleUtils.removeExpandedContractionWords(words);
|
|||
|
|
if (words) {
|
|||
|
|
sequences.push(words.slice(-1));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return sequences;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.DoubleBlinkRule = DoubleBlinkRule;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"./AutoRule":22,"./AutoRuleManager":23,"./AutoRuleUtils":24,"./timeline_mod/TimelineModUtils":47}],32:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const AutoRule_1 = require("./AutoRule");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const AssetNode_1 = require("../AssetNode");
|
|||
|
|
const AutoRuleUtils_1 = require("./AutoRuleUtils");
|
|||
|
|
const AutoRuleManager_1 = require("./AutoRuleManager");
|
|||
|
|
class ExclamationRule extends AutoRule_1.AutoRule {
|
|||
|
|
constructor(priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.AutoRuleNames.Exclamation, priority, probability);
|
|||
|
|
}
|
|||
|
|
_createNode(children) {
|
|||
|
|
let atts = new Map();
|
|||
|
|
atts.set('filter', '!exclamation-mark');
|
|||
|
|
let n = new AssetNode_1.AssetNode(Types_1.AssetNodeType.ANIM, atts);
|
|||
|
|
n.setAttribute('cat', 'exclamation');
|
|||
|
|
n.setAttribute('rule', AutoRuleManager_1.AutoRuleNames.Exclamation);
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
_applyInternal(nlpTreeRoot, otherRoots) {
|
|||
|
|
let sequences = [];
|
|||
|
|
nlpTreeRoot.forEachChildType(Types_1.NLPNodeType.SENTENCE, (sentence) => {
|
|||
|
|
if (sentence.sentenceType === Types_1.SentenceType.EXCLAMATION) {
|
|||
|
|
let chosenWords = AutoRuleUtils_1.AutoRuleUtils.getLastWordNodesInSentence(sentence);
|
|||
|
|
sequences.push(chosenWords);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return sequences;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.ExclamationRule = ExclamationRule;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"../AssetNode":16,"./AutoRule":22,"./AutoRuleManager":23,"./AutoRuleUtils":24}],33:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const _ = require("lodash/lodash.min");
|
|||
|
|
const jibo_cai_utils_1 = require("jibo-cai-utils");
|
|||
|
|
const AutoRule_1 = require("./AutoRule");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const AssetNode_1 = require("../AssetNode");
|
|||
|
|
const AutoRuleManager_1 = require("./AutoRuleManager");
|
|||
|
|
const AutoRuleUtils_1 = require("./AutoRuleUtils");
|
|||
|
|
const REJECT_FUZZY_SIZE = 2;
|
|||
|
|
class HotWordsRule extends AutoRule_1.AutoRule {
|
|||
|
|
constructor(priority = 1, probability = 1, hotWordMap, rejectWordMap, descendingPhraseLengths) {
|
|||
|
|
super(AutoRuleManager_1.AutoRuleNames.HotWords, priority, probability);
|
|||
|
|
this.hotWordMap = hotWordMap;
|
|||
|
|
this.rejectWordMap = rejectWordMap;
|
|||
|
|
this.descendingPhraseLengths = descendingPhraseLengths;
|
|||
|
|
}
|
|||
|
|
_createNode(children) {
|
|||
|
|
const words = children.map(word => {
|
|||
|
|
const contractedForm = word.getAttribute("contraction");
|
|||
|
|
if (contractedForm) {
|
|||
|
|
return contractedForm;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
return word.value;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
const wordStr = words.join(' ').toLowerCase();
|
|||
|
|
const match = this.hotWordMap.get(words.length).get(wordStr);
|
|||
|
|
if (!match) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
const hotWordAsset = jibo_cai_utils_1.RandomUtils.weightedRandomSample(match);
|
|||
|
|
let atts = new Map();
|
|||
|
|
const mappedAsset = new Map();
|
|||
|
|
Object.keys(hotWordAsset).forEach(asset => {
|
|||
|
|
mappedAsset.set(asset, hotWordAsset[asset]);
|
|||
|
|
});
|
|||
|
|
mappedAsset.forEach((val, key) => {
|
|||
|
|
atts.set(key, val);
|
|||
|
|
});
|
|||
|
|
let n = new AssetNode_1.AssetNode(Types_1.AssetNodeType.ANIM, atts);
|
|||
|
|
n.setAttribute('rule', AutoRuleManager_1.AutoRuleNames.HotWords);
|
|||
|
|
const isBounded = n.getAttribute('bounded');
|
|||
|
|
if (!isBounded) {
|
|||
|
|
n.setAttribute('nonBlocking', 'true');
|
|||
|
|
n.timeSyncNode = children[0];
|
|||
|
|
}
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
_applyInternal(nlpTreeRoot) {
|
|||
|
|
let sequences = [];
|
|||
|
|
if (this.descendingPhraseLengths.length === 0) {
|
|||
|
|
return sequences;
|
|||
|
|
}
|
|||
|
|
const wordNodes = nlpTreeRoot.gatherDescendantsType(Types_1.NLPNodeType.WORD);
|
|||
|
|
const noExpansions = AutoRuleUtils_1.AutoRuleUtils.removeExpandedContractionWords(wordNodes);
|
|||
|
|
noExpansions.forEach(wordNode => {
|
|||
|
|
wordNode.setAttribute('phraseLengthMember', 0);
|
|||
|
|
});
|
|||
|
|
const nodesAndWords = noExpansions.map((word) => {
|
|||
|
|
let pair = [];
|
|||
|
|
pair.push(word);
|
|||
|
|
const contractedForm = word.getAttribute("contraction");
|
|||
|
|
const value = contractedForm || word.value;
|
|||
|
|
pair.push(value.toLowerCase());
|
|||
|
|
return pair;
|
|||
|
|
});
|
|||
|
|
this.descendingPhraseLengths.forEach(phraseLength => {
|
|||
|
|
if (nodesAndWords.length >= phraseLength) {
|
|||
|
|
const hotWordMap = this.hotWordMap.get(phraseLength);
|
|||
|
|
for (let idx = 0; idx <= (nodesAndWords.length - phraseLength); idx++) {
|
|||
|
|
let slidingWindowMemberCheck = false;
|
|||
|
|
for (let walker = 0; walker < phraseLength; walker++) {
|
|||
|
|
if (nodesAndWords[idx + walker][0].getAttribute('phraseLengthMember') <= phraseLength) {
|
|||
|
|
slidingWindowMemberCheck = true;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (slidingWindowMemberCheck) {
|
|||
|
|
let slidingWindowNodes = [];
|
|||
|
|
let slidingWindowWords = [];
|
|||
|
|
for (let walker = 0; walker < phraseLength; walker++) {
|
|||
|
|
slidingWindowNodes.push(nodesAndWords[idx + walker][0]);
|
|||
|
|
slidingWindowWords.push(nodesAndWords[idx + walker][1]);
|
|||
|
|
}
|
|||
|
|
const slidingWindowStr = slidingWindowWords.join(' ');
|
|||
|
|
if (hotWordMap.get(slidingWindowStr)) {
|
|||
|
|
const rejectList = this.rejectWordMap.get(slidingWindowStr);
|
|||
|
|
let shouldReject = false;
|
|||
|
|
if (rejectList) {
|
|||
|
|
const rejectMin = Math.round(idx - REJECT_FUZZY_SIZE);
|
|||
|
|
const rejectMax = Math.round(idx + (phraseLength - 1) + REJECT_FUZZY_SIZE);
|
|||
|
|
const rejectWalkStart = Math.max(0, rejectMin);
|
|||
|
|
const rejectWalkStop = Math.min(nodesAndWords.length - 1, rejectMax);
|
|||
|
|
for (let walker = rejectWalkStart; walker <= rejectWalkStop; walker++) {
|
|||
|
|
for (let rejWalker = 0; rejWalker < rejectList.length; rejWalker++) {
|
|||
|
|
if (nodesAndWords[walker][1] === rejectList[rejWalker]) {
|
|||
|
|
shouldReject = true;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (!shouldReject) {
|
|||
|
|
slidingWindowNodes.forEach(node => {
|
|||
|
|
node.setAttribute('phraseLengthMember', phraseLength);
|
|||
|
|
});
|
|||
|
|
sequences.push(slidingWindowNodes);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return _.shuffle(sequences);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.HotWordsRule = HotWordsRule;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"../AssetNode":16,"./AutoRule":22,"./AutoRuleManager":23,"./AutoRuleUtils":24,"jibo-cai-utils":undefined,"lodash/lodash.min":undefined}],34:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const AutoRule_1 = require("./AutoRule");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const AssetNode_1 = require("../AssetNode");
|
|||
|
|
const AutoRuleUtils_1 = require("./AutoRuleUtils");
|
|||
|
|
const AutoRuleManager_1 = require("./AutoRuleManager");
|
|||
|
|
class InitiateRule extends AutoRule_1.AutoRule {
|
|||
|
|
constructor(jibo, priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.AutoRuleNames.Initiate, priority, probability);
|
|||
|
|
this.jibo = jibo;
|
|||
|
|
this.Orientation = this.jibo.animDB.Orientation;
|
|||
|
|
this.lastOrientation = (Math.random() > 0.5) ? this.Orientation.LEFT : this.Orientation.RIGHT;
|
|||
|
|
}
|
|||
|
|
_createNode(children) {
|
|||
|
|
this.lastOrientation = this.lastOrientation === this.Orientation.LEFT ? this.Orientation.RIGHT : this.Orientation.LEFT;
|
|||
|
|
let atts = new Map();
|
|||
|
|
atts.set('layers', 'body');
|
|||
|
|
atts.set('filter', 'initiation');
|
|||
|
|
atts.set('cat', 'poses');
|
|||
|
|
let n = new AssetNode_1.AssetNode(Types_1.AssetNodeType.ANIM, atts);
|
|||
|
|
n.setAttribute('rule', AutoRuleManager_1.AutoRuleNames.Initiate);
|
|||
|
|
n.setAttribute('orientation', this.lastOrientation);
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
_applyInternal(nlpTreeRoot, otherRoots) {
|
|||
|
|
let sequences = [];
|
|||
|
|
nlpTreeRoot.forEachChildType(Types_1.NLPNodeType.SENTENCE, sentence => {
|
|||
|
|
const wordNodes = sentence.gatherDescendantsType(Types_1.NLPNodeType.WORD);
|
|||
|
|
const noExpansions = AutoRuleUtils_1.AutoRuleUtils.removeExpandedContractionWords(wordNodes);
|
|||
|
|
let firstWords = [];
|
|||
|
|
for (let idx = 0; idx < Math.min(3, noExpansions.length); idx++) {
|
|||
|
|
firstWords.push(noExpansions[idx]);
|
|||
|
|
}
|
|||
|
|
if (firstWords.length > 0) {
|
|||
|
|
sequences.push(firstWords);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return sequences;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.InitiateRule = InitiateRule;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"../AssetNode":16,"./AutoRule":22,"./AutoRuleManager":23,"./AutoRuleUtils":24}],35:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const _ = require("lodash/lodash.min");
|
|||
|
|
const AutoRule_1 = require("./AutoRule");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const AssetNode_1 = require("../AssetNode");
|
|||
|
|
const AutoRuleUtils_1 = require("./AutoRuleUtils");
|
|||
|
|
const AutoRuleManager_1 = require("./AutoRuleManager");
|
|||
|
|
const AR_LIST_SUB_RULE_KEY = 'ar-list-subrule';
|
|||
|
|
const AR_LIST_SUB_RULE_PART_KEY = 'ar-list-subrule-part';
|
|||
|
|
exports.LIST_RULE_TYPES = {
|
|||
|
|
SUB_RULE_1: 'list-rule-sr1',
|
|||
|
|
SUB_RULE_2: 'list-rule-sr2'
|
|||
|
|
};
|
|||
|
|
class ListRule extends AutoRule_1.AutoRule {
|
|||
|
|
constructor(jibo, priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.AutoRuleNames.List, priority, probability);
|
|||
|
|
this.jibo = jibo;
|
|||
|
|
this.Orientation = this.jibo.animDB.Orientation;
|
|||
|
|
}
|
|||
|
|
_createNode(children) {
|
|||
|
|
const segmentSubRule = children[0].getAttribute(AR_LIST_SUB_RULE_KEY);
|
|||
|
|
const segmentSubRulePart = children[0].getAttribute(AR_LIST_SUB_RULE_PART_KEY);
|
|||
|
|
this.lastOrientation = (Math.random() > 0.5) ? this.Orientation.LEFT : this.Orientation.RIGHT;
|
|||
|
|
let atts = new Map();
|
|||
|
|
if (segmentSubRulePart) {
|
|||
|
|
atts.set('filter', segmentSubRulePart);
|
|||
|
|
}
|
|||
|
|
let n = new AssetNode_1.AssetNode(Types_1.AssetNodeType.ANIM, atts);
|
|||
|
|
n.setAttribute('cat', segmentSubRule);
|
|||
|
|
n.setAttribute('orientation', this.lastOrientation);
|
|||
|
|
n.setAttribute('rule', AutoRuleManager_1.AutoRuleNames.List);
|
|||
|
|
if (segmentSubRule === exports.LIST_RULE_TYPES.SUB_RULE_2 && segmentSubRulePart === 'a') {
|
|||
|
|
n.setAttribute('endNeutral', 'false');
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
n.setAttribute('endNeutral', `true`);
|
|||
|
|
}
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
_applyInternal(nlpTreeRoot, otherRoots) {
|
|||
|
|
let sequences = [];
|
|||
|
|
nlpTreeRoot.forEachChildType(Types_1.NLPNodeType.SENTENCE, (sentence) => {
|
|||
|
|
const wordSegments = AutoRuleUtils_1.AutoRuleUtils.getWordsFromSentenceSegmentedBy([',', 'and'], sentence);
|
|||
|
|
if (wordSegments.length >= 3) {
|
|||
|
|
let possibleListSegments = [];
|
|||
|
|
let segmentCount = 0;
|
|||
|
|
wordSegments.forEach(segment => {
|
|||
|
|
if (segmentCount === 0) {
|
|||
|
|
let verbIdx = -1;
|
|||
|
|
for (let idx = 0; idx < segment.length; idx++) {
|
|||
|
|
if (segment[idx].wordType === Types_1.WordType.VERB) {
|
|||
|
|
verbIdx = idx;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
let slicedSegment;
|
|||
|
|
if (verbIdx !== -1) {
|
|||
|
|
slicedSegment = segment.slice(verbIdx + 1);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
slicedSegment = segment.slice(-3);
|
|||
|
|
}
|
|||
|
|
if (slicedSegment.length > 0) {
|
|||
|
|
possibleListSegments.push(slicedSegment);
|
|||
|
|
segmentCount++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (segment.length <= 3) {
|
|||
|
|
segmentCount++;
|
|||
|
|
possibleListSegments.push(segment);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
if (segmentCount < 3) {
|
|||
|
|
possibleListSegments = [];
|
|||
|
|
segmentCount = 0;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
sequences.push(...this._addListSubRuleInfo(possibleListSegments));
|
|||
|
|
possibleListSegments = [];
|
|||
|
|
segmentCount = 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
if (possibleListSegments && possibleListSegments.length >= 3) {
|
|||
|
|
sequences.push(...this._addListSubRuleInfo(possibleListSegments));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return sequences;
|
|||
|
|
}
|
|||
|
|
_addListSubRuleInfo(listSegments) {
|
|||
|
|
const choice = _.sample(_.values(exports.LIST_RULE_TYPES));
|
|||
|
|
let mergedSegments = [];
|
|||
|
|
if (choice === exports.LIST_RULE_TYPES.SUB_RULE_1) {
|
|||
|
|
let mergingList = [];
|
|||
|
|
for (let idx = 0; idx < listSegments.length - 1; idx++) {
|
|||
|
|
if ((idx === 0) && (listSegments[idx].length > 0)) {
|
|||
|
|
listSegments[idx][0].setAttribute(AR_LIST_SUB_RULE_KEY, choice);
|
|||
|
|
}
|
|||
|
|
mergingList.push(...listSegments[idx]);
|
|||
|
|
}
|
|||
|
|
mergedSegments.push(mergingList);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
let mergingList = [];
|
|||
|
|
for (let idx = 0; idx < listSegments.length; idx++) {
|
|||
|
|
if (idx === 0) {
|
|||
|
|
if (listSegments[idx].length > 0) {
|
|||
|
|
listSegments[idx][0].setAttribute(AR_LIST_SUB_RULE_KEY, choice);
|
|||
|
|
listSegments[idx][0].setAttribute(AR_LIST_SUB_RULE_PART_KEY, 'a');
|
|||
|
|
}
|
|||
|
|
mergingList.push(...listSegments[idx]);
|
|||
|
|
}
|
|||
|
|
else if (idx === listSegments.length - 1) {
|
|||
|
|
mergedSegments.push(mergingList);
|
|||
|
|
mergingList = [];
|
|||
|
|
if (listSegments[idx].length > 0) {
|
|||
|
|
listSegments[idx][0].setAttribute(AR_LIST_SUB_RULE_KEY, choice);
|
|||
|
|
listSegments[idx][0].setAttribute(AR_LIST_SUB_RULE_PART_KEY, 'b');
|
|||
|
|
}
|
|||
|
|
mergingList.push(...listSegments[idx]);
|
|||
|
|
mergedSegments.push(mergingList);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
mergingList.push(...listSegments[idx]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return mergedSegments;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.ListRule = ListRule;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"../AssetNode":16,"./AutoRule":22,"./AutoRuleManager":23,"./AutoRuleUtils":24,"lodash/lodash.min":undefined}],36:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const AutoRule_1 = require("./AutoRule");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const AssetNode_1 = require("../AssetNode");
|
|||
|
|
const AutoRuleManager_1 = require("./AutoRuleManager");
|
|||
|
|
const NLPTools_1 = require("../../utils/NLPTools");
|
|||
|
|
exports.AR_EXEMPT_NOUNS = new Set(['i', 'you', 'we', 'me']);
|
|||
|
|
class NounRule extends AutoRule_1.AutoRule {
|
|||
|
|
constructor(priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.AutoRuleNames.Noun, priority, probability);
|
|||
|
|
}
|
|||
|
|
_createNode(children) {
|
|||
|
|
let atts = new Map();
|
|||
|
|
atts.set('filter', '!down');
|
|||
|
|
let n = new AssetNode_1.AssetNode(Types_1.AssetNodeType.ANIM, atts);
|
|||
|
|
n.setAttribute('nonBlocking', 'true');
|
|||
|
|
n.setAttribute('cat', 'glances');
|
|||
|
|
n.setAttribute('rule', AutoRuleManager_1.AutoRuleNames.Noun);
|
|||
|
|
n.timeSyncNode = children[0];
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
_applyInternal(nlpTreeRoot, otherRoots) {
|
|||
|
|
let sequences = [];
|
|||
|
|
let nounCount = 0;
|
|||
|
|
const wordAndPunctNodes = nlpTreeRoot.gatherDescendantsType(Types_1.NLPNodeType.WORD);
|
|||
|
|
const wordNodes = wordAndPunctNodes.filter(word => !NLPTools_1.NLPTools.isPunctuation(word.value));
|
|||
|
|
wordNodes.forEach(word => {
|
|||
|
|
if (!word.contractionBase && (word.wordType === Types_1.WordType.NOUN) && !exports.AR_EXEMPT_NOUNS.has(word.value.toLowerCase())) {
|
|||
|
|
sequences.push([word]);
|
|||
|
|
nounCount++;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return sequences;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.NounRule = NounRule;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"../../utils/NLPTools":62,"../AssetNode":16,"./AutoRule":22,"./AutoRuleManager":23}],37:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const _ = require("lodash/lodash.min");
|
|||
|
|
const AutoRule_1 = require("./AutoRule");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const AssetNode_1 = require("../AssetNode");
|
|||
|
|
const AutoRuleUtils_1 = require("./AutoRuleUtils");
|
|||
|
|
const AutoRuleManager_1 = require("./AutoRuleManager");
|
|||
|
|
const AR_OR_SEGMENT_START_KEY = 'ar-or-segment-start';
|
|||
|
|
const AR_OR_SEGMENT_STOP_KEY = 'ar-or-segment-stop';
|
|||
|
|
exports.OR_KEYS = [
|
|||
|
|
'Or_01',
|
|||
|
|
'Or_02',
|
|||
|
|
'Or_03'
|
|||
|
|
];
|
|||
|
|
const NUM_WORDS_TO_WRAP = 5;
|
|||
|
|
class OrRule extends AutoRule_1.AutoRule {
|
|||
|
|
constructor(jibo, priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.AutoRuleNames.Or, priority, probability);
|
|||
|
|
this.jibo = jibo;
|
|||
|
|
this.Orientation = this.jibo.animDB.Orientation;
|
|||
|
|
this.lastOrientation = (Math.random() > 0.5) ? this.Orientation.LEFT : this.Orientation.RIGHT;
|
|||
|
|
}
|
|||
|
|
_createNode(children) {
|
|||
|
|
const newSegment = children[0].getAttribute(AR_OR_SEGMENT_START_KEY);
|
|||
|
|
const endSegment = children[0].getAttribute(AR_OR_SEGMENT_STOP_KEY);
|
|||
|
|
if (newSegment) {
|
|||
|
|
this.currentSegmentAnim = _.sample(exports.OR_KEYS);
|
|||
|
|
}
|
|||
|
|
this.lastOrientation = this.lastOrientation === this.Orientation.LEFT ? this.Orientation.RIGHT : this.Orientation.LEFT;
|
|||
|
|
let atts = new Map();
|
|||
|
|
let n = new AssetNode_1.AssetNode(Types_1.AssetNodeType.ANIM, atts);
|
|||
|
|
n.setAttribute('name', this.currentSegmentAnim);
|
|||
|
|
n.setAttribute('orientation', this.lastOrientation);
|
|||
|
|
n.setAttribute('rule', AutoRuleManager_1.AutoRuleNames.Or);
|
|||
|
|
n.setAttribute('endNeutral', 'false');
|
|||
|
|
if (endSegment) {
|
|||
|
|
n.setAttribute('endNeutral', 'true');
|
|||
|
|
}
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
_applyInternal(nlpTreeRoot, otherRoots) {
|
|||
|
|
let sequences = [];
|
|||
|
|
nlpTreeRoot.forEachChildType(Types_1.NLPNodeType.SENTENCE, (sentence) => {
|
|||
|
|
let wordSegments = AutoRuleUtils_1.AutoRuleUtils.getWordsFromSentenceSegmentedBy(['or'], sentence, true);
|
|||
|
|
if (wordSegments.length > 0) {
|
|||
|
|
const zippedWordSegments = wordSegments.map(arr => [arr, arr.map(wordNode => wordNode.value)]);
|
|||
|
|
let segmentIdx = 0;
|
|||
|
|
let endSegment;
|
|||
|
|
zippedWordSegments.forEach(nodesAndStrings => {
|
|||
|
|
const [nodes, strings] = nodesAndStrings;
|
|||
|
|
let choppedWordSegment;
|
|||
|
|
if (segmentIdx === 0) {
|
|||
|
|
let commaIndex = strings.lastIndexOf(',');
|
|||
|
|
if (commaIndex !== -1) {
|
|||
|
|
nodes.splice(0, nodes.length - commaIndex - 1);
|
|||
|
|
}
|
|||
|
|
choppedWordSegment = nodes.slice(-NUM_WORDS_TO_WRAP);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
let commaIndex = strings.indexOf(',');
|
|||
|
|
if (commaIndex !== -1) {
|
|||
|
|
nodes.splice(commaIndex, nodes.length - commaIndex);
|
|||
|
|
}
|
|||
|
|
choppedWordSegment = nodes.slice(0, NUM_WORDS_TO_WRAP);
|
|||
|
|
}
|
|||
|
|
if (choppedWordSegment.length > 0) {
|
|||
|
|
if (segmentIdx === 0) {
|
|||
|
|
choppedWordSegment[0].setAttribute(AR_OR_SEGMENT_START_KEY, true);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
endSegment = choppedWordSegment;
|
|||
|
|
}
|
|||
|
|
sequences.push(choppedWordSegment);
|
|||
|
|
}
|
|||
|
|
segmentIdx++;
|
|||
|
|
});
|
|||
|
|
if (endSegment) {
|
|||
|
|
endSegment[0].setAttribute(AR_OR_SEGMENT_STOP_KEY, true);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return sequences;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.OrRule = OrRule;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"../AssetNode":16,"./AutoRule":22,"./AutoRuleManager":23,"./AutoRuleUtils":24,"lodash/lodash.min":undefined}],38:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const AutoRule_1 = require("./AutoRule");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const AssetNode_1 = require("../AssetNode");
|
|||
|
|
const AutoRuleUtils_1 = require("./AutoRuleUtils");
|
|||
|
|
const AutoRuleManager_1 = require("./AutoRuleManager");
|
|||
|
|
class QuestionRule extends AutoRule_1.AutoRule {
|
|||
|
|
constructor(priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.AutoRuleNames.Question, priority, probability);
|
|||
|
|
}
|
|||
|
|
_createNode(children) {
|
|||
|
|
let atts = new Map();
|
|||
|
|
atts.set('layers', 'body');
|
|||
|
|
atts.set('filter', '!eye-only');
|
|||
|
|
let n = new AssetNode_1.AssetNode(Types_1.AssetNodeType.ANIM, atts);
|
|||
|
|
n.setAttribute('cat', 'question');
|
|||
|
|
n.setAttribute('rule', AutoRuleManager_1.AutoRuleNames.Question);
|
|||
|
|
n.setAttribute('endNeutral', 'false');
|
|||
|
|
if (children.length <= 3) {
|
|||
|
|
n.setAttribute('nonBlocking', 'true');
|
|||
|
|
n.timeSyncNode = children[0];
|
|||
|
|
}
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
_applyInternal(nlpTreeRoot, otherRoots) {
|
|||
|
|
let sequences = [];
|
|||
|
|
nlpTreeRoot.forEachChildType(Types_1.NLPNodeType.SENTENCE, (sentence) => {
|
|||
|
|
if (sentence.sentenceType === Types_1.SentenceType.QUESTION) {
|
|||
|
|
let chosenWords = AutoRuleUtils_1.AutoRuleUtils.getLastWordNodesInSentence(sentence);
|
|||
|
|
sequences.push(chosenWords);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return sequences;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.QuestionRule = QuestionRule;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"../AssetNode":16,"./AutoRule":22,"./AutoRuleManager":23,"./AutoRuleUtils":24}],39:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const AutoRule_1 = require("./AutoRule");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const ThemeRhemeParser_1 = require("../parsers/ThemeRhemeParser");
|
|||
|
|
const AssetNode_1 = require("../AssetNode");
|
|||
|
|
const AutoRuleManager_1 = require("./AutoRuleManager");
|
|||
|
|
class ThemeRhemeGazeRule extends AutoRule_1.AutoRule {
|
|||
|
|
constructor(priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.AutoRuleNames.ThemeRhemeGaze, priority, probability);
|
|||
|
|
}
|
|||
|
|
_createNode() {
|
|||
|
|
let n = new AssetNode_1.AssetNode(Types_1.AssetNodeType.ANIM);
|
|||
|
|
n.setAttribute('cat', 'glances');
|
|||
|
|
n.setAttribute('rule', AutoRuleManager_1.AutoRuleNames.ThemeRhemeGaze);
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
_applyInternal(nlpTreeRoot, otherRoots) {
|
|||
|
|
let sequences = [];
|
|||
|
|
if (!otherRoots || otherRoots.length === 0) {
|
|||
|
|
throw new Error(`Need ThemeRheme tree root`);
|
|||
|
|
}
|
|||
|
|
otherRoots[0].forEachChildType(Types_1.NLPNodeType.SENTENCE, sentence => {
|
|||
|
|
sentence.forEachChildType(ThemeRhemeParser_1.TRPart.TR, tr => {
|
|||
|
|
let theme = tr.findFirstChildType(ThemeRhemeParser_1.TRPart.THEME);
|
|||
|
|
if (theme) {
|
|||
|
|
let words = theme.gatherDescendantsType(Types_1.NLPNodeType.WORD);
|
|||
|
|
for (let idx = 0; idx < words.length; idx++) {
|
|||
|
|
if (words[idx].contractionBase) {
|
|||
|
|
words.splice(idx, 1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (words.length > 1) {
|
|||
|
|
sequences.push(words);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
return sequences;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.ThemeRhemeGazeRule = ThemeRhemeGazeRule;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"../AssetNode":16,"../parsers/ThemeRhemeParser":52,"./AutoRule":22,"./AutoRuleManager":23}],40:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
function __export(m) {
|
|||
|
|
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|||
|
|
}
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
__export(require("./timeline_mod"));
|
|||
|
|
__export(require("./AutoRule"));
|
|||
|
|
__export(require("./AutoRuleManager"));
|
|||
|
|
__export(require("./AutoRuleUtils"));
|
|||
|
|
__export(require("./BeatFirstWordPartRule"));
|
|||
|
|
__export(require("./BeatNewWordRule"));
|
|||
|
|
__export(require("./BlinkRule"));
|
|||
|
|
__export(require("./BeatBlinkRule"));
|
|||
|
|
__export(require("./ButRule"));
|
|||
|
|
__export(require("./CommaRule"));
|
|||
|
|
__export(require("./DoubleBlinkRule"));
|
|||
|
|
__export(require("./ExclamationRule"));
|
|||
|
|
__export(require("./HotWordsRule"));
|
|||
|
|
__export(require("./ListRule"));
|
|||
|
|
__export(require("./NounRule"));
|
|||
|
|
__export(require("./OrRule"));
|
|||
|
|
__export(require("./QuestionRule"));
|
|||
|
|
__export(require("./ThemeRhemeGazeRule"));
|
|||
|
|
__export(require("./InitiateRule"));
|
|||
|
|
|
|||
|
|
},{"./AutoRule":22,"./AutoRuleManager":23,"./AutoRuleUtils":24,"./BeatBlinkRule":25,"./BeatFirstWordPartRule":26,"./BeatNewWordRule":27,"./BlinkRule":28,"./ButRule":29,"./CommaRule":30,"./DoubleBlinkRule":31,"./ExclamationRule":32,"./HotWordsRule":33,"./InitiateRule":34,"./ListRule":35,"./NounRule":36,"./OrRule":37,"./QuestionRule":38,"./ThemeRhemeGazeRule":39,"./timeline_mod":48}],41:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const TimelineAutoRule_1 = require("./TimelineAutoRule");
|
|||
|
|
const AssetNode_1 = require("../../AssetNode");
|
|||
|
|
const Types_1 = require("../../../common/Types");
|
|||
|
|
const InputProcessor_1 = require("../../InputProcessor");
|
|||
|
|
const AutoRuleManager_1 = require("../AutoRuleManager");
|
|||
|
|
const AutoRuleUtils_1 = require("../AutoRuleUtils");
|
|||
|
|
const TimelineModUtils_1 = require("./TimelineModUtils");
|
|||
|
|
class EllipsisRule extends TimelineAutoRule_1.TimelineAutoRule {
|
|||
|
|
constructor(priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.TimelineModifyingRuleNames.Ellipsis, TimelineModUtils_1.TimelineAutoRuleType.TIMEFUL, priority, probability);
|
|||
|
|
}
|
|||
|
|
_createTimelineModifyingData(matchInfo) {
|
|||
|
|
const offset = 1;
|
|||
|
|
let n = new AssetNode_1.AssetNode(Types_1.AssetNodeType.ANIM);
|
|||
|
|
n.setAttribute('cat', 'ellipsis');
|
|||
|
|
return TimelineModUtils_1.TimelineModUtils.getInsertionInfo(n, matchInfo.sibling, offset);
|
|||
|
|
}
|
|||
|
|
_applyInternal(xmlTree) {
|
|||
|
|
let matchesInfo = [];
|
|||
|
|
xmlTree.forEachDescendant(node => {
|
|||
|
|
if (node.value === AutoRuleUtils_1.AR_SUBRULE.ELLIPSIS) {
|
|||
|
|
let ancestorConflict = false;
|
|||
|
|
node.forEachAncestor(ancestor => {
|
|||
|
|
if (InputProcessor_1.InputProcessor.isAsset(ancestor)) {
|
|||
|
|
ancestorConflict = true;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
if (!ancestorConflict) {
|
|||
|
|
matchesInfo.push({
|
|||
|
|
sibling: node,
|
|||
|
|
subRule: AutoRuleUtils_1.AR_SUBRULE.ELLIPSIS
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return matchesInfo;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.EllipsisRule = EllipsisRule;
|
|||
|
|
|
|||
|
|
},{"../../../common/Types":13,"../../AssetNode":16,"../../InputProcessor":19,"../AutoRuleManager":23,"../AutoRuleUtils":24,"./TimelineAutoRule":46,"./TimelineModUtils":47}],42:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const InputProcessor_1 = require("../../InputProcessor");
|
|||
|
|
const Types_1 = require("../../../common/Types");
|
|||
|
|
const TimelineAutoRule_1 = require("./TimelineAutoRule");
|
|||
|
|
const TimelineModUtils_1 = require("./TimelineModUtils");
|
|||
|
|
const AutoRuleManager_1 = require("../AutoRuleManager");
|
|||
|
|
class EmotionalVoiceRule extends TimelineAutoRule_1.TimelineAutoRule {
|
|||
|
|
constructor(jibo, priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.TimelineModifyingRuleNames.EmotionalVoice, TimelineModUtils_1.TimelineAutoRuleType.TIMELESS, priority, probability);
|
|||
|
|
this.jibo = jibo;
|
|||
|
|
this.emotionToVoiceConfig = new Map();
|
|||
|
|
this.emotionToVoiceConfig.set(jibo.emotion.EmotionName.NEUTRAL, [
|
|||
|
|
{
|
|||
|
|
type: Types_1.SSMLNodeType.STYLE,
|
|||
|
|
attrs: {
|
|||
|
|
set: Types_1.SSMLStyleTagType.NEUTRAL
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]);
|
|||
|
|
this.emotionToVoiceConfig.set(jibo.emotion.EmotionName.INSECURE, [
|
|||
|
|
{
|
|||
|
|
type: Types_1.SSMLNodeType.STYLE,
|
|||
|
|
attrs: {
|
|||
|
|
set: Types_1.SSMLStyleTagType.CONFUSED
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]);
|
|||
|
|
this.emotionToVoiceConfig.set(jibo.emotion.EmotionName.FRUSTRATED, [
|
|||
|
|
{
|
|||
|
|
type: Types_1.SSMLNodeType.STYLE,
|
|||
|
|
attrs: {
|
|||
|
|
set: Types_1.SSMLStyleTagType.CONFUSED
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]);
|
|||
|
|
this.emotionToVoiceConfig.set(jibo.emotion.EmotionName.HOPEFUL, [
|
|||
|
|
{
|
|||
|
|
type: Types_1.SSMLNodeType.STYLE,
|
|||
|
|
attrs: {
|
|||
|
|
set: Types_1.SSMLStyleTagType.CONFIDENT
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]);
|
|||
|
|
this.emotionToVoiceConfig.set(jibo.emotion.EmotionName.JOYFUL, [
|
|||
|
|
{
|
|||
|
|
type: Types_1.SSMLNodeType.STYLE,
|
|||
|
|
attrs: {
|
|||
|
|
set: Types_1.SSMLStyleTagType.ENTHUSIASTIC
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]);
|
|||
|
|
this.emotionToVoiceConfig.set(jibo.emotion.EmotionName.PLEASED, [
|
|||
|
|
{
|
|||
|
|
type: Types_1.SSMLNodeType.STYLE,
|
|||
|
|
attrs: {
|
|||
|
|
set: Types_1.SSMLStyleTagType.ENTHUSIASTIC
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]);
|
|||
|
|
this.emotionToVoiceConfig.set(jibo.emotion.EmotionName.DETERMINED, [
|
|||
|
|
{
|
|||
|
|
type: Types_1.SSMLNodeType.STYLE,
|
|||
|
|
attrs: {
|
|||
|
|
set: Types_1.SSMLStyleTagType.SHEEPISH
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]);
|
|||
|
|
this.emotionToVoiceConfig.set(jibo.emotion.EmotionName.SAD, [
|
|||
|
|
{
|
|||
|
|
type: Types_1.SSMLNodeType.STYLE,
|
|||
|
|
attrs: {
|
|||
|
|
set: Types_1.SSMLStyleTagType.SHEEPISH
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]);
|
|||
|
|
this.emotionToVoiceConfig.set(jibo.emotion.EmotionName.CONFIDENT, [
|
|||
|
|
{
|
|||
|
|
type: Types_1.SSMLNodeType.STYLE,
|
|||
|
|
attrs: {
|
|||
|
|
set: Types_1.SSMLStyleTagType.CONFIDENT
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]);
|
|||
|
|
}
|
|||
|
|
_createTimelineModifyingData(matchInfo) {
|
|||
|
|
let voiceConfig = this.emotionToVoiceConfig.get(this.emotion.name);
|
|||
|
|
if (!voiceConfig) {
|
|||
|
|
voiceConfig = this.emotionToVoiceConfig.get(this.jibo.emotion.EmotionName.NEUTRAL);
|
|||
|
|
}
|
|||
|
|
const ssmlNodesToInsert = voiceConfig.map(ssmlConfig => TimelineModUtils_1.TimelineModUtils.SSMLNodeBuilder(ssmlConfig.type, ssmlConfig.attrs));
|
|||
|
|
const parent = matchInfo.children[0].parents[0];
|
|||
|
|
const insertionInfo = {
|
|||
|
|
nodes: ssmlNodesToInsert,
|
|||
|
|
children: matchInfo.children
|
|||
|
|
};
|
|||
|
|
return [parent, insertionInfo];
|
|||
|
|
}
|
|||
|
|
_applyInternal(xmlTree) {
|
|||
|
|
let matchesInfo = [];
|
|||
|
|
this.emotion = this.jibo.emotion.getNearestEmotion();
|
|||
|
|
const allNodes = xmlTree.gatherDescendants();
|
|||
|
|
const containsTimelessSSML = allNodes.every(node => !InputProcessor_1.InputProcessor.isTimelessSSML(node));
|
|||
|
|
if (containsTimelessSSML) {
|
|||
|
|
matchesInfo.push({
|
|||
|
|
children: xmlTree.gatherChildren()
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
return matchesInfo;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.EmotionalVoiceRule = EmotionalVoiceRule;
|
|||
|
|
|
|||
|
|
},{"../../../common/Types":13,"../../InputProcessor":19,"../AutoRuleManager":23,"./TimelineAutoRule":46,"./TimelineModUtils":47}],43:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const jibo_node_xml_1 = require("jibo-node-xml");
|
|||
|
|
const TimelineAutoRule_1 = require("./TimelineAutoRule");
|
|||
|
|
const TimelineModUtils_1 = require("./TimelineModUtils");
|
|||
|
|
const AutoRuleManager_1 = require("../AutoRuleManager");
|
|||
|
|
const AutoRuleUtils_1 = require("../AutoRuleUtils");
|
|||
|
|
const jibo_node_xml_2 = require("jibo-node-xml");
|
|||
|
|
class ExclamationVoiceRule extends TimelineAutoRule_1.TimelineAutoRule {
|
|||
|
|
constructor(priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.TimelineModifyingRuleNames.ExclamationVoice, TimelineModUtils_1.TimelineAutoRuleType.TIMELESS, priority, probability);
|
|||
|
|
}
|
|||
|
|
_createTimelineModifyingData(matchInfo) {
|
|||
|
|
let nodeToInsert = new jibo_node_xml_1.default('DEPRECATED');
|
|||
|
|
nodeToInsert.setAttribute('config', 'happy');
|
|||
|
|
const parent = matchInfo.children[0].parents[0];
|
|||
|
|
const insertionInfo = {
|
|||
|
|
nodes: [nodeToInsert],
|
|||
|
|
children: matchInfo.children
|
|||
|
|
};
|
|||
|
|
return [parent, insertionInfo];
|
|||
|
|
}
|
|||
|
|
_applyInternal(xmlTree) {
|
|||
|
|
let matchesInfo = [];
|
|||
|
|
let sentenceWords = [];
|
|||
|
|
xmlTree.forEachDescendantType(jibo_node_xml_2.NodeType.TEXT, node => {
|
|||
|
|
switch (node.value) {
|
|||
|
|
case AutoRuleUtils_1.AR_SUBRULE.PERIOD:
|
|||
|
|
case AutoRuleUtils_1.AR_SUBRULE.QUESTION:
|
|||
|
|
case AutoRuleUtils_1.AR_SUBRULE.COMMA:
|
|||
|
|
case AutoRuleUtils_1.AR_SUBRULE.ELLIPSIS:
|
|||
|
|
sentenceWords = [];
|
|||
|
|
break;
|
|||
|
|
case AutoRuleUtils_1.AR_SUBRULE.EXCLAMATION:
|
|||
|
|
sentenceWords.push(node);
|
|||
|
|
matchesInfo.push({
|
|||
|
|
children: sentenceWords
|
|||
|
|
});
|
|||
|
|
sentenceWords = [];
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
sentenceWords.push(node);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return matchesInfo;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.ExclamationVoiceRule = ExclamationVoiceRule;
|
|||
|
|
|
|||
|
|
},{"../AutoRuleManager":23,"../AutoRuleUtils":24,"./TimelineAutoRule":46,"./TimelineModUtils":47,"jibo-node-xml":undefined}],44:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const TimelineAutoRule_1 = require("./TimelineAutoRule");
|
|||
|
|
const AutoRuleManager_1 = require("../AutoRuleManager");
|
|||
|
|
const AutoRuleUtils_1 = require("../AutoRuleUtils");
|
|||
|
|
const TimelineModUtils_1 = require("./TimelineModUtils");
|
|||
|
|
exports.AR_MIN_PERIOD_PAU = 0.1;
|
|||
|
|
exports.AR_MAX_PERIOD_PAU = 0.3;
|
|||
|
|
exports.AR_QUESTION_PAU = 0.3;
|
|||
|
|
exports.AR_EXCLAMATION_PAU = 0.3;
|
|||
|
|
exports.AR_ELLIPSIS_PAU = 0.75;
|
|||
|
|
class InterSentenceTimingRule extends TimelineAutoRule_1.TimelineAutoRule {
|
|||
|
|
constructor(priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.TimelineModifyingRuleNames.InterSentenceTiming, TimelineModUtils_1.TimelineAutoRuleType.TIMEFUL, priority, probability);
|
|||
|
|
}
|
|||
|
|
_createTimelineModifyingData(matchInfo) {
|
|||
|
|
let breakSize = 0;
|
|||
|
|
switch (matchInfo.subRule) {
|
|||
|
|
case AutoRuleUtils_1.AR_SUBRULE.PERIOD:
|
|||
|
|
breakSize = (matchInfo.sibling.getNumberAtt('wordCount') <= 3) ? exports.AR_MIN_PERIOD_PAU : exports.AR_MAX_PERIOD_PAU;
|
|||
|
|
break;
|
|||
|
|
case AutoRuleUtils_1.AR_SUBRULE.QUESTION:
|
|||
|
|
breakSize = exports.AR_QUESTION_PAU;
|
|||
|
|
break;
|
|||
|
|
case AutoRuleUtils_1.AR_SUBRULE.EXCLAMATION:
|
|||
|
|
breakSize = exports.AR_EXCLAMATION_PAU;
|
|||
|
|
break;
|
|||
|
|
case AutoRuleUtils_1.AR_SUBRULE.ELLIPSIS:
|
|||
|
|
breakSize = exports.AR_ELLIPSIS_PAU;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
if (breakSize > 0) {
|
|||
|
|
const n = TimelineModUtils_1.TimelineModUtils.breakNodeBuilder(breakSize);
|
|||
|
|
return TimelineModUtils_1.TimelineModUtils.getInsertionInfo(n, matchInfo.sibling, 1);
|
|||
|
|
}
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
_applyInternal(xmlTree, doPunctuation) {
|
|||
|
|
let matchesInfo = [];
|
|||
|
|
let endedTextInPunctLoc = null;
|
|||
|
|
let wordCount = 0;
|
|||
|
|
xmlTree.forEachDescendant(node => {
|
|||
|
|
switch (node.value) {
|
|||
|
|
case AutoRuleUtils_1.AR_SUBRULE.PERIOD:
|
|||
|
|
case AutoRuleUtils_1.AR_SUBRULE.QUESTION:
|
|||
|
|
case AutoRuleUtils_1.AR_SUBRULE.EXCLAMATION:
|
|||
|
|
endedTextInPunctLoc = matchesInfo.length;
|
|||
|
|
node.setAttribute('wordCount', wordCount);
|
|||
|
|
matchesInfo.push({
|
|||
|
|
sibling: node,
|
|||
|
|
subRule: node.value
|
|||
|
|
});
|
|||
|
|
wordCount = 0;
|
|||
|
|
break;
|
|||
|
|
case AutoRuleUtils_1.AR_SUBRULE.ELLIPSIS:
|
|||
|
|
if (!doPunctuation) {
|
|||
|
|
endedTextInPunctLoc = matchesInfo.length;
|
|||
|
|
matchesInfo.push({
|
|||
|
|
sibling: node,
|
|||
|
|
subRule: AutoRuleUtils_1.AR_SUBRULE.ELLIPSIS
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
endedTextInPunctLoc = null;
|
|||
|
|
if (/\w+/.test(node.value)) {
|
|||
|
|
wordCount++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
if (endedTextInPunctLoc !== null) {
|
|||
|
|
matchesInfo.splice(endedTextInPunctLoc, 1);
|
|||
|
|
}
|
|||
|
|
return matchesInfo;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.InterSentenceTimingRule = InterSentenceTimingRule;
|
|||
|
|
|
|||
|
|
},{"../AutoRuleManager":23,"../AutoRuleUtils":24,"./TimelineAutoRule":46,"./TimelineModUtils":47}],45:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const TimelineAutoRule_1 = require("./TimelineAutoRule");
|
|||
|
|
const AutoRuleManager_1 = require("../AutoRuleManager");
|
|||
|
|
const AutoRuleUtils_1 = require("../AutoRuleUtils");
|
|||
|
|
const TimelineModUtils_1 = require("./TimelineModUtils");
|
|||
|
|
exports.AR_BUT_PAU = 0.2;
|
|||
|
|
exports.AR_OR_PAU = 0.2;
|
|||
|
|
class IntraSentenceTimingRule extends TimelineAutoRule_1.TimelineAutoRule {
|
|||
|
|
constructor(priority = 1, probability = 1) {
|
|||
|
|
super(AutoRuleManager_1.TimelineModifyingRuleNames.IntraSentenceTiming, TimelineModUtils_1.TimelineAutoRuleType.TIMEFUL, priority, probability);
|
|||
|
|
}
|
|||
|
|
_createTimelineModifyingData(matchInfo) {
|
|||
|
|
let breakSize = 0;
|
|||
|
|
let offset = 1;
|
|||
|
|
switch (matchInfo.subRule) {
|
|||
|
|
case AutoRuleUtils_1.AR_SUBRULE.OR:
|
|||
|
|
breakSize = exports.AR_OR_PAU;
|
|||
|
|
offset = 0;
|
|||
|
|
break;
|
|||
|
|
case AutoRuleUtils_1.AR_SUBRULE.BUT:
|
|||
|
|
breakSize = exports.AR_BUT_PAU;
|
|||
|
|
offset = 0;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
let n = TimelineModUtils_1.TimelineModUtils.breakNodeBuilder(breakSize);
|
|||
|
|
return TimelineModUtils_1.TimelineModUtils.getInsertionInfo(n, matchInfo.sibling, offset);
|
|||
|
|
}
|
|||
|
|
_applyInternal(xmlTree) {
|
|||
|
|
let matchesInfo = [];
|
|||
|
|
xmlTree.forEachDescendant(node => {
|
|||
|
|
switch (node.value) {
|
|||
|
|
case AutoRuleUtils_1.AR_SUBRULE.BUT:
|
|||
|
|
matchesInfo.push({
|
|||
|
|
sibling: node,
|
|||
|
|
subRule: node.value
|
|||
|
|
});
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return matchesInfo;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.IntraSentenceTimingRule = IntraSentenceTimingRule;
|
|||
|
|
|
|||
|
|
},{"../AutoRuleManager":23,"../AutoRuleUtils":24,"./TimelineAutoRule":46,"./TimelineModUtils":47}],46:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
class TimelineAutoRule {
|
|||
|
|
constructor(ruleName, ruleType, priority, probability = 1) {
|
|||
|
|
this.ruleName = ruleName;
|
|||
|
|
this.ruleType = ruleType;
|
|||
|
|
this.priority = priority;
|
|||
|
|
this.probability = probability;
|
|||
|
|
}
|
|||
|
|
_applyInternal(xmlTree, context) {
|
|||
|
|
throw new Error('Should be implemented by subclass');
|
|||
|
|
}
|
|||
|
|
_createTimelineModifyingData(matchInfo) {
|
|||
|
|
throw new Error('Should be implemented by subclass');
|
|||
|
|
}
|
|||
|
|
applyRule(xmlTree, context) {
|
|||
|
|
let matches = this._applyInternal(xmlTree, context);
|
|||
|
|
let ruleData = {};
|
|||
|
|
ruleData.autoRule = this.ruleName;
|
|||
|
|
ruleData.type = this.ruleType;
|
|||
|
|
ruleData.priority = this.priority;
|
|||
|
|
ruleData.matches = new Map();
|
|||
|
|
matches.forEach(matchInfo => {
|
|||
|
|
if (Math.random() < this.probability) {
|
|||
|
|
const [parent, nodeToInsertInfo] = this._createTimelineModifyingData(matchInfo);
|
|||
|
|
let childrenToInsert = ruleData.matches.get(parent);
|
|||
|
|
if (!childrenToInsert) {
|
|||
|
|
ruleData.matches.set(parent, childrenToInsert = []);
|
|||
|
|
}
|
|||
|
|
childrenToInsert.push(nodeToInsertInfo);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return ruleData;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.TimelineAutoRule = TimelineAutoRule;
|
|||
|
|
|
|||
|
|
},{}],47:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const jibo_node_xml_1 = require("jibo-node-xml");
|
|||
|
|
const SSMLNode_1 = require("../../SSMLNode");
|
|||
|
|
const AssetNode_1 = require("../../AssetNode");
|
|||
|
|
const Types_1 = require("../../../common/Types");
|
|||
|
|
var TimelineAutoRuleType;
|
|||
|
|
(function (TimelineAutoRuleType) {
|
|||
|
|
TimelineAutoRuleType["TIMELESS"] = "TIMELESS";
|
|||
|
|
TimelineAutoRuleType["TIMEFUL"] = "TIMEFUL";
|
|||
|
|
})(TimelineAutoRuleType = exports.TimelineAutoRuleType || (exports.TimelineAutoRuleType = {}));
|
|||
|
|
var BlinkNodeType;
|
|||
|
|
(function (BlinkNodeType) {
|
|||
|
|
BlinkNodeType["SINGLE"] = "SINGLE";
|
|||
|
|
BlinkNodeType["DOUBLE"] = "DOUBLE";
|
|||
|
|
})(BlinkNodeType = exports.BlinkNodeType || (exports.BlinkNodeType = {}));
|
|||
|
|
class TimelineModUtils {
|
|||
|
|
static breakNodeBuilder(size) {
|
|||
|
|
let nodeToInsert = new jibo_node_xml_1.default(Types_1.SSMLNodeType.BREAK);
|
|||
|
|
nodeToInsert.setAttribute('size', (Math.round(size * 1e2) / 1e2));
|
|||
|
|
return nodeToInsert;
|
|||
|
|
}
|
|||
|
|
static blinkNodeBuilder(type) {
|
|||
|
|
let atts = new Map();
|
|||
|
|
atts.set('filter', type);
|
|||
|
|
atts.set('layers', 'screen');
|
|||
|
|
atts.set('cat', 'blinks');
|
|||
|
|
let nodeToInsert = new AssetNode_1.AssetNode(Types_1.AssetNodeType.ANIM, atts);
|
|||
|
|
return nodeToInsert;
|
|||
|
|
}
|
|||
|
|
static SSMLNodeBuilder(type, attrs) {
|
|||
|
|
let nodeToInsert = new SSMLNode_1.SSMLNode(type);
|
|||
|
|
Object.keys(attrs).forEach(key => {
|
|||
|
|
nodeToInsert.setAttribute(key, attrs[key]);
|
|||
|
|
});
|
|||
|
|
return nodeToInsert;
|
|||
|
|
}
|
|||
|
|
static getInsertionInfo(nodeToInsert, siblingNode, offset) {
|
|||
|
|
const parent = siblingNode.parents[0];
|
|||
|
|
const insertIdx = parent.children.indexOf(siblingNode) + offset;
|
|||
|
|
const insertionInfo = {
|
|||
|
|
nodes: [nodeToInsert],
|
|||
|
|
offset: insertIdx
|
|||
|
|
};
|
|||
|
|
return [parent, insertionInfo];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.TimelineModUtils = TimelineModUtils;
|
|||
|
|
|
|||
|
|
},{"../../../common/Types":13,"../../AssetNode":16,"../../SSMLNode":20,"jibo-node-xml":undefined}],48:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
function __export(m) {
|
|||
|
|
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|||
|
|
}
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
__export(require("./EllipsisRule"));
|
|||
|
|
__export(require("./ExclamationVoiceRule"));
|
|||
|
|
__export(require("./EmotionalVoiceRule"));
|
|||
|
|
__export(require("./InterSentenceTimingRule"));
|
|||
|
|
__export(require("./IntraSentenceTimingRule"));
|
|||
|
|
__export(require("./TimelineAutoRule"));
|
|||
|
|
__export(require("./TimelineModUtils"));
|
|||
|
|
|
|||
|
|
},{"./EllipsisRule":41,"./EmotionalVoiceRule":42,"./ExclamationVoiceRule":43,"./InterSentenceTimingRule":44,"./IntraSentenceTimingRule":45,"./TimelineAutoRule":46,"./TimelineModUtils":47}],49:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
function __export(m) {
|
|||
|
|
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|||
|
|
}
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const auto_rules = require("./auto_rules");
|
|||
|
|
exports.auto_rules = auto_rules;
|
|||
|
|
const parsers = require("./parsers");
|
|||
|
|
exports.parsers = parsers;
|
|||
|
|
__export(require("./AssetNode"));
|
|||
|
|
__export(require("./Formats"));
|
|||
|
|
__export(require("./InputProcessor"));
|
|||
|
|
__export(require("./SSMLNode"));
|
|||
|
|
__export(require("./TagTreeNode"));
|
|||
|
|
__export(require("./ContentValidator"));
|
|||
|
|
|
|||
|
|
},{"./AssetNode":16,"./ContentValidator":17,"./Formats":18,"./InputProcessor":19,"./SSMLNode":20,"./TagTreeNode":21,"./auto_rules":40,"./parsers":53}],50:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|||
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|||
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|||
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|||
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|||
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
class Lexer {
|
|||
|
|
constructor(jibo) {
|
|||
|
|
this.jibo = jibo;
|
|||
|
|
}
|
|||
|
|
lex(input) {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
let data = yield this.jibo.tts.getPOSTokens(input);
|
|||
|
|
return data.tokens;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.Lexer = Lexer;
|
|||
|
|
|
|||
|
|
},{}],51:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|||
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|||
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|||
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|||
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|||
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const jibo_node_xml_1 = require("jibo-node-xml");
|
|||
|
|
const jibo_node_xml_2 = require("jibo-node-xml");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
const jibo_cai_utils_1 = require("jibo-cai-utils");
|
|||
|
|
const Lexer_1 = require("./Lexer");
|
|||
|
|
let stemmer = require('stemmer');
|
|||
|
|
let root = jibo_cai_utils_1.PathUtils.getProjectRoot(__filename);
|
|||
|
|
let common_words = require(root + '/resources/common_words_stemmed_500.json');
|
|||
|
|
class PartNode extends jibo_node_xml_1.default {
|
|||
|
|
constructor(value) {
|
|||
|
|
super(Types_1.NLPNodeType.PART, value);
|
|||
|
|
this.tags = [];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.PartNode = PartNode;
|
|||
|
|
class SentenceNode extends jibo_node_xml_1.default {
|
|||
|
|
constructor(value) {
|
|||
|
|
super(Types_1.NLPNodeType.SENTENCE, value);
|
|||
|
|
this.words = [];
|
|||
|
|
this.sentenceType = Types_1.SentenceType.REGULAR;
|
|||
|
|
}
|
|||
|
|
set sentenceType(type) {
|
|||
|
|
this.setAttribute('sentenceType', type);
|
|||
|
|
}
|
|||
|
|
get sentenceType() {
|
|||
|
|
return this.getAttribute('sentenceType');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.SentenceNode = SentenceNode;
|
|||
|
|
class WordNode extends jibo_node_xml_1.default {
|
|||
|
|
set wordType(type) {
|
|||
|
|
this.setAttribute('wordType', type);
|
|||
|
|
}
|
|||
|
|
get wordType() {
|
|||
|
|
return this.getAttribute('wordType');
|
|||
|
|
}
|
|||
|
|
constructor(value) {
|
|||
|
|
super(Types_1.NLPNodeType.WORD, value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.WordNode = WordNode;
|
|||
|
|
class Tagger {
|
|||
|
|
constructor(jibo) {
|
|||
|
|
this.jibo = jibo;
|
|||
|
|
this.jibo = jibo;
|
|||
|
|
}
|
|||
|
|
tag(words) {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
let data = yield this.jibo.tts.getPOSTags(words);
|
|||
|
|
return data.tokentags;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.Tagger = Tagger;
|
|||
|
|
class NLParser {
|
|||
|
|
constructor(jibo) {
|
|||
|
|
this.neverNew = new Set();
|
|||
|
|
this.globalInd = 0;
|
|||
|
|
this.contractionBase = null;
|
|||
|
|
this.wordCounts = new Map();
|
|||
|
|
this.lexer = new Lexer_1.Lexer(jibo);
|
|||
|
|
this.tagger = new Tagger(jibo);
|
|||
|
|
common_words
|
|||
|
|
.map(w => stemmer(w))
|
|||
|
|
.forEach(w => this.neverNew.add(w));
|
|||
|
|
}
|
|||
|
|
_parseWord(word, pos) {
|
|||
|
|
let textNode = new WordNode(word);
|
|||
|
|
textNode.setAttribute('globalInd', this.globalInd++);
|
|||
|
|
textNode.setAttribute('stem', stemmer(word));
|
|||
|
|
textNode.setAttribute('pos', pos);
|
|||
|
|
if (this.expansions && this.contractions) {
|
|||
|
|
let wordCount = this.wordCounts.get(word);
|
|||
|
|
if (wordCount !== undefined) {
|
|||
|
|
wordCount++;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
wordCount = 0;
|
|||
|
|
}
|
|||
|
|
this.wordCounts.set(word, wordCount);
|
|||
|
|
let foundIndexes = this.expansions.reduce((arr, elm, idx) => {
|
|||
|
|
if (elm === word) {
|
|||
|
|
arr.push(idx);
|
|||
|
|
}
|
|||
|
|
return arr;
|
|||
|
|
}, []);
|
|||
|
|
if (foundIndexes.length > 0) {
|
|||
|
|
let contractedForm = this.contractions[foundIndexes[wordCount]];
|
|||
|
|
if (contractedForm !== word) {
|
|||
|
|
if (contractedForm !== '') {
|
|||
|
|
textNode.setAttribute('contraction', contractedForm);
|
|||
|
|
this.contractionBase = textNode;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
if (this.contractionBase) {
|
|||
|
|
textNode.contractionBase = this.contractionBase;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw new Error('Cannot find base word of expanded contraction');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw new Error('Error when attempting to expand contractions.');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (pos.startsWith('VB')) {
|
|||
|
|
textNode.wordType = Types_1.WordType.VERB;
|
|||
|
|
}
|
|||
|
|
else if (pos.startsWith('N')) {
|
|||
|
|
textNode.wordType = Types_1.WordType.NOUN;
|
|||
|
|
}
|
|||
|
|
else if (pos.startsWith('P')) {
|
|||
|
|
textNode.wordType = Types_1.WordType.PREP;
|
|||
|
|
}
|
|||
|
|
else if (word[0] === ',' ||
|
|||
|
|
pos.startsWith('CC')) {
|
|||
|
|
textNode.wordType = Types_1.WordType.CONN;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
textNode.wordType = Types_1.WordType.UNKN;
|
|||
|
|
}
|
|||
|
|
let stemmed = textNode.getAttribute('stem');
|
|||
|
|
if (!this.neverNew.has(stemmed) && !this.dialogContext.existing.has(stemmed)) {
|
|||
|
|
this.dialogContext.existing.add(stemmed);
|
|||
|
|
textNode.setAttribute('new', true);
|
|||
|
|
}
|
|||
|
|
return textNode;
|
|||
|
|
}
|
|||
|
|
_createWordNodes(tags) {
|
|||
|
|
return tags.map(tag => {
|
|||
|
|
const pos = tag[1];
|
|||
|
|
const word = tag[0];
|
|||
|
|
return this._parseWord(word, pos);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
setDialogContext(dialogContext) {
|
|||
|
|
this.dialogContext = dialogContext;
|
|||
|
|
}
|
|||
|
|
parse(input, expansions, contractions) {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
if (typeof input === 'string') {
|
|||
|
|
input = yield this.lexer.lex(input);
|
|||
|
|
}
|
|||
|
|
return this._parse(input, expansions, contractions);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
_parse(words, expansions, contractions) {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
this.globalInd = 0;
|
|||
|
|
this.wordCounts = new Map();
|
|||
|
|
this.expansions = null;
|
|||
|
|
this.contractions = null;
|
|||
|
|
if (!this.dialogContext) {
|
|||
|
|
this.dialogContext = {
|
|||
|
|
existing: new Set()
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
if (expansions && contractions) {
|
|||
|
|
this.expansions = expansions;
|
|||
|
|
this.contractions = contractions;
|
|||
|
|
}
|
|||
|
|
let root = new jibo_node_xml_1.default(jibo_node_xml_2.NodeType.ROOT);
|
|||
|
|
root.setAttribute('treeType', 'NLP_TREE');
|
|||
|
|
let sentence = new SentenceNode();
|
|||
|
|
root.addChild(sentence);
|
|||
|
|
words.forEach(w => {
|
|||
|
|
if (w === '.' || w === '?' || w === '!' || w === ';' || w === ':') {
|
|||
|
|
if (w === '?') {
|
|||
|
|
sentence.sentenceType = Types_1.SentenceType.QUESTION;
|
|||
|
|
}
|
|||
|
|
else if (w === '!') {
|
|||
|
|
sentence.sentenceType = Types_1.SentenceType.EXCLAMATION;
|
|||
|
|
}
|
|||
|
|
let endNode = new WordNode(w);
|
|||
|
|
endNode.wordType = Types_1.WordType.END;
|
|||
|
|
root.addChild(endNode);
|
|||
|
|
sentence = new SentenceNode();
|
|||
|
|
sentence.words = [];
|
|||
|
|
sentence.sentenceType = Types_1.SentenceType.REGULAR;
|
|||
|
|
root.addChild(sentence);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
sentence.words.push(w);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
let lastSentence = root.children[root.children.length - 1];
|
|||
|
|
if (lastSentence.type === Types_1.NLPNodeType.SENTENCE && !lastSentence.words.length) {
|
|||
|
|
root.removeChild(lastSentence);
|
|||
|
|
}
|
|||
|
|
const sentences = root.gatherChildrenType(Types_1.NLPNodeType.SENTENCE);
|
|||
|
|
for (let sentence of sentences) {
|
|||
|
|
sentence.value = sentence.words.join(' ');
|
|||
|
|
let tags;
|
|||
|
|
try {
|
|||
|
|
tags = yield this.tagger.tag(sentence.words);
|
|||
|
|
}
|
|||
|
|
catch (err) {
|
|||
|
|
throw new Error('Error when attempting to retreive POS tags');
|
|||
|
|
}
|
|||
|
|
sentence.words = null;
|
|||
|
|
let part = new PartNode();
|
|||
|
|
part.setAttribute('verbCount', 0);
|
|||
|
|
sentence.addChild(part);
|
|||
|
|
tags.forEach(tag => {
|
|||
|
|
let word = tag[0];
|
|||
|
|
let pos = tag[1];
|
|||
|
|
if (word === ',' || pos.startsWith('CC')) {
|
|||
|
|
let endNode = new WordNode(word);
|
|||
|
|
endNode.wordType = Types_1.WordType.CONN;
|
|||
|
|
endNode.setAttribute('pos', pos);
|
|||
|
|
sentence.addChild(endNode);
|
|||
|
|
part = new PartNode();
|
|||
|
|
part.setAttribute('verbCount', 0);
|
|||
|
|
sentence.addChild(part);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
if (pos.startsWith('V')) {
|
|||
|
|
part.modifyAttribute('verbCount', (oldVal) => oldVal + 1);
|
|||
|
|
}
|
|||
|
|
part.tags.push(tag);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
sentence.gatherChildrenType(Types_1.NLPNodeType.PART, (p) => !p.tags.length)
|
|||
|
|
.forEach(p => {
|
|||
|
|
sentence.removeChild(p);
|
|||
|
|
});
|
|||
|
|
sentence.setAttribute('verbCount', 0);
|
|||
|
|
const parts = sentence.gatherChildrenType(Types_1.NLPNodeType.PART);
|
|||
|
|
parts.forEach(part => {
|
|||
|
|
const pvc = part.getAttribute('verbCount');
|
|||
|
|
sentence.modifyAttribute('verbCount', (svc) => svc + pvc);
|
|||
|
|
part.value = part.tags.map(t => t[0]).join(' ');
|
|||
|
|
this._createWordNodes(part.tags)
|
|||
|
|
.forEach(w => part.addChild(w));
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
root.gatherChildrenType(Types_1.NLPNodeType.SENTENCE, p => !p.children.length)
|
|||
|
|
.forEach(p => root.removeChild(p));
|
|||
|
|
return root;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.NLParser = NLParser;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"./Lexer":50,"jibo-cai-utils":undefined,"jibo-node-xml":undefined,"stemmer":undefined}],52:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const jibo_node_xml_1 = require("jibo-node-xml");
|
|||
|
|
const jibo_node_xml_2 = require("jibo-node-xml");
|
|||
|
|
const Types_1 = require("../../common/Types");
|
|||
|
|
function addAllWords(node, out) {
|
|||
|
|
if (node.type === Types_1.NLPNodeType.WORD) {
|
|||
|
|
out.addChild(node);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
node.forEachDescendantType(Types_1.NLPNodeType.WORD, n => {
|
|||
|
|
out.addChild(n);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function parseVP(vp, preV, V, postV) {
|
|||
|
|
let internalVP = vp.findFirstChildType('VP');
|
|||
|
|
if (!internalVP) {
|
|||
|
|
let verbDone = false;
|
|||
|
|
for (let i = 0; i < vp.children.length; i++) {
|
|||
|
|
let node = vp.children[i];
|
|||
|
|
if (!verbDone) {
|
|||
|
|
if (node.type !== Types_1.NLPNodeType.WORD) {
|
|||
|
|
verbDone = true;
|
|||
|
|
addAllWords(node, postV);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
addAllWords(node, V);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
addAllWords(node, postV);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
for (let i = 0; i < vp.children.length; i++) {
|
|||
|
|
let node = vp.children[i];
|
|||
|
|
if (node.type === 'VP') {
|
|||
|
|
if (i !== vp.children.length - 1) {
|
|||
|
|
throw Error(`Don't think that this should happen`);
|
|||
|
|
}
|
|||
|
|
parseVP(node, preV, V, postV);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
addAllWords(node, preV);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.VerbPart = {
|
|||
|
|
COMPLEX: 'COMPLEX',
|
|||
|
|
PRE: 'PRE',
|
|||
|
|
V: 'V',
|
|||
|
|
POST: 'POST',
|
|||
|
|
};
|
|||
|
|
exports.TRPart = {
|
|||
|
|
TR: 'TR',
|
|||
|
|
THEME: 'THEME',
|
|||
|
|
RHEME: 'RHEME',
|
|||
|
|
};
|
|||
|
|
class ThemeRhemeParser {
|
|||
|
|
parse(nlpTreeRoot) {
|
|||
|
|
let tempRoot = new jibo_node_xml_1.default(jibo_node_xml_2.NodeType.ROOT);
|
|||
|
|
for (let j = 0; j < nlpTreeRoot.children.length; j++) {
|
|||
|
|
let node = nlpTreeRoot.children[j];
|
|||
|
|
if (node.type === Types_1.NLPNodeType.WORD) {
|
|||
|
|
tempRoot.addChild(node);
|
|||
|
|
}
|
|||
|
|
else if (node.type === Types_1.NLPNodeType.SENTENCE) {
|
|||
|
|
let newSentence = node.cloneShallow();
|
|||
|
|
tempRoot.addChild(newSentence);
|
|||
|
|
for (let k = 0; k < node.children.length; k++) {
|
|||
|
|
let node2 = node.children[k];
|
|||
|
|
if (node2.type === Types_1.NLPNodeType.PART) {
|
|||
|
|
let complex = new jibo_node_xml_1.default(exports.VerbPart.COMPLEX);
|
|||
|
|
newSentence.addChild(complex);
|
|||
|
|
let preV = new jibo_node_xml_1.default(exports.VerbPart.PRE);
|
|||
|
|
let V = new jibo_node_xml_1.default(exports.VerbPart.V);
|
|||
|
|
let postV = new jibo_node_xml_1.default(exports.VerbPart.POST);
|
|||
|
|
complex.addChild(preV);
|
|||
|
|
complex.addChild(V);
|
|||
|
|
complex.addChild(postV);
|
|||
|
|
for (let i = 0; i < node2.children.length; i++) {
|
|||
|
|
let n = node2.children[i];
|
|||
|
|
if (n.type === 'VP') {
|
|||
|
|
parseVP(n, preV, V, postV);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
addAllWords(n, preV);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (!V.children.length) {
|
|||
|
|
complex.att.set('noVerb', true);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (node2.type === Types_1.NLPNodeType.WORD) {
|
|||
|
|
newSentence.addChild(node2);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw Error(`Shouldn't happen`);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
newSentence.forEachChildType(exports.VerbPart.COMPLEX, compl => {
|
|||
|
|
compl.att.set('newCount', 0);
|
|||
|
|
compl.forEachChild(part => {
|
|||
|
|
part.att.set('newCount', 0);
|
|||
|
|
part.forEachChildType(Types_1.NLPNodeType.WORD, c => {
|
|||
|
|
if (c.att.get('new')) {
|
|||
|
|
part.modifyAttribute('newCount', (old) => old + 1);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
compl.modifyAttribute('newCount', (old) => {
|
|||
|
|
return old + part.getAttribute('newCount');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw Error(`Shouldn't happen`);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
let newRoot = new jibo_node_xml_1.default(jibo_node_xml_2.NodeType.ROOT);
|
|||
|
|
for (let i = 0; i < tempRoot.children.length; i++) {
|
|||
|
|
let c = tempRoot.children[i];
|
|||
|
|
if (c.type === Types_1.NLPNodeType.SENTENCE) {
|
|||
|
|
let newSentence = c.cloneShallow();
|
|||
|
|
newRoot.addChild(newSentence);
|
|||
|
|
c.forEachChild(n => {
|
|||
|
|
if (n.type === exports.VerbPart.COMPLEX) {
|
|||
|
|
let tr = new jibo_node_xml_1.default(exports.TRPart.TR);
|
|||
|
|
let theme = new jibo_node_xml_1.default(exports.TRPart.THEME);
|
|||
|
|
let rheme = new jibo_node_xml_1.default(exports.TRPart.RHEME);
|
|||
|
|
newSentence.addChild(tr);
|
|||
|
|
let pre = n.children[0];
|
|||
|
|
let v = n.children[1];
|
|||
|
|
let post = n.children[2];
|
|||
|
|
let flipped = false;
|
|||
|
|
if (!this._hasNewCount(pre)) {
|
|||
|
|
if (!this._hasNewCount(post)) {
|
|||
|
|
theme.addChild(pre);
|
|||
|
|
rheme.addChild(v);
|
|||
|
|
rheme.addChild(post);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
theme.addChild(pre);
|
|||
|
|
theme.addChild(v);
|
|||
|
|
rheme.addChild(post);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
if (!this._hasNewCount(post)) {
|
|||
|
|
if (!this._hasNewCount(v)) {
|
|||
|
|
rheme.addChild(pre);
|
|||
|
|
theme.addChild(v);
|
|||
|
|
theme.addChild(post);
|
|||
|
|
tr.addChild(rheme);
|
|||
|
|
tr.addChild(theme);
|
|||
|
|
flipped = true;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
theme.addChild(pre);
|
|||
|
|
rheme.addChild(v);
|
|||
|
|
rheme.addChild(post);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
theme.addChild(pre);
|
|||
|
|
theme.addChild(v);
|
|||
|
|
rheme.addChild(post);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (!flipped) {
|
|||
|
|
tr.addChild(theme);
|
|||
|
|
tr.addChild(rheme);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (n.type === Types_1.NLPNodeType.WORD) {
|
|||
|
|
newSentence.addChild(n);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw Error(`Shouldn't happen`);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
else if (c.type === Types_1.NLPNodeType.WORD) {
|
|||
|
|
newRoot.addChild(c);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw Error(`Shouldn't happen`);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return newRoot;
|
|||
|
|
}
|
|||
|
|
_hasNewCount(node) {
|
|||
|
|
let n = node.att.get('newCount');
|
|||
|
|
return !!n;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.ThemeRhemeParser = ThemeRhemeParser;
|
|||
|
|
|
|||
|
|
},{"../../common/Types":13,"jibo-node-xml":undefined}],53:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
function __export(m) {
|
|||
|
|
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|||
|
|
}
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
__export(require("./Lexer"));
|
|||
|
|
__export(require("./NLParser"));
|
|||
|
|
__export(require("./ThemeRhemeParser"));
|
|||
|
|
|
|||
|
|
},{"./Lexer":50,"./NLParser":51,"./ThemeRhemeParser":52}],54:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|||
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|||
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|||
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|||
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|||
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const jibo_state_machine_1 = require("jibo-state-machine");
|
|||
|
|
const jibo_cai_utils_1 = require("jibo-cai-utils");
|
|||
|
|
const InputProcessor_1 = require("../processing/InputProcessor");
|
|||
|
|
const Utils_1 = require("../../utils/Utils");
|
|||
|
|
class BuildDispatchableState extends jibo_state_machine_1.State {
|
|||
|
|
constructor(sm, es, name) {
|
|||
|
|
super(sm, name);
|
|||
|
|
this.es = es;
|
|||
|
|
this.onEntry = (transition, data) => __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
this.es.log.debug("Building dispatchable Action Timelines");
|
|||
|
|
this.ttsDispatchChainPr = Promise.resolve();
|
|||
|
|
this.animDispatchChainPr = Promise.resolve();
|
|||
|
|
this.animDispatchPrs = [];
|
|||
|
|
this.screenDispatchPrs = new jibo_cai_utils_1.PromiseQueue();
|
|||
|
|
this.ttsDone = new Utils_1.ExtPromise();
|
|||
|
|
this.animDone = new Utils_1.ExtPromise();
|
|||
|
|
this.audioDone = new Utils_1.ExtPromise();
|
|||
|
|
this.lastTTSFrame = null;
|
|||
|
|
this.lastAnimFrame = null;
|
|||
|
|
this.lastAudioStop = 0;
|
|||
|
|
let dispatchableTimeline = [];
|
|||
|
|
let consume = {
|
|||
|
|
ttsFrame: data.timeline.tts._root,
|
|||
|
|
animFrame: data.timeline.anim._root,
|
|||
|
|
};
|
|||
|
|
while (consume.ttsFrame || consume.animFrame) {
|
|||
|
|
if (consume.ttsFrame) {
|
|||
|
|
this.lastTTSFrame = consume.ttsFrame;
|
|||
|
|
let currentTTSFrame = consume.ttsFrame;
|
|||
|
|
if (currentTTSFrame.data.speakingSSMLText) {
|
|||
|
|
dispatchableTimeline.push(this._generateTTSAction(currentTTSFrame));
|
|||
|
|
}
|
|||
|
|
consume.ttsFrame = consume.ttsFrame.next;
|
|||
|
|
}
|
|||
|
|
if (consume.animFrame) {
|
|||
|
|
this.lastAnimFrame = consume.animFrame;
|
|||
|
|
const currentAnimFrame = consume.animFrame;
|
|||
|
|
const returnToIdle = currentAnimFrame.data.getAttribute(InputProcessor_1.TagAttributes.END_NEUTRAL) === 'true';
|
|||
|
|
const playOptions = {
|
|||
|
|
forceReturnToIdle: returnToIdle,
|
|||
|
|
screenCenterOverride: true,
|
|||
|
|
ownerInformation: this.es.ownerInformation
|
|||
|
|
};
|
|||
|
|
const playbackData = currentAnimFrame.data.playbackData;
|
|||
|
|
if (playbackData.playbackLayers.Audio && (currentAnimFrame.stop > this.lastAudioStop)) {
|
|||
|
|
this.lastAudioStop = currentAnimFrame.stop;
|
|||
|
|
}
|
|||
|
|
dispatchableTimeline.push(this._generateAnimAction(currentAnimFrame, playbackData, playOptions));
|
|||
|
|
consume.animFrame = consume.animFrame.next;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (data.timeline.anim.length > 0 && this.lastAnimFrame) {
|
|||
|
|
if (this.lastAudioStop === 0) {
|
|||
|
|
this.audioDone.resolve();
|
|||
|
|
}
|
|||
|
|
dispatchableTimeline.push(this._generateFinalAnimAction(data));
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
this.audioDone.resolve();
|
|||
|
|
this.animDone.resolve(data.speakOptions.dispatchComplete);
|
|||
|
|
}
|
|||
|
|
if (data.timeline.tts.length > 0 && this.lastTTSFrame) {
|
|||
|
|
dispatchableTimeline.push(this._generateFinalTTSAction(data));
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
this.audioDone.promise.then(() => {
|
|||
|
|
this.ttsDone.resolve(data.speakOptions.dispatchComplete);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
dispatchableTimeline.sort((actionA, actionB) => {
|
|||
|
|
return actionA.timeMs - actionB.timeMs;
|
|||
|
|
});
|
|||
|
|
data.dispatchableTimeline = dispatchableTimeline;
|
|||
|
|
data.ttsDonePr = this.ttsDone.promise;
|
|||
|
|
data.animDonePr = this.animDone.promise;
|
|||
|
|
return data;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
_generateTTSAction(ttsFrame) {
|
|||
|
|
return {
|
|||
|
|
timeMs: Utils_1.Utils.secToMillisec(ttsFrame.start),
|
|||
|
|
action: () => {
|
|||
|
|
this.ttsDispatchChainPr = this.ttsDispatchChainPr.then(() => {
|
|||
|
|
if (!ttsFrame.prev) {
|
|||
|
|
this.es.jibo.performance.log('EmbodiedSpeechTTSStartSkill', 'Before calling first TTS.speak');
|
|||
|
|
this.es.jibo.performance.log('EmbodiedSpeech_currentTTSFrameData', ttsFrame.data.speakingSSMLText);
|
|||
|
|
}
|
|||
|
|
this.es.jibo.autobot.log('EmbodiedSpeech sending TTS', ttsFrame.data.speakingSSMLText, ttsFrame.data.params);
|
|||
|
|
return this.es.jibo.tts.speak(ttsFrame.data.speakingSSMLText, ttsFrame.data.params)
|
|||
|
|
.catch(e => {
|
|||
|
|
this.es.log.error(e);
|
|||
|
|
return this.es.stop();
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
_generateFinalTTSAction(data) {
|
|||
|
|
return {
|
|||
|
|
timeMs: Utils_1.Utils.secToMillisec(this.lastTTSFrame.start),
|
|||
|
|
action: () => {
|
|||
|
|
this.ttsDispatchChainPr = this.ttsDispatchChainPr
|
|||
|
|
.then(() => {
|
|||
|
|
this.es.jibo.performance.log('EmbodiedSpeechTTSStopSkill', 'After last TTS.speak is finished');
|
|||
|
|
return this.audioDone;
|
|||
|
|
})
|
|||
|
|
.then(() => {
|
|||
|
|
this.es.jibo.performance.log('EmbodiedSpeechTTSStopSkill', 'All speech (verbal and SSA) is finished');
|
|||
|
|
this.ttsDone.resolve(data.speakOptions.dispatchComplete);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
_generateAnimAction(animFrame, playbackData, playOptions) {
|
|||
|
|
return {
|
|||
|
|
timeMs: Utils_1.Utils.secToMillisec(animFrame.start),
|
|||
|
|
action: () => {
|
|||
|
|
let playback;
|
|||
|
|
const _playedPrProvider = () => playbackData.playbackPr
|
|||
|
|
.then(_playback => {
|
|||
|
|
playback = _playback;
|
|||
|
|
return this.play(_playback, playOptions);
|
|||
|
|
})
|
|||
|
|
.then(() => {
|
|||
|
|
if (animFrame.stop === this.lastAudioStop) {
|
|||
|
|
this.audioDone.resolve();
|
|||
|
|
}
|
|||
|
|
const pbIdx = this.es.playingKeys.indexOf(playback);
|
|||
|
|
if (pbIdx !== -1) {
|
|||
|
|
this.es.playingKeys.splice(pbIdx, 1);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
if (playbackData.playbackLayers.Screen) {
|
|||
|
|
this.screenDispatchPrs.add(_playedPrProvider);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
this.animDispatchPrs.push(_playedPrProvider());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
_generateFinalAnimAction(data) {
|
|||
|
|
return {
|
|||
|
|
timeMs: Utils_1.Utils.secToMillisec(this.lastAnimFrame.start),
|
|||
|
|
action: () => {
|
|||
|
|
this.animDispatchPrs.push(this.screenDispatchPrs.waitUntilEmpty());
|
|||
|
|
this.animDispatchChainPr = this.animDispatchChainPr
|
|||
|
|
.then(() => {
|
|||
|
|
return Promise.all(this.animDispatchPrs);
|
|||
|
|
})
|
|||
|
|
.then(() => {
|
|||
|
|
this.es.jibo.performance.log('EmbodiedSpeechAnimStopSkill', 'After last animation is finished');
|
|||
|
|
this.animDone.resolve(data.speakOptions.dispatchComplete);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
play(playback, options) {
|
|||
|
|
this.es.playingKeys.push(playback);
|
|||
|
|
return playback.play(options);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.BuildDispatchableState = BuildDispatchableState;
|
|||
|
|
|
|||
|
|
},{"../../utils/Utils":65,"../processing/InputProcessor":19,"jibo-cai-utils":undefined,"jibo-state-machine":undefined}],55:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|||
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|||
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|||
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|||
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|||
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const jibo_state_machine_1 = require("jibo-state-machine");
|
|||
|
|
class CompleteState extends jibo_state_machine_1.State {
|
|||
|
|
constructor(sm, es, name) {
|
|||
|
|
super(sm, name);
|
|||
|
|
this.es = es;
|
|||
|
|
this.onEntry = () => __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
this.es.jibo.performance.log('EmbodiedSpeechCenterRobotStopSkill', 'After end-speech clean-up is finished');
|
|||
|
|
this.es.log.info("Cleaning up session");
|
|||
|
|
yield this.sm.stop();
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.CompleteState = CompleteState;
|
|||
|
|
|
|||
|
|
},{"jibo-state-machine":undefined}],56:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|||
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|||
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|||
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|||
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|||
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const jibo_state_machine_1 = require("jibo-state-machine");
|
|||
|
|
const InputProcessor_1 = require("../processing/InputProcessor");
|
|||
|
|
class CreateTimelineState extends jibo_state_machine_1.State {
|
|||
|
|
constructor(sm, es, name) {
|
|||
|
|
super(sm, name);
|
|||
|
|
this.es = es;
|
|||
|
|
this.onEntry = (transition, data) => __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
let preInputTree;
|
|||
|
|
let nlParseTree;
|
|||
|
|
let autoTagTrees;
|
|||
|
|
this.es.jibo.performance.log('EmbodiedSpeechBuildingStartSkill', 'When ES starts building structures for dispatch');
|
|||
|
|
this.es.log.debug("Generating pre-Input Tree");
|
|||
|
|
preInputTree = yield this.es.inputProcessor.generatePreInputTree(data.textToSpeak);
|
|||
|
|
if (!data.speakOptions.disableAutoRules) {
|
|||
|
|
this.es.log.debug("Applying Timeline-modifying Auto Rules");
|
|||
|
|
const timelineAutoRuleMatches = this.es.autoRuleManager.applyTimelineModifyingRules(preInputTree, data.autoRuleConfig);
|
|||
|
|
preInputTree = this.es.inputProcessor.insertTimelineAutoRules(preInputTree, timelineAutoRuleMatches);
|
|||
|
|
}
|
|||
|
|
this.es.log.debug("Cleaning input and generating NL Parse Tree");
|
|||
|
|
const cleanTextArray = InputProcessor_1.InputProcessor.getPlainTextArrayFromTree(preInputTree);
|
|||
|
|
nlParseTree = yield this.es.nlParser.parse(cleanTextArray, preInputTree.expansions, preInputTree.contractions);
|
|||
|
|
if (!data.speakOptions.disableAutoRules) {
|
|||
|
|
this.es.log.debug("Applying standard Auto Rules");
|
|||
|
|
autoTagTrees = this.es.autoRuleManager.applyRules(nlParseTree, data.autoRuleConfig);
|
|||
|
|
}
|
|||
|
|
this.es.log.debug("Generating Input Tree");
|
|||
|
|
const inputTree = InputProcessor_1.InputProcessor.generateInputTree(preInputTree, nlParseTree);
|
|||
|
|
this.es.jibo.performance.log('EmbodiedSpeechBuildingTreesCompleteSkill', 'When ES completes building trees for timelines');
|
|||
|
|
this.es.log.debug("Generating Timeline of TTS and Animations");
|
|||
|
|
const timeline = yield this.es.timelineManager.generateTimeline(inputTree, data.speakOptions, autoTagTrees);
|
|||
|
|
this.es.jibo.performance.log('EmbodiedSpeechBuildingTimelinesCompleteSkill', 'When ES completes building timelines for dispatch');
|
|||
|
|
data.timeline = timeline;
|
|||
|
|
return data;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.CreateTimelineState = CreateTimelineState;
|
|||
|
|
|
|||
|
|
},{"../processing/InputProcessor":19,"jibo-state-machine":undefined}],57:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|||
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|||
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|||
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|||
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|||
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const jibo_state_machine_1 = require("jibo-state-machine");
|
|||
|
|
const jibo_cai_utils_1 = require("jibo-cai-utils");
|
|||
|
|
const jibo_common_types_1 = require("jibo-common-types");
|
|||
|
|
const Types_1 = require("../common/Types");
|
|||
|
|
const Utils_1 = require("../../utils/Utils");
|
|||
|
|
const TIMEOUT = 3000;
|
|||
|
|
const STOP_FAILED = 'STOP_FAILED';
|
|||
|
|
class DispatchState extends jibo_state_machine_1.State {
|
|||
|
|
constructor(sm, es, name) {
|
|||
|
|
super(sm, name);
|
|||
|
|
this.es = es;
|
|||
|
|
let dataflowCache;
|
|||
|
|
let actionTimeline;
|
|||
|
|
let dispatched;
|
|||
|
|
let dispatchedPr;
|
|||
|
|
let attnModeHandle;
|
|||
|
|
let dispatchInterruptPr;
|
|||
|
|
let failsafeTimeoutHandle;
|
|||
|
|
let failsafeTriggered;
|
|||
|
|
let stopped;
|
|||
|
|
this.onEntry = (transition, data) => __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
dataflowCache = data;
|
|||
|
|
attnModeHandle = null;
|
|||
|
|
dispatched = false;
|
|||
|
|
dispatchInterruptPr = new Utils_1.ExtPromise();
|
|||
|
|
failsafeTriggered = false;
|
|||
|
|
stopped = false;
|
|||
|
|
this.es.animationDispatchPr = dataflowCache.animDonePr;
|
|||
|
|
const resolvedDispatchType = data.timeline.tts._root.data.dispatchOverride || dataflowCache.speakOptions.dispatchComplete;
|
|||
|
|
dispatchedPr = (resolvedDispatchType === Types_1.DispatchType.TTS) ? dataflowCache.ttsDonePr : Promise.all([dataflowCache.ttsDonePr, dataflowCache.animDonePr]);
|
|||
|
|
actionTimeline = new jibo_cai_utils_1.ActionTimeline();
|
|||
|
|
this.es.playingKeys = [];
|
|||
|
|
let currAttnMode;
|
|||
|
|
if (!stopped) {
|
|||
|
|
this.es.log.info("Pushing Speaking Attention Mode");
|
|||
|
|
currAttnMode = yield Utils_1.timeout(this.es.jibo.expression.getAttentionMode(), TIMEOUT, {
|
|||
|
|
log: this.es.log,
|
|||
|
|
logMessage: 'expression.getAttentionMode',
|
|||
|
|
timeoutValue: jibo_common_types_1.AttentionMode.OFF
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
if (!stopped) {
|
|||
|
|
if (currAttnMode !== jibo_common_types_1.AttentionMode.OFF) {
|
|||
|
|
attnModeHandle = yield Utils_1.timeout(this.es.jibo.expression.pushAttentionMode(jibo_common_types_1.AttentionMode.SPEAKING), TIMEOUT, {
|
|||
|
|
log: this.es.log,
|
|||
|
|
logMessage: 'pushAttentionMode(AttentionMode.SPEAKING)',
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (!stopped) {
|
|||
|
|
const activeMode = this.es.ed.listen.getActiveMode();
|
|||
|
|
if (!activeMode) {
|
|||
|
|
this.es.log.info("Waiting for Embodied Listen to finish");
|
|||
|
|
yield Utils_1.timeout(this.es.ed.listen.waitForIdle(), TIMEOUT, {
|
|||
|
|
log: this.es.log,
|
|||
|
|
logMessage: 'embodiedListen.waitForIdle'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (!stopped) {
|
|||
|
|
this.es.jibo.performance.log('EmbodiedSpeechDispatchStartSkill', 'Before starting all ES TTS/ANIM dispatch');
|
|||
|
|
this.es.log.info("Dispatching Timeline: ", dataflowCache.session);
|
|||
|
|
actionTimeline.dispatchTimeline(dataflowCache.dispatchableTimeline);
|
|||
|
|
dispatched = true;
|
|||
|
|
if (dataflowCache.timeline.anim.length > 0) {
|
|||
|
|
const FAILSAFE_TIMEOUT_MS = ((3 * Math.max(dataflowCache.timeline.tts.stop, dataflowCache.timeline.anim.stop)) * 1000);
|
|||
|
|
failsafeTimeoutHandle = this.es.jibo.timer.setTimeout(() => {
|
|||
|
|
if (this.es.active && (this.es.active.id === dataflowCache.session)) {
|
|||
|
|
this.es.log.warn("Timeline dispatch timeout reached -- triggering failsafe stopping of dispatch: ", dataflowCache.session);
|
|||
|
|
failsafeTriggered = true;
|
|||
|
|
this.es._stop();
|
|||
|
|
}
|
|||
|
|
}, FAILSAFE_TIMEOUT_MS);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
yield Promise.race([dispatchedPr, dispatchInterruptPr.promise]);
|
|||
|
|
});
|
|||
|
|
this.onStop = () => __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
this.es.log.info("Timeline Dispatch Stopped");
|
|||
|
|
stopped = true;
|
|||
|
|
let reset = failsafeTriggered;
|
|||
|
|
if (failsafeTimeoutHandle) {
|
|||
|
|
this.es.jibo.timer.clearTimeout(failsafeTimeoutHandle);
|
|||
|
|
}
|
|||
|
|
if (actionTimeline) {
|
|||
|
|
this.es.log.debug("Fast forwarding action timeline");
|
|||
|
|
actionTimeline.fastForward();
|
|||
|
|
}
|
|||
|
|
const stopPromises = [];
|
|||
|
|
if (this.es.playingKeys.length > 0) {
|
|||
|
|
this.es.log.debug("Stopping all in-progress keys");
|
|||
|
|
this.es.playingKeys.forEach(keysToStop => {
|
|||
|
|
stopPromises.push(keysToStop.stop());
|
|||
|
|
});
|
|||
|
|
this.es.playingKeys = [];
|
|||
|
|
}
|
|||
|
|
try {
|
|||
|
|
this.es.log.debug("Awaiting all in progress keys being stopped");
|
|||
|
|
const stopAllResult = yield Utils_1.timeout(Promise.all(stopPromises), TIMEOUT, {
|
|||
|
|
log: this.es.log,
|
|||
|
|
logMessage: 'embodiedSpeech.stop awaiting in progress keys stop',
|
|||
|
|
timeoutValue: STOP_FAILED
|
|||
|
|
});
|
|||
|
|
if (typeof stopAllResult === 'string') {
|
|||
|
|
if (stopAllResult === STOP_FAILED) {
|
|||
|
|
this.es.log.debug('Stopping timeout encountered, attempting hard reset');
|
|||
|
|
reset = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (error) {
|
|||
|
|
this.es.log.error(error);
|
|||
|
|
this.es.log.debug('Bad stop encountered, attempting hard reset');
|
|||
|
|
reset = true;
|
|||
|
|
}
|
|||
|
|
this.es.log.debug("Stopping any active TTS output");
|
|||
|
|
try {
|
|||
|
|
yield this.es.jibo.tts.stop();
|
|||
|
|
}
|
|||
|
|
catch (error) {
|
|||
|
|
this.es.log.error(error);
|
|||
|
|
}
|
|||
|
|
if (dataflowCache.centeringEnabled) {
|
|||
|
|
this.es.log.debug("Centering the robot after speech");
|
|||
|
|
const centerRobotConfig = {
|
|||
|
|
requestor: this.es.ownerInformation,
|
|||
|
|
dofs: this.es.dofsToCenter,
|
|||
|
|
centerGlobally: false
|
|||
|
|
};
|
|||
|
|
try {
|
|||
|
|
const centerResult = yield Utils_1.timeout(this.es.jibo.expression.centerRobot(centerRobotConfig), TIMEOUT, {
|
|||
|
|
log: this.es.log,
|
|||
|
|
logMessage: 'embodiedSpeech.stop awaiting center robot',
|
|||
|
|
timeoutValue: STOP_FAILED
|
|||
|
|
});
|
|||
|
|
if (typeof centerResult === 'string') {
|
|||
|
|
if (centerResult === STOP_FAILED) {
|
|||
|
|
this.es.log.debug('Stopping timeout encountered, attempting hard reset');
|
|||
|
|
reset = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (error) {
|
|||
|
|
this.es.log.error(error);
|
|||
|
|
this.es.log.debug('Bad stop encountered, attempting hard reset');
|
|||
|
|
reset = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (!reset && dispatched) {
|
|||
|
|
this.es.log.debug("Awaiting all dispatch promises completion");
|
|||
|
|
try {
|
|||
|
|
const dispatchResult = yield Utils_1.timeout(dispatchedPr, TIMEOUT, {
|
|||
|
|
log: this.es.log,
|
|||
|
|
logMessage: 'embodiedSpeech.stop awaiting dispatch completion',
|
|||
|
|
timeoutValue: STOP_FAILED
|
|||
|
|
});
|
|||
|
|
if (typeof dispatchResult === 'string') {
|
|||
|
|
if (dispatchResult === STOP_FAILED) {
|
|||
|
|
this.es.log.debug('Stopping timeout encountered, attempting hard reset');
|
|||
|
|
reset = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (error) {
|
|||
|
|
this.es.log.error(error);
|
|||
|
|
this.es.log.debug('Bad stop encountered, attempting hard reset');
|
|||
|
|
reset = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
actionTimeline = null;
|
|||
|
|
dispatchInterruptPr.resolve();
|
|||
|
|
});
|
|||
|
|
this.onExit = () => __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
this.es.jibo.performance.log('EmbodiedSpeechDispatchStopSkill', 'After completing all ES TTS/ANIM dispatch');
|
|||
|
|
this.es.log.info("Timeline Dispatch Complete: ", dataflowCache.session);
|
|||
|
|
if (failsafeTimeoutHandle) {
|
|||
|
|
this.es.jibo.timer.clearTimeout(failsafeTimeoutHandle);
|
|||
|
|
}
|
|||
|
|
if (attnModeHandle) {
|
|||
|
|
this.es.log.debug("Releasing Speaking AttentionMode Handle");
|
|||
|
|
try {
|
|||
|
|
yield Utils_1.timeout(attnModeHandle.release(), TIMEOUT, {
|
|||
|
|
log: this.es.log,
|
|||
|
|
logMessage: 'attnModeHandle.release()',
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
catch (error) {
|
|||
|
|
this.es.log.warn(error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (actionTimeline) {
|
|||
|
|
this.es.log.debug("Fast forwarding action timeline");
|
|||
|
|
actionTimeline.fastForward();
|
|||
|
|
}
|
|||
|
|
if ((dataflowCache.timeline.anim.length > 0) && (dataflowCache.centeringEnabled)) {
|
|||
|
|
this.es.log.debug("Centering the robot after speech");
|
|||
|
|
try {
|
|||
|
|
const centerRobotConfig = {
|
|||
|
|
requestor: this.es.ownerInformation,
|
|||
|
|
dofs: this.es.dofsToCenter,
|
|||
|
|
centerGlobally: false
|
|||
|
|
};
|
|||
|
|
yield Utils_1.timeout(this.es.jibo.expression.centerRobot(centerRobotConfig), TIMEOUT, {
|
|||
|
|
log: this.es.log,
|
|||
|
|
logMessage: 'embodiedSpeech awaiting center robot'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
catch (error) {
|
|||
|
|
this.es.log.warn(error);
|
|||
|
|
}
|
|||
|
|
this.es.jibo.performance.log('EmbodiedSpeechCenterRobotStopSkill', 'After automatic CenterRobot is finished');
|
|||
|
|
}
|
|||
|
|
this.es.log.info("Speak Complete: ", dataflowCache.session);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.DispatchState = DispatchState;
|
|||
|
|
|
|||
|
|
},{"../../utils/Utils":65,"../common/Types":13,"jibo-cai-utils":undefined,"jibo-common-types":undefined,"jibo-state-machine":undefined}],58:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const CreateTimeline_1 = require("./CreateTimeline");
|
|||
|
|
exports.CreateTimelineState = CreateTimeline_1.CreateTimelineState;
|
|||
|
|
const BuildDispatchable_1 = require("./BuildDispatchable");
|
|||
|
|
exports.BuildDispatchableState = BuildDispatchable_1.BuildDispatchableState;
|
|||
|
|
const Dispatch_1 = require("./Dispatch");
|
|||
|
|
exports.DispatchState = Dispatch_1.DispatchState;
|
|||
|
|
const Complete_1 = require("./Complete");
|
|||
|
|
exports.CompleteState = Complete_1.CompleteState;
|
|||
|
|
|
|||
|
|
},{"./BuildDispatchable":54,"./Complete":55,"./CreateTimeline":56,"./Dispatch":57}],59:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const Types_1 = require("../common/Types");
|
|||
|
|
exports.TimelineLayerType = {
|
|||
|
|
ANIM: Types_1.AssetNodeType.ANIM,
|
|||
|
|
TTS: Types_1.TTSNodeType.TTS
|
|||
|
|
};
|
|||
|
|
class TimelineFrame {
|
|||
|
|
constructor(start, stop, data = undefined, blocking = false, prev = null, next = null) {
|
|||
|
|
this.start = start;
|
|||
|
|
this.stop = stop;
|
|||
|
|
this.data = data;
|
|||
|
|
this.blocking = blocking;
|
|||
|
|
this.prev = prev;
|
|||
|
|
this.next = next;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.TimelineFrame = TimelineFrame;
|
|||
|
|
class TimelineLayer {
|
|||
|
|
constructor(name, _timeline, _frameBuffer, _assetRelativeEnd, _enableMerging = false) {
|
|||
|
|
this.name = name;
|
|||
|
|
this._timeline = _timeline;
|
|||
|
|
this._frameBuffer = _frameBuffer;
|
|||
|
|
this._assetRelativeEnd = _assetRelativeEnd;
|
|||
|
|
this._enableMerging = _enableMerging;
|
|||
|
|
this._root = null;
|
|||
|
|
this.length = 0;
|
|||
|
|
}
|
|||
|
|
insert(pendingFrame, withBuffer = false, layerMergeOverride) {
|
|||
|
|
const pendingLayerData = pendingFrame.data.playbackData.playbackLayers;
|
|||
|
|
if ((this._assetRelativeEnd !== undefined) && ((pendingFrame.stop > (this._timeline.tts.stop + this._assetRelativeEnd))) && !pendingLayerData.Audio) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
const pendingFrameLayersAsInt = TimelineLayer._metaLayerToInt(pendingLayerData);
|
|||
|
|
const conflicts = this._gatherPotentialConflicts(pendingFrame, withBuffer);
|
|||
|
|
const allowMerging = (layerMergeOverride !== undefined) ? layerMergeOverride : this._enableMerging;
|
|||
|
|
let insert = (conflicts.length === 0);
|
|||
|
|
if (conflicts.length !== 0 && allowMerging) {
|
|||
|
|
insert = conflicts.every(frame => {
|
|||
|
|
let conflictLayerData = frame.data.playbackData.playbackLayers;
|
|||
|
|
let layersAsInt = TimelineLayer._metaLayerToInt(conflictLayerData);
|
|||
|
|
let inConflict = layersAsInt & pendingFrameLayersAsInt;
|
|||
|
|
return (inConflict === 0);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
if (insert) {
|
|||
|
|
if ((this.start === undefined) || (pendingFrame.start < this.start)) {
|
|||
|
|
this.start = pendingFrame.start;
|
|||
|
|
}
|
|||
|
|
if ((this.stop === undefined) || (pendingFrame.stop > this.stop)) {
|
|||
|
|
this.stop = pendingFrame.stop;
|
|||
|
|
}
|
|||
|
|
this._insert(pendingFrame);
|
|||
|
|
}
|
|||
|
|
return insert;
|
|||
|
|
}
|
|||
|
|
static _metaLayerToInt(metaLayerPresence) {
|
|||
|
|
const layerBits = [
|
|||
|
|
Number(metaLayerPresence.Body),
|
|||
|
|
Number(metaLayerPresence.Screen),
|
|||
|
|
Number(metaLayerPresence.Audio)
|
|||
|
|
];
|
|||
|
|
return parseInt(layerBits.join(''), 2);
|
|||
|
|
}
|
|||
|
|
_gatherPotentialConflicts(pendingFrame, useBuffer) {
|
|||
|
|
let currentFrame;
|
|||
|
|
let potentialConflicts = [];
|
|||
|
|
if (!this._root) {
|
|||
|
|
return potentialConflicts;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
currentFrame = this._root;
|
|||
|
|
while (currentFrame) {
|
|||
|
|
const dynamicBuffer = (useBuffer ? this._frameBuffer : 0);
|
|||
|
|
const currentFrameStart = Math.round((currentFrame.start - dynamicBuffer) * 1000) / 1000;
|
|||
|
|
const currentFrameStop = Math.round((currentFrame.stop + dynamicBuffer) * 1000) / 1000;
|
|||
|
|
const pendingFrameStart = Math.round((pendingFrame.start - dynamicBuffer) * 1000) / 1000;
|
|||
|
|
const pendingFrameStop = Math.round((pendingFrame.stop + dynamicBuffer) * 1000) / 1000;
|
|||
|
|
if (pendingFrameStart < currentFrameStop && pendingFrameStop > currentFrameStart) {
|
|||
|
|
potentialConflicts.push(currentFrame);
|
|||
|
|
}
|
|||
|
|
currentFrame = currentFrame.next;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return potentialConflicts;
|
|||
|
|
}
|
|||
|
|
_insert(pendingFrame) {
|
|||
|
|
let currentFrame;
|
|||
|
|
let previousFrame;
|
|||
|
|
if (!this._root) {
|
|||
|
|
this._root = pendingFrame;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
currentFrame = this._root;
|
|||
|
|
while (currentFrame) {
|
|||
|
|
if (pendingFrame.start <= currentFrame.start) {
|
|||
|
|
pendingFrame.next = currentFrame;
|
|||
|
|
pendingFrame.prev = currentFrame.prev;
|
|||
|
|
if (currentFrame.prev) {
|
|||
|
|
currentFrame.prev.next = pendingFrame;
|
|||
|
|
}
|
|||
|
|
currentFrame.prev = pendingFrame;
|
|||
|
|
if (currentFrame === this._root) {
|
|||
|
|
this._root = pendingFrame;
|
|||
|
|
}
|
|||
|
|
this.length++;
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
previousFrame = currentFrame;
|
|||
|
|
currentFrame = currentFrame.next;
|
|||
|
|
}
|
|||
|
|
pendingFrame.prev = previousFrame;
|
|||
|
|
previousFrame.next = pendingFrame;
|
|||
|
|
}
|
|||
|
|
this.length++;
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.TimelineLayer = TimelineLayer;
|
|||
|
|
class Timeline {
|
|||
|
|
constructor(frameBuffer, assetRelativeEnd, enableLayerMerging = false) {
|
|||
|
|
this.tts = new TimelineLayer(exports.TimelineLayerType.TTS, this, frameBuffer, assetRelativeEnd);
|
|||
|
|
this.anim = new TimelineLayer(exports.TimelineLayerType.ANIM, this, frameBuffer, assetRelativeEnd, enableLayerMerging);
|
|||
|
|
}
|
|||
|
|
_init(ttsFrames) {
|
|||
|
|
ttsFrames.forEach(frame => {
|
|||
|
|
if ((this.tts.start === undefined) || (frame.start < this.tts.start)) {
|
|||
|
|
this.tts.start = frame.start;
|
|||
|
|
}
|
|||
|
|
if ((this.tts.stop === undefined) || (frame.stop > this.tts.stop)) {
|
|||
|
|
this.tts.stop = frame.stop;
|
|||
|
|
}
|
|||
|
|
this.tts._insert(new TimelineFrame(frame.start, frame.stop, frame.data));
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.Timeline = Timeline;
|
|||
|
|
|
|||
|
|
},{"../common/Types":13}],60:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|||
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|||
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|||
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|||
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|||
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const _ = require("lodash/lodash.min");
|
|||
|
|
const path = require("path");
|
|||
|
|
const jibo_cai_utils_1 = require("jibo-cai-utils");
|
|||
|
|
const Timeline_1 = require("./Timeline");
|
|||
|
|
const InputProcessor_1 = require("../processing/InputProcessor");
|
|||
|
|
const Timeline_2 = require("./Timeline");
|
|||
|
|
const SSMLNode_1 = require("../processing/SSMLNode");
|
|||
|
|
const Formats_1 = require("../processing/Formats");
|
|||
|
|
const AutoRuleManager_1 = require("../processing/auto_rules/AutoRuleManager");
|
|||
|
|
const Types_1 = require("../common/Types");
|
|||
|
|
const log_1 = require("../../log");
|
|||
|
|
const log = log_1.speechLog.createChild("TimelineManager");
|
|||
|
|
const TTS_PAU = '[lpau]';
|
|||
|
|
const TTS_BREAK = '<break>';
|
|||
|
|
const TTS_AUDIO_BREAK = '<audioBreak>';
|
|||
|
|
const TTS_SAY_AS = '<say-as>';
|
|||
|
|
const FRAME_RATE = 30.0;
|
|||
|
|
const AUTORULE_GATE_RATE = 1.0;
|
|||
|
|
const AUTORULE_ORIENTATION_PROBABILITY = 0.5;
|
|||
|
|
class AssetResolution {
|
|||
|
|
constructor(resolved = false, identifier = null, reason = null) {
|
|||
|
|
this.resolved = resolved;
|
|||
|
|
this.identifier = identifier;
|
|||
|
|
this.reason = reason;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.AssetResolution = AssetResolution;
|
|||
|
|
class TimelineManager {
|
|||
|
|
constructor(jibo, _resourceRoot, _animResourceRoot, _audioResourceRoot) {
|
|||
|
|
this.jibo = jibo;
|
|||
|
|
this._resourceRoot = _resourceRoot;
|
|||
|
|
this._animResourceRoot = _animResourceRoot;
|
|||
|
|
this._audioResourceRoot = _audioResourceRoot;
|
|||
|
|
this._tempAnimationCollection = new this.jibo.animDB.AnimCollection(this.jibo.animDB._animDB);
|
|||
|
|
}
|
|||
|
|
generateTimeline(inputTree, options, autoTagTrees) {
|
|||
|
|
this.emojiCapReached = false;
|
|||
|
|
return this._preProcessPathBasedAssets(inputTree)
|
|||
|
|
.then(pathAssets => {
|
|||
|
|
this._pathAssets = pathAssets;
|
|||
|
|
return this._inputTreeToTimeline(inputTree, options);
|
|||
|
|
})
|
|||
|
|
.then(timelineData => {
|
|||
|
|
const [timeline, wordSchedule] = timelineData;
|
|||
|
|
if (!autoTagTrees) {
|
|||
|
|
return Promise.resolve(timeline);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
let pending = this._autoTagTreesToPrioritizedTimelines(autoTagTrees, wordSchedule, timeline);
|
|||
|
|
return this._mergePendingWithMaster(pending, timeline);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
_preProcessPathBasedAssets(inputTree) {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
let pathAssetsPr = [];
|
|||
|
|
let pathAssetMap = new Map();
|
|||
|
|
let cachedAssetMap = new Map();
|
|||
|
|
let pathAssets = inputTree.gatherDescendants(node => {
|
|||
|
|
return InputProcessor_1.InputProcessor.isAsset(node) && node.att.has('path');
|
|||
|
|
});
|
|||
|
|
pathAssets.forEach(node => {
|
|||
|
|
let identifier = node.getAttribute('path');
|
|||
|
|
if (node.type === Types_1.AssetNodeType.ES) {
|
|||
|
|
const animPath = path.join(this._animResourceRoot, identifier);
|
|||
|
|
pathAssetsPr.push(new Promise(resolve => {
|
|||
|
|
this.jibo.animDB.AnimDBParser.parseAnimation(this.jibo, animPath, this._resourceRoot)
|
|||
|
|
.then(resolve)
|
|||
|
|
.catch(e => {
|
|||
|
|
resolve();
|
|||
|
|
});
|
|||
|
|
}));
|
|||
|
|
}
|
|||
|
|
else if (node.type === Types_1.AssetNodeType.AUDIO) {
|
|||
|
|
const audioPath = this.jibo.utils.PathUtils.getAssetUri(identifier, undefined, this._audioResourceRoot);
|
|||
|
|
pathAssetsPr.push(new Promise(resolve => {
|
|||
|
|
identifier = path.join('audio', identifier);
|
|||
|
|
this.jibo.loader.load({
|
|||
|
|
type: 'sound',
|
|||
|
|
id: identifier,
|
|||
|
|
src: audioPath,
|
|||
|
|
complete: (err, loadedSound) => {
|
|||
|
|
if (err) {
|
|||
|
|
resolve();
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
resolve(this._getSoundMetadata(loadedSound, audioPath, node, cachedAssetMap));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}));
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
try {
|
|||
|
|
const metaDatum = yield Promise.all(pathAssetsPr);
|
|||
|
|
if (pathAssets.length === metaDatum.length) {
|
|||
|
|
let nodeAnimMetaZip = _.zip(pathAssets, metaDatum);
|
|||
|
|
nodeAnimMetaZip.forEach(([node, metadata]) => {
|
|||
|
|
if (metadata) {
|
|||
|
|
if (metadata.path) {
|
|||
|
|
metadata.path = path.relative(this._resourceRoot, metadata.path);
|
|||
|
|
}
|
|||
|
|
let cached = cachedAssetMap.get(node);
|
|||
|
|
pathAssetMap.set(node, new this.jibo.animDB.Animation(this._tempAnimationCollection, metadata, this._resourceRoot, cached));
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
log.warn('Missing data about local (path-based) animation(s) or audio; unable to utilize in output.');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (e) {
|
|||
|
|
log.warn(e);
|
|||
|
|
}
|
|||
|
|
return pathAssetMap;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
_getSoundMetadata(loadedSound, audioPath, node, cachedAssetMap) {
|
|||
|
|
let duration = Math.ceil(loadedSound.buffer.duration * FRAME_RATE);
|
|||
|
|
if (duration > 0) {
|
|||
|
|
let relAudioPath = path.relative(this._audioResourceRoot, audioPath);
|
|||
|
|
let anim = new Formats_1.AudioAnimTemplate(duration, relAudioPath);
|
|||
|
|
cachedAssetMap.set(node, anim);
|
|||
|
|
try {
|
|||
|
|
return this.jibo.animDB.AnimDBParser.parseAnimationFromAnim(anim);
|
|||
|
|
}
|
|||
|
|
catch (e) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
_inputTreeToTimeline(inputTree, options) {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
const blockingNodes = inputTree.gatherDescendants(node => {
|
|||
|
|
return InputProcessor_1.InputProcessor.isBlocking(node);
|
|||
|
|
});
|
|||
|
|
blockingNodes.forEach((node) => {
|
|||
|
|
let resolution = this._resolveAssetToPlayback(node);
|
|||
|
|
if (!resolution.resolved) {
|
|||
|
|
log.debug(`Could not find match for requested Asset ${resolution.identifier} because ${resolution.reason}`);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
let wordScheduleRelevantNodes = [];
|
|||
|
|
let nonBlockers = [];
|
|||
|
|
let noWords = true;
|
|||
|
|
inputTree.gatherDescendants().forEach(node => {
|
|||
|
|
if (InputProcessor_1.InputProcessor.isUnboundedNonBlocking(node)) {
|
|||
|
|
nonBlockers.push(node);
|
|||
|
|
}
|
|||
|
|
else if (InputProcessor_1.InputProcessor.isBlocking(node)) {
|
|||
|
|
const blockingNode = node;
|
|||
|
|
if (blockingNode.playbackData) {
|
|||
|
|
const newBreak = TimelineManager._buildBreak(blockingNode.playbackData.playbackDuration / FRAME_RATE);
|
|||
|
|
wordScheduleRelevantNodes.push(newBreak);
|
|||
|
|
blockingNode.timeSyncNode = newBreak;
|
|||
|
|
nonBlockers.forEach(nBNode => nBNode.timeSyncNode = newBreak);
|
|||
|
|
nonBlockers = [];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
if (!InputProcessor_1.InputProcessor.isAsset(node)) {
|
|||
|
|
if (!InputProcessor_1.InputProcessor.isTimelessSSML(node)) {
|
|||
|
|
nonBlockers.forEach(nBNode => nBNode.timeSyncNode = node);
|
|||
|
|
nonBlockers = [];
|
|||
|
|
}
|
|||
|
|
wordScheduleRelevantNodes.push(node);
|
|||
|
|
if (noWords && (node.type === Types_1.NLPNodeType.WORD || InputProcessor_1.InputProcessor.isSayAs(node))) {
|
|||
|
|
noWords = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
let dispatchOverride;
|
|||
|
|
if (options.followedByListen) {
|
|||
|
|
dispatchOverride = noWords ? Types_1.DispatchType.ALL : Types_1.DispatchType.TTS;
|
|||
|
|
}
|
|||
|
|
const fullSSMLText = InputProcessor_1.InputProcessor.getSSMLTextFromArray(wordScheduleRelevantNodes);
|
|||
|
|
const shouldPrune = ((options.dispatchComplete === Types_1.DispatchType.TTS) && (dispatchOverride !== Types_1.DispatchType.ALL));
|
|||
|
|
const timingSSMLText = `<speak>${fullSSMLText}</speak>`;
|
|||
|
|
const speakingSSMLText = noWords ? null : timingSSMLText;
|
|||
|
|
const cached = timingSSMLText === speakingSSMLText;
|
|||
|
|
if (options.debugMode) {
|
|||
|
|
console.log(`TIMING:\n ${timingSSMLText}`);
|
|||
|
|
console.log(`SPEAKING:\n ${speakingSSMLText}`);
|
|||
|
|
console.log('-----------');
|
|||
|
|
}
|
|||
|
|
const params = {
|
|||
|
|
locale: this.jibo.tts.TTSLocale.EN_US,
|
|||
|
|
voice: this.jibo.tts.TTSVoice.GRIFFIN,
|
|||
|
|
mode: this.jibo.tts.TTSMode.SSML,
|
|||
|
|
skipWordEvents: this.jibo.tts.TTSBoolean.TRUE,
|
|||
|
|
cached: cached ? this.jibo.tts.TTSBoolean.TRUE : this.jibo.tts.TTSBoolean.FALSE
|
|||
|
|
};
|
|||
|
|
const ttsSpeakData = {
|
|||
|
|
timingSSMLText: timingSSMLText,
|
|||
|
|
speakingSSMLText: speakingSSMLText,
|
|||
|
|
params: params,
|
|||
|
|
dispatchOverride: dispatchOverride
|
|||
|
|
};
|
|||
|
|
const ttsTiming = yield this.jibo.tts.getWordTimings(timingSSMLText, params);
|
|||
|
|
let [timeline, mergedTokenTimes] = TimelineManager._initTimeline(ttsSpeakData, ttsTiming.tokentimes.tokens, options, shouldPrune);
|
|||
|
|
const wordSchedule = TimelineManager._generateWordSchedule(wordScheduleRelevantNodes, mergedTokenTimes, options);
|
|||
|
|
timeline = this._populateTimelineLayers(inputTree, timeline, wordSchedule);
|
|||
|
|
return [timeline, wordSchedule];
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
static _buildBreak(size) {
|
|||
|
|
let newBreak = new SSMLNode_1.SSMLNode(Types_1.SSMLNodeType.BREAK);
|
|||
|
|
const roundedSize = Math.round(size * 1000) / 1000;
|
|||
|
|
newBreak.setAttribute('size', roundedSize);
|
|||
|
|
return newBreak;
|
|||
|
|
}
|
|||
|
|
_resolveAssetToPlayback(node, durationSeconds, randomizeOrient, cache) {
|
|||
|
|
const requestDescription = node.requestInfo.description;
|
|||
|
|
let resolution = new AssetResolution();
|
|||
|
|
let identifier;
|
|||
|
|
let asset;
|
|||
|
|
let durationFramesToFill;
|
|||
|
|
let durationFramesLoopedPlayback;
|
|||
|
|
let durationFramesSinglePlayback;
|
|||
|
|
let playbackLoops = node.loops;
|
|||
|
|
if (durationSeconds !== undefined) {
|
|||
|
|
durationFramesToFill = durationSeconds * FRAME_RATE;
|
|||
|
|
if ((playbackLoops !== undefined) && (playbackLoops > 0)) {
|
|||
|
|
log.warn(`Requested invalid loops '${playbackLoops}' for time-bounded playback.`);
|
|||
|
|
playbackLoops = undefined;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (node.requestInfo.type === Types_1.RequestType.NAME) {
|
|||
|
|
identifier = node.att.get('name');
|
|||
|
|
if (identifier) {
|
|||
|
|
this.jibo.performance.log('EmbodiedSpeech_resolveAssetToPlayback_namedAnimationAsset', requestDescription);
|
|||
|
|
resolution.identifier = requestDescription;
|
|||
|
|
asset = this.jibo.animDB.getAnimByName(identifier);
|
|||
|
|
}
|
|||
|
|
if (!asset) {
|
|||
|
|
resolution.reason = 'animation could not be found in the AnimationDB';
|
|||
|
|
return resolution;
|
|||
|
|
}
|
|||
|
|
else if (durationFramesToFill) {
|
|||
|
|
if (playbackLoops === 0) {
|
|||
|
|
let choice;
|
|||
|
|
if (asset.meta.duration < durationFramesToFill) {
|
|||
|
|
choice = TimelineManager.findOptimalLoop([asset], durationFramesToFill);
|
|||
|
|
}
|
|||
|
|
else if (asset.durationRange.min < durationFramesToFill) {
|
|||
|
|
choice = TimelineManager.findOptimalLoop([asset], durationFramesToFill, true);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
resolution.reason = 'animation cannot fit in the requested time bounds';
|
|||
|
|
return resolution;
|
|||
|
|
}
|
|||
|
|
asset = choice.asset;
|
|||
|
|
durationFramesLoopedPlayback = choice.duration;
|
|||
|
|
playbackLoops = choice.loops;
|
|||
|
|
}
|
|||
|
|
else if (asset.durationRange.min <= durationFramesToFill) {
|
|||
|
|
durationFramesSinglePlayback = Math.max(asset.durationRange.min, Math.min(durationFramesToFill, asset.durationRange.max));
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
resolution.reason = 'animation cannot fit in the requested time bounds';
|
|||
|
|
return resolution;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (node.requestInfo.type === Types_1.RequestType.QUERY) {
|
|||
|
|
this.jibo.performance.log('EmbodiedSpeech_resolveAssetToPlayback_queryAnimationAsset', requestDescription);
|
|||
|
|
const query = {
|
|||
|
|
categories: (node.categoryFilter.someOf.length > 0) ? node.categoryFilter.someOf : node.categoryFilter.allOf,
|
|||
|
|
includeMeta: node.metaFilter.allOf,
|
|||
|
|
includeSomeMeta: node.metaFilter.someOf,
|
|||
|
|
excludeMeta: node.metaFilter.noneOf,
|
|||
|
|
};
|
|||
|
|
const results = this.jibo.animDB.query(query);
|
|||
|
|
if (results.matching.length > 0) {
|
|||
|
|
if (durationFramesToFill) {
|
|||
|
|
if (playbackLoops === 0) {
|
|||
|
|
let choice;
|
|||
|
|
const loopableResults = results.matching.filter(result => {
|
|||
|
|
return result.meta.duration < durationFramesToFill;
|
|||
|
|
});
|
|||
|
|
if (loopableResults.length > 0) {
|
|||
|
|
choice = TimelineManager.findOptimalLoop(loopableResults, durationFramesToFill);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
const minResults = results.matching.filter(result => {
|
|||
|
|
return result.durationRange.min < durationFramesToFill;
|
|||
|
|
});
|
|||
|
|
if (minResults.length > 0) {
|
|||
|
|
choice = TimelineManager.findOptimalLoop(loopableResults, durationFramesToFill, true);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (choice) {
|
|||
|
|
asset = choice.asset;
|
|||
|
|
durationFramesLoopedPlayback = choice.duration;
|
|||
|
|
playbackLoops = choice.loops;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (playbackLoops === undefined) {
|
|||
|
|
const goodFitResults = results.matching.filter(result => {
|
|||
|
|
return (result.durationRange.distanceFrom(durationFramesToFill) === 0);
|
|||
|
|
});
|
|||
|
|
if (goodFitResults.length > 0) {
|
|||
|
|
asset = _.sample(goodFitResults);
|
|||
|
|
durationFramesSinglePlayback = durationFramesToFill;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
const validResults = results.matching.filter(result => {
|
|||
|
|
return (result.durationRange.min < durationFramesToFill);
|
|||
|
|
});
|
|||
|
|
if (validResults.length > 0) {
|
|||
|
|
validResults.sort((a, b) => {
|
|||
|
|
return a.durationRange.max - b.durationRange.max;
|
|||
|
|
});
|
|||
|
|
asset = results.matching[0];
|
|||
|
|
durationFramesSinglePlayback = Math.min(durationFramesToFill, asset.durationRange.max);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
asset = _.sample(results.matching);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (!asset) {
|
|||
|
|
resolution.identifier = requestDescription;
|
|||
|
|
resolution.reason = 'no animation could be found in DB that matched requested attribute (i.e. CAT, META, DURATION) combination';
|
|||
|
|
return resolution;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (node.requestInfo.type === Types_1.RequestType.PATH) {
|
|||
|
|
identifier = node.att.get('path');
|
|||
|
|
this.jibo.performance.log('EmbodiedSpeech_resolveAssetToPlayback_pathAnimationAsset', requestDescription);
|
|||
|
|
asset = this._pathAssets.get(node);
|
|||
|
|
if (!asset) {
|
|||
|
|
resolution.identifier = requestDescription;
|
|||
|
|
resolution.reason = 'requested path based asset could not be loaded';
|
|||
|
|
return resolution;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
resolution.identifier = requestDescription;
|
|||
|
|
resolution.reason = 'no animation could be found in DB (asset tag was malformed)';
|
|||
|
|
return resolution;
|
|||
|
|
}
|
|||
|
|
const [metaLayerPresence, muteConfig] = TimelineManager._createLayerPresences(asset, node);
|
|||
|
|
if (!cache) {
|
|||
|
|
cache = this.jibo.face.eye.CACHE_ID;
|
|||
|
|
}
|
|||
|
|
let animConfig = {
|
|||
|
|
cache: cache
|
|||
|
|
};
|
|||
|
|
if (muteConfig) {
|
|||
|
|
animConfig.mutes = muteConfig;
|
|||
|
|
}
|
|||
|
|
const reqOrient = node.att.get('orientation');
|
|||
|
|
if (reqOrient) {
|
|||
|
|
animConfig.orientation = this.jibo.animDB.Orientation[reqOrient];
|
|||
|
|
}
|
|||
|
|
else if (randomizeOrient) {
|
|||
|
|
animConfig.orientation = (Math.random() > AUTORULE_ORIENTATION_PROBABILITY) ? this.jibo.animDB.Orientation.LEFT : this.jibo.animDB.Orientation.RIGHT;
|
|||
|
|
}
|
|||
|
|
if (durationFramesToFill) {
|
|||
|
|
if (playbackLoops) {
|
|||
|
|
animConfig.duration = durationFramesLoopedPlayback;
|
|||
|
|
animConfig.loops = playbackLoops;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
animConfig.duration = durationFramesSinglePlayback;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
if (playbackLoops) {
|
|||
|
|
durationFramesToFill = asset.meta.duration * playbackLoops;
|
|||
|
|
animConfig.loops = playbackLoops;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
durationFramesToFill = asset.meta.duration;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
node.playbackData = {
|
|||
|
|
playbackGenerator: () => asset.createFromConfig(animConfig),
|
|||
|
|
playbackDuration: durationFramesToFill,
|
|||
|
|
playbackName: asset.name,
|
|||
|
|
playbackLayers: metaLayerPresence
|
|||
|
|
};
|
|||
|
|
resolution.resolved = true;
|
|||
|
|
resolution.identifier = identifier;
|
|||
|
|
return resolution;
|
|||
|
|
}
|
|||
|
|
static findOptimalLoop(candidates, durationFramesToFill, allowMin = false) {
|
|||
|
|
let optimalResult = {
|
|||
|
|
asset: undefined,
|
|||
|
|
duration: undefined,
|
|||
|
|
loops: undefined
|
|||
|
|
};
|
|||
|
|
let smallestError = Infinity;
|
|||
|
|
candidates.forEach(candidate => {
|
|||
|
|
const candidateDuration = allowMin ? candidate.durationRange.min : candidate.meta.duration;
|
|||
|
|
const loops = Math.floor(durationFramesToFill / candidateDuration);
|
|||
|
|
const remainder = durationFramesToFill % candidateDuration;
|
|||
|
|
const adjustment = Math.floor(remainder / loops);
|
|||
|
|
const optimalDuration = Math.min(candidateDuration + adjustment, candidate.durationRange.max);
|
|||
|
|
const error = durationFramesToFill - (optimalDuration * loops);
|
|||
|
|
if (error < smallestError) {
|
|||
|
|
smallestError = error;
|
|||
|
|
optimalResult.asset = candidate;
|
|||
|
|
optimalResult.duration = optimalDuration;
|
|||
|
|
optimalResult.loops = loops;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return optimalResult;
|
|||
|
|
}
|
|||
|
|
static _createLayerPresences(anim, node) {
|
|||
|
|
const runtimeLayers = node.layers;
|
|||
|
|
const runtimeLayersToAdd = node.layersToAdd;
|
|||
|
|
let muteConfig;
|
|||
|
|
let metaLayerPresence = {
|
|||
|
|
Body: false,
|
|||
|
|
Screen: false,
|
|||
|
|
Audio: false
|
|||
|
|
};
|
|||
|
|
if (anim.meta.layers.Body) {
|
|||
|
|
metaLayerPresence.Body = true;
|
|||
|
|
}
|
|||
|
|
if (anim.meta.layers.AudioEvent) {
|
|||
|
|
metaLayerPresence.Audio = true;
|
|||
|
|
}
|
|||
|
|
if (anim.meta.layers.Eye || anim.meta.layers.EyeTexture || anim.meta.layers.Overlay || anim.meta.layers.OverlayTexture || anim.meta.layers.Pixi || anim.meta.layers.BackgroundTexture) {
|
|||
|
|
metaLayerPresence.Screen = true;
|
|||
|
|
}
|
|||
|
|
if (runtimeLayers) {
|
|||
|
|
muteConfig = {
|
|||
|
|
BODY: runtimeLayers.Body,
|
|||
|
|
SCREEN: runtimeLayers.Screen,
|
|||
|
|
AUDIO: runtimeLayers.Audio
|
|||
|
|
};
|
|||
|
|
if (runtimeLayers.Body !== undefined) {
|
|||
|
|
if (runtimeLayersToAdd.Body || ((runtimeLayers.Body && !metaLayerPresence.Body) || (!runtimeLayers.Body && metaLayerPresence.Body))) {
|
|||
|
|
metaLayerPresence.Body = runtimeLayers.Body;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (runtimeLayers.Audio !== undefined) {
|
|||
|
|
if (runtimeLayersToAdd.Audio || ((runtimeLayers.Audio && !metaLayerPresence.Audio) || (!runtimeLayers.Audio && metaLayerPresence.Audio))) {
|
|||
|
|
metaLayerPresence.Audio = runtimeLayers.Audio;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (runtimeLayers.Screen !== undefined) {
|
|||
|
|
if (runtimeLayersToAdd.Screen || ((runtimeLayers.Screen && !metaLayerPresence.Screen) || (!runtimeLayers.Screen && metaLayerPresence.Screen))) {
|
|||
|
|
metaLayerPresence.Screen = runtimeLayers.Screen;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return [metaLayerPresence, muteConfig];
|
|||
|
|
}
|
|||
|
|
static _initTimeline(ttsSpeakData, tokenTimes, options, shouldPrune = false) {
|
|||
|
|
let timeline = new Timeline_1.Timeline(options.frameBuffer, options.assetRelativeEnd, options.enableLayerMerging);
|
|||
|
|
const start = tokenTimes[0].start;
|
|||
|
|
let stop = tokenTimes[tokenTimes.length - 1].end;
|
|||
|
|
if (shouldPrune) {
|
|||
|
|
stop = this.getPrunedStopTime(tokenTimes);
|
|||
|
|
ttsSpeakData.params.earlyStopTime = stop;
|
|||
|
|
}
|
|||
|
|
const ttsFrame = {
|
|||
|
|
start: start,
|
|||
|
|
stop: stop,
|
|||
|
|
data: ttsSpeakData
|
|||
|
|
};
|
|||
|
|
timeline._init([ttsFrame]);
|
|||
|
|
return [timeline, tokenTimes];
|
|||
|
|
}
|
|||
|
|
static getPrunedStopTime(tokenTimes) {
|
|||
|
|
let idx;
|
|||
|
|
let pauseTime = 0;
|
|||
|
|
for (idx = tokenTimes.length - 1; idx >= 0; idx--) {
|
|||
|
|
if (tokenTimes[idx].name === TTS_BREAK) {
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
else if ((idx === tokenTimes.length - 1) && (tokenTimes[idx].name === TTS_PAU)) {
|
|||
|
|
pauseTime = (tokenTimes[idx].end - tokenTimes[idx].start);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (idx < 0) {
|
|||
|
|
return tokenTimes[0].start + pauseTime;
|
|||
|
|
}
|
|||
|
|
return tokenTimes[idx].end + pauseTime;
|
|||
|
|
}
|
|||
|
|
static _generateWordSchedule(wordNodes, tokenTimes, options) {
|
|||
|
|
if (options.debugMode) {
|
|||
|
|
console.log('Word timing report (with buffer):');
|
|||
|
|
console.log('--------------------------------');
|
|||
|
|
}
|
|||
|
|
let ttsWordSchedule = new Map();
|
|||
|
|
let lastNodeIdx = 0;
|
|||
|
|
for (let i = 0; i < tokenTimes.length; i++) {
|
|||
|
|
let wordNodeFound = false;
|
|||
|
|
const token = tokenTimes[i];
|
|||
|
|
const tokenTime = {
|
|||
|
|
start: token.start,
|
|||
|
|
stop: token.end
|
|||
|
|
};
|
|||
|
|
for (let j = lastNodeIdx; j < wordNodes.length; j++) {
|
|||
|
|
const word = wordNodes[j];
|
|||
|
|
if (token.name === TTS_BREAK || token.name === TTS_SAY_AS || token.name === TTS_AUDIO_BREAK) {
|
|||
|
|
if (((token.name === TTS_BREAK) && (word.type === Types_1.SSMLNodeType.BREAK)) ||
|
|||
|
|
((token.name === TTS_AUDIO_BREAK) && (word.type === Types_1.SSMLNodeType.AUDIO_BREAK)) ||
|
|||
|
|
((token.name === TTS_SAY_AS) && (word.type === Types_1.SSMLNodeType.SAY_AS))) {
|
|||
|
|
ttsWordSchedule.set(word, tokenTime);
|
|||
|
|
lastNodeIdx = ++j;
|
|||
|
|
wordNodeFound = true;
|
|||
|
|
if (options.debugMode) {
|
|||
|
|
console.log(`${token.name}: ${token.start.toFixed(3)} - ${token.end.toFixed(3)} (${(token.end - token.start).toFixed(3)})`);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (word.value && (token.name.toLowerCase() === word.value.toLowerCase())) {
|
|||
|
|
ttsWordSchedule.set(word, tokenTime);
|
|||
|
|
if (options.debugMode) {
|
|||
|
|
console.log(`${word.value}: ${token.start.toFixed(3)} - ${token.end.toFixed(3)} (${(token.end - token.start).toFixed(3)})`);
|
|||
|
|
}
|
|||
|
|
lastNodeIdx = ++j;
|
|||
|
|
wordNodeFound = true;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if ((token.name !== TTS_PAU) && (!wordNodeFound)) {
|
|||
|
|
if (options.debugMode) {
|
|||
|
|
console.log(`Unable to align TTS token: ${token.name} with requested words`);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (options.debugMode) {
|
|||
|
|
console.log('-------------------');
|
|||
|
|
}
|
|||
|
|
return ttsWordSchedule;
|
|||
|
|
}
|
|||
|
|
_populateTimelineLayers(inputTree, timeline, wordSchedule) {
|
|||
|
|
let assetNodes = inputTree.gatherDescendantsType(Types_1.AssetNodeType.ES);
|
|||
|
|
assetNodes = assetNodes.concat(inputTree.gatherDescendantsType(Types_1.AssetNodeType.AUDIO));
|
|||
|
|
let blockingAssetNodes = assetNodes.filter((node) => InputProcessor_1.InputProcessor.isBlocking(node));
|
|||
|
|
let emptyAssetNodes = blockingAssetNodes.concat(assetNodes.filter((node) => (InputProcessor_1.InputProcessor.isEmpty(node) && !InputProcessor_1.InputProcessor.isBlocking(node))));
|
|||
|
|
let prioritizedAssetNodes = emptyAssetNodes.concat(assetNodes.filter((node) => !InputProcessor_1.InputProcessor.isEmpty(node)));
|
|||
|
|
log.debug('ESML resolution report:');
|
|||
|
|
log.debug('-----------------------');
|
|||
|
|
prioritizedAssetNodes.forEach((node) => {
|
|||
|
|
let bounds;
|
|||
|
|
let blocking = false;
|
|||
|
|
if (InputProcessor_1.InputProcessor.isBlocking(node)) {
|
|||
|
|
blocking = true;
|
|||
|
|
if ((node.playbackData) && (wordSchedule.has(node.timeSyncNode))) {
|
|||
|
|
const timeSyncNode = node.timeSyncNode;
|
|||
|
|
bounds = Object.assign({}, wordSchedule.get(timeSyncNode));
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
log.debug(`Could not resolve time-sync information for blocking asset request: ${node.requestInfo.description}`);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
let resolution;
|
|||
|
|
if (InputProcessor_1.InputProcessor.isEmpty(node)) {
|
|||
|
|
if (wordSchedule.has(node.timeSyncNode)) {
|
|||
|
|
let timeSyncNode = node.timeSyncNode;
|
|||
|
|
bounds = Object.assign({}, wordSchedule.get(timeSyncNode));
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
log.debug(`Could not resolve time-sync information for non-blocking asset request: ${node.requestInfo.description}`);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
resolution = this._resolveAssetToPlayback(node);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
try {
|
|||
|
|
bounds = TimelineManager._getBoundariesFromChildren(node, wordSchedule);
|
|||
|
|
}
|
|||
|
|
catch (e) {
|
|||
|
|
log.warn(e);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
resolution = this._resolveAssetToPlayback(node, (bounds.stop - bounds.start));
|
|||
|
|
}
|
|||
|
|
if (!resolution.resolved) {
|
|||
|
|
log.debug(`Could not find match for requested Asset ${resolution.identifier} because ${resolution.reason}`);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
const dynamicStopBoundary = bounds.start + (node.playbackData.playbackDuration / FRAME_RATE);
|
|||
|
|
const inserted = timeline.anim.insert(new Timeline_2.TimelineFrame(bounds.start, dynamicStopBoundary, node, blocking));
|
|||
|
|
if (inserted) {
|
|||
|
|
node.playbackData.playbackPr = node.playbackData.playbackGenerator();
|
|||
|
|
if (node.playbackData.playbackName.toLowerCase().indexOf('emoji') !== -1) {
|
|||
|
|
log.info(`Emoji ${node.playbackData.playbackName} triggered via ESML`);
|
|||
|
|
this.emojiCapReached = true;
|
|||
|
|
}
|
|||
|
|
log.debug(`Inserted asset ${node.playbackData.playbackName} in Timeline @ ${bounds.start.toFixed(3)} - ${dynamicStopBoundary.toFixed(3)}`);
|
|||
|
|
if (node.playbackData.playbackName.includes('SSA')) {
|
|||
|
|
this.jibo.performance.log('EmbodiedSpeech_ESML_ToBeDispatchedSSA', node.playbackData.playbackName);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
this.jibo.performance.log('EmbodiedSpeech_ESML_ToBeDispatchedAnim', node.playbackData.playbackName);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
log.debug(`Could not insert asset ${node.playbackData.playbackName} in Timeline because it conflicts with other content @ ${bounds.start.toFixed(3)} - ${dynamicStopBoundary.toFixed(3)}`);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
log.debug('-----------------------');
|
|||
|
|
return timeline;
|
|||
|
|
}
|
|||
|
|
_autoTagTreesToPrioritizedTimelines(autoTagTrees, wordSchedule, timeline) {
|
|||
|
|
let priorityMap = new Map();
|
|||
|
|
autoTagTrees.forEach(ruleTree => {
|
|||
|
|
let cache;
|
|||
|
|
const autoRule = ruleTree.getAttribute('autoRule');
|
|||
|
|
switch (autoRule) {
|
|||
|
|
case AutoRuleManager_1.AutoRuleNames.Question:
|
|||
|
|
case AutoRuleManager_1.AutoRuleNames.Comma:
|
|||
|
|
case AutoRuleManager_1.AutoRuleNames.Initiate:
|
|||
|
|
case AutoRuleManager_1.AutoRuleNames.Blink:
|
|||
|
|
case AutoRuleManager_1.AutoRuleNames.DoubleBlink:
|
|||
|
|
case AutoRuleManager_1.AutoRuleNames.BeatBlink:
|
|||
|
|
cache = jibo_cai_utils_1.CacheUtils.GlobalCacheName;
|
|||
|
|
break;
|
|||
|
|
case AutoRuleManager_1.AutoRuleNames.HotWords:
|
|||
|
|
default:
|
|||
|
|
cache = this.jibo.face.eye.CACHE_ID;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
if (ruleTree.children.length > 0) {
|
|||
|
|
const priority = ruleTree.getAttribute('priority');
|
|||
|
|
let ruleFrames = [];
|
|||
|
|
ruleTree.forEachChild((subTree) => {
|
|||
|
|
let bounds;
|
|||
|
|
let resolution;
|
|||
|
|
if (InputProcessor_1.InputProcessor.isEmpty(subTree) || InputProcessor_1.InputProcessor.isExplicitlyNonBlocking(subTree)) {
|
|||
|
|
if (!wordSchedule.has(subTree.timeSyncNode)) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
const timeSyncNode = subTree.timeSyncNode;
|
|||
|
|
bounds = Object.assign({}, wordSchedule.get(timeSyncNode));
|
|||
|
|
const position = subTree.getAttribute('position');
|
|||
|
|
bounds.start = (position === 'after') ? bounds.stop : bounds.start;
|
|||
|
|
resolution = this._resolveAssetToPlayback(subTree, undefined, true, cache);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
try {
|
|||
|
|
bounds = TimelineManager._getBoundariesFromChildren(subTree, wordSchedule);
|
|||
|
|
}
|
|||
|
|
catch (e) {
|
|||
|
|
log.warn(e);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
resolution = this._resolveAssetToPlayback(subTree, (bounds.stop - bounds.start), true, cache);
|
|||
|
|
if (!resolution.resolved && (Math.random() < AUTORULE_GATE_RATE)) {
|
|||
|
|
resolution = this._resolveAssetToPlayback(subTree, undefined, true, cache);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (!resolution.resolved) {
|
|||
|
|
log.debug(`Could not find match for AutoRule ${resolution.identifier} because ${resolution.reason}`);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
const dynamicStopBoundary = bounds.start + (subTree.playbackData.playbackDuration / FRAME_RATE);
|
|||
|
|
ruleFrames.push({
|
|||
|
|
layer: timeline.anim,
|
|||
|
|
frame: new Timeline_2.TimelineFrame(bounds.start, dynamicStopBoundary, subTree)
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
if (ruleFrames.length > 0) {
|
|||
|
|
let currMatches = priorityMap.get(priority);
|
|||
|
|
if (!currMatches) {
|
|||
|
|
priorityMap.set(priority, currMatches = []);
|
|||
|
|
}
|
|||
|
|
currMatches.push(ruleFrames);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return priorityMap;
|
|||
|
|
}
|
|||
|
|
static _getBoundariesFromChildren(node, wordSchedule) {
|
|||
|
|
let firstWordBounds;
|
|||
|
|
let lastWordBounds;
|
|||
|
|
node.forEachChild(child => {
|
|||
|
|
let wordBounds = wordSchedule.get(child);
|
|||
|
|
if (!wordBounds && (InputProcessor_1.InputProcessor.isAsset(child) || InputProcessor_1.InputProcessor.isBreak(child))) {
|
|||
|
|
wordBounds = wordSchedule.get(child.timeSyncNode);
|
|||
|
|
}
|
|||
|
|
else if (!InputProcessor_1.InputProcessor.isEmpty(child)) {
|
|||
|
|
wordBounds = TimelineManager._getBoundariesFromChildren(child, wordSchedule);
|
|||
|
|
}
|
|||
|
|
if (wordBounds) {
|
|||
|
|
if (!firstWordBounds) {
|
|||
|
|
firstWordBounds = wordBounds;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
lastWordBounds = wordBounds;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
if (firstWordBounds) {
|
|||
|
|
lastWordBounds = lastWordBounds || firstWordBounds;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw new Error('Unable to find timing bounds for word length based Animation.');
|
|||
|
|
}
|
|||
|
|
const timeBounds = {
|
|||
|
|
start: firstWordBounds.start,
|
|||
|
|
stop: lastWordBounds.stop
|
|||
|
|
};
|
|||
|
|
return timeBounds;
|
|||
|
|
}
|
|||
|
|
_mergePendingWithMaster(pending, timeline) {
|
|||
|
|
let priorities = [];
|
|||
|
|
pending.forEach((_val, key) => priorities.push(key));
|
|||
|
|
priorities.sort();
|
|||
|
|
log.debug('AutoRules resolution report:');
|
|||
|
|
log.debug('---------------------------------------');
|
|||
|
|
priorities.forEach(priority => {
|
|||
|
|
_.shuffle(pending.get(priority)).forEach((autoRule) => {
|
|||
|
|
autoRule.forEach((ruleMatch) => {
|
|||
|
|
const isEmoji = (ruleMatch.frame.data.playbackData.playbackName.toLowerCase().indexOf('emoji') !== -1);
|
|||
|
|
if (isEmoji && this.emojiCapReached) {
|
|||
|
|
log.debug(`Could not insert AutoRule ${ruleMatch.frame.data.getAttribute('rule')}:${ruleMatch.frame.data.playbackData.playbackName} in Timeline because only 1 Emoji is allowed per input`);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
const inserted = ruleMatch.layer.insert(ruleMatch.frame, true);
|
|||
|
|
if (inserted) {
|
|||
|
|
ruleMatch.frame.data.playbackData.playbackPr = ruleMatch.frame.data.playbackData.playbackGenerator();
|
|||
|
|
if (isEmoji) {
|
|||
|
|
log.info(`Emoji ${ruleMatch.frame.data.playbackData.playbackName} triggered via AutoRule`);
|
|||
|
|
this.emojiCapReached = true;
|
|||
|
|
}
|
|||
|
|
log.debug(`AutoRule ${ruleMatch.frame.data.getAttribute('rule')}:${ruleMatch.frame.data.playbackData.playbackName} inserted @ ${ruleMatch.frame.start.toFixed(3)} - ${ruleMatch.frame.stop.toFixed(3)}`);
|
|||
|
|
this.jibo.performance.log('EmbodiedSpeech_AutoRule_ToBeDispatchedAnim', ruleMatch.frame.data.playbackData.playbackName);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
log.debug(`Could not insert AutoRule ${ruleMatch.frame.data.getAttribute('rule')}:${ruleMatch.frame.data.playbackData.playbackName} in Timeline because it conflicts with other content @ ${ruleMatch.frame.start.toFixed(3)} - ${ruleMatch.frame.stop.toFixed(3)}`);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
log.debug('---------------------------------------');
|
|||
|
|
return timeline;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.TimelineManager = TimelineManager;
|
|||
|
|
|
|||
|
|
},{"../../log":11,"../common/Types":13,"../processing/Formats":18,"../processing/InputProcessor":19,"../processing/SSMLNode":20,"../processing/auto_rules/AutoRuleManager":23,"./Timeline":59,"jibo-cai-utils":undefined,"lodash/lodash.min":undefined,"path":undefined}],61:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
function __export(m) {
|
|||
|
|
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|||
|
|
}
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
__export(require("./Timeline"));
|
|||
|
|
__export(require("./TimelineManager"));
|
|||
|
|
|
|||
|
|
},{"./Timeline":59,"./TimelineManager":60}],62:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const TIME_PATTERN = /(?:[0-9]|0[0-9]|1[0-9]|2[0-3]):(?:[0-5][0-9])\s?(?:[aApP][mM])/ig;
|
|||
|
|
const uniqueContractionRules = [];
|
|||
|
|
uniqueContractionRules.push([/ma'am/gi, `madam`]);
|
|||
|
|
uniqueContractionRules.push([/o'clock/gi, `of the clock`]);
|
|||
|
|
const doubleContractionsRules = [];
|
|||
|
|
doubleContractionsRules.push([/(y)('all)/gi, `$1ou$2`]);
|
|||
|
|
doubleContractionsRules.push([/(sha)(n't)/gi, `shall$2`]);
|
|||
|
|
doubleContractionsRules.push([/(ai)(n't)/gi, `am$2`]);
|
|||
|
|
doubleContractionsRules.push([/(aim)(n't)/gi, `am$2`]);
|
|||
|
|
doubleContractionsRules.push([/(ca)(n't)/gi, `can$2`]);
|
|||
|
|
doubleContractionsRules.push([/(wo)(n't)/gi, `will$2`]);
|
|||
|
|
const contractionRules = [];
|
|||
|
|
contractionRules.push([/(let)'s/gi, `$1 us`]);
|
|||
|
|
contractionRules.push([/'s/gi, ` is`]);
|
|||
|
|
contractionRules.push([/n't/gi, ` not`]);
|
|||
|
|
contractionRules.push([/'ve/gi, ` have`]);
|
|||
|
|
contractionRules.push([/'re/gi, ` are`]);
|
|||
|
|
contractionRules.push([/'ll/gi, ` will`]);
|
|||
|
|
contractionRules.push([/'m/gi, ` am`]);
|
|||
|
|
contractionRules.push([/'d/gi, ` would`]);
|
|||
|
|
contractionRules.push([/'all/gi, ` all`]);
|
|||
|
|
class NLPTools {
|
|||
|
|
static isPunctuation(str) {
|
|||
|
|
if (!str) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
return str.length === 1 && (str[0] === '.' ||
|
|||
|
|
str[0] === '...' ||
|
|||
|
|
str[0] === ',' ||
|
|||
|
|
str[0] === ':' ||
|
|||
|
|
str[0] === ';' ||
|
|||
|
|
str[0] === '!' ||
|
|||
|
|
str[0] === '-' ||
|
|||
|
|
str[0] === '?');
|
|||
|
|
}
|
|||
|
|
static getExpansionsAndContractions(text) {
|
|||
|
|
let splext = text.split(' ');
|
|||
|
|
let textExpansions = [];
|
|||
|
|
let textContractions = [];
|
|||
|
|
splext.forEach(token => {
|
|||
|
|
let contracted = NLPTools.applyContractionRules(token);
|
|||
|
|
let expanded = contracted.split(' ');
|
|||
|
|
let baseWordSet = false;
|
|||
|
|
expanded.forEach(word => {
|
|||
|
|
if (!baseWordSet) {
|
|||
|
|
textExpansions.push(word);
|
|||
|
|
if (word !== token) {
|
|||
|
|
textContractions.push(token.toLowerCase());
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
textContractions.push(token);
|
|||
|
|
}
|
|||
|
|
baseWordSet = true;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
textExpansions.push(word);
|
|||
|
|
textContractions.push('');
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
return [textExpansions, textContractions];
|
|||
|
|
}
|
|||
|
|
static applyContractionRules(text) {
|
|||
|
|
if (NLPTools.hasContractions(text)) {
|
|||
|
|
for (let i = 0; i < uniqueContractionRules.length; i++) {
|
|||
|
|
let contr = uniqueContractionRules[i];
|
|||
|
|
text = text.replace(contr[0], contr[1]);
|
|||
|
|
}
|
|||
|
|
for (let i = 0; i < doubleContractionsRules.length; i++) {
|
|||
|
|
let contr = doubleContractionsRules[i];
|
|||
|
|
text = text.replace(contr[0], contr[1]);
|
|||
|
|
}
|
|||
|
|
for (let i = 0; i < contractionRules.length; i++) {
|
|||
|
|
let contr = contractionRules[i];
|
|||
|
|
text = text.replace(contr[0], contr[1]);
|
|||
|
|
}
|
|||
|
|
text = text.toLowerCase();
|
|||
|
|
}
|
|||
|
|
return text;
|
|||
|
|
}
|
|||
|
|
static hasContractions(text) {
|
|||
|
|
return text.match(/[A-Za-z]+'[A-Za-z]+/g) !== null;
|
|||
|
|
}
|
|||
|
|
static cleanInput(str) {
|
|||
|
|
str = str.trim()
|
|||
|
|
.replace(/[‘’\`\´]/g, `'`)
|
|||
|
|
.replace(/[“”]/g, `"`)
|
|||
|
|
.replace(/\s'(\s)/g, `$1`)
|
|||
|
|
.replace(/(\.{3})\.*/ig, `$1`)
|
|||
|
|
.replace(/(^|[^\.])\.{2}([^\.]|$)/ig, `$1.$2`)
|
|||
|
|
.replace(TIME_PATTERN, timeStr => timeStr.replace(' ', ''))
|
|||
|
|
.replace(/\[/g, `(`)
|
|||
|
|
.replace(/\]/g, `)`)
|
|||
|
|
.replace(/[{}]/g, ``);
|
|||
|
|
return str;
|
|||
|
|
}
|
|||
|
|
static joinWordsIntoSentence(wordArray) {
|
|||
|
|
return wordArray.join(' ');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.NLPTools = NLPTools;
|
|||
|
|
|
|||
|
|
},{}],63:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const Utils_1 = require("../../utils/Utils");
|
|||
|
|
const Types_1 = require("../common/Types");
|
|||
|
|
const DEFAULT_OVERFLOW_LIMIT_MS = 0;
|
|||
|
|
class Validation {
|
|||
|
|
static validateSpeakOptions(validatedOptions, speakOptions) {
|
|||
|
|
let mergedValidatedOptions = Object.assign({}, validatedOptions);
|
|||
|
|
if (speakOptions) {
|
|||
|
|
if (speakOptions.disableAutoRules !== undefined) {
|
|||
|
|
if (typeof speakOptions.disableAutoRules === 'boolean') {
|
|||
|
|
mergedValidatedOptions.disableAutoRules = speakOptions.disableAutoRules;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw new Error('Invalid DisableAutoRules value');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (speakOptions.enableLayerMerging !== undefined) {
|
|||
|
|
if (typeof speakOptions.enableLayerMerging === 'boolean') {
|
|||
|
|
mergedValidatedOptions.enableLayerMerging = speakOptions.enableLayerMerging;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw new Error('Invalid Layer Merging value');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (speakOptions.frameBuffer !== undefined) {
|
|||
|
|
if (typeof speakOptions.frameBuffer === 'number' && speakOptions.frameBuffer >= 0) {
|
|||
|
|
mergedValidatedOptions.frameBuffer = speakOptions.frameBuffer;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw new Error('Invalid Frame Buffer value');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (speakOptions.followedByListen !== undefined) {
|
|||
|
|
if (typeof speakOptions.followedByListen === 'boolean') {
|
|||
|
|
mergedValidatedOptions.followedByListen = speakOptions.followedByListen;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw new Error('Invalid FollowByListen value');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (mergedValidatedOptions.followedByListen) {
|
|||
|
|
mergedValidatedOptions.dispatchComplete = Types_1.DispatchType.TTS;
|
|||
|
|
}
|
|||
|
|
else if (speakOptions.dispatchComplete) {
|
|||
|
|
let dispatchType = Types_1.DispatchType[speakOptions.dispatchComplete.toUpperCase()];
|
|||
|
|
if (dispatchType) {
|
|||
|
|
mergedValidatedOptions.dispatchComplete = dispatchType;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw new Error('Invalid Dispatch value');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (speakOptions.assetRelativeEnd !== undefined) {
|
|||
|
|
if (typeof speakOptions.assetRelativeEnd === 'number') {
|
|||
|
|
mergedValidatedOptions.assetRelativeEnd = speakOptions.assetRelativeEnd;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw new Error('Invalid AssetRelativeEnd value');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (mergedValidatedOptions.followedByListen) {
|
|||
|
|
mergedValidatedOptions.assetRelativeEnd = Utils_1.Utils.millisecToSec(DEFAULT_OVERFLOW_LIMIT_MS);
|
|||
|
|
}
|
|||
|
|
if (speakOptions.debugMode !== undefined) {
|
|||
|
|
if (typeof speakOptions.debugMode === 'boolean') {
|
|||
|
|
mergedValidatedOptions.debugMode = speakOptions.debugMode;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw new Error('Invalid Debug Mode value');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return mergedValidatedOptions;
|
|||
|
|
}
|
|||
|
|
static validateAutoRuleConfig(validatedConfig, autoRuleConfig) {
|
|||
|
|
let mergedValidatedConfig = Object.assign({}, validatedConfig);
|
|||
|
|
if (autoRuleConfig) {
|
|||
|
|
Object.keys(mergedValidatedConfig).forEach(key => {
|
|||
|
|
if (validatedConfig[key] && autoRuleConfig[key] !== undefined) {
|
|||
|
|
if (typeof autoRuleConfig[key] === 'boolean') {
|
|||
|
|
mergedValidatedConfig[key] = autoRuleConfig[key];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
return mergedValidatedConfig;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.Validation = Validation;
|
|||
|
|
|
|||
|
|
},{"../../utils/Utils":65,"../common/Types":13}],64:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
function __export(m) {
|
|||
|
|
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|||
|
|
}
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
__export(require("./Validation"));
|
|||
|
|
__export(require("./NLPTools"));
|
|||
|
|
|
|||
|
|
},{"./NLPTools":62,"./Validation":63}],65:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|||
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|||
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|||
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|||
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|||
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
class Utils {
|
|||
|
|
static secToMillisec(seconds) {
|
|||
|
|
return seconds * 1000;
|
|||
|
|
}
|
|||
|
|
static millisecToSec(milliseconds) {
|
|||
|
|
return milliseconds / 1000;
|
|||
|
|
}
|
|||
|
|
static loadAnimationIntoCache(jibo, query, cacheName) {
|
|||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
let assets = [];
|
|||
|
|
if (typeof query === 'string') {
|
|||
|
|
const asset = jibo.animDB.getAnimByName(query);
|
|||
|
|
if (!asset) {
|
|||
|
|
return Promise.reject(`No animation of name '${query}' found in animDB`);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
assets.push(asset);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
const results = jibo.animDB.query(query);
|
|||
|
|
if (!results.matching.length) {
|
|||
|
|
return Promise.reject(`No animation of ${query} found in animDB`);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
assets.push(...results.matching);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
assets.forEach((asset) => __awaiter(this, void 0, void 0, function* () {
|
|||
|
|
yield asset.createFromConfig({
|
|||
|
|
cache: cacheName
|
|||
|
|
});
|
|||
|
|
}));
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.Utils = Utils;
|
|||
|
|
class ExtPromise {
|
|||
|
|
constructor() {
|
|||
|
|
this.promise = new Promise((res, rej) => {
|
|||
|
|
this.resolve = res;
|
|||
|
|
this.reject = rej;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
exports.ExtPromise = ExtPromise;
|
|||
|
|
function timeout(pr, timeoutTimeMs, options = {}) {
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
let timeout = setTimeout(() => {
|
|||
|
|
if (options.log) {
|
|||
|
|
let msg = `Timeout of ${timeoutTimeMs} ms occurred`;
|
|||
|
|
if (options.logMessage) {
|
|||
|
|
msg += `. ${options.logMessage}`;
|
|||
|
|
}
|
|||
|
|
options.log.warn(msg);
|
|||
|
|
}
|
|||
|
|
resolve(options.timeoutValue);
|
|||
|
|
}, timeoutTimeMs);
|
|||
|
|
pr.then((data) => {
|
|||
|
|
clearTimeout(timeout);
|
|||
|
|
resolve(data);
|
|||
|
|
}).catch(e => {
|
|||
|
|
clearTimeout(timeout);
|
|||
|
|
reject(e);
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
exports.timeout = timeout;
|
|||
|
|
|
|||
|
|
},{}],66:[function(require,module,exports){
|
|||
|
|
"use strict";
|
|||
|
|
function __export(m) {
|
|||
|
|
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|||
|
|
}
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
const speech = require("./speech");
|
|||
|
|
exports.speech = speech;
|
|||
|
|
const listen = require("./listen");
|
|||
|
|
exports.listen = listen;
|
|||
|
|
const api = require("./api");
|
|||
|
|
exports.api = api;
|
|||
|
|
__export(require("./EmbodiedDialog"));
|
|||
|
|
|
|||
|
|
},{"./EmbodiedDialog":2,"./api":4,"./listen":10,"./speech":15}]},{},[66])(66)
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
//# sourceMappingURL=jibo-embodied-dialog.js.map
|