Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 64 additions & 31 deletions src/utils/urgencyScorer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
13 changes: 13 additions & 0 deletions testUrgency.js
Original file line number Diff line number Diff line change
@@ -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}`)
}