2016年12月11日日曜日

卒論発表お疲れ様でした

昨日は卒論発表会でした。とても良い発表だったと思います。これで約一年半にわたってやってきた卒業研究に一区切りをつけることができました。あとは結果を待つだけです。卒業式を楽しみにしていましょう。


2016年11月28日月曜日

いよいよ来週は卒論提出です

来週は卒論提出、そして週末は卒論発表会です。さて、今回の卒研で主張するポイントとしてWebAPIの利用によるシステム間連携を挙げました。これに関連する話として最近ホットな話題にHL7 FHIR というのがあります。なんとかこの話と関連づけられるといいのですが・・・。
FHIRのご紹介

2016年11月21日月曜日

もうあまり日がありません

卒論提出まであと2週間とちょっとです。今朝確認してみるとほとんど進んでいないようです。おそらくアンケートの結果がまだ届いていないからだと思いますが,もう待てません。アンケート結果なしで卒論をまとめましょう。そして,アンケート結果が戻ってきたら追加することにしましょう。
まず,結果に何を書くか考えなければなりません。結果と言ってもアプリを作っただけですから,「こんなのができました」としか書けません。それでは,つまらないのでこうしませんか?
今回,ORCAの画面にある項目を一覧表にまとめてもらいました。この中で在宅医療に使えそうなものは何か,そのうちどれを実際にスマホアプリで表示できるようにしたか。また,使えそうにないものはどれか,そういった分類をして項目数を挙げてみませんか?
そうすれば数字も出せるし,客観的な「結果」を示すことができます。
それから考察ですが,ORCAのWebAPI公開の意図・戦略について考えてみませんか。これなんか役に立つかもしれません。


2016年11月14日月曜日

見栄えをよくしました

アプリを少し修正して見栄えをよくしてみました。

患者一覧
患者基本情報
診療行為























卒論提出まであと3週間になってしまいました!

アンケート回答フォームについて


前回,作成したORCA Clientアプリの動画を撮影し, Youtubeへアップロードしました。
https://www.youtube.com/watch?v=49iruIsiiAg
アンケートはこの動画を見てもらい回答することにしました。
ところで,アンケート回答紙ですが,これも紙ではなく電子的なものにしてはどうでしょう。GoogleにはGoogleフォームというのがあるので,これを使えば回答フォームを作るのは簡単です。

ORCA Client アプリの問題点について

  1. 患者基本情報の下に禁忌、アレルギー、感染症、コメント情報が出ているが、文字が大きすぎるのと、それらが何かという見出しが出ていません。
  2. 川崎太郎さんは男性であるにもかかわらず病名に乳がんがあります。他の病名に変えましょう。また、うつ病も他の病名に変えてください。これらは私が入力したものなので申し訳ありませんが・・・

卒論について


今週は卒論がほとんど進んでいません。これにはアンケート結果が得られないことも絡んでいるでしょうが、卒論提出まであと3週間しかないことを考えるとのんびりはしていられません。卒論を提出するだけでなく、発表スライドを作って練習もしなければならないのですから。
また、 発表するには在宅医療についての知識もつけなければなりません。そのためにはいろいろな資料を読み込む必要があります。たとえば厚生労働省が出している次のPDFなど大変参考になると思います。
在宅医療・介護の推進について
在宅医療連携拠点事業

是非目を通しておくべきです。

2016年11月7日月曜日

卒論の進捗が少し遅れ気味です

アンケート調査について


先生方へのアンケート方法は決まりましたか?
多忙な先生方に、アンケートのためだけにゼミ室へ来てもらい、回答してもらうのは難しいように思います。そこで、スマホとORCAの操作をしているところをビデオに撮影してYoutubeにアップロードして、それを見ていただくのはどうでしょう?
アンケート用紙にそのYoutubeのサイトのQRコードとURLを書いておけば簡単にスマホやPCで視聴できると思います。
検討してみてください。

Excelで作成したORCAの項目一覧表を確認しました。
今回の研究では、この項目のうち、いくつかをピックアップしてスマホアプリで参照できるようにしているわけですが、先生方にアプリを評価してもらうにあたって項目に過不足がないか、また必要十分であるか、の判断材料を提供しなければなりません。
そこで、作成したORCAの項目一覧表の中で、スマホで参照できるようにしている項目のセルに色を付けるとわかりやすいのでないでしょうか。

卒論について


予定では、今週から「第4章 考察」を書くことになっていましたが、アンケート調査が済んでいないので「第3章 結果」が書けず、考察にまで至っていません。
しかし、卒論提出まであと1か月と迫ってきたので、考察のうち、書けるところは書いていきましょう。
今書けるところと言えば、システム開発に関することくらいでしょうか。
ORCAは医事会計システムなので在宅医療に使用するにはもう少し・・・といった情報が必要である、とか、在宅医療で多職種連携を行うには・・・といった機能が必要だと考えた、といった内容はどうでしょうか?

参考となる情報として、岡山の地域医療連携システムの晴れやかネットの拡張機能「ケアキャビネット」というのがあります。
一度調べてみて今回開発したシステムと比較してはどうでしょう?

http://www.city.soja.okayama.jp/data/open/cnt/3/3938/1/hareyakanetto.pdf

また、昨年のゼミでPACSサーバの構築を行って画像をスマホで参照する機能は既に開発済みです。今回の卒研はそれを受けて、さらに画像以外の情報も在宅医療の現場で利用できるようにしたものです。その点についても考察で触れてください。

2016年10月31日月曜日

今日からシステムテストです

システムテストと改善

前回でシステム開発が完了しました。今日からシステムテストです。まず,データをORCAで入力してみます。入力したデータがスマホアプリで参照できることを確認します。また,表示の仕方はこれでよいか,表示する内容はこれで十分か,不要なものはないか,そういった視点でも確認していきます。これまでわかっている問題点を列挙してみます。
  • 患者基本情報に禁忌・アレルギー・感染症・コメントを表示する
  • スタイルシートを使って文字の大きさ,出力位置を調整する
また,これ以外にも何か問題はないか話し合ってみます。
例えば
診療行為が当日分しか表示されない(期間を指定できるようにした方が良いのでは?)
  • 画面が白黒で淋しい(色を付けたほうが良いのでは?)
  • ORCAの機能で他にもスマホを使ってできたらよいものはないか(たとえば予約など)

システム評価と方法

システム評価の方法として詳しい先生に評価をお願いすると決めました。とは言ってもアプリを見せて評価しろではあんまりです。アプリをどのように見てもらい,どのような観点で評価してもらうか,評価用アンケート用紙を作成する必要があるでしょう。

卒業論文

予定では今日までで第2章の方法を書き終えて,今日から第3章の結果を書くことになっています。結果は「アンケート結果の集計」となっていますが,学生からアンケートをとるのはやめたので,ここは先生方から評価してもらった結果を書くことになります。とはいえ,まだ評価してもらっていないので,まずはどのように評価してもらうかを考えなければなりません。

2016年10月24日月曜日

いよいよORCA Client Ver.1.0の仕上げです

前回は病名一覧画面を作りました。今回は最後に診療行為一覧画面を作成してアプリを完成させます。

診療行為一覧画面

この画面は,病名一覧画面(detail-page)において「Add a note」ボタンがタップされたときに表示します。

作成手順は以下の通りです。
  1. 診療行為一覧画面(medical-page)を作成する。これは,病名一覧画面とほとんど同じです。detail.htmlをコピーして作成すればよいでしょう。HTML名はmedical.htmlとします。
  2. 病名一覧画面(detail.html)で「Add a note」を「診療情報」と改め,このボタンがタップされたとき,診療行為一覧画面を表示するようにjavascriptを修正する。
  3. medical-pageが表示されたときのjavascriptを作成する。これも,病名一覧画面の場合とほとんど同じになる。診療行為を取得するには日レセAPIの診療情報の返却を使う。
なお,診療行為一覧画面の上部には,病名一覧画面と同様に患者基本情報を表示する。

2016年10月17日月曜日

卒論までのスケジュールを変更しました

システム開発は順調に進んでいるため,卒論提出までのスケジュールを修正しました。

卒論提出までのスケジュール(10月17日修正)
前回のゼミで患者基本情報をORCAからとってくるところを作りました。とってくる項目としては氏名,カナ氏名,性別,生年月日,住所,電話番号などの基本情報に加えてORCAの登録画面から入力できる禁忌,アレルギー,感染症,コメントも出しましょう。
ORCAの登録画面を以下に示します。

ORCA登録画面

なお,ORCAから患者基本情報をとってくるAPIについてはここを見てください。

患者病名情報


次は,患者病名一覧の表示です。患者病名情報は患者基本情報の下部に出します。

ORCAクライアント(患者病名一覧)

 この情報はORCAの病名登録画面(下図)から登録した情報を患者病名情報の返却APIによって取得して出力します。

ORCA(病名登録画面)

病名一覧は傷病名と開始日,転帰日,転帰,疾患区分などを表示すればよいでしょう。可能であれば,主病名,疑い,原疾患,合併症なども表示するとよいのかもしれません。

プログラムの修正と追加


病名情報は詳細画面(detail-page)を表示したタイミングで出力します。この画面の上部には患者情報が出力されています(ORCAクライアント(患者病名一覧)参照)。
まず,ORCAから患者病名情報をとってくる関数getDiseaseData()を作成します。これは,患者一覧情報をとってくる関数getPatientList()とほとんど同じです。異なるのはurl,requestXML,そしてORCAのレスポンスからDisease_Informationを探してそれを変数diseaseDataへセットすることくらいでしょうか。もちろんdiseaseDataはグローバル変数として定義しておかねばなりません。
 次は,詳細画面が表示されたときのイベントハンドラの修正です。まず,最初にgetDiseaseData()を実行して病名情報を取得します。次いで,取得した病名情報を使ってHTMLを編集していきます。この辺りの書き方は患者一覧画面(list-page)とほとんど変わりませんね。

卒論


卒論は,前回「第1章 はじめに」を書きました。今回は添削にしたがって修正してきているはずですね。そして,今日からは「第2章 方法」を書いていきます。ここにはシステム開発の方法と開発したシステムの評価方法を書きます。

システム開発の方法

 

ここには,システム構成や開発に用いた技術や開発ツールを書けばよいでしょう。システム構成は図にするとわかりやすいと思います。システム要素はORCAサーバとORCAクライアントであるスマホです。その間を無線で結んでいます。
開発に用いた技術はなんといってもORCAの日医標準レセプトAPIです。 これなくして今回のシステム開発は不可能でした。このWeb APIをスマホからAjaxを用いて呼び出し,必要なデータを取得して画面に出力したのです。
スマホアプリはHTML5ハイブリッドアプリ開発手法を用いて開発しました。これは,Cordovaという仕組みを使ってHTML5レイヤーからスマホのネイティブレイヤーを呼び出す開発手法です。そのため,開発者はHTML5とjavascriptそしてCSSの知識だけでスマホのデバイスを制御できるアプリを開発できます。
そして,私たちは,このHTML5ハイブリッドアプリを開発するための統合開発環境(IDE)としてMonacaを使用しました。Monacaはクラウド上の開発環境なので,ブラウザさえあれば他に何も必要としないという手軽さが開発効率を向上させました。
ORCAとスマホアプリの間の通信インターフェースはXMLを使っている点にも言及しておく必要があるでしょう。
ORCAとスマホアプリがこんなに簡単に接続できたのはこのWebAPIのおかげです。通信の標準化といえばHL7やDICOMが取沙汰されることが多いですが,私はWebAPIを公開することが相互接続性を高めるキーポイントだと考えています。APIが公開されていればシステムの中身を知らなくとも簡単な処理でデータにアクセスできます。ある意味,WebAPIを公開することが標準化の究極の姿ではないかと考えています。

開発したシステムの評価方法


これはとても難しい問題です。しかし,研究というからにはシステムを開発しましただけでは終われません。開発したシステムをきちんと評価してこそ研究と呼べます。
しかし,何をしたら評価したことになるのでしょう?それは実際に開発したシステムを利用してもらい,システムが在宅医療を支援したかどうかを評価することでしょう。その場合,利用者は医事会計システムとしてORCAを利用して在宅医療を行っている医師でしょう。
しかし,今回開発したシステムをそのような人に使ってもらうことは不可能です。ならば誰に評価してもらえばいいのか。学生?学生に正当な評価ができるでしょうか?ただ便利だと思うとか使いやすい(あるいは使いにくい)といった表面上の反応しか返ってこない危惧があります。ではどうすればよいか?
これを考えるのも卒研の一環です。みんなでどうすれば正当な評価ができるか考えてみましょう。
また,これも重要なことですが,本来,ORCAのような医事会計システムではなく,電子カルテシステムと連携してこそ有用なスマホアプリと考えてきましたが,手ごろな電子カルテがなかったのでやむなくORCAを使ったという経緯があります。とはいえ,ORCAでも有益なシステムとなり得ることを示さなければなりません。ORCAで管理できる情報の中で在宅医療に利用できる情報は何でしょうか?これを整理しておく必要がありそうです。
そこで,ORCAの各画面から入力できる全情報をエクセルに入力して,その中からスマホで見ることができると在宅医療で役立ちそうな項目に印をつけていきましょう。完成した表は卒論の目玉の一つとなるでしょう。

2016年10月3日月曜日

いいもの見つけた!-SurveyMonkey

こんなものがあるんだね。
SurveyMonke
これは卒研で使えるかもしれない。
無料アカウントはいつものやつで作ったので早速アンケートを作ってみよう。
今さらですが,こういうのもあるんだね。
Monacaで学ぶ初めてのプログラミング~モバイルアプリ入門編~

2016年10月1日土曜日

いよいよORCAとの通信です。

前回までは,スマホアプリはORCAと通信しているのではなく,ORCAが返してくるのと同じ形式のXMLデータを返してくるダミーのWebサーバと通信していました。それは,ORCAとの通信が少々込み入っているため,そのことに頭を悩ませてプログラム開発が先に進まないことを避けるためでした。
しかし,前回,スマホアプリの表示部分は出来上がったので,いよいよORCAと通信して”本物の”データを引っ張ってこれるようにします。
ORCAとの通信には日医標準レセプトAPIを使います。このAPIは,機能ごとにインターフェース(送信データ,応答データ)が決められています。そして,インターフェースは1つを除いてすべてXML形式でやりとりします。個々の機能の具体的なインターフェースは日医標準レセプトAPIで確認してください。
今作っているスマホアプリに必要な情報は

  1. 患者一覧情報
  2. 患者基本情報

の2つです。患者一覧情報のAPIはここを見てください。そして,患者基本情報のAPIはここです。

患者一覧情報


患者一覧情報を取得するにはORCAサーバにPOSTメソッドで要求データを送ります(17行目)。また,このAPIではXML形式でいくつかのデータをORCAへ送ります。開始日(10行目),終了日(11行目),そしてテスト患者区分(12)行目です。ORCAは指定した開始日と終了日の間に新規登録されたかまたは更新された患者情報の一覧を返してきます。このXMLデータは22行目に設定しています。このプログラムでは開始日を2016/4/1に,終了日を当日に設定してあります。
ORCAサーバへはXML形式の入力データだけでなく認証情報も送ります(19~21行目)。認証情報はユーザ名:パスワードをBase64でエンコードしたものをヘッダに付けて送ります(20行目)。
     function getPatientList() {
        var url = 'http://172.16.108.250:8000/api01rv2/patientlst1v2?class=01';
        patientList = null;

        var baseStartDate = '2016-04-01';
        var today = new Date();
        var baseEndDate = today.getFullYear() + '-' + zeroPadding(today.getMonth() + 1) + '-' + today.getDate();
        var requestXML = '<data>';
        requestXML += '<patientlst1req type="record">';
        requestXML += '<Base_StartDate type="string">' + baseStartDate + '</Base_StartDate>';
        requestXML += '<Base_EndDate type="string">' + baseEndDate + '</Base_EndDate>';
        requestXML += '<Contain_TestPatient_Flag type="string">1</Contain_TestPatient_Flag>';
        requestXML += '</patientlst1req>';
        requestXML += '</data>';

        $.ajax({
            type: 'POST',
            url: url,
            headers:{
                'Authorization' : 'Basic ' + window.btoa(g_user + ':' + g_passwd)
            },
            data: requestXML,
            contentType: "application/xml",
            async: false,
            cache: false,
            // レスポンスデータの形式
            dataType: "xml"
        }).done(function(xml, status, error){
            if (status == 'success') {
                patientList = $(xml).find('Patient_Information');
            } else {
                alert('文書データ取得失敗');
            }
        }).fail(function(xhr, status, error){
            var message = "xhr.status = " + xhr.status + ", xhr.statusText = " + xhr.statusText + ", status = " + status + ", error = " + error;
            alert('サーバから応答がありません: ' + message);
        });
    }
なお,7行目のzeroPaddingは数字の先頭に0を付けて2ケタにする(たとえば1を01にする)関数で以下のように定義されています。
//ゼロパディング
function zeroPadding( val ) {
    return ( "0" + val ).slice( -2 )
}

患者基本情報


患者基本情報はGETメソッドでサーバへ要求データを送ります(5行目)。GETメソッドではデータをクエリストリングとしてURLの一部として送ります(2行目)。?以降がそれです。クエリストリングは「パラメタ=値」という対を必要な数だけ&でつなげて書きます。
    function getPatientData(patientId) {
        var url = 'http://172.16.108.250:8000/api01rv2/patientgetv2?id=' + patientId;
        patientData = null;
        $.ajax({
            type: 'GET',
            headers:{
                'Authorization' : 'Basic ' + window.btoa(g_user + ':' + g_passwd)
            },
            url: url,
            async: false,
            cache: false,
            dataType: "xml"
        }).done(function(xml, status, error){
            if (status == 'success') {
                patientData = $(xml).find('Patient_Information');
            } else {
                alert('文書データ取得失敗');
            }
        }).fail(function(xhr, status, error){
            var message = "xhr.status = " + xhr.status + ", xhr.statusText = " + xhr.statusText + ", status = " + status + ", error = " + error;
            alert('サーバから応答がありません: ' + message);
        });
    }

患者病名情報


次は患者病名情報です。患者病名は詳細画面の下側に表示します(4~16行目)。 2行目のgetDiseaseDataが病名情報をORCAから取得する関数です。
    var diseaseData = null;

    $(document).on('pageinit', '#detail-page', function() {
        getDiseaseData(currentItem.id);
        var html = '';
        $(diseaseData).find('Disease_Information_child').each(function(){
            html += '<ons-list-item class="detail-item">';
            html += '<header>';
            html += '<span class="detail-item-date">' + $(this).find('Disease_StartDate').text() + '</span>';
            html += '</header>';
            html += '<p class="detail-item-diseaseName">' + $(this).find('Disease_Name').text() + '</p>';
            html += '</ons-list-item>';
        });
        $("#detail-item-list").html(html);
        var content = $("#detail-item-list").get(0);
        ons.compile(content);
        
        getPatientData(currentItem.id);
        var homeAddress = patientData.find('Home_Address_Information');
        var address = homeAddress.find('WholeAddress1').text();
        var phone = homeAddress.find('PhoneNumber1').text();
        $('.item-id', this).text(currentItem.id);
        $('.item-gender', this).text(currentItem.gender);
        $('.item-name', this).text(currentItem.name);
        $('.item-name-kana', this).text(currentItem.name_kana);
        $('.item-birthdate', this).text(currentItem.birthdate);
        $('.item-address', this).text(address);
        $('.item-phone', this).text(phone);
        $('.add-note-action-item', this).click(function () {
            // ここに Add a noteがタップされた時の処理を書く
        });
    });
getDiseaseData関数は次のようになります。患者一覧情報取得関数と同じようにXML形式のパラメタをPOSTメソッドをORCAサーバへ送ります。
    function getDiseaseData(patientId) {
        var url = 'http://172.16.108.250:8000/api01rv2/diseasegetv2?class=01';
        diseaseData = null;
        var requestXML = '<data>';
        requestXML += '<disease_inforeq type="record">';
        requestXML += '<Patient_ID type="string">' + patientId + '</Patient_ID>';
        requestXML += '<Base_Date type="string"></Base_Date>';
        requestXML += '</disease_inforeq>';
        requestXML += '</data>';
        $.ajax({
            type: 'POST',
            url: url,
            headers:{
                'Authorization' : 'Basic ' + window.btoa(g_user + ':' + g_passwd)
            },
            data: requestXML,
            contentType: "application/xml",
            async: false,
            cache: false,
            dataType: "xml"
        }).done(function(xml, status, error){
            if (status == 'success') {
                diseaseData = $(xml).find('Disease_Information');
            } else {
                alert('文書データ取得失敗');
            }
        }).fail(function(xhr, status, error){
            var message = "xhr.status = " + xhr.status + ", xhr.statusText = " + xhr.statusText + ", status = " + status + ", error = " + error;
            alert('サーバから応答がありません: ' + message);
        });
    }

診療行為情報


詳細画面で「Add a note」をタップされたら当該患者の診療行為を出力するようプログラムを改良します。

診療行為情報 (medical-page)

そのためには,まず,診療行為を表示する画面(html)を作成します。 単体ファイルでもons-templateとして作成しても構いません。 HTMLファイルの名前をmedical.html,ons-pageのidをmedical-pageとします。 ファイルの中身は詳細画面とほぼ同じで次のようになります。
<ons-template id="medical.html">
    <ons-page id="medical-page">

      <ons-toolbar>
        <div class="left"><ons-back-button>Back</ons-back-button></div>
        <div class="center">診療情報</div>
      </ons-toolbar>

      <ons-list modifier="inset" style="margin-top: 10px">
        <ons-list-item class="item">
          <ons-row>
            <ons-col width="60px"> 
              <div class="item-thum">
                <img src="" class="item-thum-photo" width="50px"></img>  
              </div>
            </ons-col>
            <ons-col>
              <header>
                <span class="item-id">id</span>
                <span class="item-gender">gender</span>
              </header>
              <p class="item-name">name</p>
              <p class="item-name-kana">name_kana</p>
              <p class="item-birthdate">birthdate</p>
              <p class="item-address">address</p>
              <p class="item-phone">phone</p>
            </ons-col>
          </ons-row>
        </ons-list-item>

        <ons-list-item modifier="chevron" id="add-note-action" class="add-note-action-item">
          <ons-icon icon="ion-chatboxes" fixed-width="true" style="color: #ccc"></ons-icon>
          症状詳記
        </ons-list-item>
      </ons-list>

      <ons-list id="medical-item-list" style="margin-top: 10px">
      </ons-list>

      <br>

    </ons-page>
</ons-template>
次に,この画面が表示された時の処理を書きます。 これも,詳細画面(detail-page)と変わりありません。
    var medicalData = null;
    
    $(document).on('pageinit', '#medical-page', function() {
        getMedicalData(currentItem.id);
        var html = '';
        $(medicalData).find('Medical_List_Information_child').each(function(){
            html += '<ons-list-item class="detail-item">';
            html += '<header>';
            html += '<span class="detail-item-date">' + $(this).find('Medical_Class_Name').text() + '</span>';
            html += '</header>';
            html += '<p class="detail-item-diseaseName">' + $(this).find('Medication_Name').text() + '</p>';
            html += '</ons-list-item>';
        });
        $("#medical-item-list").html(html);
        var content = $("#medical-item-list").get(0);
        ons.compile(content);
        
        getPatientData(currentItem.id);
        var homeAddress = patientData.find('Home_Address_Information');
        var address = homeAddress.find('WholeAddress1').text();
        var phone = homeAddress.find('PhoneNumber1').text();
        $('.item-id', this).text(currentItem.id);
        $('.item-gender', this).text(currentItem.gender);
        $('.item-name', this).text(currentItem.name);
        $('.item-name-kana', this).text(currentItem.name_kana);
        $('.item-birthdate', this).text(currentItem.birthdate);
        $('.item-address', this).text(address);
        $('.item-phone', this).text(phone);
        $('.add-note-action-item', this).click(function () {
            alert('病状詳記はまだ実装されていません!');
        });
    });
最後にORCAから当該患者の診療情報を取得する関数getMedicalDataを書きます。 これも患者一覧情報や患者病名情報の取得と同じようにPOSTメッセージでXMLデータを送信します。
    function getMedicalData(patientId) {
        var url = 'http://172.16.108.250:8000/api01rv2/medicalgetv2?class=03';
        medicalData = null;
        var today = new Date();
        var performDate = today.getFullYear() + '-' + zeroPadding(today.getMonth() + 1) + '-' + today.getDate();
        var requestXML = '<data>';
        requestXML += '<medicalgetreq type="record">';
        requestXML += '<InOut type="string">O</InOut>';
        requestXML += '<Patient_ID type="string">' + patientId + '</Patient_ID>';
        requestXML += '<Perform_Date type="string">' + performDate + '</Perform_Date>';
        requestXML += '<For_Months type="string">1</For_Months>';
        requestXML += '<Medical_Information type="record">';
        requestXML += '<Department_Code type="string">01</Department_Code>';
        requestXML += '</Medical_Information>';
        requestXML += '</medicalgetreq>';
        requestXML += '</data>';
        $.ajax({
            type: 'POST',
            url: url,
            headers:{
                'Authorization' : 'Basic ' + window.btoa(g_user + ':' + g_passwd)
            },
            data: requestXML,
            contentType: "application/xml",
            async: false,
            cache: false,
            dataType: "xml"
        }).done(function(xml, status, error){
            if (status == 'success') {
                medicalData = $(xml).find('Medical_List_Information');
            } else {
                alert('文書データ取得失敗');
            }
        }).fail(function(xhr, status, error){
            var message = "xhr.status = " + xhr.status + ", xhr.statusText = " + xhr.statusText + ", status = " + status + ", error = " + error;
            alert('サーバから応答がありません: ' + message);
        });
    }
なお,Add a noteをタップしたときに以下のようにすれば診療行為画面を表示することができます。
        $('.add-note-action-item', this).click(function () {
            app.navi.pushPage('medical.html');
        });

2016年9月25日日曜日

夏休みが終わりました!

早いもので2か月間の夏休みがあけ,秋学期のゼミが始まります。
夏休み明け初日のメニューは次の通りです。
  • 夏休みの宿題確認
  • 今後のスケジュールの確認
  • ORCA Client Ver 0.1の開発着手
まず,夏休みの宿題の確認です。夏休みの宿題は,中間報告会で質問された下記に対する回答を各自で考えてくることでした。
  1. 何故電子カルテではなくORCAとスマホを接続するのか?
  2. スマホをレセコン(あるいは電カル)の端末として利用するという先行研究はあるか?どのような内容か?
  3. 研究テーマが「在宅医療を支援するための医事会計システム(ORCA)連携スマホアプリの開発」となっているが、これは何が「連携」しているのか?人と人の連携?それともスマホの連携?
  4. 研究の目的をもっとしっかり説明する(なぜ、この研究をするのか、する必要があるのか)
  5. ORCAはレセコンなので、検査結果や画像データは入っていない。それを在宅医療の現場でどのように活用するのか?また、活用する意味はあるのか?
もう一つあります。
それは,これまでJSON形式のデータを扱っていたスマホアプリをXML形式のデータを扱えるように修正することでした。これがやがてORCAクライアント開発へと繋がっていきます。

今後のスケジュールの確認

卒論発表までのスケジュールを作成しました。


卒論発表までもう2か月半しかありません。その間にアプリの開発と卒論執筆をやらなければならないのですから気を引き締めて取り掛からないと痛い目にあいそうです。
アプリを開発してから卒論を書いていたのでは間に合わないので並行して行うことにします。またゼミの時間だけではアプリを開発することができないのでゼミとゼミの合間にも開発作業は続けてください。

ORCA Client Ver 0.1の開発

夏休みの課題アプリをもとにしてORCAクライアントアプリの開発に着手します。
まず,初期画面です。これまで通り患者一覧を表示します。患者一覧データはORCA APIを使います。APIの中に患者番号一覧の取得というのがあり,これを用いてORCAに登録されている患者一覧情報を取得できます。


ORCA Client 初期画面


 ただし,このAPIでは患者の住所は入手できません。したがって,これまでと違って患者一覧の中には住所が出力されません。

次に,一覧から患者をタップしたとき,患者の基本情報と病名情報を表示します(下図)。

ORCA Client 患者情報画面

これまでは,患者受診一覧を表示していましたが,APIには受診一覧を取得する機能が見当たらないので,ここでは代わりに病名情報を表示してあります(画面下部)。患者病名情報を取得するAPIは患者病名情報の返却です。
また,画面上部には患者一覧画面に表示されていた項目を出力していましたが,ここでは患者基本情報を取得するAPIを使って住所や電話番号を出力しています。このAPIではほかにも禁忌,感染情報,アレルギー,コメント,保険情報なども取得できるので,必要に応じてそれらも出力するとよいでしょう。

APIを使う前に

最終的にはORCAの提供するAPIを使ってスマホはORCAサーバと通信することになります。しかし,ORCAと通信するには認証を受けたり,必要なデータをポストメッセージで送信したりといろいろ面倒な手順を踏まなければなりません。
そこで,最初は従来と同じようにWebサーバから固定XMLデータを取得してそれを画面編集するプログラムを作成し,それが完成してからORCAサーバと通信するように修正していこうと思います。このようにプログラムの初心者はいきなり難しいことに取り組もうとするのではなく徐々に修正して最終的に完成されるというスタイルで開発を進めていったほうが無難です。
下記はそのために使う固定XMLデータです。

2016年7月26日火曜日

夏休み前の最後のゼミです!

さて、今日は夏休み前の最後のゼミです。先週は、サーバからJSON形式で患者一覧情報と患者受診一覧情報を受け取り、それを画面に表示するプログラムを作成しました。今日は、その応用で、JSON形式ではなくXML形式で患者一覧情報と患者受診一覧情報を受け取り、それを画面に表示するプログラムを作成します。

患者一覧XMLデータ

Ajaxで取得する患者一覧のXMLデータです。このデータは次のURLで取得します。
http://172.16.108.250/~semi2015/XML/getPatientList.php
JSON形式と違ってXMLタグで各データ要素の意味が明確です。
<?xml version="1.0" encoding="UTF-8"?>
<patientList>
  <patient>
    <id>A0001</id>
    <name>在本 璃奈</name>
    <gender>female</gender>
    <birthdate>1996/4/1</birthdate>
    <address>岡山県倉敷市山田町1丁目-2-3</address>
  </patient>
  <patient>
    <id>A0002</id>
    <name>清水 伸平</name>
    <gender>male</gender>
    <birthdate>1995/5/10</birthdate>
    <address>岡山県岡山市苦米地3丁目-5-6</address>
  </patient>
  <patient>
    <id>A0003</id>
    <name>田中 昌昭</name>
    <gender>male</gender>
    <birthdate>1958/7/6</birthdate>
    <address>岡山県瀬戸内市大岡5丁目-9-8</address>
  </patient>
</patientList>

患者受診一覧XMLデータ

続いて患者受診一覧のXMLデータです。このデータは、以下のURLで取得します。
http://172.16.108.250/~semi2015/XML/getVisitData.php
<?xml version="1.0" encoding="UTF-8"?>
<visitData>
  <patient id="A0001">
    <visit>
      <date>2016/5/20</date>
      <dept>内科</dept>
      <diseaseName>気管支炎</diseaseName>
    </visit>
    <visit>
      <date>2014/1/29</date>
      <dept>外科</dept>
      <diseaseName>大腿骨骨折</diseaseName>
    </visit>
    <visit>
      <date>2015/8/6</date>
      <dept>耳鼻科</dept>
      <diseaseName>中耳炎</diseaseName>
    </visit>
  </patient>
  <patient id="A0002">
    <visit>
      <date>2016/3/19</date>
      <dept>内科</dept>
      <diseaseName>インフルエンザ</diseaseName>
    </visit>
    <visit>
      <date>2015/2/10</date>
      <dept>外科</dept>
      <diseaseName>虫垂炎</diseaseName>
    </visit>
  </patient>
  <patient id="A0003">
    <visit>
      <date>2016/4/8</date>
      <dept>眼科</dept>
      <diseaseName>白内障</diseaseName>
    </visit>
    <visit>
      <date>2013/2/5</date>
      <dept>内科</dept>
      <diseaseName>心筋梗塞</diseaseName>
    </visit>
    <visit>
      <date>2011/11/4</date>
      <dept>皮膚科</dept>
      <diseaseName>アトピー性皮膚炎</diseaseName>
    </visit>
    <visit>
      <date>2014/12/15</date>
      <dept>精神科</dept>
      <diseaseName>気分障害</diseaseName>
    </visit>
  </patient>
</visitData>
患者受診一覧XMLデータには、複数の患者の受診履歴があり、patient要素のid属性でどの患者の受診履歴か区別できるようになっています。

XML形式のデータの扱い方

サーバからのレスポンスがJSON形式からXML形式に変わったからといってもプログラムが大きく変わるわけではありません。変更点は大きく以下の2点です。
  1. サーバのURLが変わる
  2. サーバからのレスポンスが変わる
URLについては上で示した通りです。サーバからのレスポンスはJSON形式ではなくXML形式となり、Ajaxで取得したデータはJSON形式の時のように解析(JSON.parse)する必要はなく、そのまま使えます。
次に、XML形式のデータはXMLオブジェクトとしてプログラム中に取り込まれ、JSON形式のデータがJSON.parseによってjavascriptオブジェクトに変換されるのと異なります。XMLオブジェクトの取り扱い方は専用のメソッドを使います。
具体的には、タグ名が'ABC'の要素を取り出すには、$(XMLオブジェクト).find('ABC').text()とします。また,タグ名が'ABC'の要素の中にある属性値名が'XYZ'の属性値を取り出したい場合は$(XMLオブジェクト).find('ABC').attr('XYZ')とします。

2016年7月19日火曜日

いよいよ後半開始!

中間発表も終わり、いよいよ後半開始です。これまで、JSON形式のデータをスマホに表示するプログラムを作成してきましたが、ここからは、スマホに表示するデータをサーバから取得します。

AjaxによるJSON形式データの取得





図のように、スマホからHttpRequestと呼ばれるWebサービス要求を行います。すると、Webサーバは要求に対する応答をJSON形式のデータに編集してスマホへ返送します。たとえば、次の例は患者一覧を要求したときのJSON形式のレスポンスを示しています。

患者一覧要求に対するサーバのレスポンス(JSON形式)

これを受け取ったスマホ側のアプリは画面に患者一覧を表示します。このように、Webサーバと通信を行うことによって必要な情報を取得し、それを画面上に表示するプログラミング形態をAjaxと言います。これまで作成してきたアプリとの違いは、患者一覧データなどのデータを、javascriptファイルとしてあらかじめスマホ側に持たせるのではなく、必要になった時点で、サーバへ要求して取得する点が異なります。

では、Ajaxを用いたアプリを作成しましょう。修正すべきファイルは index.html と app.js です。

index.htmlの修正


患者一覧データ(js/patientList.js)と患者受診データ(js/visitData.js)は不要なのでコメントにします。

app.jsの修正


  • 患者一覧データ(patientList)を宣言する
  • 患者受診データ(visitData)を宣言する
  • 関数getPatientListを作成する
  • list-pageが表示されたとき、関数getPatientListを呼び出す
  • 関数getVisitDataを作成する
  • detail-pageが表示されたとき、関数getVisitDataを呼び出す

これまで、患者一覧データと患者受診データは、javascritファイルとして読み込んでいましたが、ここではAjaxを使ってサーバから取得するため、空の配列を宣言します。

  var currentItem = {};
  var visitData = [];
  var patientList = [];

上記の2~3行目がそれです。

患者一覧の作成


次に関数getPatientListを作成します。この関数は、app.js内に作成します(どこに作っても構いませんが、末尾に追加するのが良いでしょう)。この関数は、Ajaxを用いて、2行名に指定したURLに対して患者一覧データをリクエストしています。結果は doneコールバック関数の第1引数(response)に返ってきます。JSON形式の患者一覧を11行目でパース(解析)してjavascriptオブジェクトに変換して変数 res へ代入しています。実際の患者一覧は、このオブジェクトのメンバ変数であるpatientListに格納されているので、これを上で宣言したグローバル変数 patientList へ代入します。
function getPatientList() {
    var url = 'http://172.16.108.250/~semi2015/sample/getPatientList.php';

    $.ajax({
        type: 'GET',
        url: url,
        async: false,
        cache: false
    }).done(function(response, status, error){
        if (status == 'success') {
            var res = JSON.parse(response);
            if (res.status == 'OK') {
                patientList = res.patientList;
            } else {
                alert('ERROR:res.status=' + res.status);
            }
        } else {
            alert('文書データ取得失敗');
        }
    }).fail(function(xhr, status, error){
        var message = "xhr.status = " + xhr.status + ", xhr.statusText = " + xhr.statusText + ", status = " + status + ", error = " + error;
        alert('サーバから応答がありません: ' + message);
    });
}
作成した関数getPatientListは、list-pageが表示されたタイミングで呼び出し(2行目)、患者一覧データ(patientList)を取得した後、画面に出力します。その部分が下記のプログラムです。
  $(document).on('pageinit', '#list-page', function() {
    getPatientList();
    var html = '';
    $.each(patientList, function(i, item) {
        html += '<ons-list-item modifier="chevron" class="item">';
        html += '<ons-row>';
        html += '<ons-col width="60px"> ';
        html += '<div class="item-thum">';
        html += '</div>';
        html += '</ons-col>';
        html += '<ons-col>';
        html += '<header>';
        html += '<span class="item-id">' + item.id + '</span>';
        html += '<span class="item-gender">' + item.gender + '</span>';
        html += '</header>';
        html += '<p class="item-name">' + item.name + '</p>';
        html += '<p class="item-birthdate">' + item.birthdate + '</p>';
        html += '<p class="item-address">' + item.address + '</p>';
        html += '</ons-col>';
        html += '</ons-row> ';                        
        html += '</ons-list-item>';
      }
    );
    $("#item-list").html(html);
    var content = $("#item-list").get(0);
    ons.compile(content);

    $('.item', this).on('click', function() {
      currentItem = {
        id : $('.item-id', this).text(),
        gender : $('.item-gender', this).text(),
        name : $('.item-name', this).text(),
        birthdate : $('.item-birthdate', this).text(),
        address : $('.item-address', this).text()
      };

      app.navi.pushPage('detail.html');
    });
  });

受診一覧の作成


次に関数getVisitDataを作成します。 この関数も、app.js内に作成します。上記で作成したgetPatientListに続いて作成してください。この関数は、Ajaxを用いて、2行目に指定したURLに 対して指定した患者(patientId)の受診一覧データをリクエストしています。患者を指定するために、クエリストリング(?patientId=患者番号)を使っている点に注目してください。指定する患者IDは関数getVisitDataの引数で関数へ渡しています。結果は、getPatientListの場合と同様に doneコールバック関数の第1引数(response)に返ってきます。JSON形式の受診一覧を11行目でパース(解析)してjavascriptオ ブジェクトに変換して変数 res へ代入しています。実際の受診一覧は、このオブジェクトのメンバ変数であるvisitDataに格納されているので、これを上で宣言したグローバル変 数 visitData へ代入します。
function getVisitData(patientId) {
    var url = 'http://172.16.108.250/~semi2015/sample/getVisitData.php?patientId=' + patientId;

    $.ajax({
        type: 'GET',
        url: url,
        async: false,
        cache: false
    }).done(function(response, status, error){
        if (status == 'success') {
            var res = JSON.parse(response);
            if (res.status == 'OK') {
                visitData = res.visitData;
            } else {
                alert('ERROR:res.status=' + res.status);
            }
        } else {
            alert('文書データ取得失敗');
        }
    }).fail(function(xhr, status, error){
        var message = "xhr.status = " + xhr.status + ", xhr.statusText = " + xhr.statusText + ", status = " + status + ", error = " + error;
        alert('サーバから応答がありません: ' + message);
    });
}
作成した関数getVisitDataは、detail-pageが表示されたタイミングで当該患者ID(currentItem.id)を引数として呼び出し(2行目)、患者受診データ(visitData)を取得した後、画面に出力します。その部分が下記のプログラムです。
  $(document).on('pageinit', '#detail-page', function() {
    getVisitData(currentItem.id);
    var html = '';
    $.each(visitData, function(i, item) {
        html += '<ons-list-item class="detail-item">';
        html += '<header>';
        html += '<span class="detail-item-date">' + item.date + '</span>';
        html += '</header>';
        html += '<p class="detail-item-dept">' + item.dept + '</p>';
        html += '<p class="detail-item-diseaseName">' + item.diseaseName + '</p>';
        html += '</ons-list-item>';
    });
    $("#detail-item-list").html(html);
    var content = $("#detail-item-list").get(0);
    ons.compile(content);
    $('.item-id', this).text(currentItem.id);
    $('.item-gender', this).text(currentItem.gender);
    $('.item-name', this).text(currentItem.name);
    $('.item-birthdate', this).text(currentItem.birthdate);
    $('.item-address', this).text(currentItem.address);
    $('.add-note-action-item', this).click(function () {
        alert('dummy message');
    });
  });

なお、このプログラムが、従来の処理と違うのは、4行目の繰り返し処理において visitData が連想記憶の要素 visitData[currentItem.id] になっていない点です。これは、関数getVisitDataで取得した受診データが、指定した患者の受診データなので、わざわざ患者IDを指定して配列要素を取ってくる必要がないからです。

2016年7月13日水曜日

中間発表終わりました!

今日、中間発表が終わりました。発表自体は悪くなかったですが、質問には明快に答えられませんでした。忘れないうちに質問を書き残しておきましょう。
  • 何故電子カルテではなくORCAなのか?
  • スマホをORCAの端末として利用するという研究?
  • それは「連携」と言えるのか?
  • ORCAとスマホをつなぐ先行事例はある?
  • 研究の目的をもっとしっかり説明した方がいい(なぜ、この研究をするのか、する必要があるのか)
いかがでしょう。どれもなかなか本質を突いた厳しい質問です。漫然と言われたことだけやっていてはだめですね。何のためにやっているのかを意識しながらやらないとね。ORCAは医事コンなので、検査結果や画像データは入っていない。それを在宅医療の現場でどのように活用するのか?また、活用する意味はあるのか?そのあたりについても考えていかないといけませんね。



2016年6月29日水曜日

中間発表に向けての準備

いよいよ中間発表が迫ってきました。今日はその準備です。まず中間発表の流れを考えます。
  • これまでやってきたこと(3年生秋学期~今日まで)
    • VMware上にLinuxインストール
    • Javascriptの勉強
    • PHP+MySQL
    • 成果:ボールゲーム(オープンキャンパスでパネルからリンク)
  • 卒研テーマ:在宅医療を支援するための医事会計システム(ORCA)連携スマホアプリの開発
    • 概要:
    • 研究の目的(この研究は何のためにやるのか):
    • 目標(卒研でどこまでを目標とするか):
    • 現状(どこまで研究が進んでいるか、今後何をしなければならないか、何か問題はないか):
      • これについては、現在Monacaで開発中のスマホアプリを報告する
      • 患者一覧→患者の受診履歴

VMwareのインストール


VMwareの初期画面

VMwareはWindowsパソコンでLinuxを利用するために必要なコンピュータの仮想化ソフトウェアです。使用したのはVMware Workstation 12 Playerです。

CentOSのインストール

VMware上で稼働するCentOS 6.7

次にVMware上にCentOSをインストールしました。バージョンはCentOS 6.7です。これは、Javascriptの勉強をするためのWebサーバとして稼働させたものです。WebサーバにはApacheを用いました。

ボールゲームの作成

javascriptで開発したボールゲーム
javascriptを勉強するためにボールゲームを作成しました。このゲームは、画面上に3つのボール(バスケットボール、サッカーボール、赤いボール)を動かせ、バスケットボールを上下左右のボタンでコントロールし、サッカーボールにぶつけたら得点、赤玉にぶつけたら減点するというルールで一定の時間内に何点取れるかを競うゲームです。PCだけでなくスマホでも楽しめ、オープンキャンパスで展示しました。

在宅医療を支援するための医事会計システム(ORCA)連携スマホアプリの開発

次に4年生になってから卒研テーマを決定しました。テーマは、診療所内で動いている医療情報システムを、訪問診療の際に、スマホから利用できるようにするシステムを開発することです。なぜこのようなシステムを開発しようとしたかと言うと、医師が訪問先の患者宅や自宅で患者情報を確認したり、処方内容や検査内容を見たいとき、スマホで手軽に見ることができたら便利だと考えたからです。しかし、これはあくまでもで私たちが想像したことで、実際にそのような必要性があるかどうかはきちんと調査しなければなりません。
今回は、医療情報システムとして、日本医師会が開発した日医標準レセプトORCAを利用することにしました。これはいわゆる開業医向けのレセコンです。なぜ、ORCAを選んだかと言うと、ORCAは無料で使えるからです。それだけでなく、全国で1万6千を超えるユーザがいるので、開発したシステムが利用される可能性もあると考えたからです。また、ユーザが多い分、技術情報もたくさんネットから得られるます。しかし、何よりも魅力なのは、ORCAが日医標準レセプトAPIというWebAPIを提供していたことです。WebAPIがあれば、スマホのアプリから簡単にORCAの機能を利用できます。ORCAの内部構造を知らなくても簡単に連携ができるのです。

ORCAのクライアント(患者登録画面)

システム構成図

開発するシステムの構成は次のようになっています。

システム構成

スマホアプリからORCAサーバに向けて患者情報や受診履歴などのリクエストを行います。その際、スマホアプリは日医標準レセプトAPIを利用します。 今回、スマホアプリは3年次生の時に勉強したjavascriptで作成しました。開発環境としてはクラウド型スマホアプリ開発環境であるMonacaを利用しています。MonacaはHTML5+javascriptでハイブリッドスマホアプリを開発できる開発環境です。また、javascriptライブラリとしてはjQueryを利用しました。そのjavascriptを使ってHttpRequestを利用してORCAサーバにHTTPリクエストを送ります。すると、ORCAはリクエストに対するレスポンスをXML形式で返してきます。たとえば、次のXMLデータは、スマホが患者基本情報を要求したときのレスポンスデータです。

<?xml version="1.0" encoding="UTF-8"?>
<xmlio2>
  <patientinfores type="record">
    <Information_Date type="string">2016-06-29</Information_Date>
    <Information_Time type="string">09:18:03</Information_Time>
    <Api_Result type="string">00</Api_Result>
    <Api_Result_Message type="string">処理終了</Api_Result_Message>
    <Reskey type="string">Patient Info</Reskey>
    <Patient_Information type="record">
      <Patient_ID type="string">00001</Patient_ID>
      <WholeName type="string">川崎 太郎</WholeName>
      <WholeName_inKana type="string">カワサキ タロウ</WholeName_inKana>
      <BirthDate type="string">1958-07-06</BirthDate>
      <Sex type="string">1</Sex>
      <HouseHolder_WholeName type="string">川崎 太郎</HouseHolder_WholeName>
      <Relationship type="string">本人</Relationship>
      <Home_Address_Information type="record">
        <Address_ZipCode type="string">7010114</Address_ZipCode>
        <WholeAddress1 type="string">岡山県倉敷市松島</WholeAddress1>
        <PhoneNumber1 type="string">086-462-1234</PhoneNumber1>
        <PhoneNumber2 type="string">086-462-1111</PhoneNumber2>
      </Home_Address_Information>
      <Community_Cid_Agree type="string">False</Community_Cid_Agree>
      <FirstVisit_Date type="string">2016-06-11</FirstVisit_Date>
      <LastVisit_Date type="string">2016-06-12</LastVisit_Date>
      <HealthInsurance_Information type="array">
        <HealthInsurance_Information_child type="record">
          <Insurance_Combination_Number type="string">0001</Insurance_Combination_Number>
          <InsuranceCombination_Rate_Admission type="string">0.30</InsuranceCombination_Rate_Admission>
          <InsuranceCombination_Rate_Outpatient type="string">0.30</InsuranceCombination_Rate_Outpatient>
          <InsuranceProvider_Class type="string">060</InsuranceProvider_Class>
          <InsuranceProvider_Number type="string">330019</InsuranceProvider_Number>
          <InsuranceProvider_WholeName type="string">国保</InsuranceProvider_WholeName>
          <HealthInsuredPerson_Symbol type="string">あいう</HealthInsuredPerson_Symbol>
          <HealthInsuredPerson_Number type="string">123456</HealthInsuredPerson_Number>
          <HealthInsuredPerson_Assistance type="string">3</HealthInsuredPerson_Assistance>
          <HealthInsuredPerson_Assistance_Name type="string">3割</HealthInsuredPerson_Assistance_Name>
          <RelationToInsuredPerson type="string">1</RelationToInsuredPerson>
          <HealthInsuredPerson_WholeName type="string">川崎 太郎</HealthInsuredPerson_WholeName>
          <Certificate_StartDate type="string">2016-06-05</Certificate_StartDate>
          <Certificate_ExpiredDate type="string">9999-12-31</Certificate_ExpiredDate>
          <Insurance_CheckDate type="string">2016-06-05</Insurance_CheckDate>
        </HealthInsurance_Information_child>
      </HealthInsurance_Information>
    </Patient_Information>
  </patientinfores>
</xmlio2>
スマホアプリは受け取ったXMLデータを画面にレンダリングします。
なぜこのようなシステムを開発するのか
私たちのゼミではなぜスマホを使ったこうしたシステムを開発するのか説明しておきましょう。私たちのゼミでは、3年前からスマホを使って在宅医療を支援するシステムの開発を行ってきました。昨年はPACSサーバを構築して、訪問診察など外出先からスマホを使って画像を送ったり検索・閲覧したりするシステムを開発しました。 画像ができたので、じゃあ、今度は電子カルテをスマホから利用できるようにしたいと思い、今年のテーマに選びました。しかし、診療所向きで私たちが入手できる電子カルテがありませんでした。そこで、日本医師会が無料で提供しているORCAに注目したのです。ORCAは医事会計システム(レセプトシステム:レセコン)で、電子カルテではありません。したがって、医師が書く診療録は入っていません。患者情報と診療行為のみです。しかも、診療報酬に必要なデータしか入っていないので、例えば検査結果などは入っていません。ですから在宅診療に利用するには機能はかなり限定的です。しかし、手法自体はスマホが連携する相手がORCAであろうが電子カルテであろうが変わりません。つまり、今回の研究は実用性を目指すというよりも方法論を示すための研究です。この方法でうまくスマホ連携ができれば、あとはこの考え方で様々なシステムを連携を図ればよいのです。ですから、今回の研究の目的は「スマホを使って在宅医療を支援する」ですが、目標は「スマホとORCAの情報連携を確立する」ということになります。その際に利用するのがWebAPIというわけです。

2016年6月22日水曜日

ORCAについてもっと知ろう!

私たちのゼミではORCAの機能をスマートフォンから利用できるアプリを開発しています。ではなぜこのようなアプリを開発する必要があるのでしょうか?ORCAは診療所で利用されているオープンソフトウェアの医事会計システムです。2016-05-16現在で稼働実績は15,656施設にも達しており、非常によく利用されている医事会計システムといってよいでしょう。ちなみに平成27年1月現在の診療所の数は100,801施設です(厚生労働省医療施設実態調査)。すなわちORCAのシェアは約16%ということになります。ちなみに一般診療所向け医事会計システムのシェアNo.1はパナソニックのメディコムで38.9%(2015年9月現在)ということです。
さて、そのORCAをスマホ等のモバイル端末で操作できるソフトウェアは殆どありません(ORCA mobiClipla)。医事会計システムをモバイル端末で操作できるメリットを考えてみましょう。
  • 在宅医療など出先からでも患者の情報を参照できる
  • どんな薬をいつ出したかがわかる
  • どんな検査をいつ行ったかがわかる
  • 外出先から診療予約を入れることができる
  • 外出先から診療行為を入力することができる
このようにいろいろ考えることができますが、実際の現場で利用されるかどうか、必要性があるかどうかはわかりません。今はそういうアプリがあったらいいなという思い込みで開発を進めていますが、いずれそれについても調べる必要があるでしょう。


2016年6月15日水曜日

ORCAに触ってみよう!

ORCAは日本医師会が開発した診療所向けの医事会計システムです。オープンソフトなので自由にダウンロードして利用できます。実際の業務で利用することを想定していますので膨大な機能があります。このゼミではスマホからORCAの機能を呼び出して利用するアプリの開発を目指しています。
では、ORCAがどのようなものかを把握するために操作マニュアルに従ってORCAで職員登録と患者登録を行ってみます。
ORCAを利用するには、ORCAクライアントを使います。ORCAクライアントはGoogleドライブのORCAフォルダへ保存してあります(ORCAクライアントはここからダウンロードできます。Java Web Start版をダウンロードしてください)。起動したら次の手順でサーバの設定を行います。
  1. [ホスト(ポート)]に172.16.108.250と8000を入力
  2. [ユーザ]にormaster
  3. [パスワード]にormaster
  4. [パスワードを保存]をチェック
  5. [接続]をクリック
 ORCAクライアントが起動したら、職員登録を行います。職員登録についてはマニュアルの「第5章マスタ登録」-[5.1システム管理マスタ]の「1010 職員情報」に従って行ってください。
職員登録ができたらいったんORCAクライアントを終了させて、再び起動して、登録したユーザでログインしてください。
次に患者登録を行います。患者登録は入力マニュアルの「第2章日時業務」-「2.2登録(患者登録について)」に従って行ってください。

2016年5月25日水曜日

今日は試験です!

さて、これまでMonacaのOnsenUI Master-Detaiをカスタマイズして、JSONデータを組み合わせてアプリを作ってきました。今回は前回の宿題(詳細画面にJSONデータを表示する)を確認した後、確認テストをします。テスト問題は以下の通りです。

 問題1 プログラムリスト1について以下の設問に答えなさい。
  1. patient.idの値を答えなさい。
  2. patient. genderと同じ意味を表すのは patient[A] である。Aには何が入るか?
  3. 患者オブジェクト patientに属性emailを加えたい。どうすればよいか。ただし、メールアドレスはA0001@kwmw.jpとする。

 問題2 プログラムリスト2について以下の設問に答えなさい。
  1. patientList[2].nameの値は何か
  2. 次の命令を実行したときの実行結果を書きなさい
    $.each(patientList, function(i, patient) {
      console.log(i + ',' + patient.id);
     }
    );
    
  3. これは上記と同じ実行結果を出力するプログラムである。AとBには何が入るか?
    for(var i = 0; i < A; i++) {
     console.log(i + ',' + patientList[B].id);
    }
    
問題3 プログラムリスト3について以下の設問に答えなさい。
  1. 下記の変数の値は何か
    visitData['A0001'][1].date
    visitData['A0002'][0].diseaseName
    visitData['A0003'][2].dept
    visitData['A0003'][3].diseaseName
  2. 次の命令を実行したときの実行結果を書きなさい
    var patientId = 'A0002';
    for(var i = 0; i < visitData[patientId].length; i++) {
     var visit = visitData[patientId][i];
     console.log(i + ',' + visit.date);
    }
    
  3. これは上記と同じ実行結果を出力するプログラムである。AとBには何が入るか?
    var patientId = 'A0002';
    A(visitData[B], function(i, visit) {
      console.log(i + ',' + visit.date);
     }
    );
    

なお、問題文中のプログラムリストは下記の通りです。

プログラムリスト1
var patient = {
 "id": "A0001",
 "name": "在本 璃奈",
 "gender": "female",
 "birthdate": "1996/4/1",
 "address": "岡山県倉敷市山田町1丁目-2-3"
};

プログラムリスト2
var patientList = [
 {
  "id": "A0001",
  "name": "在本 璃奈",
  "gender": "female",
  "birthdate": "1996/4/1",
  "address": "岡山県倉敷市山田町1丁目-2-3"
 },
 {
  "id": "A0002",
  "name": "清水 伸平",
  "gender": "male",
  "birthdate": "1995/5/10",
  "address": "岡山県岡山市苦米地3丁目-5-6"
 },
 {
  "id": "A0003",
  "name": "田中 昌昭",
  "gender": "male",
  "birthdate": "1958/7/6",
  "address": "岡山県瀬戸内市大岡5丁目-9-8"
 }
];

プログラムリスト3
var visitData = {
 "A0001": [
  {
   "date": "2016/5/20",
   "dept": "内科",
   "diseaseName": "気管支炎"
  },
  {
   "date": "2014/1/29",
   "dept": "外科",
   "diseaseName": "大腿骨骨折"
  },
  {
   "date": "2015/8/6",
   "dept": "耳鼻科",
   "diseaseName": "中耳炎"
  }
 ],
 "A0002": [
  {
   "date": "2016/3/19",
   "dept": "内科",
   "diseaseName": "インフルエンザ"
  },
  {
   "date": "2015/2/10",
   "dept": "外科",
   "diseaseName": "虫垂炎"
  }
 ],
 "A0003": [
  {
   "date": "2016/4/8",
   "dept": "眼科",
   "diseaseName": "白内障"
  },
  {
   "date": "2013/2/5",
   "dept": "内科",
   "diseaseName": "心筋梗塞"
  },
  {
   "date": "2011/11/4",
   "dept": "皮膚科",
   "diseaseName": "アトピー性皮膚炎"
  },
  {
   "date": "2014/12/15",
   "dept": "精神科",
   "diseaseName": "気分障害"
  }
 ]
};

応用 

上記の問題文中のpatientList(プログラムリスト2)とvisitData(プログラムリスト3)を使って次のようなアプリを作ってみよう。

 

左側の患者リストはプログラムリスト2のpatientListを使っている。表示項目はカルテ番号(id)、性別(gender)、氏名(name)、生年月日(birthdate)、住所(address)で、患者をタップするとその患者の受診一覧が表示される(右側)。この画面には患者の基本属性(カルテ番号、性別、氏名、生年月日、住所)に加えてこれまで受診した診療科(dept)と受診日(date)、そして診断名(diseaseName)が一覧となって表示される。この受診履歴は1患者につき受診した診療科とその受診日の数だけある。
プログラムを作成するうえでの注意点としては、これまではtitle, label, desc, photoという項目だったのに対して、今度はid, gender, name, birthdate, addressという項目になるので、それに合わせてclass名やスタイルシートの変更が必要になる。

2016年5月17日火曜日

詳細画面を完成させよう!

前回はリスト画面でタップして詳細画面を出したら写真が出なかったのでどうしてだろうということで時間切れになった。今回はその原因究明とさらに詳細画面の充実を図る!



まず、写真が出ていない件。これはタップしたリストから画像ファイル名が詳細画面へ引き継がれていないため。もともとサンプルプログラムはリストからタップした項目の情報(タイトル、ラベル、説明)をそのまま詳細画面へ表示しているだけ。それを行っているのがテキストP.126~127のコード。だから、それらの情報と同じようにして画像ファイル名も引き継げばいい。それをやっているのが次のコード。
(function(){
  'use strict';

  var currentItem = {};

    $('.item-title', this).text(currentItem.title);
    $('.item-desc', this).text(currentItem.desc);
    $('.item-label', this).text(currentItem.label);
    $('.item-thum-photo', this).attr('src', currentItem.photo);
    $('.add-note-action-item', this).click(function () {
        alert('dummy message');
    });
  });

  $(document).on('pageinit', '#list-page', function() {
    var html = '';
    $.each(listData, function(i, item) {
        html += '';
        html += '';
        html += '';
        html += '
'; html += ''; html += '
'; html += '
'; html += ''; html += '
'; html += '' + item.title + ''; html += '' + item.label + ''; html += '
'; html += '
' + item.desc + '
'; html += '
'; html += '
'; html += '
'; } ); $("#item-list").html(html); var content = $("#item-list").get(0); ons.compile(content); $('.item', this).on('click', function() { currentItem = { title : $('.item-title', this).text(), desc : $('.item-desc', this).text(), label : $('.item-label', this).text(), photo : $('.item-thum-photo', this).attr('src') }; app.navi.pushPage('detail.html'); }); }); })();
49行目でリスト画面で項目がタップされたとき画像ファイル名をcurrentItem.photoに保存し、9行目で詳細画面が表示されるときimgタグのsrcプロパティにcurrentItem.photoを設定しています。
次に、詳細画面の表示内容をタップされた項目ごとに変えます。そのために、まず、detail.htmlを次のように修正します。
<ons-template id="detail.html">
    <ons-page id="detail-page">
      <ons-toolbar>
        <div class="left"><ons-back-button>Back</ons-back-button></div>
        <div class="center">Details</div>
      </ons-toolbar>

      <ons-list modifier="inset" style="margin-top: 10px">
        <ons-list-item class="item">
          <ons-row>
            <ons-col width="60px"> 
              <div class="item-thum">
                <img src="" class="item-thum-photo" width="50px"></img>  
              </div>
            </ons-col>
            <ons-col>
              <header>
                <span class="item-title">Title</span>
                <span class="item-label">Foobar</span>
              </header>
              <p class="item-desc">desc</p>
            </ons-col>
          </ons-row>
        </ons-list-item>

        <ons-list-item modifier="chevron" id="add-note-action" class="add-note-action-item">
          <ons-icon icon="ion-chatboxes" fixed-width="true" style="color: #ccc"></ons-icon>
          Add a note
        </ons-list-item>

      </ons-list>

      <ons-list id="detail-item-list" style="margin-top: 10px">
      </ons-list>

    </ons-page>
</ons-template>

修正したのは33~34行目です。もともとはこのons-listタグ内にons-list-itemタグが3つあり、その中に前の画面でタップされた項目のタイトルと説明が表示されていました。今度は前にリスト画面でやったのと同じようにデータをHTMLから分離しjavascriptファイルとして独立させ、javascriptのプログラムでデータからons-list-itemタグを作ってやります。まず、detailData.jsというファイル名で次のようなデータを作成し、index.htmlからscriptタグで読み込ませます。
var detailData = {
 "在本 璃奈": [
  {
   "title": "我が家の子供用品の選び方",
   "desc": "冬は子供たちもココアや紅茶などを飲むので、キッズマグを探していましたがセリアでなかなかいい感じのマグを見つけました。"
  },
  {
   "title": "好みや成長具合によって選ぶ",
   "desc": "ずっと使うことを意識して、大人と同じマグやグラスという選択肢もありますが、モノに対する大人の思い入れを子供と共有できる自信もないので、子供のモノは、それなりに子供ウケしそうなもので…と割り切っています。"
  },
  {
   "title": "一番のお気に入りポイント",
   "desc": "お友達が遊びにきてくれたとき用のプラコップ(IKEA)はほんの時々しか出番はないので、他の場所に仕舞っています。"
  }
 ],
 "犬飼 佑汰": [
  {
   "title": "ソフトB 若鷹育てるファーム60億円基地",
   "desc": "ソフトバンクが2・3軍の施設を福岡県福岡市から同県筑後市の「HAWKSベースボールパーク筑後」に移転して、約2カ月が過ぎた。"
  },
  {
   "title": "完成間もないタマホームスタジアム筑後",
   "desc": "その正面入り口の横には「めざせ 世界一!」と書かれた竣工(しゅんこう)の碑がある。孫正義オーナー(58)が掲げるスローガンは、ファーム施設にまで行き届いていた。"
  }
 ],
 "臼井 彰生": [
  {
   "title": "車の購入価格とは",
   "desc": "実はインターネット上で掲載されている中古車情報は全体の約30%に過ぎません。"
  },
  {
   "title": "スマートカーライフプランナー",
   "desc": "燃費がよく小回りがきく車がいいです。また、子供が2人いるので、スペースが広い車で。できるだけ高年式でキズやヘコミがなく、内装もシンプルで状態の良いものだとありがたいです。"
  },
  {
   "title": "片道30分程度の通勤",
   "desc": "アメリカで人気のピックアップトラックを探しています。中古ではなかなか見つからないため苦労しています。左ハンドル・年式が新しい・色は黒を希望しています。"
  }
 ],
 "中村 綾斗": [
  {
   "title": "素晴らしい打楽器奏者リンゴ",
   "desc": "今回のリマスターは素晴らしいですね。アナログの良さを充分引き出して高音質に仕上げたエンジニアの方々へ感謝です。後期のビートルズのアルバムは何百回聴いただろうか?数えきれない回数であることに違いない・・・。"
  }
 ],
 "清水 伸平": [
  {
   "title": "Forever Man",
   "desc": "初回限定オブジェ付を買ったはずが普通のパッケージ。嫌な予感がして商品裏を見ると、薄い箱が。取り出すと、オブジェとは思えない貧相なおまけ。"
  },
  {
   "title": "仁義を通すってことはこういうことなのだろう",
   "desc": "「Old Sock」以来、僅か1年足らずで発売された昨年亡くなった敬愛するJ・J・ケイルに捧げる作品。まずゲスト陣が豪華、ウィリー・ネルソン、マーク・ノップラー、トムペティ、ジョン・メイヤーなどだ。"
  },
  {
   "title": "JJへの感謝とECへの感謝",
   "desc": "Pilgrim以降のECのアルバムはCFGは別物として惰性で聞き流す程度で真剣に聞き入ることもありませんでした。JJのことは昔からAfter MidnightやCocaineの作者であるくらいの認識でRoad to Escondidoもお気に入りではありませんでした。"
  },
  {
   "title": "到着した翌日からヘビロテ盤!",
   "desc": "クラプトン先生のこういう企画は最早や商業的成功なんて全く考えてないんでしょうね。JJ.ケイルに対する敬愛だけは充分に伝わってくる。JJ.ケイルの韜晦なところを聴き易く万人向けにアレンジした感じで、僕は気に入ったのでこの数日間ヘビロテで聴いております。でも音楽にとって「個性」って何なの?とかフト思っちゃいます。"
  }
 ],
 "田中 昌昭": [
  {
   "title": "天国への階段",
   "desc": "6曲目のbornだけで天国へいける。何度繰り返し聴いてもあきない。信じる者は救われるで、この一曲のおかげでアメリカがまた好きになった。"
  },
  {
   "title": "最高のバンドと最高のオーディエンス",
   "desc": "バンドももちろんなのですが、年齢層の高いオーディエンスの皆さんが素晴らしかった!皆さんパットの曲を古いものまで熟知しており、Letter From Homeあたりの曲ではイントロ一小節で「オオッ」と歓声があがり、バンドのメンバーもびっくり。"
  },
  {
   "title": "百花繚乱!ザッツ メセニーミュージック!",
   "desc": "個人的に、日本の歌謡界にも影響を与えたと考えているパットお得意の転調と上昇のアンサンブルが展開します。ジュリオがホーンも演ってるようで、オーケストリオンも自然ですし、ビッグバンドなのかと錯覚してしまいます。ベンのエレベはジャコを思い出させます。"
  },
  {
   "title": "心地よいジャズ・フュージョン最高!!",
   "desc": "このアルバムは、Metheny Groupとしては20年前に発表されたものですが、そのサウンドは今聞いても新鮮な感じがしていてブラジル・ティスト溢れる仕上がりになっています。"
  }
 ]
};
このデータがdata.jsと違うところは名前をキーとした連想配列になっているところです。たとえばリスト画面で「在本 璃奈」さんがタップされたら「在本 璃奈」をキーとして詳細表示データにアクセスします。それはdetailData['在本 璃奈']です。そして、detailData['在本 璃奈']がオブジェクト配列になっているので、要素を一つずつ取り出してはtitleとdescをons-list-itemタグへ設定していきます。それを書いたのが次のコードです。
  var html = '';
  $.each(detailData[currentItem.title], function(i, item) {
   html += '';
   html += '
'; html += '' + item.title + ''; html += '
'; html += '
' + item.desc + '
'; html += '
'; } ); $("#detail-item-list").html(html); var content = $("#detail-item-list").get(0); ons.compile(content);
これは、app.jsで詳細画面(#detail-page)が表示されるとき(pageinitイベント発生時)に実行します。

2016年5月11日水曜日

Onsen UI Master-Detail テンプレート

前回、Onsen UI Master-Detail テンプレートを少しかじって終わりました。そして今回までの宿題として、このアプリをメールアプリに見立てて、タイトル(title)や説明(desc)を日本語にし、できればサムネイルに顔写真を出してみるという課題を与えました。たとえば次のような感じです。


まず、日本語にするにはlist.htmlを修正します。class="item-title"のspanタグに差出人氏名を、class="item-label"のspanタグに経過時間を、そしてclass="item-desc"のpタグにメール本文を書きます。さらに、サムネイルを表示するには顔写真のファイルを用意し、それをimagesフォルダを作ってその中に入れ、class="item-thum"のdivタグ内にimgタグを挿入して写真を出します。このとき、写真の横サイズは50pxに設定しておきます。これだけです。HTMLファイルは次のようになります。
    <ons-page id="list-page">
      <ons-toolbar>
        <div class="center">Master Details</div>
      </ons-toolbar>

      <ons-list>
        <ons-list-item modifier="chevron" class="item">
          <ons-row>
            <ons-col width="60px"> 
              <div class="item-thum">
                <img src="images/arimoto.jpg" class="item-thum-photo" width="50px"></img>  
              </div>
            </ons-col>
            <ons-col>
              <header>
                <span class="item-title">在本 璃奈</span>
                <span class="item-label">3day ago</span>
              </header>
              <p class="item-desc">
                お仕事お疲れ様です。本社営業部の在本です。
                先日(4月30日)の出張の際には、さまざまなお心遣いをいただき、
                誠にありがとうございました。
                深くお礼申し上げます。
                </p>
            </ons-col>
          </ons-row>                          
        </ons-list-item>

        <ons-list-item modifier="chevron" class="item">
          <ons-row>
            <ons-col width="60px"> 
              <div class="item-thum">
                <img src="images/inukai.jpg" class="item-thum-photo" width="50px"></img>  
              </div>
            </ons-col>
            <ons-col>
              <header>
                <span class="item-title">犬飼 佑汰</span>
                <span class="item-label">4h</span>
              </header>
              <p class="item-desc">
                ご多忙中にもかかわらず、
                工場・店舗視察にご同行くださったことを、
                心より感謝しております。
                おかげさまで右往左往することなく、
                仕事に邁進することができました。
                今回いただいたアドバイスを生かし、
                しっかりと精進していきたいと存じます。
                今後ともよろしくご指導のほどお願い申し上げます。
              </p>
            </ons-col>
          </ons-row>                          
        </ons-list-item>

        <ons-list-item modifier="chevron" class="item">
          <ons-row>
            <ons-col width="60px"> 
              <div class="item-thum">
                <img src="images/usui.jpg" class="item-thum-photo" width="50px"></img>  
              </div>
            </ons-col>
            <ons-col>
              <header>
                <span class="item-title">臼井 彰生</span>
                <span class="item-label">6h</span>
              </header>
              <p class="item-desc">
                  お疲れ様です。臼井彰生です。
                    先日お借りしました資料、5月31日にお返しに伺います。
                    お陰様で、大変参考になるデータが多くあり、仕事の上で有意義に生かすことが
                    できました。ご好意に感謝しております。
                    まずは御礼かたがたご連絡まで。
              </p>
            </ons-col>
          </ons-row>                          
        </ons-list-item>

        <ons-list-item modifier="chevron" class="item">
          <ons-row>
            <ons-col width="60px"> 
              <div class="item-thum">
                <img src="images/nakamura.jpg" class="item-thum-photo" width="50px"></img>  
              </div>
            </ons-col>
            <ons-col>
              <header>
                <span class="item-title">中村 綾斗</span>
                <span class="item-label">2m</span>
              </header>
              <p class="item-desc">
                お疲れ様です。営業部の中村です。
                昨日は、ご馳走になりましてありがとうございました。
                また、課長からたくさんの話を伺うことができ、とても勉強になりました。
                正直なところ、今抱えている仕事が行き詰まっていまして、
                課長にご相談したいと思ってはいましたが、なかなか言い出せずにおりました。
              </p>
            </ons-col>
          </ons-row>                          
        </ons-list-item>

        <ons-list-item modifier="chevron" class="item">
          <ons-row>
            <ons-col width="60px"> 
              <div class="item-thum">
                <img src="images/shimizu.jpg" class="item-thum-photo" width="50px"></img>  
              </div>
            </ons-col>
            <ons-col>
              <header>
                <span class="item-title">清水 伸平</span>
                <span class="item-label">5day ago</span>
              </header>
              <p class="item-desc">
                いつもお世話になっております。
                清水伸平です。
                昨日、ご紹介いただいた弁護士の竹田先生にお会いし、お話を伺ってきました。
                先ほど、東京に戻ってきたところです。
              </p>
            </ons-col>
          </ons-row>                          
        </ons-list-item>

        <ons-list-item modifier="chevron" class="item">
          <ons-row>
            <ons-col width="60px"> 
              <div class="item-thum">
                <img src="images/tanaka.jpg" class="item-thum-photo" width="50px"></img>  
              </div>
            </ons-col>
            <ons-col>
              <header>
                <span class="item-title">田中 昌昭</span>
                <span class="item-label">1week ago</span>
              </header>
              <p class="item-desc">
                いつもお世話になっております。
                株式会社川崎システムズ ヘルプデスクです。
                平素は弊社のサービスをご利用いただきまして、誠にありがとうございます。
                6月1日より、レセコンORCAにスマホでアクセスできる
                アプリmyORCAの販売を開始いたしますのでご案内いたします。                  
              </p>
            </ons-col>
          </ons-row>                          
        </ons-list-item>

      </ons-list>
    </ons-page>
とても長いですね。もっと簡略化したいところです。また、このHTMLではメールの数は6件と固定ですが、実用的なものにしようとすればメールの数がいくらあっても表示できるようにしたいところです。そこで、javascriptを使って任意の件数のメールを表示できるようにしてみましょう。そのために、まずメールデータを独立させます。メールデータを次のようにjavascriptオブジェクト形式で表現します。
var listData = [
 {
  "title": "在本 璃奈",
  "label": "3day ago",
  "desc": "お仕事お疲れ様です。本社営業部の在本です。先日(4月30日)の出張の際には、さまざまなお心遣いをいただき、誠にありがとうございました。深くお礼申し上げます。",
  "photo": "images/arimoto.jpg"
 },
 {
  "title": "犬飼 佑汰",
  "label": "4h",
  "desc": "ご多忙中にもかかわらず、工場・店舗視察にご同行くださったことを、心より感謝しております。おかげさまで右往左往することなく、仕事に邁進することができました。今回いただいたアドバイスを生かし、しっかりと精進していきたいと存じます。今後ともよろしくご指導のほどお願い申し上げます。",
  "photo": "images/inukai.jpg"
 },
 {
  "title": "臼井 彰生",
  "label": "6h",
  "desc": "お疲れ様です。臼井彰生です。  先日お借りしました資料、5月31日にお返しに伺います。  お陰様で、大変参考になるデータが多くあり、仕事の上で有意義に生かすことが  できました。ご好意に感謝しております。  まずは御礼かたがたご連絡まで。",
  "photo": "images/usui.jpg"
 },
 {
  "title": "中村 綾斗",
  "label": "2m",
  "desc": "お疲れ様です。営業部の中村です。昨日は、ご馳走になりましてありがとうございました。また、課長からたくさんの話を伺うことができ、とても勉強になりました。正直なところ、今抱えている仕事が行き詰まっていまして、課長にご相談したいと思ってはいましたが、なかなか言い出せずにおりました。",
  "photo": "images/nakamura.jpg"
 },
 {
  "title": "清水 伸平",
  "label": "5day ago",
  "desc": "いつもお世話になっております。清水伸平です。昨日、ご紹介いただいた弁護士の竹田先生にお会いし、お話を伺ってきました。先ほど、東京に戻ってきたところです。",
  "photo": "images/shimizu.jpg"
 },
 {
  "title": "田中 昌昭",
  "label": "1week ago",
  "desc": "いつもお世話になっております。株式会社川崎システムズ ヘルプデスクです。平素は弊社のサービスをご利用いただきまして、誠にありがとうございます。6月1日より、レセコンORCAにスマホでアクセスできるアプリmyORCAの販売を開始いたしますのでご案内いたします。",
  "photo": "images/tanaka.jpg"
 }
];
javascriptオブジェクト形式と言うのは、(属性:属性値)のペアを必要なだけ{と}で囲んだものです。上の例では、title, label, desc, photoという4つの属性があり、それが6人分配列として定義されています(配列は[と]でカンマ区切りの要素を羅列します)。このようにすると、例えばdataList[0].titleの値は"在本 璃奈"となります。これを使ってlist.html内のons-listタグの中身を作成する処理が次のようになります。この処理はapp.jsのlist-pageが表示されるタイミングで実行されるようにしてあります。
(function(){
  'use strict';

  var currentItem = {};

  $(document).on('pageinit', '#detail-page', function() {
    $('.item-title', this).text(currentItem.title);
    $('.item-desc', this).text(currentItem.desc);
    $('.item-label', this).text(currentItem.label);
    $('.item-thum-photo', this).attr('src', currentItem.photo);
    $('.add-note-action-item', this).click(function () {
        alert('dummy message');
    });
  });

  $(document).on('pageinit', '#list-page', function() {
    var html = '';
    $.each(listData, function(i, item) {
        html += '';
        html += '';
        html += ' ';
        html += '
'; html += ''; html += '
'; html += '
'; html += ''; html += '
'; html += '' + item.title + ''; html += '' + item.label + ''; html += '
'; html += '

' + item.desc + '

'; html += '
'; html += '
'; html += '
'; } ); $("#item-list").html(html); var content = $("#item-list").get(0); ons.compile(content); $('.item', this).on('click', function() { currentItem = { title : $('.item-title', this).text(), desc : $('.item-desc', this).text(), label : $('.item-label', this).text(), photo : $('.item-thum-photo', this).attr('src') }; app.navi.pushPage('detail.html'); }); }); })();

2016年4月27日水曜日

いよいよOnsen-UIへ

今日までの宿題だったMonacaカウンターにタイマー仕掛けでストップウォッチ機能を付けました。それがこれです。


このアプリは起動と同時に1秒ごとにカウントを表示していきます。プログラムは以下のようになります。
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta http-equiv="Content-Security-Policy" content="default-src * data:; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
    <script src="components/loader.js"></script>
    <link rel="stylesheet" href="components/loader.css">
    <link rel="stylesheet" href="css/style.css">
    <script>
    var timer_id;
    var count = 0;
    function increment() {
        count++;
        update();
    }
    function reset() {
        if (count > 0 && confirm('カウンターをリセットしますか?')) {
            count = 0;
            update();
        }
    }
    function update() {
        var str = '0000' + count;
        str = str.substring(str.length - 4, str.length);
        var digits = $('.counter-digit');
        for (var i = 0; i < str.length; i++) {
            digits.get(i).src = 'img/no_0' + str[i] + '.png'
        }
    }
    $(function() {
        $('.count-button').on("touchend", increment);
        $('.reset-button').on("touchend", reset);
        $('.counter').on("touchend", function(){
            if(timer_id >= 0) {
                clearInterval(timer_id);
                timer_id = -1;
            } else {
                timer_id = setInterval( function () {
                    increment();
                } , 1000 );
            };
            
        });
        update();
        timer_id = setInterval( function () {
            increment();
        } , 1000 );
    })
    </script>
</head>
<body>
<div class="counter">
    <img src="img/no_00.png" width="55" class="counter-digit">
    <img src="img/no_00.png" width="55" class="counter-digit">
    <img src="img/no_00.png" width="55" class="counter-digit">
    <img src="img/no_00.png" width="55" class="counter-digit">
</div>
<div class="reset-button-wrapper">
    <button class="reset-button"><img src="img/btn_reset_normal.png" width="64"></button>
</div>
<button class="count-button"><img src="img/btn_count_normal.png" width="127"></button>
</body>
</html>
また、今回からOnsen-UI(5章)を始めました。今日は 5-6 Onse UI Master-Detailテンプレートまでやりました。次回までの課題として、表示内容を次のように変えてみることになりました。
  • 表示内容を日本語にする
  • 項目タイトルは名前にする
  • 項目説明はメール内容にする
  • できれば、左の四角の箱に写真を出す

2016年4月20日水曜日

「Monacaカウンター」アプリ

テキストP.70の 3-5 "jQueryで「Monacaカウンター」を作ろう"に従ってカウンターアプリを作成する。jQueryは既にインストールしているのでP.72の4からやる。③のimgフォルダへ入れる画像ファイルはWドライブの以下のフォルダにあるのでそれを利用する。
Wドライブ > 34_医療情報学科 > 田中ゼミ > Monaca > Monacaカウンター > img
なお、Wドライブへの接続方法については、右メニューのTipsに記載している内容に従って行う。

「今年は平成何年?」アプリ

Monacaを使ったスマホアプリの開発を勉強しています。前回、前々回とテキスト(公式ガイドブック)の第3章にある「今年は平成何年?」というアプリを作っています。そして、前回、次のような課題を出しました。
  • 西暦(A.D.2016)の下に月日と時分秒を表示させる
  • できれば、時分秒は刻々と変化させる
つまり次のような画面になるように改良する課題です。




















ソースコードは次のようになります。
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta http-equiv="Content-Security-Policy" content="default-src * data:; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
    <script src="components/loader.js"></script>
    <link rel="stylesheet" href="components/loader.css">
    <link rel="stylesheet" href="css/style.css">
    <script>
        var WEEK = ['日','月','火','水','木','金','土'];
        var timer_id;
        // ページの読み込みが終わったら実行する
        //document.addEventListener('DOMContentLoaded', function() {
        $(document).ready(function(){
            // 今の日付を得る
            var nowDate = new Date();
            // 西暦を得る
            var fullYear = nowDate.getFullYear();
            // 数値の西暦を文字列に変換して、そこから下2桁の文字列を得る
            var shortYear = String(fullYear).substr(2, 2);
            // 西暦の下2桁の文字列を数値に変換して、それに12を足す
            var heiseiYear = Number(shortYear) + 12;
            // 得られた数値をHTML に反映
            //document.getElementById('heisei-year').textContent = heiseiYear;
            $('#heisei-year').text(heiseiYear);
            //document.getElementById('year').textContent = fullYear;
            $('#year').text(fullYear);
            
            var month = nowDate.getMonth() + 1;
            var date = nowDate.getDate();
            var day = nowDate.getDay();
            $('#month').text(month);
            $('#date').text(date);
            $('#week').text(WEEK[day]);
            
            timer_id = setInterval( function () {
                showTime();
         } , 1000 );

        });
        
        function showTime() {
            var nowDate = new Date();
            var hours = nowDate.getHours();
            var minutes = nowDate.getMinutes();
            var seconds = nowDate.getSeconds();
            $('#hours').text(hours);
            $('#minutes').text(('0' + minutes).slice(-2));
            $('#seconds').text(('0' + seconds).slice(-2));
        }

        $(document).on('click', '#btn', function(eo){
            //alert(this.value);
            //alert($(this).val());
            if($(this).val() == 'STOP') {
                clearInterval(timer_id);
                $(this).val('START');
            } else {
                timer_id = setInterval( function () {
                    showTime();
                } , 1000 );
                $(this).val('STOP');
            };
        });
        
    </script>
</head>
<body>
 <div id="heisei">
  今年は平成<span id="heisei-year"></span>年です
 </div>
 <div id="ad">A.D. <span id="year"></span></div>
 <div id="md"><span id="month"></span>月<span id="date"></span>日(<span id="week"></span>)</div>
 <div id="time"><span id="hours"></span>:<span id="minutes"></span>:<span id="seconds"></span></div>
 <input id="btn" type="button" value="STOP">    
</body>
</html>

2016年4月19日火曜日

ゼミのテーマが決まりました!

早いもので新年度になってから3週間が過ぎました。その間、ブログの更新をサボっていましたが、ゼミの研究テーマが決まったので久しぶりに投稿します。ゼミのテーマは
在宅医療を支援するための電子カルテ連携スマホアプリの開発
です。

電子カルテとの連携だなんてなんだかカッコいいですけど、今のところ日本医師会が開発したORCAとの連携を考えています。
シナリオはこうです。
在宅医療をやっている医師がいて、診療所にはORCAを導入しているという設定です。ORCAにはWebAPIが組み込まれています。
http://www.orca.med.or.jp/receipt/tec/api/
このWebAPI、日レセAPIと言うらしいのですが、これを使うとスマホからORCAのデータを引っ張ってきたりデータを書き込んだりできるのです。そこで、Monacaでスマホアプリを作り、日レセAPIを使ってスマホをORCA端末にしようという構想です。
スマホでORCAサーバに接続できたらどんないいことがあるか?
  • 訪問患者先で患者の基本情報が見える
  • 処方内容を見たり入力もできる
  • その他、訪問先で行った処置など入力できる
ただし、ORCAはレセコンなのでどんな検査を行ったかは分かるけど、その検査結果は見ることができません。これについては次回への課題として、今回の研究ではORCAとの接続までをやろうという内容です。
また、昨年の先輩方が行った卒研(DICOMサーバの構築)と合わせれば、CTやMRIなどの医療画像をスマホで閲覧できるので、在宅医療を支えるICT環境が一層整ったと言えるんじゃないかな。