From 1ea58e3afaeb50ed3ec42d32e1c7aed29834790b Mon Sep 17 00:00:00 2001 From: Joeri Samson Date: Fri, 4 Aug 2017 11:45:25 +0200 Subject: [PATCH 1/7] First close pizza order if it's already open Note that this should probably only happen if the pizza order is too old, but dates are recorded on closing not on opening, so that requires some other changes --- scripts/pizza.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/pizza.coffee b/scripts/pizza.coffee index 6ec1da7..e0e4808 100644 --- a/scripts/pizza.coffee +++ b/scripts/pizza.coffee @@ -39,6 +39,8 @@ module.exports = (robot) -> ).join() start: -> + if this.isStarted() + this.closeOrder() robot.brain.data.currentPizzaOrder.status = 'open' isStarted: -> From 6718bd7146f251d244296783c9d419c2e045c461 Mon Sep 17 00:00:00 2001 From: Joeri Samson Date: Fri, 4 Aug 2017 11:47:28 +0200 Subject: [PATCH 2/7] Refactor a bit --- scripts/pizza.coffee | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/scripts/pizza.coffee b/scripts/pizza.coffee index e0e4808..d20b0bb 100644 --- a/scripts/pizza.coffee +++ b/scripts/pizza.coffee @@ -24,16 +24,15 @@ module.exports = (robot) -> - robot.brain.data.currentPizzaOrder = - pizzas: {}, - date: null, - status: null robot.brain.data.pizzaOrderHistory = robot.brain.data.pizzaOrderHistory or [] robot.brain.data.pizzaOrderHistoryBackup = robot.brain.data.pizzaOrderHistoryBackup or [] pizzas = + currentOrder: -> + robot.brain.data.currentPizzaOrder + current: -> - obj = robot.brain.data.currentPizzaOrder.pizzas + obj = this.currentOrder().pizzas Object.keys(obj).map((key) -> obj[key] ).join() @@ -41,37 +40,36 @@ module.exports = (robot) -> start: -> if this.isStarted() this.closeOrder() - robot.brain.data.currentPizzaOrder.status = 'open' + this.currentOrder().status = 'open' isStarted: -> - robot.brain.data.currentPizzaOrder.status == 'open' + this.currentOrder().status == 'open' currentQty: -> - Object.keys(robot.brain.data.currentPizzaOrder.pizzas).length + Object.keys(this.currentOrder().pizzas).length currentEaters: -> - Object.keys(robot.brain.data.currentPizzaOrder.pizzas).join() + Object.keys(this.currentOrder().pizzas).join() add: (user, name) -> # only 1 pizza per user atm - robot.brain.data.currentPizzaOrder.pizzas[user] = name + this.currentOrder().pizzas[user] = name remove: (user) -> - delete robot.brain.data.currentPizzaOrder.pizzas[user] + delete this.currentOrder().pizzas[user] true closeOrder: -> if pizzas.currentQty() > 0 - robot.brain.data.currentPizzaOrder.date = new Date() - robot.brain.data.currentPizzaOrder.status = 'closed' - order = robot.brain.data.currentPizzaOrder + order = this.currentOrder() + order.date = new Date() + order.status = 'closed' robot.brain.data.pizzaOrderHistory.push order - pizzas.clearOrder() + pizzas.newOrder() order else - - clearOrder: -> + newOrder: -> robot.brain.data.currentPizzaOrder = {pizzas: {}, date: null, status: null} clearHistory: -> @@ -87,6 +85,8 @@ module.exports = (robot) -> pizza_qty += Object.keys(order.pizzas).length "#{pizza_qty} pizzas ordered in #{order_qty} orders" + pizzas.newOrder() + ## HELP ## robot.respond /pizza help/i, (msg) -> msg.send "Order a pizza: '@hubby pizza me your-pizza-choice'" From 796c1782c72dbaf4fd07bddb123348756125db92 Mon Sep 17 00:00:00 2001 From: Joeri Samson Date: Fri, 4 Aug 2017 11:57:57 +0200 Subject: [PATCH 3/7] Try to not close pizza orders too soon --- scripts/pizza.coffee | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/pizza.coffee b/scripts/pizza.coffee index d20b0bb..6cc0be0 100644 --- a/scripts/pizza.coffee +++ b/scripts/pizza.coffee @@ -38,9 +38,12 @@ module.exports = (robot) -> ).join() start: -> + order = this.currentOrder() if this.isStarted() - this.closeOrder() - this.currentOrder().status = 'open' + unless order.startDate && order.startDate >= new Date(new Date() - 24 * 60 * 60 * 1000) + this.closeOrder() + order.status = 'open' + order.startDate = order.startDate || new Date() isStarted: -> this.currentOrder().status == 'open' From 130aa58b2aa12d78ac41779631d77e6d082e1404 Mon Sep 17 00:00:00 2001 From: Joren Verspeurt Date: Fri, 11 Aug 2017 18:02:28 +0200 Subject: [PATCH 4/7] Implemented a matcher for the Pazza menu --- scripts/pizza.coffee | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/scripts/pizza.coffee b/scripts/pizza.coffee index 6ec1da7..51023dd 100644 --- a/scripts/pizza.coffee +++ b/scripts/pizza.coffee @@ -21,9 +21,34 @@ # Author: # StijnP (XAOP) # +levenshtein = require 'fast-levenshtein' module.exports = (robot) -> + pazza_menu = ['funghi', 'mano', 'rochus', 'margherita', 'carbonara', 'prosciutto', 'fratello', 'capricciosa', 'calzione', '4stagioni', 'rimini', 'vesuvio', 'vulcano', 'hawaii', 'peppina', 'napoletana', 'romana', 'extravaganza', '8gusti', 'pazza', 'boscaiola', 'montana', 'primavera', 'parmigiana', 'pollo', 'pescatore', '4formaggi', '6formaggi', 'scampis', 'bruschetta', 'toscana', 'patapizza'] + match_pizza = (order) -> + # Normalization + replacements = [order.toLowerCase(), # Shut up + [/kazen/, "formaggi"], + [/fromages/, "formaggi"], + [/fromaggi/, "formaggi"], + [/quattro/, "4"], + [/quatro/, "4"], + [/sei /, "6 "], + [/octo/, "8"], + [/4 s/, "4s"], + [/4 f/, "4f"], + [/6 f/, "6f"], + [/8 g/, "8g"]] + normalized = replacements.reduce (s, r) -> + s.replace r[0], r[1] + return normalized.split(" ").map((norm_word) -> + pazza_menu.map((menu_item) -> + [levenshtein.get(norm_word, menu_item), menu_item] + ).sort()[0] + ).sort()[0][1] # TODO optimize + + robot.brain.data.currentPizzaOrder = pizzas: {}, date: null, From de631ef1c65d59e607f70008f9e44de032696519 Mon Sep 17 00:00:00 2001 From: Joren Verspeurt Date: Fri, 11 Aug 2017 20:46:51 +0200 Subject: [PATCH 5/7] Improvements to pizza ordering, added ordering for externals --- package.json | 4 ++- scripts/pizza.coffee | 79 ++++++++++++++++++++++++++++---------------- 2 files changed, 54 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index e2e2016..2d462c4 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,9 @@ "hubot-rules": "^0.1.1", "hubot-scripts": "^2.16.1", "hubot-shipit": "^0.2.0", - "hubot-slack": "^3.3.0" + "hubot-slack": "^3.3.0", + "fast-levenshtein": "^2.0.6", + "js-yaml": "^3.9.1" }, "engines": { "node": "0.10.x" diff --git a/scripts/pizza.coffee b/scripts/pizza.coffee index 943bde4..c453678 100644 --- a/scripts/pizza.coffee +++ b/scripts/pizza.coffee @@ -22,31 +22,35 @@ # StijnP (XAOP) # levenshtein = require 'fast-levenshtein' +yaml = require 'js-yaml' module.exports = (robot) -> pazza_menu = ['funghi', 'mano', 'rochus', 'margherita', 'carbonara', 'prosciutto', 'fratello', 'capricciosa', 'calzione', '4stagioni', 'rimini', 'vesuvio', 'vulcano', 'hawaii', 'peppina', 'napoletana', 'romana', 'extravaganza', '8gusti', 'pazza', 'boscaiola', 'montana', 'primavera', 'parmigiana', 'pollo', 'pescatore', '4formaggi', '6formaggi', 'scampis', 'bruschetta', 'toscana', 'patapizza'] match_pizza = (order) -> - # Normalization - replacements = [order.toLowerCase(), # Shut up - [/kazen/, "formaggi"], - [/fromages/, "formaggi"], - [/fromaggi/, "formaggi"], - [/quattro/, "4"], - [/quatro/, "4"], - [/sei /, "6 "], - [/octo/, "8"], - [/4 s/, "4s"], - [/4 f/, "4f"], - [/6 f/, "6f"], - [/8 g/, "8g"]] - normalized = replacements.reduce (s, r) -> - s.replace r[0], r[1] - return normalized.split(" ").map((norm_word) -> - pazza_menu.map((menu_item) -> - [levenshtein.get(norm_word, menu_item), menu_item] - ).sort()[0] - ).sort()[0][1] # TODO optimize + # Normalization + replacements = [[/seizoene(n)?/, "stagioni"], + [/kaze(n)?/, "formaggi"], + [/fromage(s)?/, "formaggi"], + [/fromaggi(o)?/, "formaggi"], + [/quat(t)?r(o|e)/, "4"], + [/sei/, "6"], + [/octo/, "8"], + [/vier/, "4"], + [/zes/, "6"], + [/acht/, "8"], + [/4 s/, "4s"], + [/4 f/, "4f"], + [/6 f/, "6f"], + [/8 g/, "8g"], + [/random/, pazza_menu[Math.round(Math.random()*pazza_menu.length)-1]]] + normalized = replacements.reduce(((s, r) -> + s.replace(r[0], r[1])), order.toLowerCase()) + return normalized.split(" ").map((norm_word) -> + pazza_menu.map((menu_item) -> + [levenshtein.get(norm_word, menu_item), menu_item] + ).sort()[0] + ).sort()[0][1] robot.brain.data.pizzaOrderHistory = robot.brain.data.pizzaOrderHistory or [] robot.brain.data.pizzaOrderHistoryBackup = robot.brain.data.pizzaOrderHistoryBackup or [] @@ -57,9 +61,14 @@ module.exports = (robot) -> current: -> obj = this.currentOrder().pizzas - Object.keys(obj).map((key) -> - obj[key] - ).join() + counted = yaml.safeDump(Object.keys(obj).reduce(((p, c) -> + if p[obj[c]] + p[obj[c]] += 1 + else + p[obj[c]] = 1 + return p + ), {})) + start: -> order = this.currentOrder() @@ -127,26 +136,41 @@ module.exports = (robot) -> robot.respond /pizza me (.*)/i, (msg) -> if pizzas.isStarted() sender = msg.message.user.name.toLowerCase() - pizza = msg.match[1] + pizza = match_pizza(msg.match[1]) pizzas.add(sender, pizza) msg.reply "One pizza #{pizza} ordered, now #{pizzas.currentQty()} on the list" else msg.send "Sorry, no running order at this time..." + ## ORDER a pizza for someone else ## + robot.respond /pizza for (\w+) (.*)/i, (msg) -> + if pizzas.isStarted() + external = "#{msg.message.user.name.toLowerCase()} for #{msg.match[1]}" + pizza = match_pizza(msg.match[2]) + pizzas.add(external, pizza) + msg.reply "One pizza #{pizza} ordered by #{external}, now #{pizzas.currentQty()} on the list" + else + msg.send "Apologize to #{msg.match[1]} for me, no running order at this time..." + ## CANCEL your pizza order robot.hear /no pizza for me/i, (msg) -> sender = msg.message.user.name.toLowerCase() pizzas.remove(sender) msg.reply "Ok... I cancelled your order... pussy" + ## CANCEL someone's pizza order + robot.respond /no pizza for (\w+)/i, (msg) -> + external = "#{msg.message.user.name.toLowerCase()} for #{msg.match[1]}" + pizzas.remove(external) + msg.reply "Ok... tell #{msg.match[1]} their order is cancelled" + ## SHOW CURRENT order round ## robot.respond /pizza (current|show)/i, (msg) -> qty = pizzas.currentQty() if qty > 0 heroes = pizzas.currentEaters() names = pizzas.current() - msg.send "#{qty} pizzas: #{names}" - msg.send "Pizza heroes of today are #{heroes}" + msg.send "#{qty} pizzas:\n#{names}Pizza heroes of today are #{heroes}" # msg.send "Status is '#{robot.brain.data.currentPizzaOrder.current}'" else msg.send "No orders yet" @@ -175,8 +199,7 @@ module.exports = (robot) -> names = pizzas.current() order = pizzas.closeOrder() msg.send "Pizza order CLOSED, you should now order:" - msg.send "#{qty} pizzas: #{names}" - msg.send "Pizza heroes of today are #{heroes}" + msg.send "#{qty} pizzas:\n#{names}Pizza heroes of today are #{heroes}" else msg.send "Nothing to close, you need to order first, silly! :pizza:" From 96fb106cdb83b83c0b627c9c87dcc6592de838af Mon Sep 17 00:00:00 2001 From: Joren Verspeurt Date: Fri, 11 Aug 2017 21:17:01 +0200 Subject: [PATCH 6/7] Allow ordering of special pizzas with pizza me special --- scripts/pizza.coffee | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/pizza.coffee b/scripts/pizza.coffee index c453678..a218010 100644 --- a/scripts/pizza.coffee +++ b/scripts/pizza.coffee @@ -136,7 +136,10 @@ module.exports = (robot) -> robot.respond /pizza me (.*)/i, (msg) -> if pizzas.isStarted() sender = msg.message.user.name.toLowerCase() - pizza = match_pizza(msg.match[1]) + if /special/i.test(msg.match[1]) + pizza = msg.match[1].slice(8) + else + pizza = match_pizza(msg.match[1]) pizzas.add(sender, pizza) msg.reply "One pizza #{pizza} ordered, now #{pizzas.currentQty()} on the list" else @@ -146,7 +149,10 @@ module.exports = (robot) -> robot.respond /pizza for (\w+) (.*)/i, (msg) -> if pizzas.isStarted() external = "#{msg.message.user.name.toLowerCase()} for #{msg.match[1]}" - pizza = match_pizza(msg.match[2]) + if /special/i.test(msg.match[2]) + pizza = msg.match[2].slice(8) + else + pizza = match_pizza(msg.match[2]) pizzas.add(external, pizza) msg.reply "One pizza #{pizza} ordered by #{external}, now #{pizzas.currentQty()} on the list" else From d27ff2ba996dd951e57691bbd35bd2ced03ba164 Mon Sep 17 00:00:00 2001 From: Joren Verspeurt Date: Fri, 11 Aug 2017 21:31:00 +0200 Subject: [PATCH 7/7] Fixed small bug --- scripts/pizza.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/pizza.coffee b/scripts/pizza.coffee index a218010..ac51985 100644 --- a/scripts/pizza.coffee +++ b/scripts/pizza.coffee @@ -146,7 +146,7 @@ module.exports = (robot) -> msg.send "Sorry, no running order at this time..." ## ORDER a pizza for someone else ## - robot.respond /pizza for (\w+) (.*)/i, (msg) -> + robot.respond /pizza for (\S+) (.*)/i, (msg) -> if pizzas.isStarted() external = "#{msg.message.user.name.toLowerCase()} for #{msg.match[1]}" if /special/i.test(msg.match[2]) @@ -165,7 +165,7 @@ module.exports = (robot) -> msg.reply "Ok... I cancelled your order... pussy" ## CANCEL someone's pizza order - robot.respond /no pizza for (\w+)/i, (msg) -> + robot.respond /no pizza for (\S+)/i, (msg) -> external = "#{msg.message.user.name.toLowerCase()} for #{msg.match[1]}" pizzas.remove(external) msg.reply "Ok... tell #{msg.match[1]} their order is cancelled"