{"id":121,"date":"2019-08-19T14:58:00","date_gmt":"2019-08-19T13:58:00","guid":{"rendered":"https:\/\/informedica.nl\/?p=121"},"modified":"2020-11-15T09:47:16","modified_gmt":"2020-11-15T08:47:16","slug":"event-driven-design-of-a-resuscitation-app","status":"publish","type":"post","link":"https:\/\/informedica.nl\/?p=121","title":{"rendered":"Event Driven Design of a Resuscitation app"},"content":{"rendered":"\n<p>For some time now I have been thinking of writing an app to help with running a resuscitation protocol. The resuscitation protocol as provided by the Dutch Advanced Pediatric Life Support is rather straight forward. Yet to adhere to this protocol in a stressful situation for a patient with a life threatening condition is a challenge to many physicians or health care providers.<\/p>\n\n\n<p><!--more--><\/p>\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"730\" height=\"1024\" src=\"https:\/\/informedica.nl\/wp-content\/uploads\/2019\/08\/Algorithm-for-paediatric-advanced-life-support-Reproduced-with-kind-permission-of-the-730x1024.png\" alt=\"\" class=\"wp-image-122\" srcset=\"https:\/\/informedica.nl\/wp-content\/uploads\/2019\/08\/Algorithm-for-paediatric-advanced-life-support-Reproduced-with-kind-permission-of-the-730x1024.png 730w, https:\/\/informedica.nl\/wp-content\/uploads\/2019\/08\/Algorithm-for-paediatric-advanced-life-support-Reproduced-with-kind-permission-of-the-214x300.png 214w, https:\/\/informedica.nl\/wp-content\/uploads\/2019\/08\/Algorithm-for-paediatric-advanced-life-support-Reproduced-with-kind-permission-of-the-768x1078.png 768w, https:\/\/informedica.nl\/wp-content\/uploads\/2019\/08\/Algorithm-for-paediatric-advanced-life-support-Reproduced-with-kind-permission-of-the.png 850w\" sizes=\"auto, (max-width: 730px) 100vw, 730px\" \/><figcaption>The Resuscitation Protocol for Children<\/figcaption><\/figure>\n\n\n\n<p>The protocol itself is not overly complex, there are some common pitfalls where mistakes can occur. Also, in the event of a blackout (which can happen even to the most experienced practitioner), it would be most helpful if there would be an app to guide you through the various steps in the protocol.<\/p>\n\n\n\n<p>The first thing to notice is that a protocol is very much event driven. Basically there are two kinds of events: 1) Observations, 2) Interventions.  This results in the following domain model.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"fsharp\" class=\"language-fsharp\">type Observation =\r\n    | Unresponsive\r\n    | NoSignsOfLife\r\n    | SignsOfLife\r\n    | Shockable\r\n    | NonShockable\r\n    | ChangeToNonShockable\r\n    | ChangeToShockable\r\n    | ChangeToROSC\r\n    | ROSC\r\n\r\ntype Intervention =\r\n    | BLS\r\n    | CPR\r\n    | ChargeDefib\r\n    | UnChargeDefib\r\n    | Shock\r\n    | Adrenalin\r\n    | Amiodarone<\/code><\/pre>\n\n\n\n<p>The observations drive the subsequent interventions which subsequently will be evaluated by &#8230; observations. So, the whole cycle is like:<\/p>\n\n\n\n<p>Observation -> Intervention (one or more) -> Evaluation (by observation)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"fsharp\" class=\"language-fsharp\">type Evaluation =\r\n    | CheckForSignsOfLife of Observation list\r\n    | CheckRhythm of Observation list\r\n    | Finished<\/code><\/pre>\n\n\n\n<p>There are two major groups of observations: 1) Observations for signs of life and 2) observations what the current rhythm is, the rhythm check in the protocol.  So you can implement the evaluations like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"fsharp\" class=\"language-fsharp\">let checkForSignsOfLife : Evaluation = \r\n\t[ SignsOfLife; NoSignsOfLife ]\r\n\t|> CheckForSignsOfLife\r\n\t\r\nlet checkRhythm : Evaluation = \r\n\t[ ROSC; NonShockable; ChangeToShockable ]\r\n\t|> CheckRhythm<\/code><\/pre>\n\n\n\n<p>If you check for life, the observation can be signs of life, or no signs of life. When you check the rhythm, the result can be either a &#8216;shock-able rhythm&#8217; or a &#8216;non shock-able rhythm&#8217; or a return of spontaneous circulation (ROSC). Pretty straightforward, huh.<\/p>\n\n\n\n<p>The interventions and subsequent evaluation belong together and are triggered by an observation. So, let&#8217;s call this an intervention block. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"fsharp\" class=\"language-fsharp\">type InterventionBlock = \r\n    { \r\n        Interventions : Intervention list \r\n        Evaluation : Evaluation\r\n    } \r<\/code><\/pre>\n\n\n\n<p>Then things get slightly more complicated as an intervention block can be run once, or be repeated. For example, the initial basic life support (BLS) is just performed once, but the shock-able rhythm and the non shock-able rhythm interventions are repeated over and over until ROSC. Therefore, you get:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"fsharp\" class=\"language-fsharp\">type ProtocolItem = \r\n    | Repeatable of InterventionBlock\r\n    | NonRepeatable of InterventionBlock\r\n\r\ntype ProtocolBlock = Observation * ProtocolItem list\r\n\r\ntype Protocol = ProtocolBlock list<\/code><\/pre>\n\n\n\n<p>So, a protocol item can either be a repeatable or a non-repeatable intervention block. Note that one observation can trigger multiple protocol items (that are either repeatable or non repeatable) and that they can be defined as a protocol block. Taken together, a list of protocol blocks form a protocol.<\/p>\n\n\n\n<p>An example of a combination of non-repeatable intervention blocks with repeated intervention blocks is the shock-able protocol block:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"620\" src=\"https:\/\/informedica.nl\/wp-content\/uploads\/2019\/08\/EU_PLS_shock-1024x620.jpg\" alt=\"\" class=\"wp-image-129\" srcset=\"https:\/\/informedica.nl\/wp-content\/uploads\/2019\/08\/EU_PLS_shock-1024x620.jpg 1024w, https:\/\/informedica.nl\/wp-content\/uploads\/2019\/08\/EU_PLS_shock-300x182.jpg 300w, https:\/\/informedica.nl\/wp-content\/uploads\/2019\/08\/EU_PLS_shock-768x465.jpg 768w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption>Non repeatable and repeatable intervention blocks, triggered by the same observation<\/figcaption><\/figure>\n\n\n\n<p>This can be nicely modeled like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"fsharp\" class=\"language-fsharp\">let shockable : ProtocolBlock =\r\n\tShockable,\r\n\t[\r\n\t\t\/\/ First Shock\r\n\t\t{\r\n\t\t\tInterventions = [ Shock; CPR; ChargeDefib ]\r\n\t\t\tEvaluation = \r\n\t\t\t\t[ Shockable; ChangeToNonShockable; ChangeToROSC ]\r\n\t\t\t\t|> CheckRhythm\r\n\t\t} |> NonRepeatable\r\n\t\t\/\/ Second Shock\r\n\t\t{\r\n\t\t\tInterventions = [ Shock; CPR; ChargeDefib ]\r\n\t\t\tEvaluation = \r\n\t\t\t\t[ Shockable; ChangeToNonShockable; ChangeToROSC ]\r\n\t\t\t\t|> CheckRhythm\r\n\t\t} |> NonRepeatable\r\n\t\t\/\/ Third Shock\r\n\t\t{\r\n\t\t\tInterventions = [ Shock; CPR; Adrenalin; Amiodarone; ChargeDefib ]\r\n\t\t\tEvaluation = \r\n\t\t\t\t[ Shockable; ChangeToNonShockable; ChangeToROSC ]\r\n\t\t\t\t|> CheckRhythm\r\n\t\t} |> NonRepeatable\r\n\t\t\/\/ Fourth Shock\r\n\t\t{\r\n\t\t\tInterventions = [ Shock; CPR; ChargeDefib ]\r\n\t\t\tEvaluation = \r\n\t\t\t\t[ Shockable; ChangeToNonShockable; ChangeToROSC ]\r\n\t\t\t\t|> CheckRhythm\r\n\t\t} |> NonRepeatable\r\n\t\t\/\/ Fifth Shock\r\n\t\t{\r\n\t\t\tInterventions = [ Shock; CPR; Adrenalin; Amiodarone; ChargeDefib ]\r\n\t\t\tEvaluation = \r\n\t\t\t\t[ Shockable; ChangeToNonShockable; ChangeToROSC ]\r\n\t\t\t\t|> CheckRhythm\r\n\t\t} |> NonRepeatable\r\n\t\t\/\/ Continue ...\r\n\t\t{\r\n\t\t\tInterventions = [ Shock; CPR; ChargeDefib ]\r\n\t\t\tEvaluation = \r\n\t\t\t\t[ Shockable; ChangeToNonShockable; ChangeToROSC ]\r\n\t\t\t\t|> CheckRhythm\r\n\t\t} |> Repeatable\r\n\t\t{\r\n\t\t\tInterventions = [ Shock; CPR; Adrenalin; ChargeDefib ]\r\n\t\t\tEvaluation = \r\n\t\t\t\t[ Shockable; ChangeToNonShockable; ChangeToROSC ]\r\n\t\t\t\t|> CheckRhythm\r\n\t\t} |> Repeatable\r\n\t]<\/code><\/pre>\n\n\n\n<p>Note that the first 5 protocol items are non repeatable. Meaning that when this protocol block is observed 5 times, these will not be run again. The remaining 2 protocol items will be run over and over again as long as the observation of a shock-able rhythm is made.<\/p>\n\n\n\n<p>The events and commands that result from running the protocol are:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"fsharp\" class=\"language-fsharp\">type Event =\r\n    | Observed of Observation\r\n    | Intervened of Intervention\r\n\r\ntype Command = \r\n    | Observe of Observation\r\n    | Intervene of Intervention<\/code><\/pre>\n\n\n\n<p>So, actually, really simple. The event is that an observation has been observed or that an intervention  has been &#8216;intervened&#8217;. The commands are that an observation has to be made (remember the evaluate in the intervention block) or that an intervention has to be performed.<\/p>\n\n\n\n<p>To run the protocol the following processes have to be implemented:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"fsharp\" class=\"language-fsharp\">type GetCurrentProtocolBlock = \r\n    Protocol -> Event list -> ProtocolBlock Option\r\n\r\ntype RemoveNonRepeatableFromBlock =\r\n    Event list -> ProtocolBlock -> (int * ProtocolItem list)\r\n\r\ntype GetCurrentProtocolItem = (int * ProtocolItem list) -> ProtocolItem Option\r\n\r\ntype GetCommandsFromProtocolItem =\r\n    Event list -> ProtocolItem -> Command list\r\n\r\ntype ProcessCommand = Command -> Event list -> Event list<\/code><\/pre>\n\n\n\n<p>First from what previously has happened (the event list) I can figure out where in the protocol I currently am, the <strong>GetCurrentProtocolBlock<\/strong>. <\/p>\n\n\n\n<p>When I have this block, again using previous events, the non repeatable intervention blocks have to be removed, otherwise we keep repeating. The result is a number which is a count of remaining observations that triggers the protocol items. Remember, after 5 shock-able rhythm observations, there only remains a repeatable sequence of shock, CPR and de-charge defibrillator and shock, CPR, de-charge and give adrenaline. The <strong>RemoveNonRepeatableFromBlock <\/strong>takes care of that.<\/p>\n\n\n\n<p>Next when it is known exactly what protocol item list has to be processed, the current protocol item is identified using the remaining number of observations. This is handled by the <strong>GetCurrentProtocolItem<\/strong>.<\/p>\n\n\n\n<p>Finally, the list of interventions or (when the interventions have all been &#8216;Intervened&#8217;), the list of observations (the evaluation part of the intervention block) are turned into a list of commands that can be chosen from. The <strong>GetCommandsFromProtocolItem <\/strong>function.<\/p>\n\n\n\n<p>This setup enables a protocol definition that drives the correct processing of the protocol. The protocol itself is quite readable for non programmer medical professionals.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"fsharp\" class=\"language-fsharp\">let resuscitation : Protocol =\r\n\t[\r\n\t\tunresponsive            \/\/ Start with an unresponsive patient\r\n\t\tnoSignsOfLife           \/\/ When there are no signs of life\r\n\t\tchangeToShockable       \/\/ Change to the shockable rhythm block \r\n\t\tnonShockable            \/\/ Start with a non shockable rhythm\r\n\t\tshockable               \/\/ Continue in the shockable rhythm block\r\n\t\tchangeToNonShockable    \/\/ Change to a non shockable rhythm\r\n\t\tchangeToROSC            \/\/ Change from shockable to ROSC\r\n\t]\t<\/code><\/pre>\n\n\n\n<p>As a nice proof of concept I can run the resuscitation protocol by randomly selecting commands and read the output.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"markdown\" class=\"language-markdown\">-- Start run 94                        \r\nEvent: Observed Unresponsive            \r\nEvent: Observed NoSignsOfLife           \r\nEvent: Intervened BLS                   \r\nEvent: Observed NonShockable            \r\nEvent: Intervened CPR                   \r\nEvent: Observed NonShockable            \r\nEvent: Intervened CPR                   \r\nEvent: Intervened Adrenalin             \r\nEvent: Observed NonShockable            \r\nEvent: Intervened CPR                   \r\nEvent: Observed ChangeToShockable       \r\nEvent: Intervened CPR                   \r\nEvent: Intervened ChargeDefib           \r\nEvent: Observed Shockable               \r\nEvent: Intervened Shock                 \r\nEvent: Intervened CPR                   \r\nEvent: Intervened ChargeDefib           \r\nEvent: Observed ChangeToNonShockable    \r\nEvent: Intervened UnChargeDefib         \r\nEvent: Intervened CPR                   \r\nEvent: Observed ChangeToShockable       \r\nEvent: Intervened CPR                   \r\nEvent: Intervened ChargeDefib           \r\nEvent: Observed ChangeToROSC            \r\nEvent: Intervened UnChargeDefib         \r\n--- Finished\r\n\r\n                          \r\n--- Start run 95                        \r\nEvent: Observed Unresponsive            \r\nEvent: Observed SignsOfLife             \r\n--- Finished\r\n\r\n                          \r\n--- Start run 96                        \r\nEvent: Observed Unresponsive            \r\nEvent: Observed NoSignsOfLife           \r\nEvent: Intervened BLS                   \r\nEvent: Observed ChangeToShockable       \r\nEvent: Intervened CPR                   \r\nEvent: Intervened ChargeDefib           \r\nEvent: Observed ChangeToNonShockable    \r\nEvent: Intervened UnChargeDefib         \r\nEvent: Intervened CPR                   \r\nEvent: Observed ChangeToShockable       \r\nEvent: Intervened CPR                   \r\nEvent: Intervened ChargeDefib           \r\nEvent: Observed ChangeToNonShockable    \r\nEvent: Intervened UnChargeDefib         \r\nEvent: Intervened CPR                   \r\nEvent: Observed ROSC                    \r\n--- Finished<\/code><\/pre>\n\n\n\n<p>Also, testing is very easy to do. Just feed the test with a list of events and check whether the processing produces the appropriate command list.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"fsharp\" class=\"language-fsharp\">let tests =\r\n\ttestList \"Test resuscitation protocol\" [\r\n\t\r\n\t\ttest \"For an unresponsive patient\" {\r\n\t\t\tes\r\n\t\t\t|> run\r\n\t\t\t|> fun cmds ->\r\n\t\t\t\tcmds\r\n\t\t\t\t|> checkCmdsLength 2\r\n\t\t\t\t\r\n\t\t\t\tcmds\r\n\t\t\t\t|> expectExists ((=) (Observe SignsOfLife))\r\n\t\t\t\t\t\t\t\t\"Should check for signs of life\"\r\n\r\n\t\t\t\tcmds \r\n\t\t\t\t|> expectExists ((=) (Observe NoSignsOfLife))\r\n\t\t\t\t\t\t\t\t\"Should check for signs of life\"\r\n\t\t}\r\n\t\r\n\t\ttest \"When a patient has signs of life\" {\r\n\t\t\t[ Observed SignsOfLife ]\r\n\t\t\t|> List.append es\r\n\t\t\t|> run\r\n\t\t\t|> fun cmds ->\r\n\t\t\t\tcmds\r\n\t\t\t\t|> checkCmdsLength 0\r\n\r\n\t\t}\r\n\r\n\t\ttest \"When a patient has no signs of life\" {\r\n\t\t\t[ Observed NoSignsOfLife ]\r\n\t\t\t|> List.append es\r\n\t\t\t|> run\r\n\t\t\t|> fun cmds ->\r\n\t\t\t\tcmds\r\n\t\t\t\t|> checkCmdsLength 1\r\n\t\t\t\t\r\n\t\t\t\tcmds \r\n\t\t\t\t|> expectExists ((=) (Intervene BLS)) \r\n\t\t\t\t\t\t\t\t\"Should start BLS\"\r\n\r\n\t\t}\r\n\r\n\t\ttest \"When a patient has had basic life support\" {\r\n\t\t\t[ Observed NoSignsOfLife; Intervened BLS ]\r\n\t\t\t|> List.append es\r\n\t\t\t|> run\r\n\t\t\t|> fun cmds -> \r\n\t\t\t\tcmds\r\n\t\t\t\t|> checkCmdsLength 3\r\n\t\t\t\t\/\/ Check command 1\r\n\t\t\t\tcmds\r\n\t\t\t\t|> expectExists ((=) (Observe ChangeToShockable)) \r\n\t\t\t\t\t\t\t\t\t \"Should check for a change to shockable rhythm\"\r\n\t\t\t\t\/\/ Check command 2\r\n\t\t\t\tcmds\r\n\t\t\t\t|> expectExists ((=) (Observe NonShockable)) \r\n\t\t\t\t\t\t\t\t\t \"Should check for a non shockable rhythm\"\r\n\t\t\t\t\/\/ Check command 3\r\n\t\t\t\tcmds\r\n\t\t\t\t|> expectExists ((=) (Observe ROSC)) \r\n\t\t\t\t\t\t\t\t\t \"Should check for a return of spontaneous circulation\"\r\n\t\t}\r\n\r\n\t\ttest \"When a patient has a non shockable rhythm\" {\r\n\t\t\t[ Observed NoSignsOfLife; Intervened BLS; Observed NonShockable ]\r\n\t\t\t|> List.append es\r\n\t\t\t|> run\r\n\t\t\t|> fun cmds -> \r\n\t\t\t\tcmds\r\n\t\t\t\t|> checkCmdsLength 1\r\n\t\t\t\t\/\/ Check command 1\r\n\t\t\t\tcmds\r\n\t\t\t\t|> expectExists ((=) (Intervene CPR)) \r\n\t\t\t\t\t\t\t\t\t \"Should start cardiopulmonary resuscitation\"\r\n\t\t}\r\n\r\n\t\ttest \"When a patient has a shockable rhythm\" {\r\n\t\t\t[ Observed NoSignsOfLife; Intervened BLS; Observed ChangeToShockable ]\r\n\t\t\t|> List.append es\r\n\t\t\t|> run\r\n\t\t\t|> fun cmds -> \r\n\t\t\t\tcmds\r\n\t\t\t\t|> checkCmdsLength 1\r\n\t\t\t\t\/\/ Check command 1\r\n\t\t\t\tcmds\r\n\t\t\t\t|> expectExists ((=) (Intervene CPR)) \r\n\t\t\t\t\t\t\t\t\t \"Should start cardiopulmonary resuscitation\"\r\n\t\t}\r\n\r\n\t\ttest \"When a patient has a shockable rhythm and CPR\" {\r\n\t\t\t[ Observed NoSignsOfLife\r\n\t\t\t  Intervened BLS\r\n\t\t\t  Observed ChangeToShockable\r\n\t\t\t  Intervened CPR ]\r\n\t\t\t|> List.append es\r\n\t\t\t|> run\r\n\t\t\t|> fun cmds -> \r\n\t\t\t\tcmds\r\n\t\t\t\t|> checkCmdsLength 1\r\n\t\t\t\t\/\/ Check command 1\r\n\t\t\t\tcmds\r\n\t\t\t\t|> expectExists ((=) (Intervene ChargeDefib)) \r\n\t\t\t\t\t\t\t\t\t \"Should charge the defibrillator\"\r\n\t\t}\r\n\r\n\t]<\/code><\/pre>\n\n\n\n<p>This is I think a very nice example to showcase the power of event driven design using a algebraic type system like F# has. The code can be found on <a href=\"https:\/\/github.com\/halcwb\/resuscitate\">GitHub<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>For some time now I have been thinking of writing an app to help with running a resuscitation protocol. The resuscitation protocol as provided by the Dutch Advanced Pediatric Life Support is rather straight forward. Yet to adhere to this protocol in a stressful situation for a patient with a life threatening condition is a &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/informedica.nl\/?p=121\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Event Driven Design of a Resuscitation app&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10,9],"tags":[],"class_list":["post-121","post","type-post","status-publish","format-standard","hentry","category-medicine","category-programming"],"_links":{"self":[{"href":"https:\/\/informedica.nl\/index.php?rest_route=\/wp\/v2\/posts\/121","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/informedica.nl\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/informedica.nl\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/informedica.nl\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/informedica.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=121"}],"version-history":[{"count":25,"href":"https:\/\/informedica.nl\/index.php?rest_route=\/wp\/v2\/posts\/121\/revisions"}],"predecessor-version":[{"id":184,"href":"https:\/\/informedica.nl\/index.php?rest_route=\/wp\/v2\/posts\/121\/revisions\/184"}],"wp:attachment":[{"href":"https:\/\/informedica.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=121"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/informedica.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=121"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/informedica.nl\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=121"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}