OmniAICreator/Qiita-1.07M huggingface dataset:
Salesforce APEXをスケジュール登録する方法

SalesforceでApexをスケジュール登録する方法のメモ

##やりたいこと
・SalesforceでApexを定期的に走らせる

##前提条件
・Schedulableをimplementsしたクラスを作成しておく

##方法１：Salesforceの画面上で登録
Apexクラスの一覧画面を表示して、Apexをスケジュールをクリック。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202761/ee699dbb-c8fa-e1db-4341-687dddb19cc3.png)

ジョブ名(日本語を含んでもOK)、Schedulableをimplementsしたクラスを選択し、スケジュールを登録する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202761/9df5eb9a-5c06-8c22-d8e5-83b0a9f487d8.png)

##方法２：開発者コンソールから登録
方法１だと開始日と終了日が必須になるので、終了日が未定の場合はこちらを使用します。
開発者コンソールからDebugタブ>Open Execute Anonymous Windowを選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202761/2e573f6e-af03-0afc-5529-438da5ec67fb.png)
登録用コードを書いて、Executeを実行します。

```
// スケジュールを登録する
ScheduleTestBatch batch = new ScheduleTestBatch();
// 5時に実行
String sch = '0 0 5 1 * ?';
String scheduleId = System.schedule('ジョブ名', sch, batch);
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/202761/7d9ed4c1-cfa9-fb18-befc-95cacc3a277f.png)

##確認方法
設定画面のジョブ>スケジュール済みジョブで確認できます。
CUIなサーバーだけでradikoを聞きたい！

どうも。かちおです。ちょっと作業をしているときに、無性にコマンドラインだけでラジオを聞きたくなりますよね？ということで自分なりにどうすれば再生できるか色々と試してみました。

## 方法1

https://gist.github.com/matchy2/3956266 で紹介されているスクリプトを使う方法です。
これだと録音しかできないのですが、有志の方が再生にも対応させるシェルスクリプトを書いてくれていました。

https://mtunn.wordpress.com/2017/02/08/raspberrypi3%E3%81%A7radiko/

swftoolsというパッケージが必要です。`sudo apt install swftools`で導入できました。

```bash
$ ./radiko.sh -p BAYFM78
```

で聞くことができた。この`BAYFM78`みたいなキー（文字列）は、radiko.jpの各ラジオ局のページのURLで確認できる。w3mとか使えばサーバーでもok。

自分で各ラジオ局のキーをまとめてみたら以下のようになった。

| ラジオ局  | キー |
|:--------------:|:---:|
| NHK第1         | `JOAK`
| NHK第2         | `JOAB`
| NHK FM         | `JOAK-FM`
| FM横浜         | `YFM`
| 文化放送        | `QRR`
| ラジオNIKKEI第1 | `RN1`
| ラジオNIKKEI第2 | `RN2`
| Jwave          | `FMJ`
| bayfm78        | `BAYFM78`
| TBSラジオ       | `TBS`
| NACK5          | `NACK5`
| TOKYOFM        |  `FMT`
| ニッポン放送     | `LFR`
| ラジオ日本      | `JORF`
| 放送大学        | `HOUSOU-DAIGAKU`
| InterFM       | `INT`

もしバッググラウンドで動かしたいなら以下のように。

```
$ ./radiko.sh -o key >/dev/null 2>&1 &
```

ただmplayerの出力である標準出力と標準エラー出力を捨ててるだけ。

## 方法2

上のがめんどくさかったので、もっと簡単にできないかと思い、radiko.jpをchrome開発者ツールで見ているとm3u8なリクエストを発見。ということで以下のようにすればもっと簡単にradikoを聞くことができた。

1.  mplayerをサーバーにインストール
2.  radiko.jpをなんらかのブラウザで開き、開発者ツールのnetwork欄から拡張子が`.m3u8`なリクエストを見つけ、そのURLをコピー。
3.  mplayerの引数にURLを渡すだけ。

たとえばbayfm78は以下のようになった。

```
$ http://f-radiko.smartstream.ne.jp/BAYFM78/_definst_/simul-stream.stream/chunklist_w710715257.m3u8
```

で、これの問題は時間が立つとこのURLが変わってしまうこと。
なので素直に方法1を使うことにした。

----

結局他の人が書いたブログを引用するだけになってしまったけど、まあとりあえずこれでサーバーでラジオが聞けるね！
やったね！
AWS Linux EC2 インスタンスに　Lucee　を　インストール

Adobe ColdFusion　のCFMLに互換性があるLuceeをAWS上で使う手順です。

Luceeについては、http://lucee.org/
を参考にして下さい。

なお、基本的にAmazonLinuxAMIへのインストールを想定して書いてます。

SSHでインスタンスに入ってから、

Luceeをダウンロードするのですが、例えば、ｔｍｐにダウンロードしましょう。どこでも、使いやすい場所で結構です。

cd /tmp

http://lucee.org/のサイトからDownloadURLをコピーしてきます。
例えば、以下のように！


`curl -O http://d8yjolse1mixx.cloudfront.net/downloader.cfm/id/143/file/lucee-4.5.2.018-pl0-linux-x64-installer.run`

ダウンロードが出来たら、Permissionの変更をします。

`
chmod u+x lucee-4.5.2.018-pl0-linux-x64-installer.run
`

もし、上手くいかなかったら、sudoで行なって下さい。

では、インストールを行います。

sudo ./lucee-4.5.2.018-pl0-linux-x64-installer.run

を行なうと、インストールは完成です。指示などが出てきますが、内容に沿って対応して下さい。

では、実際に作動しているかチェックしてみましょう。
Luceeのコントロールパネルは8888ポートを開けることで利用することが出来ます。

8888ポートの解放は、AWSのEC2ダッシュボードで対象のインスタンスのセキュリティグループのインバウンドのポートを８８８８を許可します。

そうすれば、インスタンスに結びついているIPアドレス:8888(例えば、123.123.123.123:8888)
で確認出来るはずです。

では、サーバが起動したら同時にLuceeを起動する方法としては

sudo cp /opt/lucee/lucee_ctl /etc/init.d/

sudo service lucee_ctl restart

sudo chkconfig lucee_ctl on

をしたら
sudo reboot
でインスタンスを再起動して完了です。

以上がカンタンなLuceeをインストールする手引です。
「実践コンピュータビジョン」の全演習問題をやってみた

#「実践コンピュータビジョン」の全演習問題をやってみた
###はじめに
夏前頃ですが積読になっていた「[実践コンピュータビジョン](https://www.oreilly.co.jp/books/9784873116075/)」を一通り読んで演習問題を全問やってみました。（正しい答えを出しているかどうかわかりませんが、自分なりに全部やってみました。私はカメラ系の画像処理は多少経験がありますがコンピュータビジョン系については勉強中です）
その内容をgithubに上げたものがこちらになります。
https://github.com/moizumi99/CVBookExercise

「実践コンピュータビジョン」は翻訳版が刊行されてから４年、原書からは５年がたっており、すでに現在の状況といろいろと食い違いがでてきています。例えば、書籍中で使われている画像データベースででもう手に入らないものがいくつか現れていますし、書籍中で利用しているWebサービスで既に終了しているものもありました。そもそもpython自体書籍で扱われている２系から３系に移行しています。（こういった点をみていると、技術系の書籍には読むべき旬があるということを痛感します。）

また、書籍では特に触れられていなくても、実際やってみると追加の準備が必要な部分などもあります。例えば、OpenCVを使ってUSBカメラから画像をキャプチャする課題では、私の環境ではバイナリー配布のOpenCVではカメラを認識せず、OpenCVのビルドから始める必要がありました。
また課題中書籍中で作成されたライブラリーを使う部分も多いのですが、どういうわけか書籍のコードがそのまま動かず変更する必要がある部分も見つかりました。おそらくライブラリーやパイソン自身のバージョンの関係かと思います。

この後の詳細編では、こういった点についてとった代替方法（画像データベース、Webサービス）、また書籍のコードに加えた変更などを、演習の内容と一緒にまとめてあります。

###詳細編
詳細については順次公開していきます。（１１月５日、全十章分の記事をアップしました）

[「実践コンピュータビジョン」の全演習問題をやってみた。詳細編　第１章　基本的な画像処理](https://qiita.com/moizumi99/items/b0bd6939d29e9de662f4)
[「実践コンピュータビジョン」の全演習問題をやってみた。詳細編　第２章　画像の局所記述子](https://qiita.com/moizumi99/items/76a51c9a1ea4e9ddb84d)
[「実践コンピュータビジョン」の全演習問題をやってみた。詳細編　第３章　画像間の写像](https://qiita.com/moizumi99/items/a2261ff0e877a0c1a336)
[「実践コンピュータビジョン」の全演習問題をやってみた。詳細編　第４章　カメラモデルと拡張現実感](https://qiita.com/moizumi99/items/b0a2c84896ce5e0deb8a)
[「実践コンピュータビジョン」の全演習問題をやってみた。詳細編　第５章　多視点幾何](https://qiita.com/moizumi99/items/594757fb69b996c7ce36)
[「実践コンピュータビジョン」の全演習問題をやってみた。詳細編　第６章　画像のクラスタリング](https://qiita.com/moizumi99/items/cb6768fd6f0b1f8110b8)
[「実践コンピュータビジョン」の全演習問題をやってみた。詳細編　第７章　画像検索](https://qiita.com/moizumi99/items/5248814765c723498048)
[「実践コンピュータビジョン」の全演習問題をやってみた。詳細編　第８章　画像認識](https://qiita.com/moizumi99/items/00f8a2096fbe042da350)
[「実践コンピュータビジョン」の全演習問題をやってみた。詳細編　第９章　画像の領域分解](https://qiita.com/moizumi99/items/0e6bef5f3defd37ea855)
[「実践コンピュータビジョン」の全演習問題をやってみた。詳細編　第10章　OpenCV](https://qiita.com/moizumi99/items/6eb3a69ef0ddf1e85f1b)
Gmail > bug? > メール日時の分が異なる > 一覧表示[受信日時] | 詳細表示[送信日時]

```txt:動作環境
Gmail (2017年10月30日現在)
```

以下のメール日時の分が異なる。

- 一覧表示 (例. 12:01)
- 詳細表示 (例. 12:00)

分のずれは、ある場合もあれば、ない場合もあるようだ。

詳細のメールが分かっている時に、該当メールを一覧から探そうとして戸惑った。

12:00:49というのがメール詳細の「Date」だった。

### 教えていただきました

@tenmyo さんに教えていただいたように、受信日時と送信日時の違いのようです。

情報感謝です。
Windows コマンド robocopy

# Robocopy

robocopy "コピー元共有フォルダ" "コピー先共有フォルダ" /E /R:0 /W:0 /MIR /LOG+:"ログファイル名" /FP /TEE /ipg:5 /COPY:DT /XJD /XJF /B /NP

 /E 空のディレクトリを含めてコピーする
 /R:1 失敗したコピーへのリトライ回数
 /W:1 再試行と再試行の間隔(秒)
 /MIR バックアップ元とバッアップ先をミラーリング
 /LOG+ ログファイル指定
 /FP ログ中、ファイルのありかをフルパス表示
 /TEE ログをファイルをログの両方に出力
 /ipg:5 帯域をすべて使わないように、1ブロックコピーするごとに5ミリ秒まつ
 /COPY:DT コピーファイルに引き継ぐ情報を指定 D=ファイルのデータ、T=ファイルのタイムスタンプ　デフォルトの/COPY:DTA=ファイルのデータ、ファイルのタイムスタンプ、アクセス権からアクセス権を除外
 /XJD:ディレクトリに対するシンボリックリンクを除外
 /XJF:ファイルに対するシンボリックリングを除外
 /B:アクセス制御リスト (ACL) など、セキュリティの構成情報をコピーしない。コピー先のフォルダーから構成情報を継承する。
 /NP:進行状況を出力しない


https://technet.microsoft.com/ja-jp/library/cc733145(v=ws.10).aspx
Fall Creators UpdateでISOがマウントできなかった問題について

最近 Windows 10 Fall Creators Updateを導入したのですが、以下のようなエラーメッセージが出て、ISOファイルがマウントできない問題が発生しました。
同じ問題に悩まされた人のために記事にします。
「ファイルのマウント中に問題が発生しました。」
![スクリーンショット (3).png](https://qiita-image-store.s3.amazonaws.com/0/134179/5b50e41f-8ad8-9afe-6707-118484474a78.png)

##環境
ISOファイルをCドライブではなくそれ以外に置いている状態。

+ Cドライブ（OSをインストールしたドライブ)
+ それ以外（microSD,USB)

##予想
システムドライブ以外にあるISOファイルはマウントできないのではないか？

##解決方法
Cドライブにコピーしてからマウントする。
USBにISOファイルを入れている場合もCドライブにコピーしてからマウントする。

##原因
細かい原因はわかりません。ただ、一度ダウングレードしたらマウントできたので、Fall Creators Updateが原因だと考えられます。
クリーンインストールも試みたのですが、効果はありませんでした。
システムドライブと同一のHDD・SSDで、パーティションで分かれているドライブの場合はどうなのかなと思いましたが、そこまでやる気がなかったので試してません（検証求む）
【メモ】ブラウザアプリをネイティブアプリ化する

動機：よく使うブラウザアプリをネイティブアプリ(デスクトップアプリ)にしたい

##ソース
https://github.com/jiahaog/nativefier

##NodeJSのインストール

[リンク](https://nodejs.org/en/download/)

・インストールが出来ているかの確認

```
$ node -v 
```

##nativefierのインストール
```
$ sudo npm install nativefier -g 
```


##アプリ化
```
$ nativefier --name " アプリ名 " " アプリ化したいウェブアプリのリンク "
```


###例
```
$ nativefier --name "Messenger" "https://www.messenger.com/"
```


##アプリの場所
```
/Users/ユーザー名/Net-darwin-x64
```
Meldを使ってみる

#Meldを使ってみる

##概要
ファイルの差分を取得する際に便利なMeldというソフトを使ってみたいと思います。

##環境

Windows8
Meld3.16.2

##詳細
ファイルの差分を取得する際に便利なMeldというソフトを使ってみます。

###Meldのインストール

まずは、Meldのインストーラのダウンロードからです。
[Meldのインストーラをダウンロード]
(http://meldmerge.org/)

サイトを開くと
Windows: Meld 3.16.2 6August 2016と書いてあるのでそこをクリックします。

![画像１.JPG](https://qiita-image-store.s3.amazonaws.com/0/195114/a003f3e2-b00d-1b95-7c46-31cde7a474dc.jpeg)


すると、インストーラであるMeld-3.16.2-win32.msiがダウンロード出来ます。
それでは、Meld-3.16.2-win32.msiを起動させてMeldを好きな場所にインストールしてください。

インストールし終わった後は、exeファイルをショートカットとしてデスクトップに出しておくと便利です。

![画像２.JPG](https://qiita-image-store.s3.amazonaws.com/0/195114/f24e2522-37ac-cd5d-024c-e086957b55ce.jpeg)




###比較するファイルの生成

デスクトップに適当に比較対象となるtest1.txtとtest2.txtを下記の内容で生成します。
日本の有名な童話である桃太郎の話を使います。


```bash:test1.txt
むかしむかし、
あるところに、
おじいさんとおばあさんが住んでいました。
おじいさんは山へしばかりに、
おばあさんは川へせんたくに行きました。
おばあさんが川でせんたくをしていると、
ドンブラコ、ドンブラコと、
40kgほどの大きな桃が流れてきました。

```


```bash:test2.txt
むかしむかし、
あるところに
おばあさんとおじいさんが住んでいました。
おじいさんはマウンテンへしばかりに、
おばあさんは川へせんたくに行きました。
おばあさんが川でせんたくをしていると、
ドンブラコ、ドンブラコ、ドンブラコ、と、
400kgほどの大きな桃が流れてきました。
まあ、でっかい！！
```

test1.txtとtest2.txtは微妙に違います。
それでは、test1.txtとtest2.txtをMeldを使って比較していきましょう。



###ファイルの比較

先ほどインストールしたMeldを起動しましょう。

Meldを起動すると
File comparsion（ファイルの比較）
Directory comparsion (ディレクトリの比較)
Version control view　など
様々なボタンが操作できる画面が出現します。

![画像３.JPG](https://qiita-image-store.s3.amazonaws.com/0/195114/06169b4a-e293-af63-0f5b-2261e931c4ad.jpeg)


今回は、File comparsionを使います。
File comparsionを押すと下にNoneと書かれたボタンが出現します。
そのボタンを押してデスクトップに配置したtest1.txtを選択してください。
同様にDirectory comparsionの下にもNoneと書かれたボタンが出現するので同じようにtest2.txtを選択してください。



すると下記のような差分を表示してくれる画面になります。
![画像４.JPG](https://qiita-image-store.s3.amazonaws.com/0/195114/251be7dd-3d39-af86-6d9f-4cc8945394e5.jpeg)



矢印を使ってどこに差分が生じているのかを教えてくれます。
とても見やすいです。

また矢印をクリックすることによって比較対象のファイルの変更箇所を取り込むことも可能です。

たとえば、test1.txtにtest2.txtの下の部分の変更を取り込みたいのであれば、ここの矢印を押して、、、

![画像５.JPG](https://qiita-image-store.s3.amazonaws.com/0/195114/c4cebabc-4929-9039-75b9-acdd03177e30.jpeg)


こんな感じで取り込める。
![画像６.JPG](https://qiita-image-store.s3.amazonaws.com/0/195114/30292901-11fd-5e61-6ca5-a2708c11b2fc.jpeg)


とても便利なので今後も愛用していきたいと思います。
個人的にはdiffコマンドより見やすくて使いやすいです。

また便利なソフトを見つけら記事にしていきたいと思います。

以上です。
Cで完全数を判定する

#前置き
##はじめに
この記事は中学数学ではありません。
基本的に僕は興味の持ったことは全部やる方針なので色々な公式（ツェラーの公式のような）や、法則、アルゴリズムを今後もやっていきたいと思っています。できたらコメントで教えていただいたら嬉しいです。

##完全数について

> *完全数*って？
>> その数以外の約数の和がその数に等しい**自然数**

簡単な完全数は`6`です約数が`1 , 2 , 3`で


```math


1 + 2 + 3 = 6 = 1 * 2 * 3


```


という感じです。
Wikipediaを見た所非常に稀なようで、五つ目にはもうすでに3000万を超えているようです。

#Cで完全数を判定する
##変数を用意（宣言）する
最初はなるべく少なく済まそうと2つで頑張ったのですが大きい数字になった時のための処理速度を見通して3つでいきました。

判定する数字とfor文のカウンタ、約数の和の変数を宣言します。

```main.c

    int number;     //判定する自然数を格納する変数
    int i;          //for文用のカウンタ
    int wa = 0;     //約数を足していく変数

```

Swiftでは自然数の型`UInt64`型などがあるのですがC言語についてはあまり詳しくないのでとりあえず`int`型にしました

##判定する自然数を取得する


いつものように`printf`で入力を促して`scanf`で自然数を取得します

```main.c

    printf("自然数を入力してください = ");      //printfで入力を促す
    scanf("%d", &number);                  //入力した自然数をnumberに格納

```

##本格的な計算
いよいよプログラムを書いていきます
仕組み的にはカウンタを約数にしてどんどん用意した変数に足していくプログラムになっています

```main.c

    //1~number-1の約数を調べるためのfor文
    for (i = 1; i < number; i++) {
        //numberがiで割り切れた時の条件（iがnumberの約数）
        if (number % i == 0) {
            //waにiを足していく
            wa += i;
        }
    }

```

そして最後に審判の時ですw

```main.c

    //waがnumberと等しかったら（完全数だったら）
    if (wa == number) {
        printf("その数字は完全数です");       //完全数と判定
    }
    //wa（約数）が1だったら（素数）
    else if (wa == 1){
        printf("もしかしてそれは素数カモ！？");       //素数と判定
    }
    //それ以外の数
    else {
        printf("完全数ではありません");       //完全数（や素数）ではないと判定
    }

```

気分で「素数かもしれない」判定も追加しました。(本当に素数かどうかは自信がないのでw)

#ソースコード

```main.c

#include <stdio.h>

int main() {
    
    int number;     //判定する自然数を格納する変数
    int i;          //for文用のカウンタ
    int wa = 0;     //約数を足していく変数
    
    printf("自然数を入力してください = ");      //printfで入力を促す
    scanf("%d", &number);                  //入力した自然数をnumberに格納
    
    //1~number-1の約数を調べるためのfor文
    for (i = 1; i < number; i++) {
        //numberがiで割り切れた時の条件（iがnumberの約数）
        if (number % i == 0) {
            //waにiを足していく
            wa += i;
        }
    }
    
    //waがnumberと等しかったら（完全数だったら）
    if (wa == number) {
        printf("その数字は完全数です");       //完全数と判定
    }
    //wa（約数）が1だったら（素数）
    else if (wa == 1){
        printf("もしかしてそれは素数カモ！？");       //素数と判定
    }
    //それ以外の数字
    else {
        printf("完全数ではありません");       //完全数（や素数）ではないと判定
    }

}

```

完全数は少ない上に、とんでもなく大きい数字なので判定できる数が本当に限られていますが、倍積完全数判定の機能を追加するなどして使う機会を増やせると思います。

ちなみに僕がやった時は33550336（五番目の完全数）までしかできませんでした、、、

ありがとうございました。
個人的React周りベストプラクティス⑤ - Reduxディレクトリ構成編

#前の記事
前回：[個人的React周りベストプラクティス④ - Lamdaパッケージ編](https://qiita.com/enshi/items/68ad5cbe6010b2d12ce9)
一番始め：[個人的React周りベストプラクティス① - 構成編](https://qiita.com/enshi/items/e6ad8c91168cfe8a88da)

#ディレクトリ構成
```
src
├ actions
│   ├ hogeHoge.js             hogeHogeのcreateAction
│   └ fugaFuga.js             fugaFugaのcreateAction
│
├ components
│   ├ App                     グローバルメニューを表示したり、ルーティングを設定したりするファイルが入ったディレクトリ
│   │  └ App.js
│   ├ HogeHoge
│   │  ├ HogeHoge.js          hogeHogeのPresentaionalのルートコンポーネント（１ページにつき１つ）
│   │  └ HogeHogeContainer.js hogeHogeのContainer Component（１ページにつき１つ）
│   └ FugaFuga
│      ├ FugaFuga.js          fugaFugaのPresentaionalのルートコンポーネント（１ページにつき１つ）
│      └ FugaFugaContainer.js fugaFugaのContainer Component（１ページにつき１つ）
│
├ constants
│   ├ common.js               共通で使う定数
│   ├ hogeHoge.js             hogeHogeでのみ使う定数
│   └ fugaFuga.js             fugaFugaでのみ使う定数
│
├ css
│   ├ common.css              共通で使うCSS
│   ├ hogeHoge.css            hogeHogeでのみ使うCSS
│   ├ fugaFuga.css            fugaFugaでのみ使うCSS
│   └ reset.css               リセットCSS
│
├ lib                         ライブラリディレクトリ
│
├ reducers
│   ├ index.js                すべてのReducerをcombineReducersで１つのReducerにまとめるファイル
│   ├ hogeHoge.js             hogeHogeのReducer
│   └ fugaFuga.js             fugaFugaのReducer
│
└ index.js
```
##簡略図
Reducer、createAction、コンポーネントはドメイン毎にわける

1ページに付き1つのContainer Componentが存在し、1つのPresentaional Componentと紐づく
その下はツリー構造で作る
![image.png](https://qiita-image-store.s3.amazonaws.com/0/156086/82ae8877-69b9-05b5-be08-ae1650bbabde.png)


#Container ComponentとPresentaional Component
JSXを書くのはPresentaional Component、createActionとPresentaional Componentの橋渡しをするのがContainer Componentである。
そのため、Container ComponentにJSXは書かない。

また、bindActionCreatorsを使用しているため、createActionを増やす度にContainer Componentを修正する必要がなく、一度ファイルを作ってしまえば変更することはない。

```js:Container_Componentの例（どのファイルもほぼ同じ　import部分とstateの中身のみ変えてコピペ）
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';

import Component from './HogeHoge';
import * as Actions from './../../actions/hogeHoge';


const mapStateToProps = (state) => (state.HogeHoge);

const mapDispatchToProps = (dispatch) => (bindActionCreators(Actions, dispatch));


const Container = connect(
  mapStateToProps,
  mapDispatchToProps,
)(Component);

export default Container;
```
#次の記事
[個人的React周りベストプラクティス⑥ - 開発編](https://qiita.com/enshi/items/289e579620ca95f3adab)
Object Pascal の文字・文字列の小ネタ

#文字と文字列について

ここでは文字と文字列の記述についてを記載します。
小ネタなので、それ以外の文字列の内部データ形式などについてはこちらをどうぞ。

[文字列の内部データ形式](http://docwiki.embarcadero.com/RADStudio/Tokyo/ja/%E5%86%85%E9%83%A8%E3%83%87%E3%83%BC%E3%82%BF%E5%BD%A2%E5%BC%8F%EF%BC%88Delphi%EF%BC%89#.E7.9F.AD.E3.81.84.E6.96.87.E5.AD.97.E5.88.97.E5.9E.8B)

##Object Pascal で文字を表す方法
1. '' シングルクォートを使う
2. # を使う
3. ^ を使う

```delphi
var
  Ch: Char;
begin
  Ch := 'A'; // (1) の方法
  Ch := #65; // (2) の方法（１６進数で Ch := #$41 とも書けます）
  Ch := ^M;  // (3) の方法（^A = #1 で始まり全ての文字が使えます。主に制御文字を書くのに使います） 
end.
```
##Object Pascal の文字・文字列の連結
1. 足し算
2. 無

```delphi
const
  Str1 = 'ABC' + 'DEF';    // (1) の方法。足し算で連結します
  Str2 = 'ABC'#13#10'DEF'; // (2) の方法。文字列と上記２，３で表現される文字の間に
  Str3 = 'ABC'^!'DEF';     // 空白など何も書かないと連結されます
```

##Object Pascal でシングルクォートを記述する方法

1. 文字コードを使う
2. '' を使う
3. '''' を使う

```delphi
const
  SQ1 = #39;    // (1) の方法。コードで指定します
  SQ2 = 'It''s' // (2) の方法。文字列中（文頭・文尾はNG）の場合は '' でシングルクォートを表します
  SQ3 = '''';   // (3) の方法。一個だけ指定するときなど。上記の文字が無い版
```

##ちなみに
改行については System.pas に sLineBreak として宣言されています。
中身は Platform 依存です（Windows: #13#10, POSIX: #10）。

他にも[パスの区切り文字](http://docwiki.embarcadero.com/Libraries/Tokyo/ja/System.IOUtils.TPath_Properties)や[ファイル名に使えない文字の集合](http://docwiki.embarcadero.com/Libraries/Tokyo/ja/System.IOUtils.TPath.GetInvalidFileNameChars)などは [TPath](http://docwiki.embarcadero.com/Libraries/Tokyo/ja/System.IOUtils.TPath) から取れたりします。

他にも色々定義済みのモノがあるので、ライブラリのソースを読むといいと思います。

#まとめ
古の Pascal の書き方でもちゃんとコンパイル通るのすごい。
Angular で終了前に処理する

# コンポーネントを破棄する前に処理をする

* Angular コンポーネントの Lifecycle Hooks の ngOnDestroy を利用する

```ts
// 任意のコンポーネント
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnDestroy { // ngOnDestroy を有効にするため OnDestroy の実装であることを宣言する
  ngOnDestroy() {
    // コンポーネント破棄前の処理
  }
}
```

# ブラウザを閉じる前に処理をする

* unload イベントのコールバックとして処理を登録する
* unload はブラウザやタブを閉じようとした際やリロードの際に実行される

```ts
// 任意のコンポーネント
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  @HostListener('window:unload', [ '$event' ])
  unloadHandler(event) {
    // ブラウザを閉じる前に実行したい処理を記述
  }

  @HostListener('window:beforeunload', [ '$event' ])
  beforeUnloadHandler(event) {
    // ついでにこちらはページ移動前の確認イベント
  }
}
Google Translation API 利用メモ【Python】

# セットアップ
クライアントのインストール

```
pip install --upgrade google-api-python-client
easy_install --upgrade google-api-python-client
```

## サービスアカウントキー(jsonファイル)を取得

Google Cloud Platfrom -> APIとサービス　-> 認証情報
1.認証情報の作成
2.サービスアカウントキーで新しいサービスアカウントキーとjsonを選択 -> 役割はProjectのオーナーにしておけば全権得られるらしいので、それにしておいて適当な名前をつけて作成
3.jsonファイルゲット。これをクローラープログラムのあるところに移動しておく

## Clowd SDKをインストール
https://cloud.google.com/sdk/docs/quickstart-mac-os-x
からインストール
[このサイト](http://www.apps-gcp.com/cloud-sdkinstall-commentary/)の解説がわかりやすい

## クライアントライブラリのインストール

```
pip install --upgrade google-cloud-translate
```

# サンプルプログラム

https://cloud.google.com/translate/docs/reference/libraries#client-libraries-install-python がお手本。
環境変数の設定がうまく行かなかったので、コードの中で定義するようにした。

```
# Imports the Google Cloud client library
from oauth2client.client import GoogleCredentials
from google.cloud import translate
import os

# add environment variable
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "jsonまでのpath"

# Certification
credentials = GoogleCredentials.get_application_default()
# Instantiates a client
translate_client = translate.Client()

# The text to translate
text = u'Hello, world!'
# The source and target language
trans_from = 'en'
trans_to = 'ja'

# Translates some text into Japanese
translation = translate_client.translate(text, source_language=trans_from, target_language=trans_to, model='nmt')

print(u'Text: {}'.format(text))
print(u'Translation: {}'.format(translation['translatedText']))
print(translation)
```
Angular のログサーバーを Go でサクッと作る

# はじめに

* Angular での開発中にログを出したいが `ng serve` の出力にそのまま出す方法がなさそうだった。
* window の unload イベント中の処理のログが欲しかったので `console.log` だと難しそう。
* ということで Go でリクエストを表示するだけの http サーバーを立ち上げて使ってみる。

# コード

* ほとんど普通に net/http サーバーを実行してリクエストを表示するだけ
* サーバーとクライアント共にローカルで実行するが、ポートが異なり別ホスト扱いになるので、CORS できるように `github.com/rs/cors` でハンドラをラップする

```go:server.go
package main

import (
  "net/http"
  "log"
  "io/ioutil"
  "github.com/rs/cors"
)

func main() {
  handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    b, err := ioutil.ReadAll(r.Body)
    log.Printf("BODY: %+v, ERROR: %+v", string(b), err)
  })
  log.Fatal(http.ListenAndServe(":8080", cors.Default().Handler(handler)))
}
```

# ログサーバーの実行

```
go run server.go
```

# Angular でログの送信

* 任意の Component でログを送信する
* Http クライアントを利用するため[ドキュメント](https://angular.io/guide/http)にしたがって `app.module.ts` で `@NgModule` の `imports` パラメータに `HttpClientModule` を追加して DI できるようにしておく

```ts

// 任意の Component
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  // ログ送信用の HttpClient 初期化
  constructor(private http: HttpClient) {
  }

  @HostListener('window:unload', [ '$event' ])
  unloadHandler(event) {
    // ログ送信実行
    this.http.post("http://localhost:8080", {message: 'App Component unload'}).subscribe();
  }
}
```
Terraform の Vault Provider を試す on AWS

Terraform 0.8 から追加されている Vault Providerを使用して
AWS の Credential を tfvars や環境変数ではなく、Vault から読み込んでみます。

# Vault とは
Hashicorp社がリリースしている機密情報(secret)を管理するためのツールです。
詳細についてはこちらのタグにわかりやすい記事がたくさんありますのでご参照ください。
https://qiita.com/tags/Vault

# やってみる
## Static Secretの作成
Vault を開発モードで起動します。
開発モードではメモリ上に secret が記録され、停止時には消去されます。
`$ vault server -dev` ※フォアグラウンドで実行され続けます

クライアントからvaultを操作するため、VAULT_ADDR環境変数を設定します。
`$ export VAULT_ADDR=http://127.0.0.1:8200`

※開発モードではTLSなし、また起動時点で Unseal、root でログインされた状態です。
実際の環境では Vaul tへのアクセスは Unseal Key よるロック解除とユーザ認証が必要になります。
このあたりのイメージは公式の [Interactive Tutorial](https://www.vaultproject.io/#/demo/0) を体験していただくとよいかと思います。

AWS のアクセスキー/シークレットアクセスキーを静的に書き込みます。

```
$ vault write secret/aws_test access_key=xxxxxxxxxxxxxx secret_key=xxxxxxxxxxxxxxxxxxxx
Success! Data written to: secret/aws_test
```
shell の history に残したくない場合は、JSON で記述し、@ でファイルを指定します

`$ vault write secret/aws_test @data.json`

## TFファイルを作成する
vault_generic_secret データソースを使用します。
[Terraform Module Registry](https://registry.terraform.io/) の [ec2-instance モジュール](https://registry.terraform.io/modules/terraform-aws-modules/ec2-instance/aws/)を使用して、EC2を起動しました。

```main.tf
data "vault_generic_secret" "aws_test" {
  path = "secret/aws_test"
}

provider "aws" {
  access_key = "${data.vault_generic_secret.aws_test.data["access_key"]}"
  secret_key = "${data.vault_generic_secret.aws_test.data["secret_key"]}"
  region     = "ap-northeast-1"
}

# fileter latest AMI
data "aws_ami" "amazon_linux" {
  most_recent = true

  filter {
    name = "name"
    values = [
      "amzn-ami-hvm-*-x86_64-gp2",
    ]
  }

  filter {
    name = "owner-alias"
    values = [
      "amazon",
    ]
  }
}

module "ec2-instance" {
  source = "terraform-aws-modules/ec2-instance/aws"

  name  = "aws_test_ec2"
  count = 1

  ami                    = "${data.aws_ami.amazon_linux.id}"
  instance_type          = "t2.micro"
  key_name               = "keyname"
  vpc_security_group_ids = ["sg-12345678"]
}
```

## 実行
```
$ terraform init
$ terraform plan
$ terraform apply
```
plan結果の一部

```
$terraform plan
Refreshing Terraform state in-memory prior to plan...
T he refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

data.vault_generic_secret.aws_test: Refreshing state...
data.aws_ami.amazon_linux: Refreshing state...
以下略..
```

Vault が Unseal されていない状態では以下のようなエラーが出力されます

```
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

Error refreshing state: 1 error(s) occurred:

* provider.vault: failed to create limited child token: Error making API request.

URL: POST http://127.0.0.1:8200/v1/auth/token/create
Code: 503. Errors:

* Vault is sealed
```


#注意点
Vault から読み取ったデータは tfstate には平文で記録されてします。。。
tfstate の管理は厳密に行う必要があります。


#参考URL
https://www.vaultproject.io/intro/getting-started/dev-server.html
https://www.terraform.io/docs/providers/vault/d/generic_secret.html
https://www.hashicorp.com/blog/terraform-0-8.html#vault

以上です。
Carbon - 「本日を含む一ヶ月以内」であるかどうかチェック


## ポイント

- `staftOfDay()` で時刻をリセットする
- Carbonは `Carbon::now()` を上書きする
	- `copy()` を忘れずに
- `between` は第3引数で `=` ありの `>` `<`かどうかを指定
	- trueのとき `=` あり

```php
Validator::extend("WithinAMonth", function ($attribute, $value, $parameters, $validator) {
    if ($value && \DateTime::createFromFormat("Y/m/d", $value)) {
        $date = Carbon::createFromFormat("Y/m/d", $value)->startOfDay();
        $today = Carbon::now()->startOfDay();
        $nextMonthDay = $today->copy()->addMonth();
        if ($date->between($today, $nextMonthDay, true)) {
            return true;
        }
        return false;
    }
    return false;
});
```
windows10で日本語入力できなくなった時に対応したこと

1. ログインしても日本語入力ができなくなった
＝＞なんでやー
　　再起動すればいけるでしょ〜
　　＝＞３回ぐらいしたけど、むり〜
　　　　orz...
　
 
2. Windows10 on Mac with Parallelsだからそれのせいかも！
＝＞いや、言語バーがそもそも表示されていないぞ。。。
　
3. とりあえずコンパネの言語の詳細設定で、言語バーを表示させようとする
＝＞でない。。。
　
4. 調べると、「TextServicesFramework」というサービスが起動していないかららしい
＝＞タスクスケジューラで起動させればいいじゃん！
　「リモートコンピュータが見つかりません」とエラーが出てスケジューラー起動しない。。。
　　＝＞心折設計ありがとうございます！
　　　　イベントビューアーでサービス開始時のシステムエラーが出ている。おや・・・？
　　　　「UBPM.dllで致命的な障害！」だってさ。
　　　　「explorer.exe とかを起動するたびに、変なサイトにアクセスしようとするウイルスが感染することで有名」ということは知っているが、、、
　　　　　いたって普通の使い方しかしていない僕はやましいことは何もないのです！
　　　　　＝＞「WindowsUpdateのタイミングでwindowsがなにかやらかしたんじゃないの？」しか思っていませんでした。
　　　　　　　　もうここから日本語では記事が出てこなくなりました。
　
5. とりあえず、タスクスケジューラ起動時に「エラーコード:1067（プロセスが強制終了しました）」と出たので、「Task schedule not started with 1067 error」と検索してみる（それっぽい英語でも検索してくれる、すごいね！）
＝＞[MSのコミュニティサイト](https://answers.microsoft.com/en-us/windows/forum/windows_10-performance/task-scheduler-service-wont-start-error-1067/021f78d7-5cc9-4efd-bbea-b7c6a084ead0)
　　お、自分の現象と同じだ！
　　基本こういうサイトでは、「Resolved」マークがついたAnswerをまず見に行くのは僕だけではないはず！
　　下記は引用です。
> this is the problem that prevent's Task Scheduler forms starting properly. Simply changing Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\Maintenance\State\ReportedState from 3 to 0 with regedit.exe and then going to Manage Computer -> Services -> Task Scheduler and clicking start or rebooting will fix it. 

とりあえず、regedit（レジストリエディタでReportedStateを3 => 0へ直してみる）
**＊自己責任でお願いします**
　　
6. よし、再度タスクスケジューラ起動するぞ。
＝＞起動した！
　
7. これでやっと、「TextServicesFramework」サービス起動できるぞ〜。
8. 起動して実行中になりましたよ〜。
9. 言語バーが無事表示されて、めでたく日本語入力できました。

お疲れ様でした。
fishでtypoしたときに大文字をスペースと小文字に展開して実行する

SanSを使っていると、たとえば`git st`と入力したい時に、よく`gitSt`と入力してしまう。そこで、[zshでtypoしたときに大文字をスペースと小文字に展開して実行する](http://blog.sushi.money/entry/20091215/1260856588)のスニペットを用いていたのだが、シェルをFishに変えてから、またしょっちゅう入力間違ってストレスが再発した。

というわけで、上記のスクリプトをFish用に移植した。

```sh:$HOME/.config/fish/functions/try_fixing_camelized_command_input.fish
function try_fixing_camelized_command_input --on-event fish_command_not_found
    set new (echo $argv | ruby -pe 'sub(/[A-Z]/){" "+$&.downcase}')

    if [ "$argv" != "$new" ]
        echo "=> $new"
        eval $new
        return 0
    end

    return 127
end
```

[ドキュメント](http://fishshell.com/docs/current/commands.html#function)にある通り、コマンドが見つからなかった場合には、Fishが`fish_command_not_found`というイベントをemitしてくるので、これをつかまえてハンドリングしたらよい。

これで、`gitSt`と入力すると、なんかいい感じに`git st`に変えて実行してくれるようになった。

```sh
$ gitSt
fish: Unknown command 'gitSt'
=> git st
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean
```

わあい。

## 追記

[ドキュメント](http://fishshell.com/docs/current/commands.html#function)によると、イベントハンドラーは自動で読み込まれないようなので、一度`config.fish`の中とかで実行してあげないとならないぽい。

```sh：$HOME/.config/fish/config.fish
# try_fixing_camelized_command_input
try_fixing_camelized_command_input
```
let'sencryptのcertbot-autoの使い方　まとめ

調べるとバージョン毎に異なるのか、いろんなサイトで説明が違うので

https://blog.koyama.me/archives/1268
こちらを参考にしました。


##certbot-auto
これが実行できるようにしておくのはいろいろありますがどこも同じです。

```bash:
/usr/local/bin/cert-bot
```
ここがベストですね。


現在のバージョンは、0.19.0です。

```bash:command
certbot-auto
```

このコマンドをオプション無で実行すると、apacheですか？nginxですか？ときいてきますので、従うとconfigファイルを参照してくれてどのドメインですか？ときいてくるので、どれかを選びます。一度にすべてはできないので、ひとつづつ行います。

あとは、httpをhttpsにリダイレクトしますか？ときいてくるので、
私の場合は、自分でリダイレクトする定義を書いていたので、リダイレクトしないを選択しましたが、
リダイレクトさせる場合は、それを選択します。すると定義を勝手に追加してくれます。



最後に、
自動更新は、cronにて

```bash:crontab-e
certbot-auto renew
```
 
これをrootで実行すればOK。タイミングはお任せ。1か月おきくらいでいいんじゃないでしょうか。
AndroidでUTF-8-MACなファイル名をS3からCognito経由でダウンロードするとAccess Deniedになる問題

# 概要

UTF-8-MACなファイル(いわゆるOSXで濁点とかがついているファイル)をS3にアップロードして、Cognito経由でダウンロードしようとするとAccess Deniedとなる問題

```
Access Denied (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied
```

↓OSXで作ったこういうファイル
![image.png](https://qiita-image-store.s3.amazonaws.com/0/56178/24bb478c-6751-13df-d0ce-ed866eb7c6cc.png)

↓実際のソースにコピペするとこんな感じ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/56178/737c6899-1583-f850-aefc-7e3498335810.png)

# 結論

- aws-android-sdk-s3のバージョンを`2.3.+`にする(2.4.+以上だと起きる)
- 最新版2.6.6でも起きる(2017/10/30現在)

```groovy:build.gradle
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    // AWS
    // 2.3.+系では動く
    compile 'com.amazonaws:aws-android-sdk-core:2.3.+'
    compile 'com.amazonaws:aws-android-sdk-s3:2.3.+'
    // 2.4.+系以上では動かない
    //compile 'com.amazonaws:aws-android-sdk-core:2.4.+'
    //compile 'com.amazonaws:aws-android-sdk-s3:2.4.+'
}
```

# 補足

一応[issue](https://github.com/aws/aws-sdk-android/issues/360)立てたのでそのうち治るかもしれないですが、現状はバージョンを下げて対応しています。
ちなみにiOS版では起きないです。AndroidのSDKのバグです。

(そもそもそんな名前のファイルあげるなよって意見もあるかもですが)

# 参考にした記事

- [Cognitoを使って公開されていないS3バケットからファイルを取得する](https://qiita.com/niusounds/items/3d9bb0429716107c3c8c)
Selenium実践入門読んだメモ


# これはなに
Selenium実践入門の個人的な読書メモです。興味のある部分だけメモしています。

# 1章と2章読み飛ばし
- 手動でテストするのつらいよねという話
- Selenium周辺の諸々紹介
	- WebDriverがどの部分かという話
	- ブラウザを操作するスクリプトを書けるよという話など
	- JSON wire protocol などについて

# 3章
各言語でスクリプト書いて動かす方法が書かれている。自分の場合はRubyで書きたいので

```
gem install selenium-webdriver
```

してサンプルスクリプトを書いて実行。

```
ruby sample.rb
```

エラーが出た。なんかダウンロードしないとダメらしい。

```
	Unable to find Mozilla geckodriver. Please download the server from https://github.com/mozilla/geckodriver/releases and place it somewhere on your PATH.
```

言われた通りにする。

https://github.com/mozilla/geckodriver/releases

パス通すのが上手くいかなかったので `/usr/local/bin` に geckodriver（実行ファイル）を置いて再度。


```
~/selenium-sample$ ruby sample.rb
stack backtrace:: Process unexpectedly closed with status: 0 (Selenium::WebDriver::Error::UnknownError)
```

なんかエラー出た。もう一度。

```
~/selenium-sample$ ruby sample.rb
```

上手く行ったようだ。

# 4章
クリック、テキスト入力、チェックボックスのチェックなどなど基本的な動作をスクリプトから行う際のメソッドなどが紹介されている。

4.7にはブラウザの操作について詳しく書かれている。重要そう。

## スクリーンショット
スクリーンショット撮るのは役に立ちそうなので自分のサイトで試してみる。

```ruby:sample.rb
require 'selenium-webdriver'

driver = Selenium::WebDriver.for :firefox
driver.get('http://kumocast.jp')
driver.save_screenshot('./sample.png')
driver.quit
```

![sample.png](https://qiita-image-store.s3.amazonaws.com/0/11316/65e91d43-fdc9-c48e-9ee9-70c13341c1b1.png "sample.png")


撮れた。前職でのエクセルにスクショ貼る作業を思い出しながら実行したので感動した。スクリーンショット撮るのはテスト用途はもちろん、スクレイピングとか情報収集用途でも使えそうな気がして楽しい。

## 待ち処理
Implicit Wait と Explicit Wait で待ち方が違うよという話

# 5章
- ファイル読み込み
- 画像読み込みのエラーチェック
- WebStorageのテスト

などを様々な画面操作をする方法について。

# 6章
- ページオブジェクトパターンの話
    - 大事そう
    - 自分の場合は[一休\.comのE2Eテスト事情 ~ギリギリ話せるところまで話します~ /cybozu\_ikyu\_e2e // Speaker Deck](https://speakerdeck.com/shotaakasaka/cybozu-ikyu-e2e)のスライドで初めてこの言葉を知った

# 9章
- Capybaraを使ったテストの書き方
- 自分の場合は特に言語にこだわりなくてRubyのテストならすでに書いてたのでこれでいいんじゃないかくらいの気持ちでCapybaraを使おうと思った


# 14章
サイボウズでの導入事例

# 15章
DeNAでの導入事例

# 感想
- Seleniumはブラウザ操作の自動化のツールなので必ずしもE2Eテストだけではなく、たくさんのページのスクリーンショットを撮って共有するときなどに使えるなと思った
    - たとえばビジネス的に重要な部分のみ、Selenium撮ったテスト結果（スクリーンショット）をQiita:Teamなどに上げることで、bizサイドと成果物の共有がいい感じにできるんじゃないか。
    - この考えはこの本からというより、[WebアプリケーションでのE2Eテストの取り組みについて – Coiney Product Team – Medium](https://medium.com/coiney-product-team/web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A7%E3%81%AEe2e%E3%83%86%E3%82%B9%E3%83%88%E3%81%AE%E5%8F%96%E3%82%8A%E7%B5%84%E3%81%BF%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6-cd0f3627bcaf) を読んでなるほどという感じ。
- 14章、15章どちらでも上げられているのが実行時間の問題。それを解決するためにCIに工夫（Cybozuの例で紹介されているSelenium Gridなど）をする必要があり、そこらへんの保守もアプリケーション開発のエンジニアが片手間でやるにはなかなか厳しいものがあるという印象を持った。
- やみくもにE2Eテストやろうという前にユニットテストちゃんと書こう、TDDに取り組もう、という話もあるんだけど、やっぱり重要な部分に関してはE2Eテストで重点的にテストをしつつ、それをビジネスの人にも見てもらうという工夫があったらいいのではないかという気持ち。
- もしもテスト実行時間も保守のコストも全く気にする必要がないのであれば全機能E2Eにしてもいいのかもしれないけど、そんな方法はなさそう
- ひとまずは特定の重要な機能に絞ってテストを書いていけばよさそう。
Windows PowerShellでコンソールログ出力

#PowerShellを使う際もTeraTermみたいなログ出力がほしい

TeraTermを使う際、作業のログを取るためにコンソールの入力・出力内容をファイルに出力されている方は多いと思います。TeraTermの場合GUIで操作してログ出力設定を行う、マクロを組んで自動で出力設定をするなど各種方法があります。一方Winwods PowerShellはどうかというと、、もちろん出来るようです！

#設定方法
PowerShellを起動し、次のコマンドを実行するだけです。

```ruby:ログ出力開始コマンド
Start-Transcript <ファイル名> -append
```

ファイルは自分のホームフォルダ（C:\Users\<ユーザー名>）に作られます。コマンド実行後の入力・出力内容が全てファイルに記録されます。
オプションにファイル名のみを指定する場合はファイルの上書きになるので、追記が必要な場合は上記の通り-appendオプションを使用します。

ログ出力を停止したい場合は、次のコマンドを実行します。

```ruby:ログ停止開始コマンド
Stop-Transcript
```

#おまけ
PowerShellを起動する度にコマンド実行するのが面倒な場合は、プロファイル機能を使用すれば自動でログ出力を行うことができます。
[PowerShellのprofile.ps1自分用設定](https://qiita.com/tomoko523/items/87ccaec05a433b02f67e)
ユーザビリティテスト２　シナリオ作成と準備

前回までの流れ
１.[サイト公開前にユーザビリティテストをすることに](https://qiita.com/Yoko3/items/d8630ad719586db8f72d)
２.[ユーザビリティテスト１　目的決めと仮説立て](https://qiita.com/Yoko3/items/5caecf09540af4adf72c)

# タスク決め
以前、社内ポータルサイトを使用している人に「何のために使用していますか？」というアンケートをメンバーが取っていたので、そこから頻度の高い使用目的をいくつか選んだ。
メールによるアンケートで取得したデータだったので、コンテクストがわかりづらく、シナリオを起こすのに足らない部分は、少し追加でデータ収集してもらった。

# シナリオ起こし
選出したタスクに肉付けをして、よくあるシーンを想定してタスクを実行するシナリオにする。なるべく普段に近い状況になるように設計する。
たとえば、「製品について調べる」というタスクを、「以前から製品Aを利用いただいているお客様から電話をいただき・・・と言われ、調べなくてはわからないので折り返すことを伝え、製品Aについて調べる為ポータルサイトを開いた」といった様に具体的にイメージしやすいように肉付けする。


# 事前質問
使ってもらう前に聞いておくべき質問をメンバー内で出し合って、決める。
・出社してからのおおまかな行動の流れ
・社内ポータルサイトの使用頻度、方法
など、評価してもらう人についての質問が中心に考える。



# 事後質問
使ってもらった後に聞いておくべき質問をメンバー内で出し合って、決める。
・操作時に想定外のことをした場合の理由
・悩んだり止まった場所があれば理由
・操作をした際に見辛い文字の有無
・今回アイコンに不安があったので、全アイコンの意味を尋ねる
など、操作してもらった結果についての質問を中心に考える。

# 台本にまとめる
全体の流れを台本にしてまとめておく。ここで時間配分も決めておく。

１.挨拶 -１分- 
２.注意事項 -１分-　
３.事前質問 -３分-
４.テスト実施 -１５分-  ＊タスク３つなら、１つ５分で計１５分
５.事後質問 -５分-
６.お礼 -１分-



# 機材の準備
ユーザビリティテストを実施する上で、必要なものをリストにして、用意。

| 用途       |       用意する機材 |
|:-----------------|:------------------|
| テストを録画する          |             iPhoneと三脚|
| 操作してもらう機器とサービス          |           普段仕事中使用しているPCを持参してもらい|
| 記録係がメモをとる          |           ノートに筆記　もしくは　PC|
| 記録係が操作を見る          |           ディスプレイ１台|
| 実施する場所          |          社内の空いてるテーブル|

ユーザビリティテスト実施時のイメージ
![memo.png](https://qiita-image-store.s3.amazonaws.com/0/55407/15ca8763-7471-9206-59ff-72c7520bf2cb.png)

次は、パイロットテストを実施へ。
eb sshコマンドを使うためには

# eb sshコマンドを使うためには

cd 対象プロジェクトフォルダ
pip install awsebcli --upgrade --user

key.pemを~/.ssh/　直下にコピー
chmod 600 ~/.ssh/*.pem

もしかしたら、フォルダ権限とownerに変更も必要
sudo chmod 700 /home/user/.ssh
chown user:user /home/user/.ssh

vi ~/.ssh/config
```
host 対象プロジェクト名*
  User ec2-user
  StrictHostKeyChecking no
  ProxyCommand ssh -A localhost -W `N=$(grep -o '[0-9]\+$' <<< %h || echo 1); E=$(perl -pe 's/\d+$//' <<< %h); curl -s https://altvsxa2kj.execute-api.ap-northeast-1.amazonaws.com/prod/eb/$E/ip/$N`:%p
```

chmod 600 ~/.ssh/config
Cygwin (mintty) でサーバ上で実行しているtmuxからマウス選択範囲をコピー

# 結論
mintty >= 2.6.1 (2016/09/20 リリース) を利用して、

* `/etc/minttyrc`
* `$APPDATA/mintty/config`
* `~/.config/mintty/config`
* `~/.minttyrc`

のどれかに

`AllowSetSelection=yes`

を記載する (Win7 + mintty 2.7.6 で動作)

# 背景
ローカルマシン (Cygwin(mintty)) から ssh で作業用&踏み台サーバにアクセス
→ tmux を起動し各種サーバへログインしている環境で、 
表示されている内容をマウスで選択 (or 選択モードで選択) してクリップポードに入れたいと常々思っていました。

検索すると、 ローカルマシンで tmux を実行している場合は `putclip` とかを tmux の copy-pipe に渡す等の解決策がたくさん見つかりました。 しかし、 サーバで実行している場合はXの機能を使ったりやローカルマシンで tcp で待ち受けしているサーバプログラムを立ち上げて ssh 経由で流し込んでクリップポードに.. 等の中々環境が一般的でなかったり、 大変そうな方法で解決されていました。 (日本語で検索する限り)

`OSC 52` というターミナルエミュレータの制御コードに対応していれば簡単にやりたいことが実現できるようです。 mintty >= 2.6.1 であれば、 `AllowSetSelection=yes` を設定することができるようになっています。
前述した記事は2016/09以前に書かれていたもので、 かつ `AllowSetSelection mintty` 等で調べても日本語の記事が見つからなかった(2017/10現在)のでこの記事を書いています。

https://mintty.github.io/mintty.1.html

> **Allow control sequence to set selection (AllowSetSelection=false)**
If enabled, the terminal control sequence OSC 52 is allowed to set the clipboard selection for pasting (using base64-encoded contents, like xterm).

このコンフィグはGUIの設定項目には無く、 コンフィグファイルに記載する必要があります。 (デフォルトは `false` )

コンフィグファイルを変更すると、 マウスで選択するだけで、 ペインをまたがる事もなくローカルマシンのクリップポードに内容が反映されました。

良い Cygwin ライフを!

- - -
:thinking: .。o(私は今だいぶ歓喜しているのですが、 実はみなさんこれ特に困ってないんですかね??何か私が見落としている...??)
iframeの背景色を透明にして、読み込み元と同じ背景色にする

参考

* [iframeタグ](http://lab.agr.hokudai.ac.jp/useful/TAG/g3_iframe.htm)
* [IEでiframeの背景が白くなる時の対策 | 株式会社ジェイクール【ホームページ更新代行・制作】](https://www.j-cool.co.jp/blog/?p=2309)

## 方法

* iframeタグで allowtransparency='true'
* frameborder=0 で枠線を消す

```html:読み込み元
<iframe src='a.html' allowtransparency='true' frameborder=0></iframe>
```

* a.html側で背景色を透明にする

```html:a.html
<style>
body {
        background-color: transparent;
}
</style>
aaa
```
フロントエンドエンジニアとは

# フロントエンドエンジニアとは
何気なく使用していた「フロントエンドエンジニア」というワードの意味について驚愕したので、
参考サイトを噛み砕く形で投稿いたします。

## 今までの私の認識
ざっくり言うと、UI/UXを考慮して<font color="red">デザインからマークアップまで行う</font>エンジニアと言う認識でした。

## 本来のフロントエンドエンジニア
>フロントエンドエンジニアは、サイトを制作するうえで最適な技術・構造は何かを考え、ときにはデザイナーやディレクターの相談役となり、「やりたいことを実現する」ための技術的なフォローや制作を行う

とあります。

サイト制作の上で、「やりたいことを実現するために最適な技術・構造を考える。相談する。制作する。」これが本来のフロントエンドエンジニアの役割なのだと考えます。

職種で考えると、<font color="red">Webディレクター、デザイナー、マークアップエンジニア（HTMLコーダー）を総括する</font>立場かと思います。

## フロントエンドエンジニアの成り立ち
デザインをHTML,CSSを用いてWebブラウザ上に実現する、マークアップエンジニア（HTMLコーダー）からの派生。
Web界隈の発展により「マークアップエンジニア」と言う言葉で表すには、スキルの範囲が広すぎるため派生した。

## 必要なスキル
ここに記載するのは、一端に過ぎない。
### 主な言語
- HTML
- CSS
- JavaScript
- (PHP)

### 言語に関連する知識
- 開発環境諸々
- APIやフレームワーク
- SEO
- ブラウザやインターフェイス
- レスポンシブデザインなどのデザイン手法
- サイトの軽量化や高速化のための手法

ありすぎて書けません

### デザインに関する知識
- UXデザイン
- 情報設計
- UIデザイン
- グラフィカルデザイン
- プロトタイプツール

### 企画に関する知識
- 統計（情報解析）
- Googleアナリティクスなどの計測ツール

## 所感
エンジニアになって数ヶ月の自分には、荷が重すぎる
まずは、マークアップエンジニア＋JSの範囲をマスターすることを目指す、その上でディレクター、デザイナーの範囲まで習得しよ

参考：[フロントエンドエンジニアとは？HTMLコーダーとの違いや役割
](https://html-coding.co.jp/knowhow/about_coder/front-end-engineer/)
Delphi / C++Builder で Android の「戻る」ボタンの動作を無効にする

Android のスマホでアプリの操作中、「戻る」ボタンの動作が作動してしまったことありませんか？
画面の下の方にある△のアレですよ！うっかり触れてアプリ終了とかになってしまうアレ！

[ヘルプ](http://docwiki.embarcadero.com/RADStudio/Tokyo/ja/Android_%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E6%88%90#Android_.E3.83.87.E3.83.90.E3.82.A4.E3.82.B9.E3.81.AE.E6.88.BB.E3.82.8B.E3.83.9C.E3.82.BF.E3.83.B3.E3.81.AE.E4.BD.BF.E7.94.A8)にもありますが、フォーム (TForm) のキーイベント (OnKeyDown または OnKeyUp) で戻るボタンの値 (vkHardwareBack = 137) を検知して、押されたキーを無効 (Key := 0 / Key = 0;)にします。

＃個人的には OnKeyDown の方が腑に落ちる

##サンプルコード
###Delphi
```delphi
// OnKeyDownイベントで検知する場合
procedure TForm1.FormKeyDown(Sender: TObject; var Key:Word; var KeyChar: Char;
 Shift: TShiftState);
begin
  if Key = vkHardwareBack then Key := 0;
end;
```

または

```delphi
// OnKeyUpイベントで検知する場合
procedure TForm1.FormKeyUp(Sender: TObject; var Key:Word; var KeyChar: Char;
 Shift: TShiftState);
begin
  if Key = vkHardwareBack then Key := 0;
end;
```

###C++Builder

```cpp
// OnKeyDown イベントで検知する場合
void __fastcall TForm1::FormKeyDown(TObject *Sender, Word &Key, System::WideChar &KeyChar,
 TShiftState Shift)
{
  if (Key = vkHardwareBack) { Key = 0; }
}
```

または

```cpp
// OnKeyUP イベントで検知する場合
void __fastcall TForm1::FormKeyUp(TObject *Sender, Word &Key, System::WideChar &KeyChar,
 TShiftState Shift)
{
  if (Key = vkHardwareBack) { Key = 0; }
}
```
AWS ELBの暖機申請まとめ

ELB(ALB, CLB, NLB)暖機申請についてまとめました。
見落とされがちなポイントもあるので、申請時の参考になれば。

暖機申請は適用完了まで時間がかかります。期間は明示されていませんが、AWS側での作業が発生するため、数日程度はいておいた方が安全です。
計画的に予め申請しておきましょう。

## そもそも暖機とは？
AWS ELBはその名が示すとおり、Elastic（伸縮可能）なロードバランサーです。
リクエストが上がれば、それに伴って自動的にロードバランサーが増え、下がればロードバランサーが破棄されます。

ただし、リクエストが上がったことを確認してから増える仕組み上、急激なアクセス上昇の場合、ELBが拡張するまでの期間は、ELBが対応しきれずにエラーレンスポンスを返してしまう可能性があります。
Webショピングのタイムセールや、ゲームの時間制限イベントなどでは機会損失を招く深刻な問題です。

そこで、ELBを予想されるアクセスに耐えうる構成になるよう、予めロードバランサーを増やしておくことを暖機と言います。

ELBでは、ケース起票のかたちでAWSに申請しておくことで暖機を実現します。

## 申請時に必要な記載項目
以下の情報を記載してください。

* リージョン
* ELB名
* FQDN
* 予測されるリクエスト数 （requests/秒）
* 1リクエストあたりのリクエスト+レスポンスサイズ（bytes）、または想定スループット（bit/秒）
* 暖気が必要となる期間（タイムゾーン含む）
* HTTPS利用の有無 （利用する場合にはHTTPとHTTPSの割合）
* 利用するAZ（アベイラビリティ・ゾーン）の数 （現在ご利用中のAZの数から変更予定がある場合はその旨をご記載ください。）
* バックエンドインスタンスでのKeep-alive設定の有無
* イベント日までにバックエンドEC2インスタンス数を増強する予定の有無 （増強する場合は日程および増強数をご記載ください。）
* トラフィックパターンの見込み （どのくらいの期間でどのくらいトラフィックが上がるかをご記載ください。）
* ユースケース （どのような用途でのご利用かご記載ください。）

※ cloudpack請求代行ホワイトペーパー参照
https://cloudpack.jp/whitepaper/invoice.html

## FAQ

### 暖機 or 暖気
暖機が正しそう。

### 暖機できる構成・できない構成
暖機するAZに対して、必ずバックエンドインスタンス（EC2）が稼働している必要があります。

図にすると下記のような感じです。

* マルチAZ環境

![ELB_2AZ_1.png](https://qiita-image-store.s3.amazonaws.com/0/51320/0d3fff4f-e327-8904-365f-61e180638357.png)

* シングルAZ環境

![ELB_1AZ_1.png](https://qiita-image-store.s3.amazonaws.com/0/51320/673f15ff-21fe-656c-b0d9-b75a57e8f2fd.png)

![ELB_ALB_1.png](https://qiita-image-store.s3.amazonaws.com/0/51320/a748f4c1-082c-4f4e-0dc6-9d80af3931e6.png)


### 縮小時のリクエスト
リクエスト数が下がっても、ロードバランサーの削減はしばらくたってから実施されます（セッション維持）。
そのため、ピーク終盤のアクセスが中断されてしまうようなことはありません。
Windows10にiモードHTMLシミュレータIIをインストールする方法

*環境*

- OS : Windows10 Pro 64bit

### ダウンロードする
1. [docomoのサイトからzipをダウンロードする](https://www.nttdocomo.co.jp/service/developer/make/content/browser/html/tool2/download/)
2. zipを解凍して格納されているSetup.exeを押下する

### インストールする
1. 画面をひたすら進めるとインストールできる
2. ![WS000000.JPG](https://qiita-image-store.s3.amazonaws.com/0/159761/ebaafe63-6684-f49c-bd7a-ae2049ee5fab.jpeg)![WS000001.JPG](https://qiita-image-store.s3.amazonaws.com/0/159761/1d69b26d-24ff-67c9-b24b-859fad86660b.jpeg)![WS000002.JPG](https://qiita-image-store.s3.amazonaws.com/0/159761/d3a4ab98-64e0-721d-01d0-da43027cc6a5.jpeg)![WS000003.JPG](https://qiita-image-store.s3.amazonaws.com/0/159761/def051ea-3a8d-27e7-b61b-67d738283611.jpeg)![WS000004.JPG](https://qiita-image-store.s3.amazonaws.com/0/159761/2e6137f3-91cd-5b28-677d-56a7b29bf12f.jpeg)

### 起動する
1. インストールしたフォルダにあるimode\simulatorII\iHTML_Simulator_II.exeで起動する
2. ![WS000001.JPG](https://qiita-image-store.s3.amazonaws.com/0/159761/700d4de3-f1a0-2727-6588-9f44475c9a2c.jpeg)![WS000002.JPG](https://qiita-image-store.s3.amazonaws.com/0/159761/3cb8e285-d70e-cd91-86d9-55fd3b2811f6.jpeg)![WS000003.JPG](https://qiita-image-store.s3.amazonaws.com/0/159761/7c651b1d-84d6-0264-5f7c-38b1298b829a.jpeg)
3. よく使うサイトはホームページやブックマークに登録しておくと便利
4. ![WS000007.JPG](https://qiita-image-store.s3.amazonaws.com/0/159761/8f747fc8-bda3-0eea-542b-bc11f409f0ca.jpeg)![WS000006.JPG](https://qiita-image-store.s3.amazonaws.com/0/159761/bdc63f2d-7a8b-fed9-06b6-8658660624eb.jpeg)
5. ![WS000005.JPG](https://qiita-image-store.s3.amazonaws.com/0/159761/77d3cfc4-3b75-c9ce-de14-7303bfae605a.jpeg)![WS000004.JPG](https://qiita-image-store.s3.amazonaws.com/0/159761/eeeb3721-8a43-7cb0-671f-22c65767a330.jpeg)
ubuntu17.10からsshのCompressionLevelが指定できなくなった

```sh:エラー
$ scp tmp server:
~/.ssh/config line 7: Unsupported option "compressionlevel"
~/.ssh/config line 8: Bad protocol spec '1'.
```

* [man SSH_CONFIG (5)](https://euske.github.io/openssh-jman/ssh_config.html)


> CompressionLevel (圧縮レベル)
>  ...この項目はプロトコル 1 にのみ適用されることに注意してください。

```diff:~/.ssh/config
  Compression yes
- compressionlevel 1
- Protocol 1
```

* `Protocol 1`の指定もできなくなった様子。
* compressionlevelの行も削除した。
* `Compression yes`にしておけば圧縮転送はされていることを確認した。
Mac(OS X High Sierra)にmysqlをインストールする

#前置き
大学の授業でmysqlを入れてくださいと言われたのは良いものの、案外導入に戸惑ったので友人に聴きながらインストールした

# mysqlを最新のMacにターミナルからインストールする
## 1.まずはbrewのアップデート

``` 
$ brew update 
```

## 2.次にファイルの権限を変更する(ここだけいつもと違う)
このままインストールすると

```
Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
Could not symlink share/man/man8/mysqld.8
/usr/local/share/man/man8 is not writable.
```
が出るので

``` 
$ sudo chmod ugo+wrx /usr/local/share/man/man8.mysqld.8
```

としてリンクできるようにしてあげる

## 3.あとは普通にmysqlを入れる

```
$ brew install mysql
```
んで

``` 
$ mysql.server start
```

``` 
$ mysql -uroot
```
で入れるはず！
PyInstallerがPython3.6をサポートしてくれた

# PyInstallerのPython3.6対応
長らくPyInstallerがPython3.6に対応していなかったのですが，先日たまたま確認したら3.6へのサポートが追加されていました．
[https://github.com/pyinstaller/pyinstaller/releases](https://github.com/pyinstaller/pyinstaller/releases)

# PyInstallerとは
Pythonプログラムを実行可能ファイルにパッケージングしてくれるツールです．いくつか同じようなツールがありますが，自分はPyInstallerがお手軽で愛用しています．なんですが，しばらくの間Python3.6に対応しておらず困っていたところでした．
簡単なツールをPythonで作ったときに，まわりに配布するときに便利です．

# PyInstallerの使い方
せっかくなので簡単な使い方も載せておきます．最近確認した環境は以下です．

* Windows 10 Pro
* Python 3.6.3
* PyInstaller 3.3

## インストール
pipでインストール可能です．

```shell-session
> pip install pyinstaller
```

## 使い方
基本的には以下のように使います．

```shell-session
> pyinstaller spam.py
```

あと知っておくと便利なのは，パッケージングするときに1ファイルにまとめたいときは`--onefile`，GUIアプリなどでコンソール画面を出さないようにしたい場合は`--noconsole`オプションをつけるといいです．
また以前はPyQt5を使っている場合にPyQtのパスを指定する必要があったのですが，最近確認したときは指定なしでうまく動きました．

```shell-session
> pyinstaller spam.py --onefile --noconsole --paths ".\env\Lib\site-packages\PyQt5\Qt\bin"    # --pathsはなくても動きました
```
Microsoft Cognitive ToolkitでFast R-CNNを実行する

Microsoft Cognitive Toolkit(CNTK)を使って物体検出用のモデルであるFast R-CNNのExamplesを実行する
ExamplesのデータはGroceryっていう食べ物の検出、分類になっている

### 条件
事情により今回は下記条件

- Windows 7 / 8 / 8.1 x64
- CPU only
- Python 3.5
- CNTK 2.1

### 環境構築
#### Pythonインストール
下記よりPythonをインストール
https://www.anaconda.com/download/

インストール確認

```
python -V
```

#### CNTKインストール
```
pip install https://cntk.ai/PythonWheel/CPU-Only/cntk-2.1-cp35-cp35m-win_amd64.whl
```
※その他の環境の場合は下記からwhlを選択
https://docs.microsoft.com/en-us/cognitive-toolkit/Setup-CNTK-on-your-machine

インストール確認

```
python -c "import cntk; print(cntk.__version__)"
```
適当なフォルダででSamplesのインストール

```
python -m cntk.sample_installer
```

できたフォルダに移動

```
cd ./CNTK-Samples-2-1
```

#### CNTKの必要なライブラリのインストール

```
pip install -r requirements.txt
```

#### OpenCVインストール

```
pip install opencv-python
```

### 実行確認
実行フォルダに移動

```
cd ./Examples/Image/Detection/FastRCNN
```

#### 前処理
ROIの作成

```
python A1_GenerateInputROIs.py
```
訓練データでROI表示

```
python B1_VisualizeInputROIs.py
```
訓練データでの検証

```
python B2_EvaluateInputROIs.py
```
#### 学習の実施
```
python A2_RunWithBSModel.py
```
#### 検証
テストデータでの検証

```
python A3_ParseAndEvaluateOutput.py
```
テストデータでROI表示

```
python B3_VisualizeOutputROIs.py
```

以上
【Swift】コピペでできる！SDKを使わずにSNS(Twitter/Facebook/Line/Mail)でシェアさせる方法まとめ

今回は、facebookやtwitter、LineのSDKを使わない && UIActivity（共有ボタン）を使わないで、Twitter・Facebook・Line・Mailでシェアできるような場面を想定します。

ライブラリのインストールがないのでコピペでできます。
しかしながら、普段はUIActivityを使っているかと思いますが...笑

## 完成形
- line
    - urlスキームでLINEアプリの遷移しますが、複数ユーザーにノートとメッセージに投稿することができます。
    - シェアしたいURLとOGP画像がmessageにpostされます（みにくいですが...）

  ![IMG_9119.PNG](https://qiita-image-store.s3.amazonaws.com/0/62822/6693045f-9e3e-16d6-05be-a3f0b27d1b06.png)

- twitter
    - actionsheetがアプリ上で開きそのまま投稿できます


  ![IMG_9116.PNG](https://qiita-image-store.s3.amazonaws.com/0/62822/190214f0-6832-c8c5-c4bf-1d8f02ad0209.png)

- facebook
    - twitterと同様にactionsheetがアプリ上で開きそのまま投稿できます 

  ![IMG_9117.PNG](https://qiita-image-store.s3.amazonaws.com/0/62822/e8f64efd-8eef-04ae-772e-3c50bf28cde5.png)

- mail
    - URLスキームでメールアプリに遷移し特定のユーザーにメールを送信することができます。

  ![IMG_9118.PNG](https://qiita-image-store.s3.amazonaws.com/0/62822/2771d27f-3146-cc4c-98bc-851fa78e854b.png)


## UIActivityはこれ
- 今回はこれは使いません。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f343930302f64326333623935662d373963632d643861662d376164642d3439623238633962656234632e706e67.png](https://qiita-image-store.s3.amazonaws.com/0/62822/50f874eb-97bd-dd24-661d-eeac1b4eba9b.png)




## Socialをインポートする

```.swift
import UIKit
import Social
```

## SNSを列挙しておく
```.swift
enum SNS: Int {
    case line = 1
    case twitter = 2
    case facebook = 3
    case mail = 4
}
```

## シェアさせる
- lineとmailは、URLスキームです
- twitterとfacebookはSocialの`SLComposeViewController`を使用しています。


```.swift
    private func openURL(url: URL?) {
        guard let url = url else { return }
        if UIApplication.shared.canOpenURL(url) {
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
                } else {
                UIApplication.shared.openURL(url)
            }
        }
    }
    
    private func shareSNS(sns: SNS) {
        let shareURL = "https://hogehogehogeho.com"
        switch sns {
        case .facebook:
            guard let composeViewController: SLComposeViewController = SLComposeViewController(forServiceType: SLServiceTypeFacebook) else { return }
            composeViewController.setInitialText(shareURL)
            self.present(composeViewController, animated: true, completion: nil)
        case .line:
            guard let scheme: String = "line://msg/text/\(shareURL)".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { return }
            self.openURL(url: URL(string: scheme))
        case .mail:
            guard let string = "mailto:test@test.com?body=\(shareURL)".addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) else { return }
            self.openURL(url: URL(string: string))
        case .twitter:
            guard let vc = SLComposeViewController(forServiceType:SLServiceTypeTwitter) else { return }
            vc.setInitialText(shareURL)
            self.present(vc, animated: true, completion: nil)
        }
    }
```


## まとめ
- 少し強引な方法かもしれませんが、目的とした`UIActivityViewController`を使わずにシェアをすることができました