Skip to content
Browse files

Adds adjustments for 'how'

  • Loading branch information...
1 parent 122d5d9 commit 006feaa83c3c52c1848588a7d52b44533b6221f8 @nhunzaker committed Jan 21, 2012
Showing with 398 additions and 63 deletions.
  1. +10 −0 actions/how.js
  2. +33 −0 actions/relabel.js
  3. +18 −0 actions/repeat.js
  4. +58 −0 actions/validate.js
  5. +96 −0 actions/watch.js
  6. +34 −41 actions/what.js
  7. +60 −0 actions/who.js
  8. +1 −1 brain/analyze.js
  9. +19 −5 brain/language/tagger.js
  10. +24 −11 brain/lexicon.js
  11. +1 −1 nodebot.js
  12. +1 −0 sax-js
  13. +36 −0 test/pos-test.js
  14. +7 −4 validator/reporter.js
View
10 actions/how.js
@@ -0,0 +1,10 @@
+// How
+// -------------------------------------------------- //
+
+module.exports = function how (a) {
+
+ this.say("I don't know how to %s", a.subject);
+
+ return this.request();
+
+};
View
33 actions/relabel.js
@@ -0,0 +1,33 @@
+// Relabel
+// -------------------------------------------------- //
+
+
+module.exports = function relabel (a) {
+
+ var nodebot = this
+ , ownership = a.ownership
+ , subject = a.subject
+ , description = lang.capitalize(a.description)
+ ;
+
+ if (ownership === subject) {
+ subject = "definition";
+ }
+
+ // Standard bullet proofing
+ nodebot.lexicon[ownership] = nodebot.lexicon[ownership] || {};
+
+ nodebot.ask("Just to confirm," + " you said that " + lang.possessify(ownership) + " " + a.subject + " " + a.keyverb + " " + description.green.bold + "? (y/n)", function(data) {
+
+ if (data[0].toLowerCase() === "y") {
+ nodebot.say("Okay, thanks! Now I know that " + (lang.possessify(ownership) + " " + subject + " is " + description).green.bold);
+ nodebot.lexicon[ownership][subject] = description;
+ } else {
+ nodebot.say("I must be confused, sorry.");
+ }
+
+ return nodebot.request();
+
+ });
+
+};
View
18 actions/repeat.js
@@ -0,0 +1,18 @@
+// Repeat actions
+// -------------------------------------------------- //
+
+actions.repeat = function() {
+
+ var action = "";
+
+ if (this.memory.tasks === []) {
+ this.say("I haven't done anything yet, silly!");
+ return this.request();
+ } else {
+ action = this.memory.tasks.slice(-1).toString();
+ }
+
+ // Run the old action
+ return this.analyze(action);
+
+};
View
58 actions/validate.js
@@ -0,0 +1,58 @@
+// Validate
+// -------------------------------------------------- //
+
+var fs = require('fs');
+
+// Scanners
+var urlEx = Nodebot.lexicon.url['regular expression']
+, fileEx = Nodebot.lexicon.file['regular expression']
+, jsEx = Nodebot.lexicon.javascript['regular expression']
+, cssEx = Nodebot.lexicon.css['regular expression']
+, htmlEx = Nodebot.lexicon.html['regular expression']
+;
+
+
+module.exports = function validate (a, skipRequest) {
+
+ var target = a.subject.split(" ").join("")
+ , nodebot = this;
+
+ if (!target.match(urlEx)) {
+
+ try {
+ fs.statSync(target);
+ } catch (err) {
+ nodebot.say("I had trouble finding " + target + ". Does it exist?".cyan);
+
+ return nodebot.request();
+ }
+ }
+
+ function dispatch(fileType) {
+ require("../validator/" + fileType).validate.apply(nodebot, [target, function cb() {
+ return (!skipRequest) ? false : nodebot.request();
+ }]);
+ }
+
+ // VALIDATORS
+ // -------------------------------------------------- //
+
+ // Javascript
+ if (target.match(jsEx)) dispatch("javascript");
+
+ // CSS
+ else if (target.match(cssEx)) dispatch("css");
+
+ // Websites
+ else if (target.match(urlEx)) dispatch("website");
+
+ // HTML
+ else if (target.match(htmlEx)) dispatch("html");
+
+ // Elsecase
+ else {
+ this.say("I'm sorry, I don't recognize that file format yet");
+ if (!skipRequest) return nodebot.request();
+ }
+
+};
View
96 actions/watch.js
@@ -0,0 +1,96 @@
+// Watch
+// -------------------------------------------------- //
+
+var fs = require('fs')
+, os = require('os');
+
+// Scanners
+var urlEx = Nodebot.lexicon.url['regular expression']
+, fileEx = Nodebot.lexicon.file['regular expression']
+, jsEx = Nodebot.lexicon.javascript['regular expression']
+, cssEx = Nodebot.lexicon.css['regular expression']
+, htmlEx = Nodebot.lexicon.html['regular expression']
+;
+
+module.exports = function watch (a) {
+
+ var file = a.subject || "./"
+ , nodebot = this
+ , stat;
+
+ // Bullet proof websites
+ if (file.match(urlEx)) {
+ this.say("This is a website. I don't know how to watch these yet, so I'll pass it through the web validator");
+ return nodebot.actions.validate.apply(this, [a]);
+ }
+
+ try {
+ stat = fs.statSync(file);
+ } catch (err) {
+ console.log(err);
+ nodebot.say("I couldn't find that file, does it exist?");
+ return nodebot.request();
+ }
+
+ // Watch files
+ // -------------------------------------------------- //
+
+ stat.isFile() && fs.watchFile(file, { persistent: true, interval: 1000 }, function (curr, prev) {
+
+ var content = fs.readFileSync(file, "utf-8");
+
+ if (content !== nodebot.memory.watched_content) {
+ nodebot.say("Looks like something has changed on " + file.blue.bold);
+ actions.validate.apply(nodebot, [a, true]);
+
+ // Update with new content
+ nodebot.memory.watched_content = content;
+ }
+ });
+
+
+ // Watch directories
+ // -------------------------------------------------- //
+
+ if (stat.isDirectory()) {
+
+ // Are we dealing with OSX?
+ switch(os.type()) {
+
+ case "Darwin":
+ nodebot.say("I can't watch for directory changes on OSX, I'm sorry :(");
+ break;
+
+ default:
+ fs.watch(file, { persistent: true, interval: 1000 }, function (event, filename) {
+
+ if (!filename) return false;
+
+ var content = fs.readFileSync(filename, "utf-8");
+
+ if (content !== nodebot.memory.watched_content) {
+ nodebot.say("Looks like something has changed on " + file.blue.bold);
+ actions.validate.apply(nodebot, [a, true]);
+
+ // Update with new content
+ nodebot.memory.watched_content = content;
+ }
+ });
+ }
+
+ }
+
+
+ // Closeout
+ // -------------------------------------------------- //
+
+ nodebot.say("I am now watching " + file.blue.bold);
+
+ // Make it so that when the user exits watching, it loads
+ // up another prompt
+ process.once('SIGINT', function () {
+ nodebot.say("I am no longer watching " + file.blue.bold);
+ nodebot.request();
+ });
+
+};
View
75 actions/what.js
@@ -54,66 +54,59 @@ module.exports = function what (a) {
// No, search WolframAlpha
// -------------------------------------------------- //
- var qs = require('querystring');
-
- var sax = require("../sax-js"),
- strict = true, // set to false for html-mode
- parser = sax.parser(strict);
-
- var request = require("request");
+ var app_id = "GVH84U-9YQ66P7PU3";
+
+ var qs = require('querystring')
+ , sax = require("../sax-js")
+ , strict = true
+ , parser = sax.parser(strict)
+ , request = require("request")
+ , data = qs.stringify({ input: a.tokens.join(" ") })
+ ;
- var app_id = "GVH84U-9YQ66P7PU3"
- , repl = require('repl');
nodebot.say("Hmm, I don't know off the top of my head. Give me a minute...");
- var result = [];
-
- var data = qs.stringify({ input: a.tokens.join(" ") });
-
request.get("http://api.wolframalpha.com/v2/query?" + data + "&appid=" + app_id, function(err, data) {
- nodebot.say("Here's what %s has to say:", "WolframAlpha".red.bold);
-
- parser.onopentag = function(tag){
- console.log(tag);
- parser.onattribute = function(att) {
-// console.log(att);
- };
-
- }
+ var result = []
parser.ontext = function(t) {
var proc = t.trim();
if (proc !== "" && proc !== "\n") result.push(proc)
};
parser.onend = function () {
- info = result;
- repl.start("> ");
+
+ nodebot.say("Here's what %s has to say:\n", "WolframAlpha".red.bold);
+
+ var tidbit = [];
+
+ var width = 80;
+ var space = Array(~~((width/2) - (result[0].length / 2))).join(" ");
+
+ console.log(Array(width).join("-"));
+ console.log(space + result[0].bold.red);
+ console.log(Array(width).join("-"));
+
+ result = result.filter(function(i) { return i.trim() !== ""; });
+
+ result.slice(1, 3).forEach(function(i) {
+
+ tidbit = i.split("|");
+
+ var term = tidbit[0];
+
+ console.log(term.bold.trim() + "\n" + tidbit.slice(1).join(":"));
+
+ });
+
};
parser.write(data.body).close();
});
-
- /*
- nodebot.ask("Hmm... I can't remember. Care to tell me what " + lang.possessify(owner) + " " + subject + " is?", function(text) {
-
- if (text[0].toLowerCase() === "no") {
- nodebot.say("Okay, I'll forget you ever asked.");
- return nodebot.request();
- }
-
- nodebot.lexicon[owner] = nodebot.lexicon[owner] || {};
- nodebot.lexicon[owner][subject] = text;
-
- nodebot.say("Great, now I know!");
-
- return nodebot.request();
- });
- */
return;
};
View
60 actions/who.js
@@ -0,0 +1,60 @@
+// Who
+// -------------------------------------------------- //
+
+
+module.exports = function who(a) {
+
+ var nodebot = this
+ , owner = a.owner
+ , key = a.subject
+ ;
+
+ // Special instances
+ // -------------------------------------------------- //
+ switch(owner){
+
+ case "nodebot":
+
+ if (this.lexicon.nodebot[key]) {
+ this.say("My " + key + " is " + this.lexicon.nodebot[key]);
+ } else {
+ this.say(this.lexicon.nodebot.name + " is " + this.lexicon.nodebot.definition);
+ }
+
+ return this.request();
+
+ case "user":
+
+ if (this.lexicon.user[key]) {
+ this.say("You are my master, " + this.lexicon.user.name);
+ } else {
+ this.say("Hmm... I can't remember, " + this.lexicon.user.name);
+ }
+ return this.request();
+ }
+
+
+ // Typical cases
+ // -------------------------------------------------- //
+
+ if (nodebot.lexicon[owner] !== undefined) {
+ this.say(lang.capitalize(owner) + " is " + this.lexicon[owner][key].green.bold);
+ return this.request();
+ }
+
+ nodebot.ask("Hmm... I haven't met " + lang.capitalize(owner) + ". Who are they?", function(text) {
+
+ if (text[0].toLowerCase() === "no") {
+ nodebot.say("Okay, I'll forget about them");
+ return nodebot.request();
+ }
+
+ nodebot.lexicon[owner] = nodebot.lexicon[owner] || {};
+ nodebot.lexicon[owner][key] = text;
+ nodebot.say("Great, now I know who " + lang.capitalize(owner) + " is!");
+
+ return nodebot.request();
+
+ });
+
+};
View
2 brain/analyze.js
@@ -9,7 +9,7 @@ module.exports = function (data) {
var a = tagger.classify.apply(n, [data]);
- if (!a.action || (!owner && subject === "")) {
+ if (!a.action || (!a.owner && a.subject === "")) {
n.say("I'm not sure what you are asking me to do, please clarify");
return n.request();
}
View
24 brain/language/tagger.js
@@ -162,7 +162,6 @@ var classify = module.exports.classify = function(speech, debug) {
action = (action) ? action.toLowerCase() : action;
-
// OWNERSHIP
// Answers : "Who is associated with the target of the
// action?"
@@ -204,15 +203,18 @@ var classify = module.exports.classify = function(speech, debug) {
// Hmm, now let's try between the action and the word "to"
else if (verbs.length > 0 && to.length > 0) {
- owner = getBetween(words, "VB", "TO", "outside").slice(0, -1).join(" ");
+ owner = getBetween(words, ["VB"], "TO", "outside").slice(0, -1).join(" ");
}
// At this point, we can really only guess that
// the owner is between the verb and the end of the
// statement
else if (verbs.length > 0) {
- owner = getBetween(words, ["VBZ", "VBP"], ".").slice(0, -1);
+ owner = getBetween(words, ["VBZ", "VBP"], ["."]).slice(0, -1);
+
+ // Do we have the word "I" in here?
+ if (owner.indexOf("I") === 0) owner = owner.slice(0,1);
// Strip accidental determinates
if (getType(owner[0]) === "DT") owner = owner.slice(1);
@@ -288,14 +290,24 @@ var classify = module.exports.classify = function(speech, debug) {
subject = subject.join(" ").trim();
}
+
+ // Is the verb after the owner present tense?
+ // Helps with "How much memory do I have?"
+ else if (owner === "I" && getType(words[words.indexOf(owner) + 1]) === "VBP") {
+
+ var answer = words.slice(0, words.indexOf(owner));
+ subject = getBetween(answer, ["JJ"], ["VBP"]).slice(0, -1);
+
+ subject = subject.join(" ");
+ }
// If there *is* ownership, and there are no prepositions
// then the subject is inside the owner/determinate/verb and the last noun
// (*phew...*)
else if (owner && preps.length === 0) {
-
+
subject = getBetween(words, ["DT", "VBP", "PRP$"], "NN", "inside");
-
+
// Strip accidental catches of the actions
if (subject[0] && subject[0].toLowerCase() === action) {
subject = subject.slice(1);
@@ -350,5 +362,7 @@ var classify = module.exports.classify = function(speech, debug) {
tokens : words
};
+ debug && console.log(ret);
+
return ret;
}
View
35 brain/lexicon.js
@@ -2,7 +2,14 @@
// The Nodebot Lexicon
// -------------------------------------------------- //
-var lexicon = module.exports = {
+var lexicon = {}
+, os = require("os")
+, home = process.cwd()
+, system = os.type().replace("Darwin", "OSX") + os.release() + "(" + os.arch() + ")"
+;
+
+
+module.exports = lexicon = {
nodebot: {
definition: "a robot, it lives to serve.",
@@ -12,15 +19,19 @@ var lexicon = module.exports = {
},
user: {
- name: "Master",
+ name : "Master",
- definition: "my master.",
+ definition : "my master.",
- "current directory": function() {
- return process.cwd();
- },
+ "current directory" : home,
- 'ip address': function() {
+ "operating system" : system,
+
+ "host name" : os.hostname(),
+
+ "free memory" : (os.freemem() / 1000000) + "MB",
+
+ 'ip address' : function() {
var os = require('os')
, ifaces = os.networkInterfaces()
@@ -52,13 +63,15 @@ var lexicon = module.exports = {
},
- // Files
+ // OS Lex
// ---------- //
"current directory" : {
- definition: function() {
- return process.cwd();
- }
+ definition: home
+ },
+
+ "operating system" : {
+ definition: system
},
View
2 nodebot.js
@@ -28,7 +28,7 @@ Nodebot.language = require("./brain/language");
// All actions the nodebot can take
Nodebot.actions = require("./actions");
-
+
// Adds the decision making module
Nodebot.analyze = require("./brain/analyze");
1 sax-js
@@ -0,0 +1 @@
+Subproject commit 13b51876eb440cefe432b2d5ade4d077d456ef59
View
36 test/pos-test.js
@@ -356,6 +356,42 @@ vows.describe('Decipher speech').addBatch({
assert.equal(topic.owner, Nodebot.memory.context);
}
+ },
+
+ 'When asked, "How much memory do I have?"': {
+
+ topic: tagger.classify("How much memory do I have?"),
+
+ 'the action should be "how"': function (topic) {
+ assert.equal(topic.action, "how");
+ },
+
+ 'the owner should be the user': function (topic) {
+ assert.equal(topic.owner, "user");
+ },
+
+ 'the subject should be memory': function (topic) {
+ assert.equal(topic.subject, "memory");
+ }
+
+ },
+
+ 'When asked, "How many processors do I have?"': {
+
+ topic: tagger.classify("How many processors do I have?"),
+
+ 'the action should be "how"': function (topic) {
+ assert.equal(topic.action, "how");
+ },
+
+ 'the owner should be the user': function (topic) {
+ assert.equal(topic.owner, "user");
+ },
+
+ 'the subject should be processors': function (topic) {
+ assert.equal(topic.subject, "processors");
+ }
+
}
View
11 validator/reporter.js
@@ -2,11 +2,13 @@
// Prints the validation report
// --------------------------------------------------- //
-var hr = "----------------------------------------------------------------------------------------------"
-, colors = ['blue', 'yellow', 'red'];
+var colors = ['blue', 'yellow', 'red', 'white']
+, width = 80
+, hr = Array(width).join("-")
+;
-module.exports = function(report) {
+module.exports = function(report, callback) {
var info = report.filter(function(i) { return (i.type === "info"); })
, warn = report.filter(function(i) { return (i.type === "warning"); })
@@ -28,7 +30,8 @@ module.exports = function(report) {
var spot = (e.line + ":" + e.character)
, message = (whitespace(spot.length) + clump(e.reason, 13, spot.length + 7));
- console.log(" " + spot[color].bold + message[color]);
+
+ return console.log(" " + spot[color].bold + message[color]);
});
if (a.length > 0) {

0 comments on commit 006feaa

Please sign in to comment.
Something went wrong with that request. Please try again.