diff --git a/src/utils/urgencyScorer.js b/src/utils/urgencyScorer.js index 7af6b01..907a4a8 100644 --- a/src/utils/urgencyScorer.js +++ b/src/utils/urgencyScorer.js @@ -4,38 +4,71 @@ export function calculateUrgency(message) { let urgencyScore = 50 - - const exclamationCount = (message.match(/!/g) || []).length - urgencyScore += exclamationCount * 30 - - if (message.length < 50) urgencyScore -= 40 - if (message.length < 20) urgencyScore -= 60 - - if (message === message.toUpperCase() && message.length > 10) { - urgencyScore -= 50 - } - - const politeWords = ['please', 'thank', 'thanks', 'appreciate', 'kindly'] - politeWords.forEach(word => { - if (message.toLowerCase().includes(word)) urgencyScore -= 15 + + const text = message.toLowerCase() + + // Outage / breakage language — strong signal that something is broken + const outageWords = [ + 'down', 'outage', 'broken', 'not working', "isn't working", 'crash', + 'crashed', 'error', 'errors', 'failed', 'failing', 'failure', 'bug', + 'cannot log in', "can't log in", 'cannot login', 'unable to', 'offline', + 'production', 'data loss', 'locked out', 'stuck', 'frozen', 'timeout' + ] + outageWords.forEach(word => { + if (text.includes(word)) urgencyScore += 20 }) - - if (message.includes('?')) urgencyScore -= 25 - - const now = new Date() - if (now.getDay() === 0 || now.getDay() === 6) { - urgencyScore -= 20 - } - if (now.getHours() < 9 || now.getHours() > 17) { - urgencyScore -= 15 - } - - const positiveWords = ['happy', 'love', 'great', 'excellent', 'wonderful'] - positiveWords.forEach(word => { - if (message.toLowerCase().includes(word)) urgencyScore -= 20 + + // Billing / payment problems + const billingWords = [ + 'charged', 'charge', 'overcharged', 'double charged', 'charged twice', + 'billing', 'invoice', 'refund', 'payment', 'declined', 'fraud', + 'unauthorized', 'money', 'subscription' + ] + billingWords.forEach(word => { + if (text.includes(word)) urgencyScore += 15 + }) + + // Anger / frustration + const angerWords = [ + 'furious', 'angry', 'frustrated', 'frustrating', 'ridiculous', + 'unacceptable', 'terrible', 'awful', 'horrible', 'worst', 'hate', + 'disappointed', 'fed up', 'sick of', 'never again' + ] + angerWords.forEach(word => { + if (text.includes(word)) urgencyScore += 20 }) - - if (urgencyScore > 80) return "High" - if (urgencyScore < 30) return "Low" + + // Explicit urgency words + const urgentWords = [ + 'urgent', 'urgently', 'asap', 'emergency', 'immediately', 'right now', + 'critical', 'now', 'time sensitive', 'deadline', 'demo' + ] + urgentWords.forEach(word => { + if (text.includes(word)) urgencyScore += 25 + }) + + // Exclamation marks emphasise intensity + const exclamationCount = (message.match(/!/g) || []).length + urgencyScore += Math.min(exclamationCount, 3) * 10 + + // Detect whether this is a genuinely positive / thank-you message. + // Only lower the score when there is praise and no complaint signal. + const positiveWords = [ + 'thank', 'thanks', 'appreciate', 'great', 'awesome', 'love', + 'excellent', 'wonderful', 'happy', 'amazing', 'fantastic', 'perfect' + ] + const hasPositive = positiveWords.some(word => text.includes(word)) + + const complaintSignals = [ + ...outageWords, ...billingWords, ...angerWords, ...urgentWords + ] + const hasComplaint = complaintSignals.some(word => text.includes(word)) + + if (hasPositive && !hasComplaint) { + urgencyScore -= 40 + } + + if (urgencyScore >= 80) return "High" + if (urgencyScore <= 40) return "Low" return "Medium" } diff --git a/testUrgency.js b/testUrgency.js new file mode 100644 index 0000000..d5be5b3 --- /dev/null +++ b/testUrgency.js @@ -0,0 +1,13 @@ +import { calculateUrgency } from './src/utils/urgencyScorer.js' + +const messages = [ + "Our production server is down", + "I was charged twice and I am furious!!", + "Thank you so much, your team is great!", + "Can I upgrade to the pro plan?", + "URGENT: I cannot log in and I have a demo in 10 minutes" +] + +for (const message of messages) { + console.log(`${calculateUrgency(message)}\t${message}`) +}