OmniAICreator/Qiita-1.07M huggingface dataset:
C#からPythonスクリプトを呼び出す

#はじめに
唐突に画像と動画を加工してみたくなり、VisualStudio2017でPython3/OpenCVを使ってみました。

- [VisualStudio2017で、Python3/OpenCVを使って画像を表示する](https://qiita.com/kaysquare1231/items/10234dbb3a5663d095c4)
- [VisualStudio2017で、Python3/OpenCVを使って動画を加工する](https://qiita.com/kaysquare1231/items/7ec224d44cb34827e18f)

普段はC#を使っているので、使い慣れたC#からPythonスクリプトを呼び出せないか試してみました。


#参考資料
下記のサイトを参考に実装しています。
[Inter-process communication between C# and Python](https://code.msdn.microsoft.com/windowsdesktop/C-and-Python-interprocess-171378ee)


#実装方法
|言語|実装する処理|
|:--|:--|
|Python|「第1引数の値」 + 「第2引数の値」　を出力する|
|C#|「第1引数の値」と「第2引数の値」を指定して、Pythonスクリプトを呼び出し、結果を出力する|

###1. Python側を実装
```AdditionSample.py
import sys

if len(sys.argv) == 3:
    firstArgument = int(sys.argv[1]) 
    secondArgument = int(sys.argv[2])
    print(firstArgument + secondArgument)
else:
    print('ArgumentException...')
```

###2. C#側を実装

```Sample.cs
class Program
{
    static void Main(string[] args)
    {
        //VisualStudioが利用しているインタープリターのパス
        var pythonInterpreterPath = @"C:\sample\path\Anaconda3\python.exe";

        //「1. Python側を実装」にて保存したスクリプトのパス
        var pythonScriptPath = @"C:\sample\path\AdditionSample.py";

        var arguments = new List<string>
        {
            pythonScriptPath ,
            "10",   //第1引数
            "20"    //第2引数
        };

        var process = new Process()
        {
            StartInfo = new ProcessStartInfo(pythonInterpreterPath)
            {
                UseShellExecute = false,
                RedirectStandardOutput = true,
                Arguments = string.Join(" ", arguments),
            },
        };

        process.Start();

        //python側でprintした内容を取得
        var sr = process.StandardOutput;
        var result = sr.ReadLine(); 

        process.WaitForExit();
        process.Close();

        Console.WriteLine("Result is ... " + result);
    }
}
```

###実行結果
>Result is ... 30

#感想
この方法を使えば、C#とPythonを組み合わせた実装ができそうです。

しかし、この方法だとPython側でprintした内容を受け取ることしかできないようです。
また、指定したPythonスクリプトを実行するだけなので、自由にPython側の処理を呼べるというわけでもありません。

処理内容にもよると思いますが、Python側をWebAPI化して、処理結果をJSON形式で結果を返すのが一番使いやすそうな気もします。
LINE Beaconを使ってわかったことをまとめてみた（他ビーコンと違う点など）

## はじめに
LINE Beaconを利用したサービスを開発したときにわかったことをまとめます。

### 対象者
- LINE Beaconを用いたサービスの設計をしたい人
- LINE BeaconとiBeaconとの違いが知りたい人
- ビーコンIoTで何かをハックしたい人

### LINE Beaconとは
BLEビーコンの一種。
LINE messaging APIを用いたLINE Botとの連携が簡単に行えます。

使用方法は、他記事や[公式ドキュメント](https://developers.line.biz/ja/docs/messaging-api/using-beacons/)を参照してください。

## 発生するイベント
現在（2019/2/25）使用できるイベントは以下の3つのみ。

*enter*
ユーザがLINE Beaconの受信範囲に入ったときに発生する。
また、受信範囲内でLINEを再起動することでも発生する。

*leave*
ユーザがLINE Beaconの受信範囲外に出たときに発生する。
（**公式より廃止予定というアナウンスあり**）

*banner*
ユーザがバナーをタップしたときに発生する。
（使用するには、LINE Partnersの申請が必要）

今後、サービスを考えるのにあたって廃止予定のleaveイベントは使わないのが無難だと思います。
そうなると、Messaging APIのみではiBeaconで検出可能な**Beaconとの距離の検出**や**Beaconの範囲内にユーザがいること**を検出できません。
つまり、LINE Beaconは検出範囲外から検出範囲内に入ったユーザを検出できるが、**範囲内にとどまっているユーザを検出することができません**。

![beacon_diff1.png](https://qiita-image-store.s3.amazonaws.com/0/286066/c3264cf1-d8cc-7542-e28a-de90b915c3f8.png)




上の図はイメージです。

**参考**
[Messaging APIリファレンス](https://developers.line.biz/ja/reference/messaging-api/#beacon-event)
[iBeacon - Apple Developer](https://developer.apple.com/ibeacon/)

## LINE BOTとLINE Beaconの紐づけ
LINE Beacon一つで複数のLINE BOTのアカウント登録（紐づけ）を行うことができません。その逆は可能です。
よって、iBeaconのように1つのビーコンを複数のアプリ(BOT)で使用することはできません。

![beacon_connection1.png](https://qiita-image-store.s3.amazonaws.com/0/286066/3a9e538d-42c7-cca4-37c2-a9010f5b4fbb.png)



## 受信電波強度の変更
LINE Beaconでは**受信電波強度の変更ができません**。
iBeaconは受信電波強度を変更できるものが多くあるそうです。
特定の小さな範囲に入ったときに通知が欲しいなどのサービスを作成するときは設置場所をよく考える必要があります。

## ユーザのLINEの設定
まず第一にLINEのタスクが切られている場合はビーコンを検出できません。
バックグラウンドで動作していれば、別アプリを起動していても問題ありません。

LINE Beaconを検出できるときの条件

1. LINEが起動中（バックグラウンドでも可）
2. LINE Beaconの設定がON（※1）
3. スマホの位置情報提供が「このAppの使用中のみ許可」、または「常に許可」（※2,3）

※1 : LINEの「設定」→「プライバシーの管理」→「情報の提供」→「LINE Beacon」をONにする
※2 : iOS 12.1.4の場合 - スマホの「設定」→「プライバシー」→「位置情報サービス」→「LINE」
※3 : バックグラウンドでPush通知を行いたい場合は「常に許可」が必要

(19/3/2 追記)
上の検証はiOSで行いました。

## さいごに
この記事を読んだときに「他ビーコンよりできること少なくない？」などと思う方もいるかも知れません。
しかし、LINE Beaconを使用する最大のメリットは日本人のユーザ数が非常に多いLINEを用いたサービス「LINE BOT」を簡単に使えることだと筆者は考えています。
LINE BOTを使用することで、ユーザがアプリをダウンロードする工程やアプリのUIを学ぶ必要がありません。


これらの特徴を活かしたサービスを開発しましょう！！！
redis-pyを使ったzaddコマンドの引数について (v3.2.0) 

# はじめに
インメモリKVS型DBのRedisをPythonから呼び出す方法として、redis-pyモジュールを使うやり方があります。
このredis-pyにZADDと呼ばれるデータを格納するコマンドがあります。
このZADDの引数に変更があり、古い記事の呼び出し方ではエラーを吐くので、新しい呼び出し方を共有します。

# Version
Redis本体は5.0.3, redis-pyはv3.2.0を想定

```{}
 Redis 5.0.3 (00000000/0) 64 bit
```


```{}
tikeda:Redis tikeda$ pip show redis
Name: redis
Version: 3.2.0
Summary: Python client for Redis key-value store
Home-page: https://github.com/andymccurdy/redis-py
Author: Andy McCurdy
Author-email: sedrik@gmail.com
License: MIT
Location: /usr/local/var/pyenv/versions/3.7.0/lib/python3.7/site-packages
Requires: 
Required-by: 
```

# ZADDとは
SortedSet型でデータを格納するコマンドです。
SortedSet型は、その名の通り順序付けされた集合の型です。
各データがscoreと呼ばれる値を持っており、それを基にソートされます。

参考: http://redis.shibu.jp/commandreference/sortedsets.html

# 呼び出し方
これまではzadd(key, score, value)やzadd(key, value, score)といった形でコマンドを叩いていましたが、現バージョンからは以下のようになりました。

```{Python}
import redis

r = redis.Redis(host='localhost', port=6379, db=0)

dict = {}
dict['value'] = 10
r.zadd('aaa', dict)

print(r.zrangebyscore('aaa', '-inf', '+inf'))
```

ここではZRANGEBYSCOREコマンドを用いて確認しています。

辞書型になったので、まとめてvalueを与えることも可能です。

```{Python}
dict = {}
dict['value'] = 10
dict['has'] = 11
dict['to'] = 12
dict['be'] = 13
dict['set'] = 14
dict['here'] = 15
r.zadd('bbb', dict)
```

# 終わりに
redis-pyですが、いつからかZADDコマンドの引数順序(latitudeとlongitudeの順序)が変わっていたりと ~~闇深な~~ カオスな印象をうけますね
How to deal with NSNull

```json
"somevalue": "<null>"
```
Sometimes when we receive the above JSON from server side, when we parse the JSON we will get NSNull. If we call a method on this object, the app will crash and generate the following error for example.

```console
-[NSNull length]: unrecognized selector sent to instance 0x388a4a70
```

in order to prevent this, we have several solutions

- there is a property called `removesKeysWithNullValues` in AFNetworking. If we set it to YES, all the NSNull will become nil and we can use it without crash.

```objective_c
((AFJSONResponseSerializer *)manager.responseSerializer).removesKeysWithNullValues = YES;
```

- use the method `AFJSONObjectByRemovingKeysWithNullValues ` originated from [here](https://github.com/AFNetworking/AFNetworking/blob/ee950948f2ef85240f8fc0a6b84f793912af9c24/AFNetworking/AFURLResponseSerialization.m)

```objective_c
id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingOptions readingOptions) {
    if ([JSONObject isKindOfClass:[NSArray class]]) {
        NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:[(NSArray *)JSONObject count]];
        for (id value in (NSArray *)JSONObject) {
            if (![value isEqual:[NSNull null]]) {
                [mutableArray addObject:AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions)];
            }
        }

        return (readingOptions & NSJSONReadingMutableContainers) ? mutableArray : [NSArray arrayWithArray:mutableArray];
    } else if ([JSONObject isKindOfClass:[NSDictionary class]]) {
        NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:JSONObject];
        for (id <NSCopying> key in [(NSDictionary *)JSONObject allKeys]) {
            id value = (NSDictionary *)JSONObject[key];
            if (!value || [value isEqual:[NSNull null]]) {
                [mutableDictionary removeObjectForKey:key];
            } else if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]]) {
                mutableDictionary[key] = AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions);
            }
        }

        return (readingOptions & NSJSONReadingMutableContainers) ? mutableDictionary : [NSDictionary dictionaryWithDictionary:mutableDictionary];
    }

    return JSONObject;
}
```
sqlalchemy で euc-jp を取り扱う

```py:error
sqlalchemy.exc.ProgrammingError: (ProgrammingError) You must not use 8-bit bytestrings unless you use a text_factory that can interpret 8-bit bytestrings (like text_factory = str). It is highly recommended that you instead just switch your application to Unicode strings. u'INSERT INTO category (parent_id, category_name) VALUES (?, ?)' (999, '\xa4\xa2')
```

```py:対策
from sqlalchemy.interfaces import PoolListener

class SetTextFactory(PoolListener):
    def connect(self, dbapi_con, con_record):
        dbapi_con.text_factory = lambda x: unicode(unescape(x), "euc-jp", "ignore")

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker

def create_session():
    engine = create_engine('sqlite:///./test.db', echo=False,  listeners=[SetTextFactory()])
    Session = scoped_session(sessionmaker(autocommit=False,
                                          autoflush=False,
                                          bind=engine))
```

# 参考
sanko-:http://saygox.blogspot.jp/2013/08/sqlalchemy.html
マウスを使わずFinderからSublime Textでディレクトリを開く

# 対象
- Macユーザ
- Sublime Text愛用者
- Finder愛用者
- 極力マウス操作したくない人

# なぜ必要なのか
Finderからキーボード操作でSublime Textでディレクトリを開くことができないから

# 手順
## 1. Automatorでサービスを作る
<img width="1112" alt="スクリーンショット 2019-02-26 20.43.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/236978/b7402200-fe2d-81c8-3e1a-7f9135d5d837.png">

こんな感じで

## 2. ショートカット設定する
<img width="780" alt="スクリーンショット 2019-02-26 20.48.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/236978/8440d3c8-c99c-5d17-01ad-602e2e775a31.png">

こんな感じで
自分は「⌘ + s」に割り当ててますがこの辺はお好みで

## 3. Finderでディレクトリ選択状態で「⌘ + s」を押す
SublimeTextでディレクトリが開いて幸せになる

おしまい

# 追伸
選択してるファイルを強制的にSublimeTextで開くようにしてるから
ディレクトリ以外でも、デフォルトで開くアプリケーションの設定無視してSublimeで開ける
画像とかCSVとか
Alibaba Cloud上のECS&SLB構成でLaravelを動かすときのroute()でhttpsを出力する方法

中国版AWSであるAlibaba CloudでLaravelを動かした際に手間取った点をまとめました。タイトルの通りです。

作ったのはSLB(Server Load Balancer)とECS(Elastic Compute Service)を用いたシンプルなアーキテクチャ。AWSにおけるELBとEC2みたいなものです。
HTTPS化するために、ELBと同様にSSL証明書をSLBにインストールしました。インストールの手順はSLBのほうが簡単かもしれません。
Alibaba CloudもAWSと同様に、

client <- 443 -> SLB <- 80 -> ECS

という通信の流れです。

これで何も考えずにLaravelで`route('auth.login')`と書いたら、
`http://hoge.foo.bar/login`
と、HTTPのURLが出力されてしまいました。
出力したいのは
`https://hoge.foo.bar/login`
です。

まあ、これはAWSでありふれた問題なので解決方法もインターネットに溢れています。
というかLaravelの公式ドキュメントに記載されています。

https://laravel.com/docs/5.7/requests#configuring-trusted-proxies
https://readouble.com/laravel/5.7/ja/requests.html#configuring-trusted-proxies

公式ドキュメントにもあるように、
`app/Http/Middleware/TrustProxies.php`
を以下のように設定します。

```app/Http/Middleware/TrustProxies.php
/**
 * The trusted proxies for this application.
 *
 * @var array
 */
protected $proxies = '*';
```

これでうまくいくかと思いきやまだHTTPのまま:sob:
どうしてだろう。。。

ここで何をしているかというと、
ロードバランサーからのリクエストを信頼できる通信であると、
しかも`protected $proxies = '*';`と、すべてを許可するようにしています。
そして信頼できる通信だと、`route()`での出力が`https://`になります。
さらに詳しく調べると、`vendor/symfony/http-foundation/Request.php`の`isSecure()`が信頼できるかどうかを判断しています。

```vendor/symfony/http-foundation/Request.php
    /**
     * Checks whether the request is secure or not.
     *
     * This method can read the client protocol from the "X-Forwarded-Proto" header
     * when trusted proxies were set via "setTrustedProxies()".
     *
     * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http".
     *
     * @return bool
     */
    public function isSecure()
    {
        if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_X_FORWARDED_PROTO)) {
            return in_array(strtolower($proto[0]), array('https', 'on', 'ssl', '1'), true);
        }

        $https = $this->server->get('HTTPS');

        return !empty($https) && 'off' !== strtolower($https);
    }
```

`X-Forwarded-Proto`を調べてますね。
そういえば、SLBのリスナー設定で`X-Forwarded-Proto`のチェック項目があったような。。。

<img width="1005" alt="スクリーンショット 2019-02-26 20.01.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/123511/d03525bc-cd5e-c9e0-0758-92cb27aa3ad4.png">

ありました！！
ということで「ヘッダーにX-Forwarded-Proto（SLBへの接続プロトコル）を追加します」にチェックを入れて更新したら、
晴れて`route()`で出力されるURLが`https://`となりました。
めでたしめでたし:relaxed:
Dynamic Feature Moduleに対応したアプリを、単一apk化する

Dynamic Feature Moduleに対応すると、

```
./gradle assembleDebug
```

とかの実行時、apkが複数作られるようになります。
AndroidStudioでビルドするときは ▶ ボタンで動くけれど、コマンドラインからのインストールだと

```
adb install-multiple app.apk feature.apk
```

みたいにしないといけない。
何より、複数apkだとDeployGateとかでの社内配布で困る…（というか無理）
という場合、以下のようなコマンドでuniversalなapkを作成できます

```
./gradle packageDebugUniversalApk
```

apkファイルは、

```
/app/build/outputs/universal_apk/${variant.name}/app-${variant.baseName}-universal.apk
```

とかあたりに作られます。
※ `${variant.name}` と `${variant.baseName}` は、gradleでの実行時のvariantのパラメータです。 `flavor` が `dev` で `buildType` が `debug` だとすると、それぞれ `devDebug` , `dev-debug` という感じになります。


なお、本件対応時、CIにて

```
Program type already present: android.databinding.layouts.DataBindingInfo
```
のようなエラーがでたのですが、 `com.android.tools.build` を最新（本記事執筆時点では `3.3.1`）まで上げると解消しました。
[こちら](https://github.com/googlesamples/android-dynamic-features/issues/26)の内容ですね。
Power shell を使おうぜ☆（＾～＾）＜その３＞ Copy-Itemを使うときのパスを倒そうぜ☆（＾～＾）

```Plain
+ C:
  + Box
    + Pen.txt
    + Eraser.html
```

とあるとき、

```Plain
+ C:
  + PenCase
    + Pen.txt
    + Eraser.html
```

と別のディレクトリーに丸ごとコピーしたいときがあるだろ。試した結果から言ってしまうと、ここでやることは

```Shell:copy.ps1
# コピー先ディレクトリの存在確認。
if (Test-Path "C:\PenCase") {
    # あれば中身を全部消す。
    Remove-Item "C:\PenCase\*" -Recurse
} else {
    # なければ作る。
    New-Item -ItemType Directory -Path "C:\PenCase"
}

# コピー元の中身をすべて指定し、コピー先はディレクトリを指定する。（ややこし……）
Copy-Item "C:\Box\*" "C:\PenCase"
```

ディレクトリーなんてものは　看板で書かれた住所みたいなもので存在せず、あくまで　ファイルをコピーする、
という物の見方をすればいいらしい。

変数を使ってみよう。

```Shell:copy.ps1
# Trailing NOT slash.
$origin = "C:\Box"
$clone = "C:\PenCase"

# コピー先ディレクトリの存在確認。
if (Test-Path $clone) {
    # あれば中身を全部消す。
    $dst = $clone + "\*"
    Remove-Item $dst -Recurse
} else {
    # なければ作る。
    New-Item -ItemType Directory -Path $clone
}

# コピー元の中身をすべて指定し、コピー先はディレクトリを指定する。（ややこし……）
$src = $origin + "\*"
Copy-Item $src $clone
```

ファイルの冒頭で Path を一覧しておき、その後は　親ディレクトリには戻るなだぜ。
よく　オリジン　の中身を消したり、
自分を自分の中にコピーして　再帰的にファイルが増えて　３０００個のファイルをゴミ箱に送るはめになったりする。
そういう不注意をなるべく減らそうぜ。
CentOS7+L2TP/IPSec+unbound+mitmproxyでiphoneのギガ不足を解消する

# 目的
格安SIMだとあっという間にギガ不足に陥るので
VPNを利用して経路を変更しテキスト/画像をVPN上で圧縮/低画質化してiphoneのギガ不足を解消する

# 構築手順
1.[VPSを契約](https://vps.sakura.ad.jp/)してCenOS7を用意する
2.[VPN(L2TP/IPSec)](https://qiita.com/mykysyk@github/items/7b952eed0c71befeca47)を構築
3.[unbound](https://qiita.com/mykysyk@github/items/73d043f260cf06b4b46e)を構築
4.[mitmproxy](https://qiita.com/mykysyk@github/items/984cf929e0bb60cc4bd3)を構築
5.iphoneにVPNの設定を入れる

# デメリット
- 基本、自己責任
- iphoneにmitmproxy経由でSSL接続するための証明書をインストールする必要がある
- iphoneで使用/未使用時は毎回証明書信頼設定で上記証明書をon/offする必要がる
- テキスト/画像を経路上で圧縮/低画質化しているのでレスポンスが若干落ちる

# メリット
####1.無料Wi-Fiの利用がセキュアになる

```
# 導入前
スマホ -> 無料Wi-Fi -> WEB

# 導入後
スマホ -> L2TP/IPSecクライアント -> 無料Wi-Fi -> L2TP/IPSecサーバ -> WEB
```

####2.DNSブロッキングを利用できる

```
# 導入前
1. スマホ -> WEB 
2. スマホ <- WEB(ブロックしたいコンテンツURL)
3. スマホ -> DNS(ブロックしたいコンテンツの名前解決)
4. スマホ <- DNS（名前解決）
5. スマホ -> WEB(ブロックしたいコンテンツサイト)
6. スマホ <- WEB(ブロックしたいコンテンツサイト)

#　導入後
1. スマホ -> リクエスト -> WEB 
2. スマホ <-　レスポンス　<- WEB(ブロックしたいコンテンツURL)
3. スマホ -> 問い合わせ -> unbound(ブロックしたいコンテンツサイト)
4. スマホ <-　レスポンス　<- unbound（DNSブロッキングでNXDOMAINを応答）
```

####3.テキスト/画像を圧縮/低画質化してパケット節約

```
# 導入前
1. スマホ -> WEB
2. スマホ <- WEB(テキスト/画像)

#　導入後
1. スマホ -> mitmproxy　-> WEB
2. スマホ <- mitmproxy(圧縮/低画質) <- WEB(テキスト/画像)
```
crontabでAWS CLIの実行結果の出力が一部で途切れた

crontabにてAWS CLIでjsonでデータ取得しファイルに保存しようとしたけど
なぜか途中で途切れてハマった次第

describeした時、TAGの内容も出力されていたが、
crontabで実行させるとその日本語文字列部分からすっぱり途切れてたので、
もしかして・・とTAGの内容をアルファベットにしてみたら次に日本語文字列のところで途切れる・・

PYTHONIOENCODING=UTF-8 も試したがうまく行かず・・
あとは、環境変数のLANGかLC_ALLのどちらかかな？と試したところ
LC_ALL環境変数うまくいきました。


例)セキュリティグループをdescribeした場合

```
#!/bin/sh

#今回の肝はコレ
export LC_ALL=ja_JP.UTF-8

/usr/local/bin/aws ec2 describe-security-groups >  describe-security-groups.json
```
Angularのフォームのそもそもが分かってなかった話

# はじめに
Angularの既存プロジェクトにjoinしたはいいものの、後回しにしていたフォームの改修をしてみると、いろいろハマりポイントあったので書き出しました。
(Angularはフォームが簡単に実装できるって聞いてたので舐めてました)

# テンプレート駆動フォームとリアクティブフォーム
そもそもAngularにどんなフォームの書き方があるのか、ここから分かってませんでした。。
Angularには大きく分けて２種類のフォームの書き方があります。

- テンプレート駆動フォーム (Template-driven forms)
- リアクティブフォーム (Reactive forms)

詳しい解説は[公式ドキュメント](https://angular.jp/guide/forms-overview)を参照いただきたいのですが、雑感以下の違いがあるかなという印象です。

#### テンプレート駆動フォーム
- バリデーションチェックをテンプレート側（~.component.html）に記載
- 簡単なフォームであれば手軽に実装できる
- コンポーネント側（~.component.ts）にはほとんど実装しない

#### リアクティブフォーム
- バリデーションチェックをコンポーネント側（~.component.ts）に記載
- コードが冗長になるが、複雑な要件を実装できる
- フォームの初期値や検証ルールはすべてコンポーネント側（~.component.ts）に実装

私が一番困ったのは、インターネット上のサンプルプログラムがどちらで書いているか分からなかったことです。
見た目上かなり書き方が違う（内部的には同じオブジェクトで管理しているらしい…）ので、どの書き方が正しいのかさっぱり分かりませんでした。

ここでは、２種類あるんだよってことが言いたかったのでそれぞれの書き方の違いなんかは別の記事に譲ります。。

# そして、bootstrap
記事の趣旨とはズレてしまうのですが、初見泣かせだと感じたので書かせてください。
リアクティブフォームで実装していると、```formGroup```や```formControl```といったワードが出てくるのですが、これがbootstrapのフォーム制御系の記述と重なり、ややこしかったです。
まぁbootstrapの設定はclassにしか記載しないので容易に区別できるはずなのですが、右も左も分かっていなかった私にとっては混乱を深めるものでした。

プロジェクトによってはMaterialデザインを導入しているものもあると思うので、さらにフォームの書き方が変わってくると思います。
フォームの構造上の記載なのか、デザイン上の記載なのか区別する意識が必要だと反省しました。

# さいごに
フォームっていろんな技術が詰め込まれる場所だと再認識しました。
やりたいことに対して、```構成・機能```と```見た目```を別で調べないと、目的の情報に辿りつかなかったです。

構成や機能は、```Angular + やりたいこと```で検索すればいいのですが、
見た目は、```bootstrap + やりたいこと```で検索しないと欲しい情報が得られませんでした。

# 補足
bootstrapも3と4でフォーム制御の仕方が変わっているので、注意してね。
大いなる力には大いなる責任が伴うらしい

先日の勉強会での話。
社内の勉強会でSVNを利用しているのだが、先日Apacheが落ちていてSVNが起動しなかった。

サーバー管理者の人はまだ来ていないけど、きっとこのコマンドで行けるはず・・・というわけで、以下コマンドをがちゃがちゃ。


```bash

sudo service httpd restart
```

Enter！

```bash

あなたはシステム管理者から通常の講習を受けたはずです。
これは通常、以下の3点に要約されます:

#1)他人のプライバシーを尊重すること。
#2)タイプする前に考えること。
#3)大いなる力には大いなる責任が伴うこと。
```

・・・ほう。



結局何かあっても怖いので管理者が来るまで待った(ノД`)・゜・。
余計なことしなきゃよかったーと涙・・。

あとから調べてみると、上記メッセージはsudoコマンドを初めて実行すると表示されるそうだ。
大いなる力には大いなる責任が伴う・・。確かにその通りかもしれない。
ちなみに3）の元ネタはスパイダーマンだそう。
PHP: Generatorの関数合成

本稿ではGeneratorを関数合成してひとつのGeneratorを作る方法を紹介する。

関数合成関数を実装する方法は、「[PHP: 関数合成する関数を作る方法 - Qiita](https://qiita.com/suin/items/7de4e9a6f60fd08a9337)」で紹介した。ここで紹介した関数合成関数を使えば、Generatorも合成することができる。

## どんな合成をしたいか？

3つのジェネレーターがある。これを合成して、ひとつのジェネレーターを作りたい。

```php
function generator(string $name): callable
{
    return function (iterable $items) use ($name): iterable {
        foreach ($items as $item) {
            echo "generator('$name') yields $item\n";
            yield $item;
        }
    };
}

// 3つのジェネレーター
$a = generator('a');
$b = generator('b');
$c = generator('c');
```

手続き型で書くとこんな感じ:

```php
$composedGenerator = function (iterable $items): iterable {
    $a = generator('a');
    $b = generator('b');
    $c = generator('c');
    yield from $c($b($a($items)));
};

foreach ($composedGenerator([1, 2, 3]) as $item) {
    echo "item = $item\n";
}
```

これを実行すると、次のような出力が出る:

```php
generator('a') yields 1
generator('b') yields 1
generator('c') yields 1
item = 1
generator('a') yields 2
generator('b') yields 2
generator('c') yields 2
item = 2
generator('a') yields 3
generator('b') yields 3
generator('c') yields 3
item = 3
```

## 関数合成関数で合成する

関数合成関数はこれを使う:

```php
$composeAll = function (callable $function, callable ...$functions): callable {
    return array_reduce(
        $functions,
        function (callable $f, callable $g): callable {
            return function (...$arguments) use ($f, $g) {
                return $g($f(...$arguments));
            };
        },
        $function
    );
};
```

合成のしかた:

```php
$composedGenerator = $composeAll(generator('x'), generator('y'), generator('z'));
```

実行してみる:

```php
foreach ($composedGenerator([1, 2, 3]) as $item) {
    echo "item = $item\n";
}
```

実行結果:

```php
generator('x') yields 1
generator('y') yields 1
generator('z') yields 1
item = 1
generator('x') yields 2
generator('y') yields 2
generator('z') yields 2
item = 2
generator('x') yields 3
generator('y') yields 3
generator('z') yields 3
item = 3
```

合成できた。


## 別解

`foreach`する方法もある。

```php
function compose(callable ...$functions): callable
{
	return function (iterable $items) use ($functions): iterable {
		foreach ($functions as $function) {
			$items = $function($items);
		}
		return $items;
	};
}

$composedGenerator = compose($a, $b, $c);

foreach ($composedGenerator([1, 2, 3]) as $item) {
	echo "item = $item\n";
}
```
PHP: 関数合成する関数を作る方法

本稿ではPHPで関数合成する方法を紹介する。

## 関数合成とは

関数合成とは2つの関数を組み合わせて1つの関数を作ることだ。この手法は、シンプルで小さく凝集性と再利用性の高い関数を組み合わせることで、保守性を保ちつつ多様な要求に応える処理を実現するために使われたりする。

## 関数合成してみる

ここに2つの関数がある。

```php
$addOne = function (int $value): int {
    return $value + 1;
};

$timesTwo = function (int $value): int {
    return $value * 2;
};
```

これを合成してひとつの関数を作ってみる。

```php
$addOneTimesTwo = function (int $value) use ($addOne, $timesTwo): int {
    $value = $addOne($value);
    return $timesTwo($value);
};

echo $addOneTimesTwo(4); //=> 10
```

これで関数合成できたわけだが、関数合成するためにその都度クロージャを書くのは手間になりそうだ。

## 関数合成する関数を作る

もっといい合成のしかたがある。それは、関数合成する関数を作ることだ。例えば、`$compose`という関数合成関数を作って、引数に関数を渡したら、さっきの`$addOneTimesTwo`と同じロジックを持つ関数が作られるようにしたい:

```php
$addOneTimesTwo = $compose($addOne, $timesTwo);
```

これは命令型の関数合成と違って、処理の順と記述の順が一致していて読みやすい。

関数合成関数`$compose`を実装してみよう。

```php
$compose = function (callable $f, callable $g): callable {
    return function (...$arguments) use ($f, $g) {
        return $g($f(...$arguments));
    };
};
```

`$compose`関数は2つの関数を受け取って、その2つを呼び出せる新しい関数(接着剤的な役割をする関数)を作って返す。

クライアントコードの読みやすさのために`$compose`は`$f`→`$g`の順で受け取るようにしつつ、合成される関数の呼び出し順序は`後(先($引数))`ではならないので、合成の式は`$g`→`$f`の順で記述する必要がある。これを逆にしてしまうとバグるので注意。

`function (...$arguments)`の`...`は可変長引数。つまり、あらゆる値をいくつでも受け取れるようにしている。`$g($f(...$arguments))`の`...`はsplat演算子と呼ばれるもので、配列の`$arguments`を関数に渡す際に一個一個の引数に展開する効果がある。

それでは関数合成して動かしてみよう:

```php
$addOneTimesTwo = $compose($addOne, $timesTwo);
echo $addOneTimesTwo(4); //=> 10
```

## 一度にたくさんの関数を合成できる関数を作る

上で作った関数合成関数は2つの関数を受け取り、関数合成してくれる実装になっていたが、一度に3つ以上の関数を合成したいこともあるだろう。

ということで、たくさんの関数を合成できる関数を作ってみよう。

```php
// さきほど作った関数合成関数
$compose = function (callable $f, callable $g): callable {
    return function (...$arguments) use ($f, $g) {
        return $g($f(...$arguments));
    };
};

// たくさんの関数を合成できる関数
$composeAll = function (callable $function, callable ...$functions) use ($compose): callable {
    return array_reduce($functions, $compose, $function);
};
```

上の`$composeAll`は`$compose`を再利用する形になっているが、次のようにべた書きしても同じ挙動になる。

```php
$composeAll = function (callable $function, callable ...$functions): callable {
    return array_reduce(
        $functions,
        function (callable $f, callable $g): callable {
            return function (...$arguments) use ($f, $g) {
                return $g($f(...$arguments));
            };
        },
        $function
    );
};
```

動かしてみよう:

```php
$addOne = function (int $value): int {
    return $value + 1;
};

$timesTwo = function (int $value): int {
    return $value * 2;
};

$minusTwo = function (int $value): int {
    return $value - 2;
};

$addOneTimesTwoMinusTwo = $composeAll($addOne, $timesTwo, $minusTwo);

echo $addOneTimesTwoMinusTwo(1); //=> 2
```

((1 + 1) * 2) - 2 が計算されて 2 が出力される。
WordPress 4.7 REST APIの時刻フォーマットがイケてないのでGolangで苦労した話

# 概要

+ wordpress 4.7にはREST APIで記事の一覧や内容を取得できる機能があります
    + https://wordpress.org/news/2016/12/vaughan/
+ これを利用してgolangで記事の一覧を取得するクライアントを作成したが時刻のパースでエラーが発生します
+ 何故かとおもったらAPIの返す時刻のフォーマットがRFC3339「もどき」でGoがパース不可能になっていました

# wordpress4.7のREST APIについて

+ REST APIで返ってくる値の形式は以下のようになっています
    + 参考: https://loumo.jp/wp/archive/20170116120010/

こちらのページのjsonを引用させてもらうと以下のようになります

```json
[
  {
    "id": 14687,
    "date": "2017-01-12T12:00:30",
    "date_gmt": "2017-01-12T03:00:30",
    "guid": {
      "rendered": "http://loumo.jp/?p=14687"
    },
    "modified": "2017-01-07T19:13:26",
    "modified_gmt": "2017-01-07T10:13:26",

```
略

# Goでパースできない

上記のようなjsonをパースするときGoでは以下のようにstructを宣言してパースを行いますが

```golang
type News struct {
	Date    time.Time `json:"date"`
	DateGmt time.Time `json:"date_gmt"`
}

var newsResponse []*News
decoder := json.NewDecoder(res.Body) // APIから取得してきます
	if err := decoder.Decode(&newsResponse); err != nil {
		fmt.Println(err)
		return nil, err
	}
```

このときこのようなエラーが出ます

```
parsing time ""2019-02-26T02:04:34"" as ""2006-01-02T15:04:05Z07:00"": cannot parse """ as "Z07:00"
```

# なぜパースができないのか

+ GoはRFC3339に則ってパースしようとしますが、Wordpressの吐いている時刻のフォーマットが正しいRFC3339ではないことが原因のようです
+ `"date": "2017-01-12T12:00:30"`
+ 正しくは `"2017-01-12T12:00:30Z"` または `"2017-01-12T12:00:30+0900"`　などでなければいけません
+ ということでWordpressのREST APIの時刻をGolangで扱うときは気をつけましょう....
GitLab導入(CentOS7)

CIについての勉強の一環としてGitlabの勉強。
構築時のメモ。

#環境
・VirtualBox
・CentOS7.6(1810) minimal

#前提条件
・firewallが無効になっていること
・rootでログインしていること

#構築
以下のページを参考に導入。
https://about.gitlab.com/install/#centos-7

必要パッケージのインストール

```console
# yum -y install policycoreutils-python
```

GitLabパッケージのリポジトリのダウンロード

```console
# curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.rpm.sh | sudo bash
```

GitLabパッケージをインストール

```console
# EXTERNAL_URL="http://[GitLabをインストールするホスト名 or IPアドレス]" yum install -y gitlab-ee
```

#動作確認
インストール時に設定したURLでアクセスしてページが表示されることを確認する。

以上
【Udemy】gRPC [Golang] Master Class: Build Modern API & Microservicesをやってみた

# はじめに
- 年末にUdemyのコースがセールになってまして、Go言語使っててHTTP/2やmicroserviceが学べるコースがないかなと探してたらこれが見つかり買ってみました。  
[gRPC [Golang] Master Class: Build Modern API & Microservices](https://www.udemy.com/grpc-golang/)
- でもすぐにやらなくて積んdemyなってました。。。
- なので【Qiita×Udemy特別企画】学習応援イベントがやってたので試しにのっかってみました。

# コース概要

の前に

## 英語
このコースは中身をみればわかると思いますが、全部英語です。
ですが大して難しい英語を使ってるわけでもありませんし、プログラミングですからソースコード見て理解すればいいので英語がハードルになることはそんなに無いかと思います。
自分はまあまあ英語が得意なんで苦手な方はいくらか差し引いて考えた方がいいかも。

## 概要
ざっとこんな感じでした。

- gRPC オーバービュー
- gRPC 詳細
- gRPC の各種実装パターン
  - Unary
  - Server Streaming
  - Client Streaming
  - Bi-Directional Streaming
- その他機能の実装
  - エラー実装
  - デッドライン
  - SSLセキュリティ
  - 別言語からの通信(Java)
  - gRPC のEvans クライアントの使い方
- 実践的なアプリを作ってみる
- MongoDBと連携してCRUD APIを実装
- おまけ(クーポンとか)

gRPC の各種実装パターンでそれぞれUnary、Server Streaming、Client Streaming、Bi-Directional Streamingを説明していて、そこについてのプログラミング解説が主な内容でした。

# やったこと
ひたすら写経！Webページを作った時のように見栄えの良いものを作るわけでもないので、かっこいいアウトプットはありません。
リポジトリを載せておきます。
https://github.com/suganoo/go-grpc-course

gRPC のサーバーを起動して、クライアントを実行してみるのをひたすらやってました。

# 学んだこと

## ざっくり各種パターン
### Unaryパターン
単純にリクエストを投げて、レスポンスを受けるというパターンです。(1:1)
REST APIみたいなものでした。ex. 2つの数字を送ったら合計値が返される。

### Server Streaming
1回リクエストを投げて、複数のレスポンスを受けるパターンです。(1:n)
ex. ある数値を送ったら素数がすべて返ってくる。

### Client Streaming
複数回リクエストを投げたら、1回のレスポンスを受けるパターンです。(n:1)
ex. 複数個の数値を送ったら、平均値が返される。

### Bi-Directional Streaming
相互に複数回通信するパターンです。(n:n)
ex. 複数個の数値を用意しておき、順次1コづつ数値を送ると、それまでに受けた数値の最大値を更新した時に最大値を返す。

## Calculator
上で例として書いてますが、平均値を返したり、最大値を返したりするアプリを作ってみました。なるほどという感じです。

## MongoDBと連携してアプリ
ブログを作ったと想定して、MongoDBにデータを入れこみCRUDを実装しました。MongoDBは実際使うのは初めてで、これはなかなかMongoDBも含めて勉強になりました。便利だねー

## Evans CLI
gRPCのサーバーに対してのクライアントアプリです。最後にちょろっと出てきてこいつは便利だなー！と思いました。でもDLしてビルドしたところなぜか接続できず残念でした。。。
https://github.com/ktr0731/evans
## 別言語からの通信(Java)

これは動画からしか見てませんが、他の言語からちゃんと通信できてて便利でした。

# MongoDBのドライバ設定はちょっと注意

バージョンが違うのかimportの定義の仕方は下記のような書き方でないとエラーになってました。

```golang

"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
```

# 時間があればやりたかったこと

Udemy特別企画の締め切りを目標にしてて、さらに始めるのが2月半ばを過ぎてからだったので、コースを終わらすことしかできませんでした。
コーディングしてるといろいろとやってみたいことが出てきたので、それが今後の宿題かなと思います。

- HTTP/2通信としてはどうなってるのか。  サーバーはnet.Listen(...)で始めてるし、クライアントはgrpc.Dial(...)で始めてたのでヘッダーとかどうなってるのか。
- protoc で生成されるGoのソースを見てみる。
- TLS通信の仕方。各種サーティフィケーションファイルはコマンドコピペだったのでちゃんと復習したい。
- gRPC 使ってチャットアプリ作ってみたいですね。

# 最後

やっぱこういう企画がないとやらないですね(汗)。
ですが今回を気にgRPCが学べたのでとてもよかったです。
またUdemyは年末年始になるとセールになるのでお得です。
Udemyだと新しい技術が出てきたときに英語版であればいち早くコースが出てくるのでチェックしてみるといいかと思います。

ザーッとやってしまったとはいえ修了証明書が最後にでるとうれしいものですね。
<img src="https://qiita-image-store.s3.amazonaws.com/0/17698/dcf3ff34-0660-cb9a-790b-f299d7426fec.png" width=50%>
Android Studioで実機にインストールするときに遭遇したInitializing ADB...というフリーズの解消法


## フリーズ
3年ぶりくらいにAndroid Studioを使って、アプリを実機にインストールしようとして、Runボタンを押したら、Initializing ADB...という画面でずっとフリーズしたままになった。


<img width="736" alt="スクリーンショット 2019-02-26 19.01.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/117549/36910620-4ee1-38c7-6321-64895e6b399a.png">

一向にデバイスが認識されないためいろいろ検索してみたところ、adbコマンドが機能していないのでは？という記事がたくさん出てきたので確認してみた。

```bash
adb
zsh: command not found: adb
```

パスが通っていないのか。。。

```bash
export PATH=$PATH:/Users/<user_name>/Library/Android/sdk/platform-tools
```

パスを通した後に以下のコマンドで復旧できるらしい。。。

```bash
adb kill-server
adb start-server
```

しかしデバイスは認識されずに**`Initializing ADB...`**のまま。。。

引き続き調べてみると[Stack Overflow](https://stackoverflow.com/questions/31786365/android-studio-freezes-on-initializing-adb)にイカした投稿を発見。
`/etc/hosts`を以下のように編集すれば良いそうだ

```bash:/etc/hosts
vim /etc/hosts

---
127.0.0.1       localhost

```

追加してみたら無事に端末が認識された。なぜ解消されたかは実は今だに不明だが、
adbの[コマンドリファレンス](https://developer.android.com/studio/command-line/adb?hl=ja)をみてみると、**Java TM Debug Wire Protocol (JDWP)**というJava 仮想マシン (VM) との間の通信に使用されるプロトコルがlocalhostを使うようで、違うIPアドレスがlocalhostとして設定されていたりするとダメなのだろう。Android Studioは主戦場ではないので、あまり深追いしないでおく。
Raspberry pi 3で、デイリースクラム用マシンを作成した

# 会社で遊んでたRaspberrypi3を活用しよう

毎朝11時からのデイリースクラム。

リモートエンジニアとのミーティングをこれまではスペアのMacbookProを使っていたのですが、Webミーティング専用機としてPC１台を使うのには、ちょっともったいなく。

ふと、最近、使っていなかったこれまた会社で遊んでいた`Raspberrypi3`を使って、appear.inでリモートワークエンジニアとデイリースクラムを行う専用機を作ろうと思い立ちました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/75162/0786a776-f96d-6030-ac6d-b2eba8a977b2.png)

# Webカメラを追加で調達

USB接続のマウスとキーボードは適当に調達して、WebカメラだけストックになかったのでAmazonで注文しました。
https://www.amazon.co.jp/gp/product/B01LXYHF71/
![image.png](https://qiita-image-store.s3.amazonaws.com/0/75162/d94602dd-8eef-50a6-31a9-11b37aea3898.png)

200万画素、マイク内蔵。税込み2,081円。前は3,000円くらいだったみたい。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/75162/c981ab19-d044-f278-9e80-ac29f3084a66.png)
さくっと到着。ここまでは問題なし。

# 何も考えずにUSB接続して映ると思ったら

早速、Raspberrypi3に接続してみて、普段使っている、appear.inのサイトへつないでみましたが、何も映りませんでした。

Amazonの説明書きをみると

`■対応OS(Windows):10(64/32)/8.1(64/32)/7(64/32)`
`■対応OS(Mac):Mac OS 10.9/10.10/10.11`

まあ、Raspberrypiはおろか、Linuxも書いてません。そんなもんです。でも、

[【BUFFALO】「BSW200MBK」をUbuntuとRaspberry Piで使ってみた](https://atsuyakoike.hatenablog.com/entry/2018/10/04/200253)

みたいな記事が、2018年10月にあがってたので、いけるんじゃないかなあ、と久しぶりにコマンドラインを叩くハメに（実は半泣き）

# 動作テスト⇒動かない

```
pi $ lsusb 
```
そもそもUSBデバイスとして生きてるか確認。リストにはあがってきます。

```
pi $ sudo raspi-config
```
カメラを有効化（そもそもしてた）

問題を切り分けるために、適当なカメラを使うアプリをいれてテスト

```
pi $ apt-get install guvcview
```
問題なく動作。

そうすると、chrome上の何か問題か？

chromium上のカメラの設定を確認するも有効化されてる。怪しげな拡張機能も念の為停止。

```
pi $ vcgencmd get_camera
supported=1 detected=0
```
あれ、`detected=0`って認識してない？


```
pi $ sudo modprobe bcm2835-v4l2
```
よくわかんないけどドライバー追加

```
pi $ sudo rpi-update
```
色々新しくしたら動いたという記事を読んだので実行

# とりあえず動きました。

実は、appear.inで、カメラではなく、マイクのところで、Webカメラデバイスを指定してあげるとうまくいく感じでした（もろもろ試したことは関係無かった？汗）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/75162/401f0470-cf5f-4eba-79fe-9f0ebf03848c.png)
・・・なんか、ソフトフォーカスっていうか、ぼんやりした感じですね・・・200万画素ってこんなものでしたっけ。

まあ、USBカメラはもう少し良いのをつなげば改善するとして、画面の前で動くとタイムラグが少し発生して、これはネットワークというよりはラズパイの処理速度の限界かなあ、という感じでした。

# 結論

ちょっと、ビジネスで常用するには、マシンパワー的にRaspberrypi3は、厳しかったです。

画質や動画はあまり関係ない監視カメラ的に利用するのであれば、場所も取らなくて十分良いです。
情報処理安全確保支援士 平成28年度春 午後1 問2

下記の問題集を参考させていただいでおります。
[午後(I・II)に集中！情報処理安全確保支援士精選17問](https://www.amazon.co.jp/%E5%8D%88%E5%BE%8C-I%E3%83%BBII-%E3%81%AB%E9%9B%86%E4%B8%AD%EF%BC%81%E6%83%85%E5%A0%B1%E5%87%A6%E7%90%86%E5%AE%89%E5%85%A8%E7%A2%BA%E4%BF%9D%E6%94%AF%E6%8F%B4%E5%A3%AB%E7%B2%BE%E9%81%B817%E5%95%8F-%E6%9E%97%E7%A7%80%E6%A8%B9-ebook/dp/B07B7LHCVN/ref=sr_1_21?s=books&ie=UTF8&qid=1551168594&sr=1-21&keywords=%E6%83%85%E5%A0%B1%E5%87%A6%E7%90%86%E5%AE%89%E5%85%A8%E7%A2%BA%E4%BF%9D%E6%94%AF%E6%8F%B4%E5%A3%AB)

#設問1
**a：オープンリレー**
メール送信において、規制をかけず全てのメールを中継、送信すること。
今回のU社では適切に設定されている。実際にも外部メールサーバはオープンリレー機能は停止しておくと良い。
また、午後問題でたまに見受けられるエンベロープについては下記サイトを参考にさせていただきました。
[メールヘッダとエンベロープの違い](http://blog.smtps.jp/entry/2018/02/06/121352)

**b：送信ドメイン**
SPFは**送信ドメイン認証技術**
図2に構文があるが、書き方を覚えておく。
SPFはエンベロープ(From)のドメイン名で送信元メールサーバの認証を行う。(ヘッダの確認は行わない)
SPFの設定を行うのは送信元サーバ

#設問2
**c：リフレクション**
プロキシサーバの機能設定で以下の攻撃例が想定される。
・DNSキャッシュポイズニング攻撃
・オープンリゾルバ防止機能が適切に設定されていない場合に起きるDNS「c」攻撃
問題文中からも設置されているプロキシサーバはDNSキャッシュサーバの機能も担っている。
オープンリゾルバとは所属ネットワーク以外からのアクセスを受け付ける状態で、外部からの問い合わせにも応答する。

DNSリフレクションは送信元IPを偽装(攻撃対象のDNSと同一IPに設定)し、踏み台となるDNSに問い合わせを行うことで応答結果を攻撃対象のDNSに送信する攻撃。
オープンリゾルバの状態だと攻撃の踏み台対象になる可能性がある

#設問3
**(1) 送信元ポート番号**
DNSキャッシュポイズニングの対策でTTLを長くすることで攻撃の発生を防いでいたが、カミンスキー攻撃の発見により有効な対策ではなくなった。
有効な対策としては**送信元ポート番号**のランダム化で、偽応答を受信しないようにすることです。

**(2) e：外部メールサーバ**
図4は偽のMXレコードをつかまされた攻撃です。
この攻撃によってメール配信に影響がでるのは、MXレコードを参照している外部メールサーバです。

**影響：取引先宛てのメールを、攻撃者が用意したメールサーバに転送してしまう**
MXレコードが本来の送信先ではなく、攻撃者が用意したメールサーバに送信されてしまう可能性があります。

**(3) パス名を送信しないという仕様**
CONNECTメソッドではGETなどとは異なり、パス名の指定はできません。
ログにも「どのホストにアクセスした」というログしか残りません。
例：CONNECT www.example.com:443

#設問4
**変更箇所：ブラックリスト3**
**変更内容：scanner@u-sha.co.jp**
scanner@u-sha.co.jpは社内利用であり、外部から送信されてくることはありえません。
そのため、メールヘッダの送信元がscanner@u-sha.co.jpは攻撃の可能性があり拒否する必要があります。
設定個所はブラックリスト3で、メールヘッダの確認を行います。
SPFではエンベロープに設定されているアドレスを認証しますが、メールヘッダの確認は行いません。
そのため、メールヘッダのみ詐称していた場合SPFの効果が出ないためブラックリスト1に登録しても意味がありません。
jQuery UI Datepickerでちょっと引っかかった話

過去ブログのQiitaへの移転シリーズ第4弾、今回は[この記事](https://yk0807.com/larablog/posts/4)を移転してみました。

今回はDatepickerというjQueryの機能を紹介したいと思います（Datepicker自体はjQuery以外の実装もあるんですが、自分が使ったことがあるのがjQueryのものだけなので、あくまで今回はjQueryに限った話です）。

Datepickerとは、テキストボックスをクリックするとカレンダーが出てくるやつで、皆さんも入力フォームとかでよく見るかと思います。
![201708161617_datepicker1.png](https://qiita-image-store.s3.amazonaws.com/0/66360/c952f763-59db-0bed-8ddc-892d5992ed95.png)
これが・・・
![201708161610_datepicker2.png](https://qiita-image-store.s3.amazonaws.com/0/66360/a116e006-871a-3a5c-a2cd-ed10cc662e4d.png)
こんな感じになるやつです。

使い方については[こちら](http://www.webdesign-fan.com/jquery-ui-datepicker)を見ていただければわかるかと思いますが、結構簡単です。 ちなみに、リンク先ではid="datepicker"としていますが、クラスでやることもできます。クラスだと該当するクラス名の箇所では全てDatepickerが使えるようになります。 クラスの場合だと、functionの中は

```JavaScript
$("".datepicker).datepicker();
```
となります。

なぜこの記事でDatepickerを紹介しようと思ったかと言いますと、その当時Datepickerでちょっとやらかして、うまく使えていないことがありまして、その備忘録も兼ねてということです。 ちなみに何があったかと言いますと、テキストボックスをクリックしてもカレンダーが出てこず、しかもページの下の方を見ると本来カレンダーの中に含まれるはずの内容が延々と表示されていました。（注意、画像は結構長いです）
![201708161620_datepicker_err1.png](https://qiita-image-store.s3.amazonaws.com/0/66360/7ed828f9-daa0-9eaf-9cd0-c281803f9c44.png)
![201708161629_datepicker_err2.png](https://qiita-image-store.s3.amazonaws.com/0/66360/859d1a8b-9268-8ed6-c5e3-401750791998.png)

最初一瞬何事かと思いましたが、右クリックで検証ツールを開いてコードをよく見てみると、***datepickerのcssが当たっていない***ことがわかりました。 何でcssが当たっていないのか調べるためにblade（Laravelなので）を見てみると、ちゃんと機能しているページではJavaScriptを読み込んでいるところとCSSを読み込んでいるところの順番の対応がうまく取れていたようなのですが、今回の現象が起きた箇所ではその順番の対応に問題があったようで（詳しく書くと長くなるので詳細は略します）、読み込む順番を機能しているページと同じ順番にすると、ちゃんとうまくいきました。

今回の教訓としては、便利なツールもちゃんと読み込めるよう正しく使ってこそ、ということですね。
平成30年(2018年)e-taxの罠

#「事前準備セットアップ ×」
↓からダウンロードしてインストールちゃんとしたのに…

[e-Taxソフト(WEB版)又は受付システムを利用するに当たって](http://www.e-tax.nta.go.jp/e-taxsoftweb/e-taxsoftweb1.htm)

#「確定申告書作成コーナー」
↓からダウンロードしたらいけた。

[確定申告書等作成コーナー](https://www.keisan.nta.go.jp/kyoutu/ky/sm/top#bsctrl)
→作成開始
→e-Taxで提出する
→マイナンバーカード方式により提出する
→事前セットアップファイルのダウンロード
→平成30年分事前準備セットアップ

#国税庁さんへ
もうちょっとテストにお金や工数かけてよ…
Proxy経由でEC2にSSHポートフォワードでRDPした話

##はじめに
社内からだと`Proxy`がきつくてssh(Secure Shell)やRDP(RemoteDisktop)が出来ないなんてことがあります。
RDPポートを空けてしまうとセキュリティ的にもリスクが高くなりますので、
`AWS`上の閉ざされたネットワーク内のサーバにアクセスする方法を実践してみました。



##やりたいこと
![Untitled Diagram-ページ9 (3).png](https://qiita-image-store.s3.amazonaws.com/0/196389/f9d76289-1141-a430-c2fd-1e12df54c8c1.png)


**こっから繋いで・・・こう！！**

sshで踏み台サーバに接続を行ない、sshポートフォワードで、ローカルで任意のポートを指定することで、
private(外部に接続していない)サーバへRDPで接続を行ないます。

私の環境だとポートが'80'と'443'しか空いていません。`HTTP`と`HTTPS`だけですね。
sshのポートを変更することで対応していますが、`Proxy`によっては中身をちゃんと見てブロックしている場合もあります。

##構成図
![Untitled Diagram-ページ9 (1).png](https://qiita-image-store.s3.amazonaws.com/0/196389/4820d412-e492-1a4c-baaf-a6c9ff8d5ac4.png)

ざっくりですが`AWS`側の構成はこんな感じですね。

BastionServer(踏み台サーバ)には`EIP`を付与し、sshポートを'22' ⇒ '443'に変更しています。
NAT経由でpriveteサブネットに対してRDPポート(3389)をルーティングして下さい。
※構成については調べたら直ぐわかりますので割愛します。

##設定方法
###【１】.接続方法
今回は**出来る男をアピール**するために`OpnenSSH`で接続します。

勿論、`TeraTarm`や`Putty`といったツールでも可能です。~~むしろそちらのほうが楽です。~~
私が使用しているPCがwindows7ですので、GitBashのインストール時に梱包されていた`OpnenSSH`を利用します。

Windows10だと`Powershell`に標準でインストールされていますので、`Powershell`で問題ありません。
念のためインストールされているか確認しておきます。

```
$ssh -V
OpenSSH_7.6p1, OpenSSL 1.0.2m  2 Nov 2017
```

認証方式は秘密鍵方式にします。特に理由はありません。
予めBastionServerで`ssh-keygen`を利用して秘密鍵(privateKey.pem)を作成してあります。

###【２】.ssh接続
ツールから設定する場合は`Proxy`を指定する箇所がありますので簡単ですが、
直接繋ぐ場合は`ProxyCommand`で指定する必要があります。

オプションの`-i`で事前に作成した秘密鍵を設定します。

`-o`で設定パラメータとなる`proxyCommand`を書き込みます。
今回は純粋な`proxy`として使用するので、`connect -H`で設定を行ないます。

最後は`user@globalIP -p 443 `でsshのポートを指定しつつBastionServerのユーザとIPを指定します。
※ 通常のsshなら'22'となります。

```
$ ssh -i privateKey.pem -o ProxyCommand='connect -H proxy.xxx.jp:80 %h %p' ec2-user@66.66.66.66 -p 443
Last login: Mon Feb 25 09:43:02 2019 from aaa.xxx.yyy.jp

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
6 package(s) needed for security, out of 8 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-10-0-1-10 ~]$

```

問題なくssh接続することが出来ました。

###【３】.sshポートフォワードでRDP接続
次はsshポートフォワードを利用して、RDP接続を行ないます。
先ほどの接続文字に、`-L`のオプションをつけるだけなので簡単です。

`-L (ローカルで使用するポート):(目的サーバのアドレス):(目的サーバで待ち受けてるポート番号)`

・ローカルで使用するポート：13389(何でもいいです。)
・目的サーバのアドレス：10.0.2.10(グローバルではないので注意)
・目的サーバで待ち受けてるポート番号：3389(RDPデフォルトポート)

```
$ ssh -i privateKey.pem -o ProxyCommand='connect -H proxy.xxx.jp:80 %h %p' -L 13389:10.0.2.10:3389 ec2-user@66.66.66.66 -p 443
Last login: Tue Feb 26 09:02:48 2019 from aaa.xxx.yyy.jp

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
6 package(s) needed for security, out of 8 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-10-0-2-10 ~]$

```
表示は通常のssh接続と変わりません。

sshを接続したままリモートディスクトップを開き、
`localhost`、または`127.0.0.1`と先ほど設定したポートを指定します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/196389/9ed37adc-7e63-d3d3-59f6-6b6bdd2e262e.png)

入力したら「接続」ボタンを押下。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/196389/64821458-92bf-4ef5-a691-fd5c58b960f9.png)

ログインパスワードの入力ウィンドウが表示されたら接続成功です！
ざっくり Reduced K-meansクラスタリング解説(数理編)

#1. 雑要約
　今回は[ざっくり Reduced K-meansクラスタリング解説(実装編)](https://qiita.com/m1t0/items/492d26c1ca338d787271)で説明しなかったモデル式や更新式について説明しています．
#2. 記号等
+ X: データ行列($n\times p)，x_i\ (p\times 1$)はその行ベクトルで個体に対応します．
+ G: メンバーシップ行列($n\times g$)．gはグループの数で，Gは以下のように個体がどのグループに所属するかを表す行列．

```math
\begin{eqnarray}
g_{ik}=\left\{
\begin{array}
1 1 &if\ x_i \in G_k\\
0 & otherwise
\end{array}
\right.
\end{eqnarray}
```
+ C: セントロイド行列($g\times m$)．グループの中心の座標の行列．mは次元縮約した後の次元数を表しています．
+ A: 負荷行列($p\times m)．A^TA=I_m$となるような列直交行列．
+ E: モデルとデータ行列Xの誤差を含む行列($n\times p$)
+ $||B||_F ^2:\ ||B||_F^2=trB^TB=trBB^T$で定義されるFrobeniusノルム



#3. 損失関数とアルゴリズム
###3.1 目的関数
Reduced K-means(以下RKMと書きます)のモデル式は，$$X = GCA^T + E$$であり，交互最小二乗法によってパラメータを計算するとすると，損失関数(loss function)は

```math
f(G,C,A)=||E||_F^2=||X-GCA^T||_F^2
```
となります．アルゴリズムの説明のために，損失関数を展開します．

```math
\begin{eqnarray}
f(G,C,A) &=& tr(X-GCA^T)^T(X-GCA^T)\\
&=& trX^TX-2trX^TGCA^T+trAC^TG^TGCA^T\\
&=& trX^TX-2trX^TGCA^T+trC^TG^TGC\\
&&(\because trVWZ=trWZV,A^TA=I_m)\\
\end{eqnarray}
```
ここでパラメータに関係しているのは，最右辺の第2項と第3項であり，損失関数を減少させるためには，これらを最適化すれば良いことがわかります．まずはGとCを固定してAを更新することを考えます．損失関数のAに関する項は$-2trX^TGCA^T$のみであり，$trX^TGCA^T$を最大化することと損失関数の最小化が等価であるということがわかります．よって損失関数の最小化が$trX^TGCA^T=trAC^TG^TX$を最大化するような列直交行列Aを計算する問題に置き換えられます(このような問題を直交プロクラステス問題といいます．)．そのようなAは$C^TG^TX$の特異値分解を$Q\Sigma P^T$とすると，[ten Berge(1983)](https://link.springer.com/article/10.1007/BF02293876)の定理から $$\widehat{A}=PQ^T\tag{1}$$で求まります．このAとCを固定してメンバーシップ行列Gを計算します．これは，通常のK-meansクラスタリングと同様に，$A^Tx_i(i=1,\cdots,n)$(負荷行列Aでデータ行列Xの各点を低次元空間に布置したもの)と各クラスター中心の距離を計算して，最も近いクラスターに割り当てます．

```math
\begin{eqnarray}
g_{ik}=\left\{
\begin{array}
1 1&if\ ||A^Tx_i-c_k||^2\le||A^Tx_i-c_{k'}||^2\\
0 &otherwise
\end{array}
\right.\tag{2}
\end{eqnarray}
```
以上のように更新したAとGを固定して，損失関数を最小にするセントロイド行列Cを計算します．そのようなCは損失関数をCで偏微分したものを$\bf{O}$と置くことによって，

```math
\begin{eqnarray}
\frac{\partial}{\partial C}f(G,C,A)&=&-2G^TXA+2G^TGC=\bf{O}\\
&\Leftrightarrow&G^TGC=G^TXA\\
&\Leftrightarrow&\widehat{C} = (G^TG)^{-1}G^TXA\tag{3}
\end{eqnarray}
```
と更新すれば良いことがわかります．以上のように求めたG,C,Aの更新式はそれぞれお互いに影響し合っているので，１つ更新するたびに他のパラメータも変化します．従って目的関数が収束する($\fallingdotseq$変化量があらかじめ決めた基準より小さくなる)まで反復計算する必要があります．
###3.2 アルゴリズム
　以上をまとめると，RKMのアルゴリズムは以下のようになります．

step0. クラスター数gと低次元空間の次元mを設定
step1. セントロイド行列C，負荷行列Aのメンバーシップ行列Gの初期化
step2. (1)のようにAを更新
step3. (2)のようにGを更新
step4. (3)のようにCを更新
step5. 目的関数の値が収束していなければstep2へ戻る．収束していれば終了．

これをpythonで実装したものは[ざっくり Reduced K-meansクラスタリング解説(実装編)](https://qiita.com/m1t0/items/492d26c1ca338d787271)に載せてあります．

#4. 参考文献
* De soete and Carroll(1994). K-means clustering in a low dimensional Euclidean space.[(こちら)](https://link.springer.com/chapter/10.1007/978-3-642-51175-2_24)
* ten Berge(1983). A generalization of Kristof's theorem on the trace of certain matrix products.[(こちら)](https://link.springer.com/article/10.1007/BF02293876)
* Terada(2014). Strong consistency of reduced K-means clustering.[(こちら)](https://onlinelibrary.wiley.com/doi/abs/10.1111/sjos.12074)
ExcelでCSVを取り込むときに常識だよと言われた話。

Excel大好き大企業さんに
「CSVに出力した値が正しいかをExcelで比較してそのエビデンスをくれ」
と要求されました。

Excelでの値の比較方法を知らなかったので上司に教えてもらったのですが、その際に「常識だよ笑」と言われてしまいました。
なので僕と同じく「浜崎あゆみ」のような常識を知らない哀れな同志たちのために、比較方法とその時失敗した内容をまとめました。

※中学生時代、浜崎あゆみを知らず「は！？浜崎あゆみ知らないの！？」と本気で驚かれました。僕は信長の野望 天翔記に夢中でした。
#CSVファイルの中身
今回Excelに取り込むデータはこちら
![image.png](https://qiita-image-store.s3.amazonaws.com/0/307024/9c6e8c9c-e51a-4e98-ee10-3b82da22cc6c.png)
#そのまま取り込んだ【NG】
1.「データ」→「外部データの取り込み」→「テキストファイル」を押下し、該当CSVファイルを選択し「インポート」を押下します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/307024/620e52c0-f6eb-ec14-ed3b-d2a14a8c8152.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/307024/eeda936d-b684-ab6b-5ddf-525e98ce2b87.png)

2.今回のCSVファイルではカンマでデータが区切られてます。
なので「カンマやタブなどの区切り文字によってフィールドごとに区切られたデータ」を選択して「次へ」を押下します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/307024/5b709ca5-2c51-2151-ff31-7b591f4525f7.png)

3.区切り文字で「カンマ」のみを選択して「完了」を押下します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/307024/d913ded5-9c12-749f-2299-d48eac62cc72.png)
4.貼り付け場所を選び「OK」を押下します。
（選択しているセルが自動で入力されているので、そのまま「OK」で大丈夫です。）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/307024/ab4e0d22-6946-640d-3ad3-c17484e2304d.png)

結果は以下の通りです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/307024/79da5617-f288-1f4c-0c7f-5440c744f4da.png)
だいぶ改竄されてます。何をするだァーッ！
##取り込み失敗箇所について
Excelは入力された値を見て、自動で書式設定を変えてくれるのですが、それが裏目にでてしまっているようです。
###電話番号1,2,3
電話番号はハイフン（「-」）があるため文字列と認識したため、最初の0が消えませんでした。
一方で、電話番号1,2,3は数字しかなかったため、数値と認識して最初の0が消えてしまっています。
###誕生年月、設定日、設定時刻
誕生年月は年月と認識したため、「Jan-05」（2005/1/1）と表示されています。（この形、初めて見たのですが……）
設定日は日付と認識したため、「2019/2/2」と月と日の「0」が消えています。
設定時刻は時刻として認識したため、「8:05:05」と最初の「0」が消えています。（逆に、5分5秒の方の「0」は消えていませんね……）
###所持金
円マークの存在によって、通貨と認識したため、カンマ（「,」）が入っています。
# 文字列で取り込んだ
とにかく、すべてを文字列として取り込めれば良いのです。

1.「そのまま取り込んだ」の1と同じです。
2.「そのまま取り込んだ」の2と同じです。
3.区切り文字で「カンマ」のみを選択して「次へ」を押下します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/307024/7fbfbd07-5013-5438-7a8e-e77b4060390a.png)
4.データのプレビューですべての項目を選んで列のデータ形式で「文字列」を選択し、「完了」を押下します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/307024/64a99fd7-bbd3-297b-9292-3664412dc88e.png)
5.「そのまま取り込んだ」の4と同じです。
結果は以下の通りです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/307024/22a20c3f-515f-37b9-51a7-86f04e5fe759.png)
ちゃんと文字列で取り込めているようです。

#最後に
シートを全選択してセルの書式設定ですべてのセルを文字列に変えてから、文字列で取り込むように言われたのですが、
セルを文字列に変えなくても文字列で取り込めるみたいですね。
Excelってむつかしい…。

新人である今のうちに「常識」を教えてもらえて良かったです。
Sassで:last-childなどの擬似クラスを使用するときの注意点

## 概要

たとえば、要素を繰り返し表示していて最後の要素のみmarginを抜きたいなど、`:last-child`を使用することがあるが、ネストして書く場合は必ず&をつけなければならない。

付けなかった場合、その配下の要素にlast-childが付いてしまい上手くスタイリングできない。

## 正しいコード

```scss
 .data {
   &__item {
     margin-bottom: 15px;

     &:last-child {
       margin-bottom: 0;
     }
   }
 }
```

## 間違っているコード

```scss
 .data {
   &__item {
     margin-bottom: 15px;

     :last-child {
       margin-bottom: 0;
     }
   }
 }
```
プログラミング学習記録10〜10日続けてよかった〜

##今日やったこと
- Progate JavaScript4,5,6リセット復習

昨日やったところを復習しました。

インポートとエクスポートがこんがらがってよくわからなかったのですが、今日復習してみて理解しました。

どれが親クラスでどれが子クラスなのかを把握してれば、こんがらないということがわかりました。

親クラス・子クラスを把握すると、ファイルを分割しても、どこからインポートすればいいかがわかります。

###Progate JavaScriptは卒業
今日でProgateは、

- HTML&CSS
- JavaScript
- Ruby
- Python
- Command Line
- Git

が一通り終わりました。

まだ、Gitは１周しかしていないので、理解が浅く、もう２、３周はする必要がありますが、他の言語に関してはもう十分な気がします。

なので、明日からは前からやろうと思っていたUdemyの**「Web開発入門完全攻略コース - プログラミングをはじめて学び創れる人へ！未経験から現場で使える開発スキルを習得！」**を進めていきたいと思います。

レッスンを進めていく中でわからない部分、忘れた部分があればProgateのスライドを検索して復習しながら進めていこうと思います。

##10日連続でQiitaに学習過程を記録して思ったこと

結論からいうと、Qiitaに学習過程を記録し始めてよかったです。

Qiitaに書くことを意識しながら学習することで、より質の高い学習ができてる気がします。

あと、人目に触れるのを意識することで多少めんどくさくても「やらなきゃな」という気持ちになれます。

Qiitaはなんとなく敷居が高そうに見えて、投稿をためらってしまいがちだと思うのですが、間違ったら訂正すればいいし、自分でクソだと思ったら投稿を消せばいいだけです。

投稿することで批判されることのデメリットよりも、投稿することで質のいいインプットができるメリットの方が大きいので、やっていない方は一度やってみることをオススメします。

ということで、明日からも引き続きプログラミング学習を頑張っていきたいと思います。

おわり
AtCoderの問題を分類しました

# 本記事について

本記事は <b>[Zenn](https://zenn.dev/koyanagihitoshi?tab=books)</b> に移行しました。
多くの方に読んで頂き、ありがとうございました。

# 編集履歴

これまでの編集履歴は下記から参照することができます。

* [「AtCoderの問題を分類しました」の編集履歴](https://qiita.com/KoyanagiHitoshi/items/32dc42d8c5ee75339e54/revisions)
レポジトリをBitbucketからGithubに移行

#はじめに
Githubにレポジトリを統一することにしたので、移行する手順をメモしようと思います。

#手順
###1. BitbucketのレポジトリをGitHubにインポート
GitHubのインポートページからBitbucketにあるレポジトリURLを貼り付けます。

<img width="1034" alt="スクリーンショット 2019-02-26 17.31.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/358444/6fb2edd2-f65a-1fd0-0fe5-c67795c6b75a.png">

Your old repository's clone URLにBitbucketのレポジトリURLを入力します。
Your new repozitory detailsにGithubでのリポジトリ名を入力します。
PublicかPrivateかを選択します。

###2. ローカルのリモートリポジトリのURLを変更
ローカルでのリモートURLはBitbucketを向いたままなので、これをGitHubに向くように変更します。

```ruby
# まずは確認
$ git remote -v
origin  https://XXXXXXXX@bitbucket.org/XXXXXXXX/レポジトリ名.git (fetch)
origin  https://XXXXXXXX@bitbucket.org/XXXXXXXX/レポジトリ名.git (push)

# GitHubに向ける（SSH設定済み）
$ git remote set-url origin git@github.com:XXXXXXXX/新レポジトリ名.git

# 再確認
$ git remote -v
origin  git@github.com:XXXXXXXX/新レポジトリ名.git (fetch)
origin  git@github.com:XXXXXXXX/新レポジトリ名.git (push)
```

ばっちりですね！
Toastには通知元アプリを識別する情報を表示した方が良いという話

# 概要

AndroidでToastを表示した際、通知元のアプリを識別してもらうために、Toastに何かしらのアプリ情報を表示した方が良いと思う、という開発者向けの話です。

# Toastについて

Androidで簡易なメッセージをユーザに表示するには、Toastを使うことが多いと思います。Toastはダイアログと異なり、Activityが無くても表示することができます。具体的には、ServiceやBroadcastReceiverなどのバックグラウンドで動作するクラスでも、Contextが参照できれば呼び出すことができます。つまり、次のように別のアプリの上やホーム画面にToastを表示することができてしまいます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/78503/80e6ec80-b480-19a0-35af-c87737fa1bc9.png" width="320" />

# Toastの問題

ここで問題になるのは、このToastを表示している元のアプリを識別することが出来ないという点です。

自分の端末では一時期、「Account has not been authenticated」という内容（うろ覚え）のメッセージが不定期に表示されるという事象が発生していました。恐らく何れかのアプリが何らかのイベントをトリガーにしてToastを表示していたのだと思いますが、そのアプリが何か分からず、面倒で放置してたらいつの間にか出なくなってしまったので、結局どのアプリだったのかは分からず仕舞いでした。

こうした、どのアプリが出したメッセージなのかが分からない状況は、ユーザにとって決して好ましい状態ではありません。実際自分は、表示されたメッセージに対応することができなかったどころか、正体不明のメッセージが表示されて気味が悪いという印象を持ちました。ユーザに対して配慮したつもりが、まったくの逆効果となっています。

# 想定される状況

画面を表示していない状態でToastが表示される場合、次のようなタイミングでToastを表示するアプリの存在が考えられます（他にもあると思いますが）。

* 起動中のService(Android 8.0以降はForegroundService）からの実行
* JobScheduler実行時
* BroadcastReceiver受信時(参考:[暗黙的なブロードキャストの例外](https://developer.android.com/about/versions/oreo/features/background-broadcasts?hl=ja))
* プッシュ通知受信時
* 非同期処理を動かしたまま画面を閉じ、かつプロセスが生きたままの状態

# 対応

この状況に対して、開発アプリにはToastにアプリを識別する情報を表示するのが望ましいのではないかと考えました。この場合、次の2パターンがあるかと思います。

## 1. Toastにアプリ名を表示する

Toastにアプリ名を表示します。メリットとしては、通常のToast表示でも対応可能なことです。デメリットとしては、長い名前だとメッセージの邪魔になります。

<img src="https://qiita-image-store.s3.amazonaws.com/0/78503/d6d6dafa-7ace-8fbf-fd64-ca919c82070f.png" width="320" />

## 2. Toastにアイコンを表示する

アプリを識別できるアイコンを表示します。メリットはメッセージ表示領域の邪魔にならないこと、デメリットはToastは標準で画像を表示することはできないので、別途Viewを作成するか、ライブラリを使用する必要があることです。
次の画像は[Dynamic Toasts](https://github.com/pranavpandey/dynamic-toasts)ライブラリを使用した場合の表示です。
<img src="https://qiita-image-store.s3.amazonaws.com/0/78503/391e7ff4-8184-7631-4ca1-3ca9ef3ca796.png" width="320" />

# 最後に

個人的には、アイコンを表示するのが適当かと考えています。
注意点としては、いくらアイコンを付与したところで、ユーザがそのアイコンから元アプリを識別できなければ意味がないので、ランチャーアイコンや通知アイコンなど、ユーザが普段目にするアイコンを使用するのが適切かと思います。

こうした「ユーザがToastの表示元を識別できない」問題を考えると、今後Toastの表示に何らかの仕様変更が加えられるような気はします。