import { normalizeText } from './normalize.js';
import { NUM10, SAME_CLAUSE, SCHEDULE } from './rules.js';
/**
* Words of intent to die or to take too much (A1b, A1c, M1), the one list for
* check symptoms and Ask (M2), with three outcomes (M-1): the self-harm sign,
* only with a wish, plan, method or amount ("I want to die", "I hope I die in
* my sleep", "Will I die if I take all of them?"), including someone else's
* wish told by their family ("Mum keeps saying she wants to die", M-B); the
* sign of feeling like dying, never labelled self-harm ("I feel like I'm
* dying", "my baby is dying"); and never a sign: figures of speech ("my back
* is killing me", "dying of thirst", "she would literally kill me"),
* end-of-life talk ("She wants to die at home", "He is ready to die and has
* stopped eating") and fear of death ("I don't want to die young"). The
* self-harm words of the sign table live here too (review 7), so there is one
* list. H-A: an amount of medicine taken, with a word about dying or killing
* now, is too much medicine ("I'm going to die from all the pills I took").
*/
const B = '(?<![a-z0-9])';
const E = '(?![a-z0-9])';
/** H-1, M-a: a wish to die said by the speaker: "want", "wish", "hope", "pray", "like", "love", Pidgin "wan" (not "wants": that's someone else). */
const WISH = '(?:want|wanted|wanting|wanna|wan|wish|wished|wishing|hope|hoped|hoping|pray|prayed|praying|plan|planned|planning|try|tried|trying|rather|deserve|deserved|like|love|longing)';
/** M-a: someone else wishing it ("she wants to die", "he's ready to die"): their own wish (M-B), or end-of-life talk. R9-M1: a boy, girl, kid, teenager or "N year old" too. */
const SOMEONE_ELSE = '(?:she|he|shes|hes|shed|hed|they|theyre|theyd|mum|mom|mother|mama|dad|father|papa|husband|wife|son|daughter|baby|child|boy|girl|kid|teen|teenager|year old|years old|patient|grandma|grandpa|grandmother|grandfather|sister|brother|aunt|aunty|auntie|uncle|friend|everyone|nobody|who)';
/** M-a: a negation before a wish: "I don't want to die young" is fear of death. */
const NEG = '(?:dont|do not|doesnt|does not|didnt|did not|never|not|no|wont|will not|wouldnt|would not|isnt|is not|arent|are not|aint)';
/** M-a: where, or how, a death is wished for at the end of life: "at home", "in hospital", "peacefully". */
const PLACE = `(?:at home|in (?:the |a )?(?:hospital|hospice)|with dignity|peacefully|in peace|in (?:my|her|his|their) own bed|surrounded by)${E}`;
/** A medicine named after "too much" ("too much of my tablets"). */
const MED = '(?:tablets?|pills?|medicines?|medication|meds|drugs?|capsules?|it|them|paracetamol|panadol|insulin|morphine|amitriptyline|amlodipine|diazepam)';
/** H-A: a medicine, by kind or by name: "all my insulin", "the whole bottle of my sleeping tablets". */
const MEDICINES = '(?:tablets?|pills?|medicines?|medication|meds|drugs?|capsules?|insulin|injections?|paracetamol|panadol|morphine|amitriptyline|amlodipine|diazepam|sleeping (?:tablets?|pills?)|painkillers?|antidepressants?)';
/** H-A: an amount: all of it, too many, a box of, or ten or more. */
const AMOUNT = `(?:all|the whole|whole|too many|too much|enough|everything|the lot|a lot of|lots of|loads of|so many|plenty(?: of)?|an overdose of|a (?:box|bottle|packet|pack|strip|card) of|${NUM10})`;
/** A word between "on purpose" and the act, never one that says the dose was stopped, skipped or prescribed (M-1). */
const NOT_STOPPING = ' (?!(?:stopped|stop|stopping|skipped|skip|skipping|missed|miss|missing|lowered|lower|reduced|reduce|halved|halve|changed|prescribed|prescribe)(?![a-z0-9]))[a-z0-9]+';
/** R9-H2, R10-H2: harming oneself: hurting, cutting, burning, scratching, hitting, punching, banging or biting (every tense; "bit", never "a bit"). */
const SELF_HARMING = '(?:hurt|hurts|hurting|harm|harms|harmed|harming|cut|cuts|cutting|burn|burns|burned|burnt|burning|scratch|scratches|scratched|scratching|hit|hits|hitting|punch|punches|punched|punching|bang|bangs|banged|banging|bite|bites|biting|(?<!a )bit)';
/** Taking or harming: what "on purpose" has to be next to (M-1, R9-H2). */
const HARMING = `(?:took|taken|swallowed|overdosed|overdose|${SELF_HARMING} (?:my|her|him|them|your)sel(?:f|ves)|cut (?:my|her|his|their) (?:arm|arms|wrist|wrists|leg|legs|skin))`;
/** M-a, LOW: "on purpose" with food, a meal or bedtime is when a dose was taken: "I took it on purpose at bedtime". */
const MEAL_OR_BEDTIME = `(?:(?: [a-z]+){0,3} (?:(?:with|before|after|at) (?:food|a meal|meals|breakfast|lunch|dinner|bed|bedtime|night)|in the (?:morning|evening)|evening dose|morning dose)${E})`;
/**
* M-C, R9-M5: how an accident happened, straight after harming oneself (one list for every method): shaving, cooking, ironing,
* baking, frying, "while ...ing", by accident or by mistake, by mixing or doubling, "when I fell" or fainted, "on a glass", "at the
* gym" (never on a part of the body: "on the arm" is not an accident), with a knife, razor, fork, pin, nail or scissors, with hot
* or boiling water; and a bleeding question ("badly and it won't stop bleeding").
*/
const BODY = `(?:arm|arms|wrist|wrists|leg|legs|thigh|thighs|stomach|skin|body)${E}`;
const ACCIDENT = `(?:(?:while|whilst) [a-z]+ing|shaving|cooking|chopping|ironing|baking|frying|by accident|accidentally|by mistake|mistakenly`
+ `|by (?:mixing|taking|using|combining|doubling)|at work|lifting|playing|gardening|exercising|(?:on|at) (?:a|the|some) (?!${BODY})[a-z]+`
+ `|with (?:a|the) (?:knife|razor|needle|lancet|fork|pin|nail|scissors)|with (?:hot|boiling) [a-z]+`
+ `|when (?:i|she|he) (?:fell|fall|slipped|tripped|fainted|collapsed|passed out|blacked out)|falling|fell|fainting`
+ `|(?:(?:quite |really |very )?badly )?and (?:it|the cut|the wound|the bleeding) (?:wont|will not|doesnt|does not|cant|keeps?)(?: stop)? bleeding)${E}`;
/** R10-M3: a part of the body, before how the accident happened ("in the face", "on my hand"). */
const PART_OF_THE_BODY = '(?:in|on) (?:the|my|her|his) (?:face|head|arm|leg|hand|finger|foot|knee|eye|nose|lip)(?: [a-z]+)?';
/** R9-H2: an itch, so scratching oneself is not self-harm ("my skin is so itchy I keep scratching myself"). */
const ITCH = `(?:itch|itches|itchy|itching|itchiness|rash|rashes|hives|eczema|psoriasis|mosquito|insect bites?|bites|allergy|allergic)${E}`;
/**
* M-d, M-D, R9 ruling 3b: words of intent in Hausa, the first-person wish only ("ina so in mutu", "ina son mutuwa", "mutuwa nake
* so", "zan kashe kaina"; never "zan mutu" alone, which is also said in fear, nor "mutu" or "mutuwa" alone: "Mahaifiyata tana
* mutuwa" is "my mother is dying"), Yoruba ("mo fe ku") and Igbo ("achoro m inwu"), all "I want to die" or "I will kill myself".
* A native speaker is to confirm them.
*/
const NOT_ENGLISH_INTENT = '(?:(?:ina so|ina son|na so) (?:in )?mutu|ina son mutuwa|mutuwa nake so|zan kashe kaina|mo fe ku|achoro m inwu)';
/** When or how a medicine is taken: "all my tablets in the morning" is a regimen, not too much (M1). */
const TIMING = `(?:${SCHEDULE}|(?:with|before|after) (?:my |her |his |their |the |a )?(?:food|meal|meals|breakfast|lunch|dinner|supper|eating)|before (?:bed|bedtime)|on an empty stomach)`;
/** L5: taking medicines with you, not taking them: "on the plane", "abroad", "in my luggage". */
const TRAVEL = '(?:on (?:the|a|my) (?:plane|flight|trip|holiday|journey)|on holiday|abroad|overseas|through (?:security|customs|the airport)'
+ '|in (?:my|her|his|the|a) (?:luggage|bag|suitcase|hand luggage|case|carry on)|with (?:me|her|him|us|them)|to (?:the )?(?:airport|uk|us|usa|nigeria|ghana|school|work)'
+ '|travel|travelling|traveling|flying|when (?:i|we|she|he) (?:travel|fly|go))(?![a-z0-9])';
/** Missing, running out of, sorting or keeping tablets: "I forgot to take all my tablets", "I keep all my tablets in a dosette box" (LOW) is not too much. */
const NOT_TAKING = '(?:missed|miss|missing|forgot|forget|forgotten|ran out of|run out of|running out of|lost|lose|skipped|skip|refill|refilled|collect|collected|order|ordered|stopped|stop|list|listed|check|checked|bring|brought|pack|packed|sort|sorted|organise|organize|organised|organized|keep|keeps|kept|store|stores|stored|put|puts|left|leave|count|counted)';
/** LOW: what a medicine kills that isn't a person: "kill my appetite", "kills the pain", "kill the germs". */
const KILLED_THING = `(?:appetite|stomach|kidneys?|liver|ankles?|back|knees?|feet|legs?|head|mood|sleep|libido|sex drive|energy|taste|joints?|skin|teeth|gut|pain|pains|germs?|bacteria|bugs?|infections?|cells?|buzz|vibe)${E}`;
/** R9 ruling 3d, R10-M5: a sick day, within three words: "when I'm sick", "if I'm vomiting", "if I have a fever", "with a cold", "during Ramadan". */
const SICK_DAY = `(?:(?: [a-z]+){0,3} (?:when|if|while|whilst) (?:i|im|i am|she|he|shes|hes|they|you|youre|we)(?: [a-z]+){0,2} (?:sick|ill|unwell|vomiting|being sick|throwing up|poorly|not eating|fasting|dehydrated)${E}`
+ `|(?: [a-z]+){0,3} (?:when|if|while|whilst)(?: [a-z]+){0,3} (?:got|have|has|having) (?:a |an |the )?(?:diarrhoea|diarrhea|fever|flu|cold|stomach bug|bug|infection|covid|temperature|virus)${E}`
+ `|(?: [a-z]+){0,3} (?:with|during|on|for) (?:a |the )?(?:cold|flu|fever|diarrhoea|diarrhea|sick days?|ramadan)${E})`;
/** LOW: the tablets doing something, not being taken: "all my tablets kill my appetite", "all my tablets make me sick" (never "kill me"). */
const TABLETS_DO = `(?:(?:kill|kills|killed) (?:my|your|her|his|the|their|our) ${KILLED_THING}|make|makes|made|give|gives|gave|cause|causes|caused|are|were|have|has|had|seem|seems|taste|tastes|cost|costs|upset|upsets|affect|affects|work|works|interact|interacts|clash|clashes)`;
/**
* Where or with whom someone wants to live, not whether: "She doesn't want to live in a care home", "I don't want to live alone",
* R9-L3: "with us" (never "at all", "in this world", "in pain", "with this pain").
*/
const LIVE_WHERE = ` (?:in (?:a|the|an|my|her|his|their|our) (?!(?:pain|agony|misery|fear|world)${E})|at (?!all${E})|with (?:my|her|his|their|our|a|the) (?!(?:pain|illness|condition|disease|cancer)${E})`
+ `|with (?:us|me|you|them|him|her)${E}|near |abroad${E}|alone${E}|on (?:my|her|his|their) own${E}|there${E}|by (?:my|her|him|them)sel(?:f|ves)${E})`;
/** Wanting to die or to harm oneself: the self-harm sign, only with a wish, plan, method or amount (M-1, H-1, M-a). */
const SELF_HARM = new RegExp([
// The sign table's own words (one list): suicide, self-harm, hurting, cutting or killing oneself, ending one's life, and the
// typos "sucide", "suiside", "kill my self", "myslef" (H-1.6); "kms", not "5 kms". R9-H2: burning, scratching, hitting, punching,
// banging or biting oneself too. M-C: not after an accident ("I cut myself shaving", "I hurt myself when I fell"), R10-M3: also
// with a part of the body first ("on the hand while cooking"); R9: not scratching an itch; not "her life saving medicine" or
// "take my life back".
`${B}(?:suicid[a-z]*|sucid[a-z]*|suisid[a-z]*|self harm[a-z]*|(?!scratch)${SELF_HARMING} (?:my|her|him|them|your)sel(?:f|ves)(?! ${ACCIDENT})(?! ${PART_OF_THE_BODY} ${ACCIDENT})`
+ `|(?<!${ITCH}(?: [a-z]+){0,8} )scratch(?:es|ed|ing)? (?:my|her|him|them|your)sel(?:f|ves)(?! ${ACCIDENT})(?!(?: [a-z]+){0,6} ${ITCH})`
+ `|(?:end|take|taking|ending) (?:my|her|his|their|your) (?:own )?life${E}(?! (?:saving|savings|insurance|back|in (?:my|her|his|their) hands)${E}))`,
// ...and a wish or plan to, whatever follows ("I want to cut myself on the bathroom floor").
`${B}(?:${WISH}|wants|wishes|plans|thinking (?:about|of)|urge to|urges to)(?: to)? (?:hurt(?:ing)?|harm(?:ing)?|cut(?:ting)?|burn(?:ing)?|scratch(?:ing)?|hit(?:ting)?|punch(?:ing)?|bang(?:ing)?|bit(?:e|ing)) (?:my|her|him|them)sel(?:f|ves)${E}`,
`${B}(?:kill(?:ing)? (?:my|her|him|them|your) ?sel(?:f|ves)|kill(?:ing)? (?:myslef|mysef|my slef|myslf)|(?<![0-9] )kms)${E}`,
`${B}(?:(?:dont|do not|doesnt|does not|no) (?:want|wan) to (?:live(?!${LIVE_WHERE})|be here)|end(?:ing)? it all|better off dead|no reason to live|tired of living|(?:want|wants|wanted) to disappear)${E}`,
// M-d: passive wishes ("I don't want to be alive anymore", "I wish I wasn't alive", "Everyone would be better off without me",
// "life is not worth living", "What's the point of living", Pidgin "I no wan live again"). M-C: "I can't go on" only at the end
// of the clause or with anymore, like this or living (never "I can't go on holiday"), and "point of living" only as "what's the
// point" or "no point". Review 8: "I don't want to exist anymore" (not "exist on painkillers"), "I no wan dey alive again".
`${B}(?:(?:dont|do not|doesnt|does not|no) (?:want|wan|wanna)(?: to)? (?:live(?!${LIVE_WHERE})|be alive|be here|dey alive|dey here|exist(?! on${E}))|not worth living|better off without me`
+ `|cant go on(?: (?:anymore|any more|like this|living))?(?=$| (?:anymore|any more|i (?:want|wanna|just)|and|but)${E})`
+ `|(?:whats the|what is the|no|dont see the|cant see the|there is no|theres no) point (?:of|in) (?:living|life|(?:going|carrying) on(?! with${E}))`
+ `|wish (?:i|id) (?:wasnt|werent|was not|were not) (?:alive|here|born)|never been born|better off (?:not|never) (?:being (?:alive|here|born)|existing|living))${E}`,
// Review 8: "nobody would miss me" (not "at the party"), "I'm done with life", "I'm tired of life", "I pray God takes my life",
// Pidgin "make God take my life".
`${B}(?:nobody|no one|noone|no body) (?:would|will|is going to|gonna)(?: even| really| ever)? miss me${E}(?! (?:at|in|from|on|for) (?!all${E}))`,
`${B}(?:done|finished|tired|sick|fed up|weary) (?:with|of) (?:my |this |dis )?life(?=$| (?:and|so|now|already|anymore|any more|but|itself|o|honestly|really|i|im|its)${E})`,
`${B}(?:pray|prays|praying|prayed|hope|hoping|wish|wishing|asking|ask|beg|begging|want|wants)(?: that)? (?:god|jesus|allah|the lord|lord|baba god|oluwa)`
+ `(?: (?:will|would|should|can|could|to|just))* (?:take|takes|call|calls) (?:my life|me)(?=$| (?:now|away|home|already|tonight|soon|in my sleep|o|abeg|please)${E})`,
`${B}make (?:god|jesus|allah|baba god|oluwa) (?:just )?(?:take|carry) (?:my life|me)${E}`,
// R9-L1, R10-L2: "God take me now", with no wish verb, at the end of the clause, the last word optional (never "God take me
// through this").
`${B}(?:god|jesus|allah|the lord|lord|baba god|oluwa)(?: please| pls| abeg| just)? (?:take|carry|call) (?:my life|me)(?: home| away)?(?: (?:now|already|tonight|today|please|pls|abeg|o))*$`,
// M-d: methods ("I want to hang myself", "I'm going to jump off a bridge", "I want to slit my wrists", "I go jump inside lagoon",
// Pidgin "I wan kpai myself"); not "shoot myself in the foot". M-C, R9-M5: not stabbing myself with a needle, a lancet or an
// insulin pen, nor after an accident.
// Review 8: "I'll throw myself off the roof", "under a train" (not "threw myself into my work", "off balance").
`${B}(?:hang|hanging|drown|drowning|shoot|shooting|kpai|poison|poisoning) (?:my|her|him|them)sel(?:f|ves)${E}(?! in the foot${E})`,
`${B}(?:stab|stabs|stabbing|stabbed) (?:my|her|him|them)sel(?:f|ves)${E}(?! ${ACCIDENT})(?!(?: [a-z]+){0,4} (?:needles?|lancets?|pens?|injections?|insulin|fingers?|foot|fork|by accident|accidentally|by mistake)${E})`,
`${B}(?:throw|throws|throwing|threw|thrown) (?:my|her|him|them)sel(?:f|ves) (?:off|under|in front of|from)${E}(?! balance${E})`,
`${B}(?:(?:slit|slitting) (?:my|her|his|their) (?:wrists?|throat)|(?:cut|cutting) (?:my|her|his|their) (?:wrists|throat))${E}`,
`${B}(?:jump|jumping)(?: off| in front of| from| inside| into)(?: a| the)? (?:bridge|building|train|roof|lagoon|car|lorry|cliff|river|sea|balcony|window)${E}`,
// Die (H-1.1): a wish, "to", "2" or "too", "just", "go to sleep and" or "lie down and", then die ("I want 2 die", "I'd like to die", "I would love
// to die", "I want to go to sleep and die", H-A: "I just want to lie down and die"); not negated ("I don't want to die young"),
// not someone else's ("she wants to die": OTHER_WISH), not where ("at home", "in hospital"), not "die my hair".
`${B}(?<!${SOMEONE_ELSE}(?: (?:really|just|still|would|did|does|always|also|truly))? )(?<!${NEG}(?: [a-z]+)? )${WISH}(?: (?:to|2|too))?`
+ `(?: (?:just|really|simply|only|go and|go to sleep and|sleep and|lie down and|go and lie down and))* (?:die|be dead)${E}(?! ${PLACE})(?! (?:my|her|his|their|the) (?:hair|clothes|shirt|dress|beard|eyebrows))`,
// ...or wish, hope or pray that I, I'd or I'll (could, would, will, just) die ("I wish I could die", "I hope I die in my sleep").
`${B}(?<!${NEG}(?: [a-z]+)? )(?:wish|wished|wishing|hope|hoped|hoping|pray|prayed|praying)(?: that)? (?:i|id|ill|im)(?: (?:could|would|will|might|can|just|did|do|was|were|really))* (?:die|be dead|dead)${E}(?! ${PLACE})`,
// "I'm ready to die", said by the speaker; not "he is ready to die" (end-of-life talk), not "ready to die at home".
`${B}(?:i am|im|i feel|i think im|i think i am)(?: so| really| just)? ready to (?:die|be dead)${E}(?! ${PLACE})`,
// "... and just die", "let me die", "dying inside", "I feel like dying" (a wish; not "I feel like I'm dying"), "I'd rather die".
`${B}(?:and just die|let me die|dying inside|feel(?:s|ing)? like dying|better off dying|rather (?:die|be dead))${E}`,
// "going to die" or "will die" said by the speaker: SPEAKER_DIE, below (R12-M1).
// "Will I die if I take all of them?": an amount. Not "Will I die if I miss a dose?".
`${B}(?:will|would|could|can|might) (?:i|she|he|we|they|you) die if (?:i|she|he|we|they|you) (?:take|took|swallow|swallowed|drink|drank|have|had)(?: [a-z]+){0,2} (?:all|the whole|too many|too much|${NUM10})${E}`,
// Kill (H-1.2, M-a): oneself, a wish or plan to ("I want to kill myself", "going to kill myself"; never "going to kill me"),
// "just kill me", "which tablets will kill me?", or an amount ("Would 20 tablets kill me?"). A modal opening the clause ("Could
// my tablets kill me?") is SELF_HARM_CLAUSE. Not "e go kill me" (Pidgin: it will kill me), "she would literally kill me".
`${B}(?:${WISH}|wants|wishes|hopes|plans|tries|going|gonna)(?: to)? kill (?:myself|my self|someone|somebody)${E}`,
`${B}(?:just|please|pls) kill me${E}`,
`${B}(?:which|what)(?: [a-z0-9]+){0,5} (?:could|would|will|can|might|may) kill (?:me|you)${E}`,
`${B}(?:${NUM10}|enough|all (?:of )?(?:my|the|these|those|them|it)|the whole|too many|too much(?: of)?(?: my| the)? ${MED})(?: [a-z]+){0,6} kill me${E}`,
// End it: "end it all", or a wish or plan ("I want to end it", "thinking about ending it"); never "end it with this medicine",
// "there", "early", "and stop the statin" or "today and start the new tablets".
`${B}(?:${WISH}|going|gonna|just|thinking (?:about|of)) (?:to )?end(?:ing)? it(?! (?:with|there|here|early|after|when|now and|and stop|and start|today and)${E})${E}`,
// "sleep forever", but not "I'm so tired I could sleep forever" (unless wished for: "I wish I could sleep forever").
'(?<![a-z0-9])(?<!(?<!(?:wish|wishes|wished|want|wants|wanted|hope|hopes) )(?:i|you|she|he|we|they) could )sleep forever(?![a-z0-9])',
// Pidgin: "I wan die", "make I (just) die", "I go die", "na (only) to die remain" (H-A), "tire for this life", "life no worth am"
// (review 8); and the Hausa, Yoruba and Igbo words (M-d, M-D).
`${B}(?:(?:i|she|he|e) wan die|make i (?:just )?die|i go die|na (?:only |just )?(?:to )?die remain|tire for (?:this|dis) life|tire of (?:this|dis) life`
+ `|life no worth (?:am|it|anything)|${NOT_ENGLISH_INTENT})${E}`,
// "on purpose", only next to taking or harming, in either order ("I took them on purpose", "I deliberately took 20"); never a
// dose stopped, skipped, lowered or prescribed on purpose, nor taken on purpose with food or at bedtime (M-a, LOW).
`${B}${HARMING}(?:${NOT_STOPPING}){0,4} (?:on purpose|deliberately|intentionally)${E}(?!${MEAL_OR_BEDTIME})`,
`${B}(?:on purpose|deliberately|intentionally|purposely)(?:${NOT_STOPPING}){0,2} ${HARMING}(?!${MEAL_OR_BEDTIME})${E}`,
// "end everything", "make it look like an accident", "stop my heart"; Pidgin "comot for this world" (leave this world), "life no get meaning".
'(?<![a-z0-9])(?:end everything|look like an accident|comot for (?:this|dis) world|life no get meaning)(?![a-z0-9])',
'(?<![a-z0-9])(?:stop|stops) (?:my|her|his) heart(?![a-z0-9])',
// Review 8: keeping tablets back for a plan: "I'm saving my tablets for when I'm ready".
`${B}(?:saving|saved|keeping|kept|hiding|hid|putting aside|put aside|collecting|stockpiling)(?: up)? (?:my |her |his |all my |all (?:of )?(?:my |the )?|the |some (?:of )?(?:my )?)?${MEDICINES}`
+ ` (?:for when (?:i|im|i am|shes|she is|hes|he is) (?:ready|done)|for (?:the|that) day|(?:until|till) (?:i|ive|i have) (?:got )?enough)${E}`,
].join('|'));
/**
* M-a, R11-M2, R12-M1: "going to die" said by the speaker, or "I will", "I'll" or "I shall die", clause by clause: not afraid of it
* ("I'm scared I'm going to die" is feeling like dying), not someone's words or what the speaker knows ("the doctor says", "I know"),
* nor "of", "from", "if", "without", "laughing", "young", "one day", "eventually", "happy" or "in peace" after it ("I'm going to
* die without my inhaler"). "I'm going to die tonight" stays; "Will I die?" is the backstop.
*/
const SPEAKER_DIE = new RegExp(`${B}(?<!(?:scared|afraid|frightened|terrified|worried|fear|fears|feared|think|thinks|thought|feel|feels|felt|feeling|like|sure`
+ `|says|said|told|tells|know|knows|knew|accept|accepted|realise|realize|realised|realized|aware)(?: [a-z]+){0,3} )`
+ `(?:(?:i am|im|i) (?:going to|gonna)|i will|ill|i shall) die${E}`
+ `(?! (?:of|from|if|without|unless|laughing|lol|when|young|one day|someday|some day|eventually|happy|a happy|old|sooner or later|at some point|in peace|peacefully)${E})`);
/** R12-M1: a prognosis (cancer, hospice, "the doctor said", weeks left): the speaker's "I will die soon" there is not intent... */
const PROGNOSIS = new RegExp(`${B}(?:cancer|hospice|palliative|end of life|terminal|terminally ill|days left|weeks left|months left|prognosis`
+ `|(?:the )?(?:doctor|doctors|nurse|consultant|team) (?:said|says|told me|thinks))${E}`);
/** R12-M1: ...unless the clause says it is ("tonight", "anyway", "I don't care", "on purpose"). */
const DIE_INTENT = new RegExp(`${B}(?:tonight|today|now|anyway|by tomorrow|before (?:the )?morning|(?:and )?(?:i )?(?:do not|dont) care|nobody cares|no one cares|i swear|on purpose)${E}`);
/**
* H-1.3, M-b, M-A: a wish not to wake, clause by clause ("so I don't wake up", "I hope I'll never wake up", "I wish I hadn't woken
* up", "I hope she never wakes up", "I don't want to wake up tomorrow"). It counts only when the clause ends there, or goes on
* with nothing but again, ever, at all, anymore, tomorrow, in the morning, tonight, for good, forever (WAKE_SOLO, to the end of
* the clause), or with one of these connectors (M-A): "and" with see, face, live, go on, have to face or do this again, they
* find me, it's over, die or end it; "because" with a despair phrase within six words; "when" they or my family find or come;
* "after" this, that, tonight or taking; "if" I take, swallow or drink. "but" never counts. "and" or "then" after someone else ("she
* is breathing slowly and won't wake up") says how they are. So never how or when someone wakes:
* "so I don't wake up with a hypo", "and need the toilet", "and cry", "because of the noise", "when the baby cries", "after
* midnight", "tomorrow feeling sick", "again for a feed". "Will she not wake up?" is hard to wake (the faint sign), not
* self-harm.
*/
const WAKE_SOLO = '(?:again|ever|at all|anymore|any more|tomorrow(?: morning| night| evening| afternoon)?|in the morning|this morning|today|tonight|(?:the )?(?:next|following) (?:morning|day|night)|this time|next time|from this|from it|for good|forever|for ever|ever again|till i die|o|abeg|pls|please|lol|tbh)';
const DESPAIR = '(?:cant (?:take|cope|go on|do this|bear)|had enough|done with|no point|hate my life|want to die|tired of|nobody|no one|burden|hopeless|worthless|give up|over it|too much)';
const WAKE_CONNECTOR = '(?:and (?:see|face|live|go on|carry on|exist|be here|be alive|have to (?:face|see|live|go on|carry on|do (?:this|it|all this)(?: again| anymore)?|deal with (?:this|it|life))'
+ '|they (?:find|found)|someone (?:finds|find)|its? (?:is |will be |would be )?(?:over|all over|the end|done)|thats (?:it|the end|all)|die|end it|never)'
+ `|(?:because|cos|cause)(?: [a-z]+){0,6} ${DESPAIR}|when (?:they|someone|people|my family|the ambulance|you) (?:find|found|come|get)`
+ '|after (?:this|that|tonight|today|(?:i take|taking|swallowing) (?:them all|all|everything|the lot|enough|an overdose|the whole))'
+ '|if (?:i|she|he) (?:take|took|swallow|swallowed|drink|drank|inject|injected))';
const WAKE_GOES_ON = `(?:(?: ${WAKE_SOLO})*$|(?: ${WAKE_SOLO})* ${WAKE_CONNECTOR}${E})`;
/** Someone else, earlier in the clause: "she is breathing slowly and won't wake up" says how she is, not a wish. */
const THEM = '(?<![a-z0-9])(?:she|he|shes|hes|they|theyre|baby|mum|mom|mother|dad|father|mama|papa|husband|wife|son|daughter|child|patient|grandma|grandpa|granny)';
/** R9-M3: ...unless the clause has the speaker's own wish ("I wish ..."), which "and won't wake up" then completes. */
const FIRST_PERSON_WISH = new RegExp(`${B}(?:i|im|i am|id|ive|i just|i really)(?: [a-z]+){0,2} (?:want|wanna|wish|hope|pray|would like|d like)${E}`);
const WAKE_AFTER_AND = new RegExp(`${B}(?:and|then)(?: (?:i|ill|id|im))? (?:dont|do not|wont|will not|never|not) (?:wake|waking)(?: up)?(?=${WAKE_GOES_ON})`);
const WAKE = new RegExp([
`${B}(?:so|hope|hopes|hoping|hoped|wish|wishes|wishing|wished|want to|wants to|wanna|to|pray|prays|praying|prayed|make|(?<!${THEM}(?: [a-z]+){0,6} )(?:and|then))(?: that)?`
+ '(?: (?:i|ill|id|im|she|shell|shed|he|hell|hed|we|they|theyll|you|youll))? (?:dont|do not|doesnt|does not|didnt|did not|hadnt|had not|wont|will not|wouldnt|would not|not|never|will never|would never|no)'
+ `(?: ever)? (?:wake|wakes|woke|woken|waking)(?: up)?(?=${WAKE_GOES_ON})`,
`${B}(?:dont|do not|doesnt|does not|never)(?: ever)? want to (?:wake|wake up)(?=${WAKE_GOES_ON})`,
// Review 8: "hopefully I won't wake up" (said of oneself: "hopefully she won't wake up" is a parent's hope), "better off not waking up".
`${B}hopefully (?:i|ill|i will|id|i would) (?:wont|will not|dont|do not|never|not|wouldnt|would not)(?: ever)? (?:wake|waking)(?: up)?(?=${WAKE_GOES_ON})`,
`${B}better off (?:not|never) (?:wake|waking)(?: up)?(?=${WAKE_GOES_ON})`,
].join('|'));
/**
* H-1.2: "kill me" with a modal that opens the clause ("Could my tablets kill
* me?", "Can this kill me?"), tested clause by clause; not "she would literally
* kill me", where the modal doesn't open it.
*/
const SELF_HARM_CLAUSE = new RegExp(`^(?:so |and |but |then |please |pls |abeg )?(?:could|would|will|can|might|may|does|do) (?!(?:i|you|she|he|we|they) )(?:[a-z0-9]+ ){1,4}kill me${E}`);
/** The clauses of a text, split on punctuation before normalizing, so a clause's start can be found (H-1.2). */
const clausesOf = (text: string) => text.split(/[.,;:!?\n]+/).map((clause) => normalizeText(clause)).filter(Boolean);
/** H-A: the sentences of a text: commas don't end one ("The pills are going to kill me tonight, I've taken them all"). */
const sentencesOf = (text: string) => text.split(/[.!?;\n]+/).map((sentence) => normalizeText(sentence)).filter(Boolean);
/** R9-M2: "is", "was" and the like end the words for a person ("my phone is dying" is never a person: every word is checked). */
const COPULA = `(?:is|was|are|were|am|be|been|being|has|had|keeps|kept|looks|looked|seems|seemed)${E}`;
/** Not a person: "my phone is dying", "the battery dey die" (LOW), R10-L1: a pet ("my dog is dying"). */
const NOT_A_PERSON = `(?:phone|phones|battery|batteries|laptop|computer|ipad|tablet|mobile|torch|car|plant|plants|tree|trees|flowers?|garden|hair|business`
+ `|dog|dogs|cat|cats|puppy|kitten|pet|pets|horse|bird|rabbit|hamster|goat|chicken|parrot|fish)${E}`;
/** R9-M2, R10-M1: a child, by any name: "my little one", "our youngest", "my grandson". */
const CHILD_NOUN = '(?:baby|babies|child|children|kid|kids|son|daughter|boy|girl|toddler|newborn|pikin|little one|little ones|youngest|eldest|grandson|granddaughter|grandchild|grandkid)';
/** Someone who could be dying: the speaker, anyone named ("my baby", "her dad", R9-M2: "my little boy", "our 3 year old"), the baby. */
const ANYONE = `(?:i|im|she|shes|he|hes|they|theyre|we|(?:my|her|his|their|our)(?: (?!${NOT_A_PERSON})(?!${COPULA})[a-z0-9]+){1,3}|the baby|baby)`;
/**
* M-1, H-1.4, M-c: feeling like they are dying, or someone dying now: the sign "Feeling like they are dying", never labelled
* self-harm. "I feel like I'm dying", "I think I'm dying", "I think my baby is dying", "I'm frightened she's dying", "she looks
* like she's dying", "I'm scared I'm going to die", "I'm dying", Pidgin "I dey die", "my pikin dey die", "Mama dey die", and
* (M-B, R9-M2, R10-M1) a child dying ("my baby is dying", "my son is dying", "my little girl is dying", "my 2 year old is dying", "our
* youngest is dying"). Only dying now ("is dying", "about to die", "going to die" after
* fear words), never a death in the future ("I'm afraid I'll die if I stop my tablets", "my dad will die if he keeps drinking").
* Not "dying of thirst", "dying to", "dying my hair", "I'm dying here", "I'm dying lol", "my phone is dying", or an adult dying
* (M-B: end-of-life talk, or the backstop).
*/
const DYING = new RegExp([
`${B}(?:feel|feels|felt|feeling|think|thinks|thought|look|looks|looked|looking|seem|seems|seemed|sound|sounds|sounded) like ${ANYONE}(?: is| am| are|m|s|re)? (?:dying|going to die|gonna die|about to die)${E}`,
`${B}(?:think|thinks|thought|feel|feels|felt|fear|fears|feared|scared|afraid|worried|frightened|terrified)(?: that)? ${ANYONE}(?: is| am| are|m|s|re)? (?:dying|about to die|going to die|gonna die)${E}`,
`${B}(?:i am|im) dying${E}(?! (?:of|for|to|my|her|his|their|the|a|an|inside|laughing|from|here|lol|haha|lmao|rn)${E})`,
`${B}(?:i|she|he|e|mama|papa|baby|pikin|(?:my|her|his|di|the) (?!${NOT_A_PERSON})[a-z]+) dey die${E}`,
`${B}(?:(?:my|our|her|his|the)(?: [a-z]+){0,2} ${CHILD_NOUN}|(?:my|our|her|his|the) [0-9]+ (?:year|month|week|day)s? old)`
+ `(?: is|s| are)? (?:dying(?! (?:of|for|to)${E})|about to die)${E}`,
].join('|'));
/** Taking too much, or a poison: the overdose sign. */
const TOO_MUCH = new RegExp([
// Poisons, not food poisoning: Sniper and Gammalin (insecticides), Otapiapia (a rat poison). L5: not bleach on its own ("I clean
// the toilet with bleach"); drinking or swallowing it is in the table (rules.ts).
// LOW: not "poison ivy", "poison oak".
'(?<![a-z0-9])(?:(?<!food )poison(?! (?:ivy|oak|sumac)(?![a-z0-9]))|(?<!food )poisons|(?<!food )poisoning|insecticide|sniper|gam+alin|otapiapia)(?![a-z0-9])',
// "all my tablets", "if I take all of them tonight"; not with when or how they are taken ("Can I take all my tablets in
// the morning?"), nor missed or run out of ("I forgot to take all my tablets"), nor what the tablets do ("all my tablets kill my
// appetite", LOW), nor (R9 ruling 3d) a sick-day question ("Should I take all my tablets when I'm sick?", "with a cold"), nor
// (R10-M4) how a regimen is taken ("Can I take all my tablets together?", "at the same time"); "what happens if I take ..." keeps it.
`(?<![a-z0-9])(?:(?<!${NOT_TAKING}(?: to (?:take|give|bring|order|collect))?(?: [a-z]+)? )all (?:of )?(?:my|me) (?:[a-z]+ )?(?:tablets?|pills?|drugs?|medicines?|meds|capsules?)`
+ `(?!(?: [a-z]+){0,2} (?:together|at the same time)${E})(?! ${TABLETS_DO}${E})(?!${SICK_DAY})`
+ `|(?:if|what if|what happens if|what would happen if) i (?:take|took|swallow|swallowed|drink|drank)(?: [a-z]+){0,2} all)(?![a-z0-9])(?!${SAME_CLAUSE}{0,2} ${TIMING}(?![a-z0-9]))`,
'(?<![a-z0-9])(?:take|swallow|drink)(?: [a-z]+){0,2} all (?:the |dis |di |this |these |my |her |his )?(?:tablets?|pills?|drugs?|medicines?|meds)(?: [a-z]+)? finish(?![a-z0-9])',
// "Is it bad to take a box of panadol?"; L5: not taking one with you ("Can I take a box of paracetamol on the plane?").
`(?<![a-z0-9])(?:take|took|taken|swallow|swallowed|drink|drank)(?: [a-z]+){0,1} (?:a|one|a full|one full) (?:box|boxes|packet|packets|pack|packs|bottle|bottles|strip|strips|card|cards) of(?![a-z0-9])(?!(?: [a-z]+){0,3} ${TRAVEL})`,
// M-d: plans ("I'm going to take them all tonight", "I've been stockpiling my tablets") and "How much insulin is lethal?".
`${B}(?:going to|gonna|will|ill|wan|go|plan to|planning to|about to)(?: just)? (?:take|swallow|drink|finish|have) (?:them|it|these|those|the lot|everything|all of them)(?: all)? (?:tonight|now|today|at once|in one go|together|at the same time)${E}`,
// R9-H3: ...after "can", "could", "so I can" or "then" ("I keep them all so I can take them all tonight"); not "together" or "at the
// same time", which ask how to take a regimen.
`${B}(?:can|could|so i can|so i could|then)(?: just)? (?:take|swallow|drink|finish) (?:them|these|those|the lot|everything|all of them)(?: all)? (?:tonight|now|at once|in one go)${E}`,
// R9 ruling 3c: a wish or plan to take, inject or drink all or the whole of a medicine, insulin and pens included; never with
// when or how it is taken ("I want to take all my tablets in the morning").
`${B}(?:want to|wanna|going to|gonna|will|ill|plan to|planning to|about to|wan)(?: just)? (?:take|swallow|inject|drink|use) (?:all|the whole|everything|the lot)(?: of)?(?: (?:my|her|his|the|these|those))? (?:[a-z]+ )?`
+ `(?:tablets?|pills?|insulin|pens?|medicines?|meds|drugs?|injections?)${E}(?!${SAME_CLAUSE}{0,2} ${TIMING}(?![a-z0-9]))`,
`${B}(?:stockpil(?:e|es|ed|ing)|hoard(?:s|ed|ing)?|saving up|saved up|been saving)(?: up)? (?:my |her |his |all my |all )?(?:tablets?|pills?|medicines?|meds|drugs?|sleeping (?:tablets?|pills?)|painkillers?)${E}`,
// Review 8: "I have been collecting my sleeping pills" (never "from the pharmacy", "every month").
`${B}(?:been (?:collecting|gathering|stashing)|stash(?:ed|ing)?)(?: up)? (?:my |her |his |all my |all (?:of )?(?:my |the )?|the |some (?:of )?(?:my )?)?`
+ `(?:sleeping (?:tablets?|pills?)|painkillers?|morphine|diazepam|antidepressants?|insulin)${E}(?! (?:from|at|in|on|for|every|each|with|by|via|when|as|myself|herself|himself)${E})`,
`${B}how (?:much|many)(?: [a-z0-9]+){0,6} (?:is|are|would be|will be|be|counts as) (?:lethal|fatal|deadly|an overdose)${E}`,
// H-1: "Can you die from taking too much paracetamol?": an amount.
`${B}(?:can|could|will|would|do|does) (?:you|i|someone|people|a person) die (?:from|of|if)(?: [a-z]+){0,2} (?:taking |swallowing )?(?:too many|too much|all|the whole|an overdose|${NUM10})${E}`,
// M-a: an amount that could kill someone else ("Would 20 tablets kill her?"); without one ("Could the morphine kill him?") it is no sign.
// LOW: not "all my tablets kill my appetite".
`${B}(?:${NUM10}|enough|all (?:of )?(?:my|her|his|the|these|those|them|it)|the whole|too many|too much(?: of)?(?: my| her| his| the)? ${MED})(?: [a-z]+){0,6} kill (?:him|her|them|(?:my|her|his) (?!${KILLED_THING})[a-z]+|the baby|a child|a person|someone)${E}`,
// "OD", not "OD" for once a day ("5 mg OD") or "odd".
'(?<![a-z0-9])(?:(?:to|i|she|he|they|we|you|might|will|would|could|can|did|gonna|wanna|wan) od|od(?:s|ed|ing)? (?:on|with))(?![a-z0-9])',
// "finish the whole bottle tonight"; not a course of treatment.
'(?<![a-z0-9])finish(?:ed|ing)? (?:the |my |her |his |a |this |dis )?whole(?! (?:course|treatment|prescription|cycle|month|week))(?![a-z0-9])',
'(?<![a-z0-9])everything in (?:my|her|his|the|our|their) (?:medicine|medicines|medication|pill|drug|first aid) (?:box|boxes|cabinet|cupboard|bag|drawer|kit)(?![a-z0-9])',
// "a lot of tablets" or Pidgin "plenty drugs", taken or about to be ("I wan take plenty drugs"); not "I take a lot of tablets",
// nor a lifetime of them ("has taken lots of medicines over the years").
`(?<![a-z0-9])(?:took|taken|swallowed|ate|eaten|drank|drunk|don take|don swallow|don chop|(?:to|wan|go|will|gonna|wanna|if i|what if i|can i|should i|fit|make i) (?:take|swallow|drink|chop))(?: [a-z]+){0,2} (?:a lot of|lots of|loads of|so many|plenty|plenty of)(?: [a-z]+)? (?:tablets?|pills?|drugs?|medicines?|meds|capsules?)(?![a-z0-9])(?!(?: [a-z]+){0,4} (?:for years|over the years|in (?:her|his|my|their) life|all (?:her|his|my|their) life|every day|each day|a day|daily)(?![a-z0-9]))`,
].join('|'));
/**
* H-A: an amount of medicine taken or about to be, for a word about dying or killing in the same sentence: "from all the pills I
* took", "if he takes all his pills", "I took all my insulin", "if I take enough of it", "30 tablets she swallowed".
*/
const AMOUNT_TAKEN = new RegExp(`${B}(?:(?:take|takes|took|taken|taking|swallow|swallows|swallowed|swallowing|drink|drinks|drank|ate|eaten|inject|injects|injected|injecting|overdose on|od on|from)`
+ `(?: [a-z]+){0,2} (?:${AMOUNT}(?: [a-z0-9]+){0,4} ${MEDICINES}|them all|all of them|all of those|all of these|all of it|the lot|everything|enough(?: of (?:it|them|those|these))?)`
+ `|${AMOUNT}(?: [a-z0-9]+){0,4} ${MEDICINES} (?:i|she|he|they|you|we) (?:took|have taken|had taken|swallowed|drank|injected))${E}`);
/**
* H-A: a word about dying or killing now: not a death that happened ("died"), "dying of", "for" or "to", "die young", "dead
* tired", "the death of me", "bored to death", "killing time", "kill my appetite", "kill the pain", "die at home".
*/
const DEATH_NOW = new RegExp(`${B}(?:die|dies|dying(?! (?:of|for|to)${E})|dead(?! (?:tired|skin|arm|leg|legs|serious|sure|right|numb|heavy|end)${E})|death(?! of me)(?<!to death)`
+ `|kill|kills|killing(?! (?:time|it)${E})|finish me)${E}(?! young${E})`
+ `(?! (?:my|your|her|his|the|their|our) ${KILLED_THING})(?! (?:at|in) (?:home|hospital|hospice|peace)${E})`);
/** H-A: a medicine that will kill me ("These pills will kill me"): never silent, the backstop at least. */
const MEDICINE_KILLS = new RegExp(`${B}${MEDICINES}(?: [a-z]+){0,3} (?:will|would|could|can|might|are going to|is going to|gonna|going to|are gonna) kill (?:me|him|her|them)${E}`);
/** H-A, R9-M3, R10-M2: ...and with intent, up to three words on ("and I don't care", "I do not care", "tonight", "I hope so", "so be it"), the self-harm sign. */
const MEDICINE_KILLS_ME_NOW = new RegExp(`${B}${MEDICINES}(?: [a-z]+){0,3} (?:will|would|could|can|might|are going to|is going to|gonna|going to|are gonna) kill me(?: [a-z]+){0,3}`
+ ` (?:and i dont care|i dont care|and i do not care|i do not care|do not care|dont care|tonight|today|now|i hope|i hope so|good|im ready|soon|so be it|i want them to)${E}`);
/**
* M-B (call 1): someone else's wish to die, told by their family ("My son wants to die", "Mum keeps saying she wants to die"):
* their own thoughts, so the self-harm sign. R9-M1, R9-H4: a child's always; an adult's with an explicit end-of-life word
* (hospice, palliative, terminal, days left), the backstop, never nothing. Never where they want to die ("at home").
*/
/** R11-H1: never a clinician, the one who wishes: "the doctor wants her to die comfortably" is not her wish. */
const CLINICIAN = `(?:doctor|doctors|dr|nurse|nurses|gp|consultant|team|staff|pharmacist|hospital|hospice|surgeon|specialist)${E}`;
/** R11-H1: one to three words after "my", "our", "the" that can name someone ("my partner", "our neighbour", "my mother in law"). */
const OTHER_WORD = `(?: (?!${NOT_A_PERSON})(?!${COPULA})(?!${CLINICIAN})(?!(?:${NEG}|no|longer|ever|also|still|really|just|always|only|says|said|keeps|keep|kept|told|tells`
+ `|wants|wanted|want|wan|wanna|wish|wishes|wished|hopes|prays|asks|asked|begs|begged|talks|talked|would|d|and|to|that|who|which|whom|dey|don)${E})[a-z0-9]+)`;
const OTHER_WORDS = `${OTHER_WORD}{1,3}`;
/** R12-M3: a title and a name ("Mr Okafor", "Aunty Bisi", "Alhaji Musa"), the name checked like the words above. */
const TITLED = `(?:mr|mrs|ms|miss|mister|aunty|auntie|uncle|mama|papa|baba|iya|oga|madam|pastor|chief|alhaji|alhaja)${OTHER_WORD}{1,2}`;
/** R11-H1: a relation named on its own ("Grandad", "Nan", "Oga"). */
const RELATION = '(?:grandad|granddad|granny|gran|nan|nana|nanna|mummy|mommy|daddy|hubby|pikin|oga|madam)';
/** R11-H1, R11-L2, R13: "die" that is a dye ("die her hair", "her wrapper", "the fabric") or a figure of speech ("die laughing", "of boredom"). */
const NOT_DYE = `(?! (?:(?:my|her|his|their|the|your) (?:[a-z]+ )?(?:hair|clothes|shirt|dress|beard|eyebrows|roots|wrapper|wrappers|cloth|fabric|material|wig|weave|braids|jeans|nails)`
+ `|laughing|of laughter|of embarrassment|of boredom)${E})`;
/** R11-H1, R11-L2, R12-M3: someone else, by any name or a title and a name: never "nobody", "everyone" or "who", never a thing, a pet or a clinician. */
const OTHER_SUBJECT = `(?:(?!(?:everyone|everybody|nobody|no one|who|anyone|anybody)${E})${SOMEONE_ELSE}|${RELATION}|${TITLED}|(?:my|our|her|his|their|the)${OTHER_WORDS})`;
/** R11-H1: ...without the -s ("my son want to die", Pidgin "wan die"), for a name, never a pronoun. */
const OTHER_WISH_PLAIN = new RegExp(`${B}(?:${RELATION}|mama|papa|(?:my|our|her|his|their|the)${OTHER_WORDS})(?: (?:still|just|really|only|dey|don))? (?:want|wan|wanna|wish)(?: to)? (?:die|be dead)${E}`
+ `(?! ${PLACE})${NOT_DYE}`);
/**
* R11-H1, R11-L3, R12-M3: how a reported wish is said: wants, wishes, hopes, longs, yearns or prays to die (or "has" one of these);
* keeps asking or begging to die, or for someone to let or help her die; hopes she dies; wishes she were dead; keeps talking about
* dying; asks, keeps praying or prays for death (R13: only at the end of the clause or before "now", "soon", "to come", "and
* she...", never "for death certificates"); wants God to take her; wants to go to sleep and not wake up. "...and" may come first
* ("is in pain and wants to die"). Asking when someone will die is a question about dying, not a wish: the backstop (R13).
*/
const OTHER_WISH = new RegExp(`${B}${OTHER_SUBJECT}(?:(?: [a-z]+){1,5} and)?(?: (?:keeps|keep|kept) (?:saying|telling (?:me|us)|talking about how)`
+ `| (?:says|said|told (?:me|us|the [a-z]+)|tells (?:me|us)|has said)(?: that)?(?: (?:she|he|they))?)?`
+ `(?: (?:really|still|just|always|only|has|had|have))? (?:(?:wants|wanted|wishes|wished|would like|d like|would love|hopes|prays|is praying|longs|longed|is longing`
+ `|yearns|yearned|is waiting|(?:keeps|kept|is|was|has been) (?:asking|begging)`
+ `|asks|asked|begs|begged) (?:to )?(?:die|be dead)`
+ `|(?:asks|asked|begs|begged|(?:keeps|kept|is|was|has been) (?:asking|begging)) (?:me|us|god|the doctors?|the nurses?|them|everyone) to let (?:her|him|them) die`
+ `|(?:wishes|wished) (?:she|he|they) (?:was|were) dead`
+ `|(?:talks|talked|(?:keeps|kept|is|was|has been) talking) about (?:dying|wanting to die|death|ending (?:it|her life|his life|their life))`
+ `|(?:wants|wanted|prays for|is praying for) god to take (?:her|him|them)`
+ `|(?:hopes|hoped|wishes|wished|prays|prayed)(?: that)? (?:she|he|they) (?:will |would |could |can |might )?(?:die|dies|died|be dead)`
+ `|(?:prays|prayed|is praying|keeps praying)(?: [a-z]+){1,3} to die`
+ `|(?:wants|wanted|asks|asked|begs|begged|(?:keeps|kept|is) (?:asking|begging))(?: (?:me|us|you|someone|somebody|the doctors?|the nurses?|god))? to help (?:her|him|them)(?: to)? die`
+ `|(?:(?:longs|longed|is longing|yearns|yearned|is yearning|asks|asked|begs|begged|is begging|prays|is praying|wishes|wished`
+ `|(?:keeps|kept|has been) (?:praying|asking|begging|longing|wishing)) for|would welcome|welcomes|craves|craved) death`
+ `(?=$| (?:now|soon|already|every (?:day|night)|daily|o|abeg|please|to come|to take (?:her|him|them))${E}| (?:and|but) (?:is|was|has|had|keeps|says|said|wants|she|he|they|now)${E})`
+ `|(?:wants|wanted|wishes|wished) to (?:go to )?sleep and (?:not|never) wake(?: up)?)${E}(?! ${PLACE})${NOT_DYE}`);
/**
* R9-M1, R11 (the open point), R12-M3: a child, whose reported wish to die is always the self-harm sign: the review-10 names,
* step-children, godchildren and the like, and an age under 18 ("my 15 year old", "16 yo"; never "my 90 year old mum").
*/
const UNDER_18 = '(?:[0-9]|1[0-7]|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen)';
const CHILD = new RegExp(`${B}(?:son|daughter|child|kid|boy|girl|baby|teen|teenager|teenage|${UNDER_18} ?years? old|[0-9]+ (?:month|week|day)s? old|pikin|little one|little ones`
+ `|youngest|eldest|grandson|granddaughter|grandchild|grandchildren|grandkid|grandkids|toddler|newborn|stepson|stepdaughter|stepchild|step son|step daughter`
+ `|stepkid|stepkids|lad|lads|wee one|wee ones|little man|little lady|godson|goddaughter|godchild|kiddo|kiddos|infant|infants|adolescent|adolescents`
+ `|(?:[0-9]|1[0-7]) ?(?:yo|y o))${E}`);
/**
* R9-M1, R9-H4: the explicit end-of-life words: an adult's reported wish to die with one of these gets the backstop, never nothing;
* weak cues ("the doctor said", soon, in hospital, cancer, dementia) keep the self-harm sign.
*/
const EXPLICIT_END_OF_LIFE = new RegExp(`${B}(?:hospice|palliative|end of life|terminal|terminally ill|days left|weeks left|last days|comfort care|syringe driver|dnr)${E}`);
/**
* M-B: end-of-life talk, for an adult dying: hospice, palliative, terminal, cancer, dementia, days or weeks left, "the doctor said",
* soon, at home, in peace, "can she stop" or "which tablets can".
*/
const END_OF_LIFE = new RegExp(`${B}(?:hospice|palliative|end of life|terminal|terminally|cancer|dementia|days left|weeks left|last days|old age|(?:next|few|coming|last)(?: few)? (?:days|weeks|months)`
+ '|accepted|stopped (?:eating|drinking)|(?:can|should|could) (?:she|he|we|they) (?:stop|keep)|which (?:tablets|medicines|meds|pills) can|comfort care|syringe driver|dnr'
+ `|the (?:doctor|doctors|nurse|nurses|team|consultant) (?:said|says|told)|soon|slowly|at home|in (?:her|his|their) sleep|in peace|peacefully|in hospital)${E}`);
/** M-B (call 2): an adult dying ("My mum is dying", "Dad is dying"): no sign with end-of-life talk, otherwise the backstop. */
const ADULT_DYING = new RegExp(`${B}(?:she|he|they|mum|mom|mother|mama|dad|father|papa|husband|wife|patient|grandma|grandpa|grandmother|grandfather|granny|aunt|aunty|auntie|uncle)`
+ `(?:s| is| was| are| were| knows (?:she|he|they)(?:s| is| are)?)? (?:dying|going to die|gonna die|ready to die)${E}`);
/** H-1.7: a word about dying, death, killing or suicide, for the backstop. */
const DEATH_WORD = new RegExp(`${B}(?:die|dies|died|dying|dead|death|kill|kills|killed|killing|suicide|suicidal|sucide|suiside)${E}`);
/**
* H-1.7: never a sign, and not the backstop either: figures of speech ("my back is killing me", "kills my appetite", "could kill
* for", "dying of thirst", "dying my hair", "my phone is dying", "I'm dying here", LOW: "bored to death", "the death of me", "over
* my dead body", "killing time", "my battery died", Pidgin "my papa don die"), end-of-life talk ("die at home", "hospice"), fear
* of death or of a missed dose ("I don't want to die young", "Will I die if I miss a dose?", "I'll die if I stop"), a death that
* already happened ("my dad died of a stroke"), "dead tired", and talk about the risk of death. An adult dying is end-of-life
* talk only with an end-of-life cue (M-B, ADULT_DYING).
*/
const NEVER_A_SIGN = new RegExp([
`${B}(?:is|are|was|were|be|been|keeps?|kept) killing (?:me|my|her|him|us)${E}`,
`${B}kill(?:s|ed|ing)? (?:my|your|her|his|the|their|our) (?:appetite|stomach|kidneys?|liver|ankles?|back|knees?|feet|legs?|head|mood|sleep|libido|sex drive|energy|taste|buzz|vibe|joints?|skin|teeth|gut)${E}`,
`${B}(?:could|would) (?:literally |honestly |just )?kill for${E}`,
// "Will this paracetamol kill the pain?", "kill my good bacteria".
`${B}kill(?:s|ed|ing)? (?:the |her |his |my |your |this |that |all the |all )?(?:[a-z]+ )?(?:pain|pains|ache|aches|headache|germs?|bacteria|bugs?|infection|infections|virus|viruses|worms?|fever|cough|lice|fungus|parasites?|cells?)${E}`,
`${B}dying (?:of|for|to|from)${E}(?! (?:an )?overdose${E})`,
`${B}dying (?:my|her|his|their|the) hair${E}`,
`${B}(?:(?:my|her|his|the|their|our) )?${NOT_A_PERSON}(?: (?:is|are|was|keeps|keep))? dying${E}`,
`${B}(?:i am|im) dying (?:here|lol|haha|lmao|rn)${E}`,
`${B}die (?:at|in) (?:home|hospital|hospice|peace)${E}`,
`${B}(?:will|ll|would|d|might|could|going to|gonna|im going to|i am going to) die (?:if|without|unless|from|of|when|young)${E}`,
`${B}(?:not|never|dont|do not|doesnt|does not|didnt|did not) (?:going to |gonna |want to |wanna |wanting to )?die${E}`,
`${B}die if (?:i|she|he|they|we|you) (?:miss|missed|forget|forgot|skip|skipped|stop|stopped|run out)${E}`,
`${B}(?:died|passed away) (?:of|from|in|at|when|last|years|recently|aged|after|before)${E}|${B}(?:has|have|had) died${E}|${B}who died${E}`,
`${B}dead (?:tired|skin|arm|leg|legs|battery|serious|easy|good|bad|cold|heavy|sure|right|numb|weight|end)${E}|${B}(?:feels?|felt|went|goes|gone) dead${E}`,
`${B}(?:death (?:certificate|rate|rates)|risk of death|cause of death|sudden death)${E}`,
`${B}(?:(?:sick|bored|scared|worried|frightened|tired)(?: (?:me|her|him|us|them))? to death|killing two birds|(?:the )?death of me|over my dead body|(?:nearly |almost )?died laughing|feel(?:s|ing)? like death`
+ `|kill(?:ing)? time|killing it|(?:id|i would|we would|i could) kill for|kill two birds|(?:phone|battery|batteries|plants?|car|laptop|torch|tv)(?: has| had| is| was)?(?: about to)? (?:die|died|dead)|don die)${E}`,
].join('|'));
/**
* R11-H1, R13: end-of-life talk ("in a hospice", "palliative", "terminally ill") silences a word about dying only when the clause has
* no word for wanting, asking, begging, praying, talking, longing, yearning, craving or welcoming: with one, it may be a wish, so the
* backstop at least.
*/
const EOL_TALK = new RegExp(`${B}(?:hospice|end of life|palliative|terminal|terminally ill|dying of (?:cancer|old age))${E}`);
const WISH_WORD = new RegExp(`${B}(?:want|wants|wanted|wanting|wanna|wan|wish|wishes|wished|wishing|hope|hopes|hoped|hoping|pray|prays|prayed|praying|beg|begs|begged|begging`
+ `|ask|asks|asked|asking|rather|talk|talks|talked|talking|given up|let (?:me|her|him|them) die`
+ `|long|longs|longed|longing|yearn|yearns|yearned|yearning|crave|craves|craved|craving|welcome|welcomes|welcomed|welcoming)${E}`);
/**
* R12-H2: "to die" ("longs to die", "is waiting to die", "can't wait to die") or "let her die", "help him die": a wish however it is
* worded, so end-of-life talk never silences it. Not "ready to die", which stays end-of-life talk (M-B).
*/
const TO_DIE = new RegExp(`${B}(?:(?<!ready )(?:to|2) (?:die|be dead)|(?:help|helps|helped|helping|let|lets|letting|allow|allows|allowed) (?:me|her|him|them)(?: to)? die)${E}`);
/** H-1.7: "kill" in a statement, not a question ("She would literally kill me", "Too much sugar will kill her"): a figure of speech, unless a medicine is the subject (H-A). */
const KILL_STATEMENT = new RegExp(`^(?!(?:so |and |but |then |please |pls |abeg )?(?:could|would|will|can|might|may|does|do|did|is|are|which|what|how|why|when)${E}).*${B}kill(?:s|ed|ing)? (?:me|him|her|them|us|you)${E}`);
/**
* The words in a text (as written, so its clauses can be found): wanting to die or harm oneself, taking too much, feeling like
* dying, and (H-1.7) unsure: a word about dying, death, killing or suicide that is neither a sign nor never a sign. Unsure gets
* no label, but still the emergency line: a "couldn't be sure" line on the check, the banner in Ask.
*/
/**
* R10-H3: tablets kept, saved or stockpiled, then all taken ("I kept my tablets and then took them all"): too much medicine. R11-M1:
* "take them all" only with tonight, now, at once, in one go or today, and neither tense with a meal, the morning or evening,
* bedtime, every day or "as prescribed" within three words (a regimen: "I keep them by the bed and take them all with breakfast");
* R12-M2: nor before bed, after a meal, at a clock time, once or twice a day, daily, as usual or with water ("this morning" stays,
* as it could be either).
*/
const KEPT_THEN_TOOK = new RegExp(`${B}(?:kept|keep|keeping|saved|saving|stored|hid|hidden|collected|collecting|stockpiled|stockpiling|hoarded|hoarding|stashed|stashing)`
+ `(?: [a-z]+){0,6} (?:then |and |so )?(?:i )?`
+ `(?:(?:took|swallowed|have taken|had taken) (?:them all|all of them|it all|the lot|everything)|(?:take|swallow) (?:them all|all of them|it all|the lot|everything) (?:tonight|now|at once|in one go|today))${E}`
+ `(?!(?: [a-z]+){0,3} (?:(?:with|after|before) (?:my |a |the |her |his )?(?:breakfast|lunch|dinner|supper|tea|food|meals?|bed|bedtime)|in the (?:morning|evening|afternoon)`
+ `|at (?:night|bedtime|lunchtime|lunch|breakfast|dinner|teatime|[0-9]{1,2}(?: ?(?:am|pm|oclock))?)|(?:every|each) (?:day|morning|night|evening)|(?:once|twice|three times|[23] times) (?:a|per) day`
+ `|daily|as prescribed|as usual|as normal|as always|(?:like|as) (?:the|my) (?:doctor|pharmacist|nurse) (?:said|told me|says)|on an empty stomach|with (?:water|milk|juice))${E})`);
/** R11-H1: someone else's reported wish to die, however it is said. */
const otherWish = (clause: string) => OTHER_WISH.test(clause) || OTHER_WISH_PLAIN.test(clause);
export function intentIn(text: string | null | undefined): { selfHarm: boolean; tooMuch: boolean; dying: boolean; unsure: boolean } {
const whole = normalizeText(text ?? '');
const clauses = clausesOf(text ?? '');
const endOfLife = END_OF_LIFE.test(whole);
// M-B, R9-M1: someone else's wish to die is the self-harm sign: a child's always, an adult's unless the text has an explicit
// end-of-life word (then the backstop, below). R9-M3: "and won't wake up" completes the speaker's own wish. R12-M1: the speaker's
// "I will die" next to a prognosis is not intent, unless the clause says so.
const selfHarm = SELF_HARM.test(whole) || clauses.some((clause) => SELF_HARM.test(clause) || SELF_HARM_CLAUSE.test(clause) || WAKE.test(clause)
|| MEDICINE_KILLS_ME_NOW.test(clause) || (otherWish(clause) && (CHILD.test(clause) || !EXPLICIT_END_OF_LIFE.test(whole)))
|| (FIRST_PERSON_WISH.test(clause) && WAKE_AFTER_AND.test(clause))
|| (SPEAKER_DIE.test(clause) && !(PROGNOSIS.test(whole) && !DIE_INTENT.test(clause))));
// H-A: an amount of medicine taken and a word about dying or killing now, in one sentence.
const tooMuch = TOO_MUCH.test(whole) || clauses.some((clause) => TOO_MUCH.test(clause)) || KEPT_THEN_TOOK.test(whole)
|| sentencesOf(text ?? '').some((sentence) => AMOUNT_TAKEN.test(sentence) && DEATH_NOW.test(sentence));
// Feeling like dying is its own sign only when it isn't self-harm: one label, never both.
const dying = !selfHarm && DYING.test(whole);
// H-A: a medicine that will kill me is never silent; M-B: an adult dying is no sign only with end-of-life talk; R9-H4: someone
// else's wish to die is never silent, whatever the never-a-sign list says.
// R11-H1, R12-H2: end-of-life talk silences a word about dying only without a word for wanting, asking or talking, or a "to die", in
// the clause.
const unsure = !selfHarm && !tooMuch && !dying && (clauses.some(otherWish)
|| clauses.some((clause) => DEATH_WORD.test(clause) && !NEVER_A_SIGN.test(clause) && !(EOL_TALK.test(clause) && !WISH_WORD.test(clause) && !TO_DIE.test(clause))
&& (!KILL_STATEMENT.test(clause) || MEDICINE_KILLS.test(clause)) && !(endOfLife && ADULT_DYING.test(clause))));
return { selfHarm, tooMuch, dying, unsure };
}
/** A word of intent (self-harm or too much): Ask's red card before anything else. Feeling like dying is a sign (screenSymptoms). */
export function hasIntent(text: string | null | undefined): boolean {
const intent = intentIn(text);
return intent.selfHarm || intent.tooMuch;
}
const NOT_ENGLISH_INTENT_WORDS = new RegExp(`${B}${NOT_ENGLISH_INTENT}${E}`, 'g');
/**
* LOW: a normalized text without the Hausa, Yoruba and Igbo words of intent this list reads ("Mo fe ku"), so a text of only
* those counts as read: the self-harm sign, without "these weren't checked".
*/
export const withoutWordsOfIntentRead = (normalized: string) => normalized.replace(NOT_ENGLISH_INTENT_WORDS, ' ').replace(/ +/g, ' ').trim();