shiisuke’s blog

文系卒。社会人5年目くらい。ITやプログラミングの勉強で学んだことを書きます。

ウインドウに任意のテキストを表示する(Java Swing)

f:id:shiisuke1229:20190909235856p:plain

Ⅰ.きっかけ

Javaの基本的な勉強を終えて、これから様々なアプリケーションを作っていきたいと考えています。その際に、何かの処理を実行した結果をGUIで表現できると面白いだろうなと思い、ウインドウを表示する方法を調べました。

Ⅱ.Swing(スウィング)とは1

  • ウィンドウ、ボタン、メニューやアイコンなどを使ったユーザーインターフェイス(操作画面)を提供するアプリケーションのことを「GUIアプリケーション」と呼ぶ
  • そのGUIアプリケーションを作るためのJavaのクラスライブラリ(クラス、インターフェイス群)の一つが「Swing」である

Ⅲ.大まかな作業の流れ

(1)トップレベルコンテナを作成

(2)中間コンテナを配置

(3)中間コンテナにコントロールを配置

Ⅳ.詳しい手順

1.ウインドウクラスを作成

(1)import文の記述

  • 必要となるパッケージ内のクラスをまとめてimportする2
import java.awt.*;
import javax.swing.*;

(2)JFrameクラスの継承

  • javax.swingパッケージにある JFrameクラスを継承してウインドウのクラスを作る
public class クラス名 extends JFrame{
  //ここに(3)以下の内容を記述していく
}

(3)コンストラクタの作成

  • ウインドウの初期設定を行う
public クラス名(){
  //ウインドウのタイトルバーに表示するテキストを設定
  this.setTitle(String title);
  //ウインドウの大きさを設定
  this.setSize(int width,int height);

  //ウインドウのクローズボックス(×印)をクリックしたときの動作を設定
  //プログラムを終了する場合、引数に「変数名.EXIT_ON_CLOSE」を指定する
  this.setDefaultCloseOperation(int operation);

  //ウィンドウの表示場所を設定
  //ウインドウを画面の中央に配置する場合、引数に「null」を指定する
  this.setLocationRelativeTo(Component c);
}

2.ウインドウにテキストを配置

(1)ウインドウクラスのインスタンスの作成

クラス名 変数f = new クラス名();

(2)ウインドウの表示領域の取得

  • JFrameの表示領域であるContentPaneを取得する
Container 変数c = 変数f.getContentPane();

(3)パネルのインスタンスの生成

JPanel 変数p = new JPanel();

(4)ラベルのインスタンスの生成

  • javax.swingパッケージにあるJLabelクラスのインスタンスを生成する
  • 引数にはウインドウで表示するテキストを指定する
JLabel 変数l = new JLabel(String text);
  • フォントのサイズと色は以下で設定する
変数l.setFont(new Font("[フォント]", Font.PLAIN, [フォントサイズ]));
変数l.setForeground(Color.[色]);

(5)ラベルをパネルに配置

変数p.add(変数l);

(6)パネルをウインドウの表示領域に配置

  • 第1引数で、組み込むJLabelインスタンスを指定する
  • 第2引数で、テキストの配置を設定する3
変数c.add(変数p, BorderLayout.CENTER);

3.ウインドウを表示

  • 引数に「true」を指定する
変数f.setVisible(boolean b);

Ⅴ.実際のソースコード

//1 ウインドウクラスの作成
//(1) import文の記述
import javax.swing.*;
import java.awt.*;

//(2) JFrameクラスの継承
public class Sample extends JFrame{
    //(3)コンストラクタの作成
    //ウインドウの初期設定を行う
    public Sample(){
        //ウインドウのタイトルバーに表示するテキストを設定
        this.setTitle("タイトル");
        //ウインドウの大きさを設定
        this.setSize(300,200);
        //ウインドウのクローズボックスをクリックしたときの動作を設定        
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //ウインドウの表示場所を設定
        this.setLocationRelativeTo(null);                  
    }
    
    //2 ウインドウにテキストを配置
    public static void main(String[] args) {
        //(1) ウインドウクラスのインスタンスの作成
        Sample f = new Sample();
        
        //(2)ウインドウの表示領域の取得
        Container c = f.getContentPane();
        
        //(3)パネルのインスタンスの生成
        JPanel p = new JPanel();
        
        //(4)ラベルのインスタンスの生成
        //テキストのフォントと色の設定
        JLabel l = new JLabel("Good Job!");        
        l.setFont(new Font("Arial", Font.PLAIN, 30));
        l.setForeground(Color.BLUE);
        
        //(5)ラベルをパネルに配置
        p.add(l);
        
        //(6)パネルをウインドウの表示領域に配置
        c.add(p, BorderLayout.CENTER);
        
        //3 ウインドウを表示
        f.setVisible(true);        
    }    
}

Ⅵ.実行結果

  • 「Good Job!」と書かれたウインドウが画面の中央に表示される
f:id:shiisuke1229:20190909235856p:plain

Ⅶ.参考


  1. https://www.atmarkit.co.jp/ait/articles/0605/31/news125.html

  2. import文を記述する理由はこちらを参照

  3. 配置の調整方法はこちらを参照

プロトコルって何だろう?

Ⅰ.調べたきっかけ

  • ネットワークの仕組みについて勉強していると、「プロトコル」という言葉が何度も出てきました
  • この言葉は文系の私には馴染みがなく、理解するのが難しかったので、どんなものかを自分なりにまとめてみました

Ⅱ.(通信)プロトコルとは?1

  • コンピュータ同士がやり取りする際のルールのこと
  • たとえば、コンピュータAがコンピュータBにファイルを送る際には「FTP」というプロトコル(ルール)が用いられ、コンピュータAからコンピュータBにメールを送る際には「SMTP」というプロトコル(ルール)が用いられる

Ⅲ.なぜプロトコルが必要なのか

1.まずは身近な例で考えてみる

  • 私たちは、コンビニでパンを買うときに以下の手順を踏んでいる
    • 商品棚からパンを選び、レジへと運ぶ
    • 店員さんがパンのバーコードを読み取り、代金を読み上げる
    • お金をレジのカウンターに置く
    • 店員さんからおつりと商品を受け取る
  • もしも、この手順(ルール)が地域ごとに異なっていたらどうなるだろうか?
    • 大阪では、商品を受け取る時に店員さんへ「おおきに!!」と言わなければならない(言うまで商品をもらえない)
    • 沖縄では、お金の支払いは必ず手渡しで行わなければならない(カウンターに置くと無視される)
  • この場合、出張客や旅行客など、ローカルルールを知らない人はコンビニでパンをなかなか買えないだろう
  • このような不都合が生じないために、買い物をする際の手順は、地域(大阪、沖縄)やコンビニの種類(ローソン、ファミマ)などに関係なく決まっている

2.次に、ネットワークでファイルを転送する場合を考えてみる

  • コンピュータAがコンピュータBに(FTPを使って)ファイルを転送するとき、おおまかに以下の手順を踏んでいる
    • AとBが、命令するための通信が行える状態であることを互いに確認する
    • AがBにユーザIDとパスワードを送り、認証を行う
    • AがBに特定のファイルを送るよう命令するとともに、送り先を指定する
    • AとBが、ファイルを転送するための通信が行える状態であることを互いに確認する
    • BがAにファイルを転送する
  • もしも、この手順がコンピュータごとに異なっていたらどうなるだろうか?
    • BはAからファイルが転送されるのを待機しているが、AはBから「ファイルを受け取る準備ができたよ」という信号が来るのを待機している(野球やバレーボールでいう「お見合い」の状態)
    • AがBにファイルを転送したが、Aの認証ができていないためにBは受け取りを拒否した
  • この場合、いつまでたってもファイルを転送することができない
  • このような不都合が生じないために、「コンピュータ間でどのようにファイルを転送するか」というルール(=プロトコル)が決まっている

Ⅳ.誰がプロトコルを決めているのか2

  • プロトコルは以下のような組織によって定められている
    • IETF(The Internet Engineering Task Force、インターネット技術特別調査委員会):インターネットで利用される技術の標準を策定する組織。策定された標準仕様は最終的にはRFCなどとして発行される。
    • IEEE(Institute of Electrical and Electronics Engineers):通信・電子・情報工学とその関連分野を対象とする技術専門家組織。
    • ISO(International Organization for Standardization国際標準化機構):各国の国家標準化団体で構成される非政府組織。
  • 他に、デファクトスタンダード(特に決められているわけではないが、みんなが使っているので標準となっているもの)もある

Ⅴ.主なプロトコル3

名称 内容
IP(Internet Protocol) ネットワークを介してデータ伝送を行うためのルーティングや中継機能を提供するプロトコル
ARP(Address Resolution Protocol) IPアドレスからMACアドレスを求めるためのプロトコル
TCP(Transmission Control Protocol) データを送信する前に、送信側と受信側で論理的な通信路を確立するコネクション型の伝送を行うプロトコル
UDP(User Datagram Protocol) コネクションレス型の伝送を行うプロトコル
SMTP(Simple Mail Transfer Protocol) メールサーバ間のメール転送、クライアントからのメール送信を行うためのプロトコル
HTTP(HyperText Transfer Protocol) HTMLファイルを転送し、WWWを実現するためのプロトコル
DNS(Domein Name System) ドメイン名とIPアドレスを対応させる名前解決のサービスを提供するプログラム
POP3(Post Office Protocol Version3) メールサーバからメールを取り出すためのプロトコル
FTP(File Transfer Protocol) ファイルを転送するためのプロトコル
DHCP(Dynamic Host Configuration Protocol) TCP/IPのLANに接続されたコンピュータに、あらかじめ設定されたIPアドレスの範囲から未使用のIPアドレスを自動的に割り振るサービスを提供するためのプロトコル
IMAP4(Internet Message Access Protocol 4) メールをメールサーバに置いたまま管理するためのプロトコル
MIME(Multipurpose Internet Mail Extensions) メールで文字以外のデータ(画像や音楽)を添付して送るプログラム

Ⅵ.参考文献


  1. プロトコルの定義としては、「コンピューター同士が通信をする際の手順や規約などの約束事」(ASCII.jpデジタル用語辞典)、「コンピューター間で、データをやりとりするために定められた手順・規約。信号の電気的規則。送受信の手順など。通信規約。通信プロトコル」(goo国語辞書)などがある。

  2. Wikipediaを参照

  3. 技術評論社基本情報技術者のよくわかる教科書』p120-121を参照

天気予報を博多弁で通知するプログラムを作ってみた(Livedoor Weather Web Service + GAS + Chatwork)

f:id:shiisuke1229:20190623200306p:plain

Ⅰ.きっかけ

数年前に福岡から東京に来て、「博多弁」に触れる機会があまりなくて寂しく感じていました。そこで、標準語のテキストを博多弁に変換するプログラムを作ってみることにしました。

Ⅱ.博多弁とは1

  • もともとは福岡市博多部を中心とする日本語の方言のことを称していたが、現在では福岡市内全域や、福岡地方の筑紫地区・糸島地区・糟屋地区南部などで一般的に使われる言葉を総称している
  • 博多弁には以下のような文法がある
    • 順接:「〜だから」→「~やけん」
      • 例)「お前が遅れるから、連絡できなかったんだよ。」 →「お前が遅れるけん、連絡できんかったとよ。」
    • 逆説:「〜んだけど」→「~っちゃけど」
      • 例)「よく探してみたんだけど、書類は見つからなかったよ。」 →「よく探してみたっちゃけど、書類は見つからんやったよ。」
    • 疑問文:「~なの?」→「~と?」
      • 例)「知っている?」→「知っとー?」

Ⅲ.作るもの

  • 天気予報をChatworkに博多弁で通知する
    • 例)「雨が降っている所があります」→「雨が降っとう所があるよ」
  • 1日に1回、任意の時間(今回は 20:00~21:00)に通知する

Ⅳ.実現方法

  1. livedoorが提供するお天気WebサービスLivedoor Weather Web Service」のWeb APIで天気予報を取得する
  2. Google Apps Scriptで天気予報を博多弁に変換する
  3. ビジネスチャット「Chatwork」に通知する

Ⅴ.手順

1.標準語→博多弁の変換テーブルを用意する

(1)Googleスプレッドシートを新規で開く

(2)A列に標準語を、B列に博多弁を記入する f:id:shiisuke1229:20190623181102p:plain

2.Chatworkを用意する

(1)アカウントを取得する

(2)APIトークンを発行する2

(3)ルームIDを確認する3

(4)以下の手順で、Googleスプレッドシートのライブラリに「ChatWorkClient for Google Apps Script」を追加する

  1. 「リソース > ライブラリ」を選択
  2. プロジェクトキーに「M6TcEyniCs1xb3sdXFF_FhI-MNonZQ_sT」を入力して追加
  3. バージョンとして最新のものを選択
  4. 「保存」をクリック
f:id:shiisuke1229:20190623184632p:plain:w400

3.スクリプトを作成する

(1)標準語→博多弁変換テーブルを用意したシートのメニューから、「ツール > スクリプトエディタ」を選択する

(2)プロジェクトに名前を付ける(今回は「天気予報を博多弁で通知」とした)

(3)以下のコードを記述する4

function myFunction() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var last_row = sheet.getLastRow();
  
  //天気予報データを取得
  //"city="の隣には、地域別に定義されたID番号を記入(今回は東京とした)
  var response = UrlFetchApp.fetch("http://weather.livedoor.com/forecast/webservice/json/v1?city=400010");
  
  //取得したJSONデータを配列jsonに格納
  var json = JSON.parse(response.getContentText());  
  var str = json["description"]["text"];
  
  for (var i = 1; i < last_row; i++){      
    var x1 = sheet.getRange(i + 1, 1).getValue();
    var x2 = sheet.getRange(i + 1, 2).getValue();
    var str = str.replace(x1, x2);
  }
  sendMessage(str); 
}

function sendMessage(body){
  var client = ChatWorkClient.factory({token: "ChatworkのAPIトークンを記入する"}); 
  client.sendMessage({
    room_id: ChatworkのルームIDを記入する,
    body: body});
}

(4)メニューの「ファイル > 保存」または「Ctrl + S」(Macの場合は command + S)で保存する

4.スクリプトを実行する

(1)メニューの「実行 > 関数を実行」または「Ctrl + R」(Macの場合は command + R)を押す

(2)【初回の実行時のみ】「承認が必要です」というダイアログが表示されるので、「承認を許可」→自分のアカウントを選択→「詳細 > 天気予報を博多弁に変換する(安全ではないページ)に移動」→「許可」という手順を踏む

(3)Chatworkに、博多弁に変換済みの天気予報が通知されていることを確認する

<届いた通知> f:id:shiisuke1229:20190623192822p:plain

  • 赤は変換がうまくいったところ
  • 青は変換できなかったところ
    • こちらの解決策は見つけられていません

5.メールの送信タイミングを設定する

(1)メニューの「編集 > 現在のプロジェクトのトリガー」を選択し、画面右下にある「トリガーを追加」を選択する

(2)「イベントのソースを選択」で時間主導型を選択し、通知を受け取りたいタイミングを設定して「保存」をクリックする

f:id:shiisuke1229:20190623193854p:plain:w400

(3)指定された時間に通知されていることを確認する

f:id:shiisuke1229:20190623203900p:plain

Ⅵ.感想

今回のプログラムは、変換表にある言葉を博多弁へ逐一変換していくという簡単なものでしたが、「雨の降っとう所がある」「低気圧が北東へ進んどうよ」など、いい感じの天気予報ができました(^^)

特に、「注意しとってね」という表現は、標準語の「注意してください」よりもスッと頭に入ってくる感じがして良かったです。

他方、このプログラムでは変換したい言葉のすべてを変換できなかったので、今後修正したいと思います。また、品詞を自動的に判別してくれるツールがあるということなので、こちらも使ってみたいと思います。

Ⅶ.参考記事

百人一首Botを作ってみた(GAS + SendGrid)

f:id:shiisuke1229:20190615182136p:plain

Ⅰ.きっかけ

GAS初心者向けのとある記事1に、「Botの作成は『コストパーヨロコビ』が大きいので初心者にとってもオススメ」と書いてあるのを見て、「これは楽しそうだからやるしかない!」と思ってトライしました。

Ⅱ.Google Apps Script(GAS)とは2

Ⅱ.方針

  • Botのテーマは個人的に好きな百人一首とする
  • 百人一首の歌を1分おきに1首ずつ、自動で送信する
  • 参考とした記事では通知先としてChatworkが使われていたが、今回はSendGridを利用してメール通知を行う

Ⅲ.使用したもの

Ⅳ.手順

1.百人一首のデータを準備する

(1)スプレッドシートを新規で開く

(2)百人一首の一覧を作成する3

f:id:shiisuke1229:20190615152102p:plain

2.スクリプトを作成・保存する

(1)SendGridのAPIキーを作成する4

(2)開いているシートのメニューから「ツール > スクリプトエディタ」を選択し、プロジェクトに名前を付ける(今回は「百人一首Bot」とした)

f:id:shiisuke1229:20190615153637p:plain

(3)以下のコードを記述する

function myFunction() {  
  /*アクティブな(スクリプトがバインドしている)スプレッドシートを
  Spreadsheetオブジェクトとして取得する(今回は「百人一首の一覧」のシート)*/
  var sheet = SpreadsheetApp.getActiveSheet();
  //最終行の行数を取得する(今回は「見出し行+歌100首」で101行)
  var lastRow = sheet.getLastRow();
  
  for(var i = 2; i <= lastRow; i++){
    //もしシート(i, 3)の値が空白ならば
    if(!sheet.getRange(i, 3).getValue()){
     //(i, 1)を起点として1行×2列分のデータを取得する
     var values = sheet.getRange(i, 1, 1, 2).getValues();
     //メールの本文を記述する
     var body = ""
     body += values[0][0] + '\n'; //歌
     body += values[0][1]; //作者
     
     //メールの宛先、件名、送信元、差出人、本文を指定する
     sendMail("宛先メールアドレス(To)を入力する", "百人一首Bot", "送信元メールアドレス(From)を入力する", "しいすけ", body);
     //送信を終えた歌の横に「送信済」と入力する
     sheet.getRange(i, 3).setValue("送信済");
     break;
    }    
  }
  
  //最終行まで行ったら、すべての行の「送信済」を削除する
  if(i >= lastRow){
    sheet.getRange(2, 3, lastRow -1).clearContent();
  }
}

//SendGridでメールを送信する
SEND_GRID_ENDPOINT = "https://api.sendgrid.com/v3/mail/send";
SEND_GRID_API_KEY = "作成したAPIキーを貼り付ける";

function sendMail(to, subject, from, from_name, body_text){
  var body = {
    "personalizations": [
      {
        "to": [
          {
            "email": to
          }
        ],
        "bcc":[
          {
            "email": from
          }
        ],
        "subject": subject
      }
    ],
    "from": {
      "email": from,
      "name": from_name
    },
    "content": [
      {
        "type": "text",
        "value": body_text
      }
    ]
  }
  var payload = JSON.stringify(body);
  UrlFetchApp.fetch(SEND_GRID_ENDPOINT, {
    method: "POST",
    headers: { "Content-Type": "application/json",
             "Authorization": "Bearer " + SEND_GRID_API_KEY},
    payload: payload
  });
}    

(4)メニューの「ファイル > 保存」または「Ctrl + S」(Macの場合は command + S)で保存する

3.メールの送信タイミングを設定する

(1)メニューの「編集 > 現在のプロジェクトのトリガー」を選択し、画面右下の「トリガーを追加」を選択する

(2)「イベントのソースを選択」で「時間主導型」を、「時間ベースのトリガーのタイプを選択」で「分ベースのタイマー」を、「時間の間隔を選択(分)」で「1分おき」をそれぞれ選択し、「保存」をクリックする

f:id:shiisuke1229:20190615173101p:plain:w400

4.スクリプトを実行する

(1)メニューの「実行 > 関数を実行」または「Ctrl + R」(Macの場合は command + R)を押す

(2)「承認が必要です」というダイアログが表示されるので、「承認を許可」→自分のアカウントを選択→「詳細 > 百人一首Bot(安全ではないページ)に移動」→「許可」という手順を踏む(初回の実行時のみ)5

(3)1分おきにメールが届き、スプレッドシートでは、送信後の歌の横に「送信済」と記載されていることを確認する

<届いたメール>

f:id:shiisuke1229:20190615173827p:plain:w400

<実行後のスプレッドシートf:id:shiisuke1229:20190615173950p:plain

Ⅴ.感想

今回の作業はとても手軽で、半日ほどで完成しました。そしてイメージ通りのものができた時は嬉しくて、一人で思わずガッツポーズしていました。「コストパーヨロコビが大きい」というのは本当でした(^^)

完成後に、「メール送信部分はGmailOutlookを使う方が簡単だったのではないか?」と気づいたので、次はそちらを試したいと思います。

Ⅵ.参考記事

ゆうパックの料金計算プログラムを作ってみた(Java)

Ⅰ.きっかけ

Javaの勉強で、基本的な構文と継承までを大まかに理解できました。今回、その理解をより確かなものにしようと、自分で手と頭を動かしてプログラムを作ってみることにしました。

Ⅱ.作成したもの

f:id:shiisuke1229:20190331235438p:plain

  • 荷物は「東京」から送る
  • 料金は「お届け先」と「荷物のサイズ」で決まる
    • お届け先は「東京」または「北海道」
    • 荷物のサイズ(3辺の長さの合計)は 170cm以内

Ⅲ.実際に書いたプログラム

import java.io.*;
public class Postage {
    public static void main(String[] args)throws IOException {
        int size, place;
        int rate[][] = {{0,800,1280},{60,1010,1500},{80,1260,1730},{100,1500,1980},{120,1750,2220},{140,1970,2440},{160,2300,2800},{170,0,0}};
               
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        System.out.println("----宛先の地域を選択してください。----\n1:東京\n2:北海道");
        place = Integer.parseInt(br.readLine());
        
        while(place < 0 || place > 2){
            System.out.println("1 または 2を選択してください。");
            place = Integer.parseInt(br.readLine());
        }
                
        System.out.println("\n----荷物のサイズ(3辺の長さの合計,1~170)を入力してください。----");
        size = Integer.parseInt(br.readLine());
        
        while(size <= 0 || size > 170){
            System.out.println("1~170 の間で入力してください。");
            size = Integer.parseInt(br.readLine());
        }
        
        int charge = 0;        
        
        for(int i = 0; i < 7; i++){
            
            if(rate[i][0] < size && size <= rate[i+1][0]){
                charge = rate[i][place]; //rate[i][place];  
                break;
            }else{
            }
        }        
        System.out.println("\n料金は " + charge + "円 です。");        
    }    
}

Ⅳ.実行結果

1.宛先を「東京」、サイズを「140」とした場合

----宛先の地域を選択してください。----
1:東京
2:北海道
1

----荷物のサイズを入力してください。----
140

料金は 1750円 です。

下記の料金表と整合するので◎。

f:id:shiisuke1229:20190401002600p:plain:w400

2.宛先を「北海道」、サイズを「170」とした場合

----宛先の地域を選択してください。----
1:東京
2:北海道
2

----荷物のサイズを入力してください。----
170

料金は 2800円 です。

下記の料金表と整合するので◎。

f:id:shiisuke1229:20190401003633p:plain:w400

3.サイズを「200」とした場合

----宛先の地域を選択してください。----
1:東京
2:北海道
2

----荷物のサイズを入力してください。----
200
1~170 の間で入力してください。
200
1~170 の間で入力してください。
200
1~170 の間で入力してください。
200
1~170 の間で入力してください。

「荷物のサイズ(3辺の長さの合計)は 170cm以内」という条件に反するので、先に進めなくて◎。

4.宛先選択で「1」「2」以外を選択した場合

---宛先の地域を選択してください。----
1:東京
2:北海道
3
1 または 2を選択してください。
3
1 または 2を選択してください。
3
1 または 2を選択してください。
3
1 または 2を選択してください。

「お届け先は『東京』または『北海道』」という条件に反するので、先に進めなくて◎。

Ⅴ.迷った点・つまづいた点

1.サイズ「161~170」の扱い

  • 料金は、2次元配列で以下のような表を作って計算した(1列目が「サイズの範囲」を表し、2,3列目が「地域」を表す)
  • その際、「サイズの範囲」は 指定されたサイズが 下の表のどの行の間に入るか(たとえば、サイズ「50」は 配列[0][0]と配列[1][0]の間に入る)という形で特定している都合上、サイズ「161~170」を扱うためには「170」の行を作る必要があったため、料金表に「170, 0 ,0」という行を作った

f:id:shiisuke1229:20190401011119p:plain:w200

2.入力値の検証

  • while文を使って、正しい値が入力されるまで入力を繰り返させるようにした(参考

3.変数「charge」の初期化

  • for文の中で使用している「charge」は、先に初期化しておかないとコンパイルエラーとなったので(参考) 、for文の前に「 int charge = 0; 」を追加した

4.for文の中にif文を入れる

  • 「break」の使いどころと、「if else」の中身をどうすれば良いのかがイマイチわからなかった(要勉強)

5.関係演算子 ≧ の書き方

  • 正)<=  
  • 誤)=<

Ⅴ.感想

今回初めて、自分でテーマを設定して、どうしたらうまくいくかを考えながらプログラムを作りましたが、教科書のコードを書き写すだけの作業よりもずっと面白かったです。また、二次元配列など、理解があやふやだった点が分かってとても有意義でした。

Ⅵ.参考

非エンジニアが JAWS DAYSで AWSを学んだ話

f:id:shiisuke1229:20190302174402j:plain:w350

AWSを触っている方は私の周りにも多く、「身近なシステムでも使われているよ~」という話もよく聞きます。しかし、開発経験のない私は、AWSがどんなものなのかのイメージをつかめずにいました。

そこで、AWSを日頃から使っている方々のお話を聞いて AWSへの理解を深められればと思い、2/23(土)に開催された「JAWS DAYS」へ参加しました。

以下では、イベントの様子を写真とともにレポートします。

1日で 1,900名の来場者!@五反田

f:id:shiisuke1229:20190302175056j:plain

当日朝9時、会場であるTOC五反田メッセに到着。10時から11個のトラックでセッションやハンズオンが始まるということで、開場前から多くの参加者が集まっていました。

ブースエリアもすごい盛り上がり!

ブースエリアには企業ブースや小規模セッション、同人誌販売のコーナーがあり、ワイワイとして賑やかな雰囲気でした。

企業ブースでは、音声認識ロボットの展示や付箋を使ったアンケートなどもあり、それらを見て回るだけでも楽しめました♪

f:id:shiisuke1229:20190301223906j:plain
▲ブースエリアは人で常にいっぱいでした。
f:id:shiisuke1229:20190301224645j:plain
▲同人誌販売ブース。「分かりやすい」と話題の技術書『AWSをはじめよう』の頒布も。

ブースエリアの中央では、サメの焼き印が入ったどら焼きの提供がありました。これは本イベントのテーマが「満漢全席」で、「胃も脳も最高な1日を」という想いから用意されたものだそうです1。その気持ちだけでもおなか一杯になる思いがしました^^

f:id:shiisuke1229:20190302184506j:plain
▲机一面にドッサリと用意されたどら焼き。生地がふわふわで美味しかったです。

AWS提案ワークショップ】RFPを元にした営業提案づくり

本ワークショップは、顧客から与えられたRFP(提案依頼書)を元に 4名1チームでディスカッションを行い、最後に提案発表を行うというものです。テーマは「サーバの移行」と「ファイルサーバの管理」でした。

AWSへの知見が深い方々の議論を実際に見学できるということで、個人的に楽しみにしていたコンテンツの一つです。

f:id:shiisuke1229:20190302195005j:plain
▲30分という短い制限時間で、真剣な議論が交わされていました。

発表では、新しいツールを積極的に導入するチームや、AWSの最新機能を採用するチーム、顧客のかゆい所まで手が届く提案をするチームなど、システム構成の工夫が幅広く、AWSを用いた提案の奥深さを感じました。

他方、「サーバー管理などのインフラ周りの作業は省力化したい」という思いは各チーム(会場全体)が共通して持たれていて、その点を実現できることがAWSの強みなのだと感じました。

f:id:shiisuke1229:20190302195030j:plain
▲発表に手書きのダッシュボードを使用するチームも。手作り感が何とも良かったです。

懇親会

まずは全員での乾杯で始まりました。

f:id:shiisuke1229:20190302201840j:plain
▲お酒を入れてフランクに語り合う、そんな素敵な雰囲気でした。

続いて、JAWS-UGの活動に大きく貢献された方を表彰する「AWS Samurai 2018」の発表がありました。表彰された方のコメントからは、「JAWS-UGの活動を盛り上げたい!」という思いが言葉の端々から伝わってきました。

f:id:shiisuke1229:20190302225237j:plain

最後はテーマ自由のLT大会。Amazon Machine Learningでの試行錯誤の共有や、Alexaスキル開発のチャレンジの紹介、AIとARを使った完成度の高いアプリケーションのデモなどがあり、1人5分という発表時間はあっという間に感じました。

また、1つ1つのテーマに情熱をかけて取り組んでいる方のお話を聞くことでき、各テーマの面白さや深さを知ることができました。

f:id:shiisuke1229:20190302235647j:plain
▲2か月ほどで100個のAlexaスキル開発に取り組んでいる方。アウトプットの速さにはただただ頭が下がります。

1日を通しての感想

JAWS DAYSに参加して、自分だけでは絶対に出会えないようなテーマに多く出会うことができ、広く浅くではありますが知見を広げることができました。

また、実際にAWSを使っている方の様々なお話を聞いて、AWSに対する心理的なハードルが下がったので、私もまずは簡単なところからAWSを触っていきたいと思いました。

家計簿アプリ「レシーピ!」でレシート500枚を読み取ってみた

f:id:shiisuke1229:20190203133548p:plain:w400

Ⅰ.きっかけ

半年前に収支管理をしようと思い立ってレシート集めを始めたのですが、その後気づけばレシートの山ができていました。

それらを効率よく整理したいと思い、レシート読み取りアプリを使ってみました。

f:id:shiisuke1229:20190203173626j:plain
取りためたレシートの山。A4トレーが一杯になりました。

Ⅱ.「レシーピ!」とは1

  • 「大日本印刷株式会社」が提供する家計簿アプリです
  • 「レシーピ!」には以下のような特長があります
    • レシートをスマホで撮ると、日付や店舗名、購入品目、金額が自動的に記録される
    • 購入した食材をもとに、8000以上のバラエティ豊かなレシピをランダムに提案してくれる
    • 対象商品を買うと、dポイントや楽天Edyなどのポイントがたまる
    • かわいいキャラクターが応援してくれる
    • すべての機能を無料で利用できる(2019年2月現在)
f:id:shiisuke1229:20190203180552p:plain:w300
アプリのホーム画面。キャラクターが何ともかわいいです。

Ⅲ.数あるレシート読み取りアプリの中で、なぜ「レシーピ!」を選んだのか?

  • アプリ選定では、以下の3つの点を重視しました
    • レシートの読み取り精度が高い
    • 購入データを「費目別(飲食、日用品など)」や「店舗別(コンビニ、スーパーなど)」に分けて集計できる(=どの項目を節約すべきかが分かる)
    • 無料で使える
  • 「レシーピ!」であれば上記3つを満たせそうだと分かり、こちらを選択しました

Ⅳ.実施手順

1.環境

  • Android 8.0.0
  • 「レシーピ!」バージョン4.2.6

2.レシートの読み取り

(1)品目の設定

  • まず、ホーム画面の「設定 > カテゴリ(費目)の設定・編集 > 支出費目の編集」を開きます
  • 次に、自分が使いやすいように費目を設定します
「食材費」や「交際費」などの費目がデフォルトで設定されています。今回は新たに、「飲食」「日用品」「カフェ」という費目を設定しました。

(2)レシートの撮影

  • ホーム画面の「レシート撮影」を選択し、10cmほどの高さからレシートを撮影します
  • その際、「日付」「店舗の電話番号」「合計金額」が入るように注意します
f:id:shiisuke1229:20190203175910p:plain:w300

(3)読み取り内容の確認 と 費目の選択

  • 「日付」や「店舗」が正しいかを確認し、入力されていない場合や、入力に誤りがある場合は手動で変更します
  • 「費目」(飲食、日用品など)については、各商品をタップして設定するか、「店舗」をタップして一括で設定します
f:id:shiisuke1229:20190203181858p:plain:w300
「店舗」から費目を一括設定すると、同じ店舗のレシートを次に撮影した時に、費目が自動的に設定されて便利です。

3.集計

  • ホーム画面の「グラフ集計」を選択すると、以下のような項目が確認できます
    • 収支
    • 費目ごとの内訳
    • お店ごとの買い物金額
    • お店ごとの買い物回数
    • 商品やお店での詳細
    • 貯金
f:id:shiisuke1229:20190203212021p:plain:w300
【費目別の支出内訳(2018年)】

Ⅴ.実施結果

1.作業時間

  • 500枚ほどのレシートを読み取るのに 6.5時間かかりました(1時間あたり70~80枚。 ドラマを観ながらの作業だったので、能率は少し低めです)
  • 半年分のレシートを6時間ほどで読み取れたことから、1か月分であれば1時間で終わる計算になり、読み取りの労力はそこまでかからないことが分かりました

2.レシートの読み取り精度

  • 全体として、精度は非常に高かったです(感覚的には、90%くらいは読み取れていたように思います)
  • 特に、「店舗名(電話番号から特定)」「日付」「合計金額」といった数字の読み取り精度は高かったです
  • 一方で、以下のものは読み取りが苦手なようでした
    • 町のパン屋さんや空港の売店などの店舗名(これは、アプリが「店舗名」の特定で使用している電話番号データベースに、当該店舗が載っていないためではないかと推測します)
    • 「2018年」という日付(「2016年」とよく間違えていました)
    • スーパーいなげやの品目(商品名)(フォントの問題でしょうか)

f:id:shiisuke1229:20190203195857p:plain:w300
アプリで読み取りにくい「いなげや」のレシート。人間でも読みにくいですね(^^;

3.集計結果の分析

  • 下図1~5から、次のようなことが分かりました
    • 2019年1月の支出が多い
    • 2018年12月は交際費が多い(忘年会?)
    • 飲食費は毎月3万円ほど
    • コンビニでは毎月1万円ほど使っている
    • セブンイレブンでの支出が 9~11月の間で増えている(忙しくて弁当に頼った?)
f:id:shiisuke1229:20190203212003p:plain:w300
【図1:収支の推移】
f:id:shiisuke1229:20190203212007p:plain:w300
【図2:費目別の支出内訳】
f:id:shiisuke1229:20190203212033p:plain:w300
【図3:飲食費の推移】
f:id:shiisuke1229:20190203212048p:plain:w300
【図4:店舗別の支出内訳】
f:id:shiisuke1229:20190203212059p:plain:w300
【図5:セブンイレブンでの支出の推移】

Ⅵ.感想

レシート読み取りアプリの利用は初めてでしたが、文字の読み取り精度が思った以上に高くて驚きました。

データ集計では、飲食・日用品などの費目別や、コンビニ・スーパーなどの店舗別での集計が実施できて大満足でした。欲をいえば、費目内訳の月ごとの推移が見られると嬉しいなと思いました。

「レシーピ!」には、今回試した機能の他にも「レシピの提案機能」があるので、こちらは友達とご飯を食べる時にでも試してみようと思います。


  1. 「レシーピ!」の公式サイト https://receipi.jp/