Help us understand the problem. What is going on with this article?

急性中耳炎の重症度が分かるLINE Botの作成

概要

プログラムの勉強を始めて4か月ほどの開業医です。
病気のおすすめの診断法や、治療法などを記載した診療ガイドランというものがあります。診療ガイドラインに従うことは強制ではないのですが、エビデンスに基づいた治療をするためにはガイドラインは重要です。しかし、忙しい臨床現場ではガイドライン通りに診療を進めることが難しい場合もあります。
今回、小児急性中耳炎の診療ガイドライン(2018年-日本耳科学会)に沿って、急性中耳炎の重症度と推奨治療が簡単に分かるLINE Botを作成しました。
医師が臨床現場で使えることはもちろんですが、一般の方でも医療機関で「鼓膜の赤さ・腫れ・耳垂れ」の程度を医師に聞いていただくと急性中耳炎の重症度が判定できます。

実装

LINE上で質問に答えていくとスコアリングが行われ、急性中耳炎の重症度と推奨治療が分かるLINE Bot。

概念図

node.js expressでLINE bot APIを連携しました。
line nodejs.png

作成方法

1. Botアカウントを作成する

2. Node.jsでBot開発

3. ngrokでトンネリング

上記の1~3を以下の参考記事の通りに行います。
1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017

4. プログラム作成

コードを以下のように書き換えます。
今回は、LINE Developersのクリックリプライを使いました。
LINE Developers

'use strict';

const express = require('express');
const line = require('@line/bot-sdk');
const PORT = process.env.PORT || 3000;

const config = {
    channelSecret: 'channelSecretを入力',
    channelAccessToken: 'channelAccessTokenを入力'
};


const app = express();

app.get('/', (req, res) => res.send('Hello LINE BOT!(GET)')); //ブラウザ確認用(無くても問題ない)
app.post('/webhook', line.middleware(config), (req, res) => {
  console.log(req.body.events);

  //ここのif分はdeveloper consoleの"接続確認"用なので削除して問題ないです。
  if(req.body.events[0].replyToken === '00000000000000000000000000000000' && req.body.events[1].replyToken === 'ffffffffffffffffffffffffffffffff'){
    res.send('Hello LINE BOT!(POST)');
    console.log('疎通確認用');
    return; 
  }

  Promise
      .all(req.body.events.map(handleEvent))
      .then((result) => res.json(result));
});


const client = new line.Client(config);

function handleEvent(event) {
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }

  // LINE botのプログラム 
  let message = event.message.text;
  let question = "";
  let label1, label2, label3 = "";
  let text1, text2, text3 = "";

  let [mes, currentScore] = message.split(":");  

  if (message == "開始") {    
    currentScore = 0;
    question = "2歳未満ですか?";
    label1 = "いいえ";//0
    text1 = "2歳以上 トータルスコア:"+String(currentScore);
    message = text1;
    label2 = "はい";//3
    text2 = "2歳未満 トータルスコア:"+String(currentScore+3);
    message = text2;
    label3 = "選択できません";
    text3= "開始";
    message = text3;
  } else if (mes == "2歳以上 トータルスコア"|| mes==  "2歳未満 トータルスコア") {
    question = "耳は痛いですか?";
    label1 = "いいえ";//0
    text1 = "耳は痛くない トータルスコア:"+String(currentScore);
    message = text1;
    label2 = "痛い、痛かった";//1
    text2 = "耳が痛い、痛かった トータルスコア:" + String(Number(currentScore)+ 1);
    message = text2;
    label3 = "とても痛いのが続いている";//2
    text3= "耳がとても痛いのが続いている トータルスコア:" + String(Number(currentScore)+2);
    message = text3;
  } else if (mes == "耳は痛くない トータルスコア"||mes=="耳が痛い、痛かった トータルスコア" ||mes== "耳がとても痛いのが続いている トータルスコア" ) {
    question = "熱はありますか?";
    label1 = "37.5未満";//0
    text1 = "37.5未満 トータルスコア:" + String(currentScore);
    message = text1;
    label2 = "38.5未満";//1
    text2 = "38.5未満 トータルスコア:" + String(Number(currentScore)+1);
    message = text2;
    label3 = "38.5以上";//2
    text3= "38.5以上 トータルスコア:" + String(Number(currentScore)+2);
    message = text3;
  } else if (mes == "37.5未満 トータルスコア"||mes== "38.5未満 トータルスコア"||mes== "38.5以上 トータルスコア") {
    question = "泣いたり、機嫌が悪いですか?";
    label1 = "いいえ"//0
    text1 = "機嫌は悪くない トータルスコア:" + String(currentScore);
    message = text1;
    label2 = "はい";//1
    text2 = "泣いたり、機嫌が悪い トータルスコア:" + String(Number(currentScore)+1);
    message = text2;
    label3 = "選択できません";
    text3= "開始";
    message = text3;
  } else if (mes == "機嫌は悪くない トータルスコア" ||mes== "泣いたり、機嫌が悪い トータルスコア" ) {
    question = "鼓膜が赤いですか?";
    label1 = "いいえ";//0
    text1 = "鼓膜は赤くない トータルスコア:" + String(currentScore);
    message = text1;
    label2 = "一部だけ赤い";//2
    text2 = "一部だけ赤い トータルスコア:" + String(Number(currentScore)+2);
    message = text2;
    label3 = "全体に赤い";//4
    text3= "全体に赤い トータルスコア:" + String(Number(currentScore)+4);
    message = text3;
  } else if (mes ==  "鼓膜は赤くない トータルスコア" ||mes== "一部だけ赤い トータルスコア" ||mes== "全体に赤い トータルスコア") {
    question = "鼓膜は腫れていますか?";
    label1 = "いいえ";//0
    text1 = "鼓膜は腫れていない トータルスコア:" + String(currentScore);
    message = text1;
    label2 = "一部だけ腫れている";//4
    text2 = "一部だけ腫れている トータルスコア:" + String(Number(currentScore)+4);
    message = text2;
    label3 = "全体に腫れている";//8
    text3= "全体に腫れている トータルスコア:" + String(Number(currentScore)+8);
    message = text3;
  } else if (mes == "鼓膜は腫れていない トータルスコア"||mes=="一部だけ腫れている トータルスコア" ||mes== "全体に腫れている トータルスコア" ) {
    question = "耳垂れは出ていますか?";
    label1 = "いいえ";//0
    text1 = "耳垂れは出ていない トータルスコア:" + String(currentScore);
    message = text1;
    label2 = "少し出ている";//2
    text2 = "少し出ている トータルスコア:" + String(Number(currentScore)+2);
    message = text2;
    label3 = "たくさん出ている";//4
    text3= "たくさん出ている トータルスコア:" + String(Number(currentScore)+4);
    message = text3;
  } 
  console.log(message);

  if (mes == "耳垂れは出ていない トータルスコア"  || mes == "少し出ている トータルスコア" || mes == "たくさん出ている トータルスコア" ) {
    let result;
    if (currentScore <= 5) {
      result="急性中耳炎は軽症です。抗生物質は使わずに3日間様子を見ましょう。"
    } else if (currentScore < 11) {
      result="急性中耳炎は中等症です。 AMPCを高用量で3~5日間投与しましょう。"
    } else {
      result="急性中耳炎は重症です。AMPCを高用量で使うか、CVA / AMPC1:14製剤を通常量で使うか、CDTR-PIを高用量で使いましょう。鼓膜切開も考慮しましょう。"
    }
    return client.replyMessage(event.replyToken, {
        type: 'text', 
        text:result    
    });
  } else {
    return client.replyMessage(event.replyToken, {
      "type": "text", 
      "text": question,
      "quickReply": { 
        "items": [
          {
            "type": "action", 
              "action": {
              "type": "message",
              "label": label1,
              "text": text1
            }
          },
          {
            "type": "action",
              "action": {
              "type": "message",
              "label": label2,
              "text": text2
            }
          },
          {
            "type": "action", 
            "action": {
              "type": "message",
              "label": label3,
              "text": text3
            }
          }
        ]
      }
    });
   } 
}

app.listen(PORT);
console.log(`Server running at ${PORT}`);

動作確認

ちゃんと動いています。
クイックリプライボタンで表示されます。
耳痛1.png

耳痛.png
鼓膜発赤3.png

IMG-1.png

動画です。


考察

LINE Developersのクリックリプライを使いUIのなかなか良いLINE Botを作ることができました。handleEvent(event)を通るとScoreが0に戻ってしまうので、Scoreを足していくプログラムを書くのが難しかったです。サーバーで情報を管理できればもっと簡単にできそうなのでサーバー管理の勉強をしたいと思いました。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした