OmniAICreator/Qiita-1.07M huggingface dataset:
supervisord.confのサンプル


###ubuntu1604でSupervisorを初めて入れてみた。
CLIで管理するか、ブラウザで管理するか選べる。（Apatchとかは不要。）

以下サンプルコンフィグ。
（デフォルトでいらないコメントはほぼ削除してます。）

```
root@ubuntu1604:/etc/supervisor# cat supervisord.conf
; supervisor config file

[unix_http_server]  ;コマンドラインから実行する場合
file=/var/run/supervisor.sock   ; (the path to the socket file)
chmod=0700                       ; sockef file mode (default 0700)
chown=root:root

;[inet_http_server]  ;ブラウザを使用する場合（unix_http_serverを使用する場合は止める。）
;port=127.0.0.1:9001
;username = admin
;password = admin


[supervisord]
logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log)
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
childlogdir=/var/log/supervisor            ; ('AUTO' child log dir, default $TEMP)
; 2017-05-18
; It resolves the «CRIT Supervisor running as root (no user in config file)» warning in the log.
user = root


[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL  for a unix socket(unix_http_server)
;serverurl=http://127.0.0.1:9001 ; use an http:// url to specify an inet socket(inet_httpserver)
;username=chris              ; should be same as in [*_http_server] if set
;password=123                ; should be same as in [*_http_server] if set
prompt=mysupervisor         ; cmd line prompt (default "supervisor")
history_file=~/.sc_history  ; use readline history if available


[include]
files = /etc/supervisor/conf.d/*.conf

```
プロセス再起動
`systemctl stop supervisor`
`systemctl start supervisor`

`/var/log/syslog`や`/var/log/supervisor/supervisord.log`に怪しいメッセージが出てなければOK。

```
2017-11-14 14:53:25,013 CRIT Set uid to user 0
2017-11-14 14:53:25,026 CRIT Server 'unix_http_server' running without any HTTP authentication checking
```
↑
こういうログが出てるけど無視でよさそう(暇があれば解決策を調べます。)
sanselanを使ったExif情報の削除


Java/AndroidでExifを削除する時にsanselanという便利なライブラリを使わせて頂きました。
このライブラリを使った理由は、metadata-extractorは読み取り専用なのでExif情報の削除や追加・修正が出来ないこと、ExifInterfaceは挙動が不安定なため使えなかったからです。

# 使い方

```java
/* import省略 */

public static void Main(String[] args) {

    String path1 = "c:\image\img0001.jpg";   // ファイルパス
    String path2 = path.toLowerCase().replace(".jpg", "_clr_exif.jpg");

    // Exif情報の削除
    removeExifTag(new File(path1), new File(path2));
}

public static void removeExifTag(final File srcJpegFile, final File dstJpegFile) {

    OutputStream os = null;

    try {
        os = new FileOutputStream(dstJpegFile);
        os = new BufferedOutputStream(os);

        // Exif削除メソッド
        new ExifRewriter().removeExifMetadata(srcJpegFile, os);

        os.close();
        os = null;

        System.out.println("SUCCESS");
    } catch (FileNotFoundException e) {
        System.out.println("ERROR");
        e.printStackTrace();
    } catch (ImageWriteException e) {
        System.out.println("ERROR1");
        e.printStackTrace();
    } catch (IOException e) {
        System.out.println("ERROR2");
        e.printStackTrace();
    } catch (ImageReadException e) {
        e.printStackTrace();
    } finally {
        if (os != null) {
            try {
                os.close();
            } catch (final IOException e) {

            }
        }
    }
}
```
SQLServer > SSIS > Visual StudioからSSISプロジェクトの配置 SQL Server SSIS サーバー側の初期設定

# Visual StudioからSSISプロジェクトの配置


## SSISDBカタログを作成せよと表示されたので作成のメモです。

VisualstudioからSSISプロジェクトを配置しようとしたら、
サーバーにカタログを作成する必用があると表示されました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/49910/1e403f45-ac06-1106-0a17-684d4007a4da.png)


## カタログを作成します。
SSMSからデータベースに接続し、
統合サービスカタログを右クリックしてカタログの作成をクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/49910/142e06f5-d467-9dff-0528-d57436f525bd.png)



![image.png](https://qiita-image-store.s3.amazonaws.com/0/49910/96b4d104-9041-10b6-4477-0c2d91efa785.png)

パスワードは必須のようなのでパスワードも入力します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/49910/5be9488c-6d59-2fc0-8f3d-e9aab31ad774.png)


## Visual Studioからの配置

![image.png](https://qiita-image-store.s3.amazonaws.com/0/49910/22634a82-521f-b707-21e3-1c161de6fb80.png)

パスの選択でカタログを参照する事で可能になりました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/49910/44e14e5a-6825-0c29-aea2-fd6cb4f5ddb0.png)
読みやすい文章の書き方

# 読みやすい文章の書き方
読みやすいには特徴があるなと思い、ブログや本を読んでしらべました。
ざっくりと読みやすい文章の特徴をまとめています。
文章には、大きく3つの分類があります。

* 構成
* 段落
* 文

ガイドラインに従って書いていけば、ある程度読みやすい文章になると思います。

## 構成
* フレームワークにそって説明する
	* ( short ver ) 見出し → 概要→ 結論 → 根拠 → 結論
	* ( long ver )  見出し → 概要 → 結論 → 根拠 → 具体例 → 疑問 → 反論 → 結論

## 段落
* 段落の役割を明確にする。
* 段落の役割に合う接続詞を選ぶ。
* 段落の概要を端的に説明する
※これは読むべきものなのか否かを早く判断してもらえると、よい文章になる。
 
## 文
* 一文を短くする
* 主語と述語を近づける
* 修飾語は長いものが先、短いものが後
* 大きな状況が先、小さな状況が後
* 受身表現をしない。
*  接続詞は段落の始めに使う。
* ひらがなを使う
* 過剰な敬語を使わない。

## 参考
文章力を高めるトレーニングに！読むだけで文章の書き方や構成が学べる7つの記事
https://creive.me/archives/5680/

第2回：わかりやすい文章の10大原則
http://hajimeteweb.jp/column/web_writing/vol2.php

文章は接続詞で決まる→（保存版）接続詞の常識チートシートにまとめてみた
http://readingmonkey.blog45.fc2.com/blog-entry-674.html
IBM Cloud(旧Bluemix)クレジットアカウントへのアップグレード手順

2017年11月にBluemixのFreeアカウント(期限1か月)は、無期限のライトアカウントに変わりました。
それにあわせて、クラウドの名称もIBM Cloudに変更になっています。
新しい仕組みになった後でのクレジットアカウントへのアップグレードを試してみましたので、その手順を以下に記載します。
ちなみに、ライトアカウントの登録手順は[IBM Cloud (aka Bluemix) ライト・アカウント作成手順](https://qiita.com/KenichiSekine/items/249d2ff691b6565fb127)にありますので、こちらを参考にされてください。

## アップグレード画面の表示
IBM Cloudダッシュボード画面の右上のメニューから「管理」->「請求および使用量」->「請求処理」を選択します。

![bluemix-step1.png](https://qiita-image-store.s3.amazonaws.com/0/206130/1ea0b7cf-fd74-f75b-951a-d1e6afa49ddf.png)

ただ、試してみたところ次の画面遷移に移る処理が相当重たいです。(2回に1回は失敗する感じ)
うまく表示されない場合は、ブラウザから上げ直してみてください。

## クレジットカードの追加ボタン
下の画面がうまく表示されたら、「クレジットカードの追加」ボタンを押します。

![bluemix-step2.png](https://qiita-image-store.s3.amazonaws.com/0/206130/4b28f457-fc79-e2b0-a772-6e04cb63cf5b.png)

## 必要事項の記入
次の画面が表示されますので、必要事項を記入します。
クレジットカードはハイフンを除いた形で数字のみ入力します。
請求がUS$になっていたら(私はそうでした)JPYに変更します。

![bluemix-step3.png](https://qiita-image-store.s3.amazonaws.com/0/206130/08061667-bd45-5261-908e-db00cff40531.png)

項目名が全部英語のままなのですが、試しに名前とか住所を日本語で入れたところ、ちゃんと通ったのでそれで問題なさそうです。

## アップグレード進行中画面
無事に登録ができると、次のようなかわいい画面が表示されますので「Done」のボタンを押して登録作業を完了させます。

![bluemix-step4.png](https://qiita-image-store.s3.amazonaws.com/0/206130/a0d56a98-2b33-8b91-f15a-93620717a6b2.png)

## 登録終了画面
最後に次の画面が表示されれば登録は完了です。

![bluemix-step5.png](https://qiita-image-store.s3.amazonaws.com/0/206130/575cdac6-918a-f0d6-e9f7-64ad68384ee4.png)

やってみるまで知らなかったのですが、登録時にボーナスで200ドル分は無料で使えるみたいです。
しかし、この画面左の「クレジット残量200円」はきっと間違いですね。
できたばっかりなので、いろいろいけてないところがまだあるみたいです。

## 登録完了後
アップグレードが完了した後でみた、Watson APIの登録画面です。

![スクリーンショット 2017-11-14 14.03.16.png](https://qiita-image-store.s3.amazonaws.com/0/206130/812b5803-8a2f-30ba-7280-86380da8c087.png)

ライトアカウントの時には見えていなかった、「Natural Language Classifier」と「Visual Recognition」が見えていて、登録可能なことがわかります。
MacでFederated Nodeをインストールする

草稿中・・・

まずはここを参照する
https://counterparty.io/docs/federated_node/

0.Xcodeを入れておく（後々gitを入れるための前提となるようだ）
Appstoreからインストールすれば良い。

1.pythonのインストール(macOS Sierraだと2.7がインストール済み）
https://www.python.org/downloads/
※3.6以上を入れましょう

2.Dockerインストール
https://docs.docker.com/docker-for-mac/
kintone から Azure の Translator Text API を使う


Cyboze kintone をカスタマイズし、Translator Text API を呼び出す。
これにあたり、kintone で用意されている API を使う。
（ Node.js や jQuery も使えるらしいのだが、あまりに知識がなく＞＜ ）

# 参考

- JavaScriptを使用したkintoneのカスタマイズ
	- https://developer.cybozu.io/hc/ja/articles/200730174

- 他サービスのAPIからデータを取得してkintoneに表示してみよう
 - https://developer.cybozu.io/hc/ja/articles/201732490

- kintone API で Promise を使ってみよう！
	- https://developer.cybozu.io/hc/ja/articles/204564604


# 実装

仕様（なんちゃって仕様）

- 新規「保存」処理で翻訳している。（編集時には翻訳してない）
- 「日本語」に入力した値を英語に翻訳して、「英語」に設定する
- 言語は、ja => en 固定としている（簡単のため）

実装上のポイント

- kintone.Promise を用いて、非同期処理の終了を待つ
- kintone.proxy を用いて、https リクエストを発行する

```js
(function() {
    "use strict";

    // レコード追加画面の保存前処理
    kintone.events.on('app.record.create.submit', function(event) {
        var record = event.record;
        var text = record["日本語_0"]["value"];

		var subscriptionKey = "アクセスキーを設定してください";
  		var options = 'https://api.microsofttranslator.com/v2/http.svc/Translate?' + 
  				'&from=ja' +
    	        '&to=en' +
    	        '&text=' + text;

        return new kintone.Promise(function(resolve, reject) {

			kintone.proxy(options, 'GET', {'Ocp-Apim-Subscription-Key': subscriptionKey}, {
			}, function(body, status, headers) {

			    //success
		        const data = body;
		        const translated = data.replace(/<("[^"]*"|'[^']*'|[^'">])*>/g, '');
		       	record['英語_0']['value'] = translated;
		       	resolve(event);

			}, function(error) {

			    //error
				alert("error: " + error); //proxy APIのレスポンスボディ(文字列)を表示
				resolve(event);

			});

	    });
    });

})();

```

# とても気に入らないこと

- アクセスキーは環境変数化できないものか。。
forward secrecyによって「サーバ証明書」の目的がサーバの証明だけになる日が来る

旧聞に属する話ですが、私にとって衝撃だったので記載しておきます。

#「サーバ証明書の目的は何か？」と聞かれたら何と答えますか？
私は以下のように理解していました。
****
* [1] ドメインの使用権を持つ組織の実在証明
* [2] 共通鍵の交換のため公開鍵情報の提供

****

しかし・・・、一部のサイトではすでに2の目的がなくなっています。
forward secrecyによって共通鍵を暗号化する実装に変化が起きています。
論より証拠。Firefox 56.0.2で[Google](https://www.google.co.jp/)にアクセスしたときの暗号スイートを表示させてみます。

****
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256、鍵長 128bit、TLS 1.2
****
(※) 暗号スイートはWebサーバとブラウザの対応状況によって変化します。

「鍵交換」は「ECDHE」
鍵交換にサーバ証明書の公開鍵を使用していないのです！
# いつからこんなことになっていたのでしょうか・・・

私が勉強不足だっただけなのですが、2013年に起きたLavabit事件が大きな転機になったとのこと。
**Lavabit事件**
アメリカ当局がスノーデン氏のメールをリアルタイムで監視するために、Lavabitメールサービスの秘密鍵の提出を要求した事件。
共通鍵をサーバ証明書の公開鍵で暗号化し、サーバの秘密鍵で復号する仕組みでは、サーバの秘密鍵が漏れてしまえば、通信パケットさえ残っていれば過去にさかのぼって全ての通信内容を解読できることになります。
****

この事件を契機に、サーバ証明書の公開鍵とサーバの秘密鍵で共通鍵を暗号化/復号する仕組みを改め、共通鍵自体だけでなく、共通鍵を暗号化/復号する鍵も使い捨てにしようという動きが加速しました。

Google/Facebook/TwitterなどITを生業としている企業はいち早く対応済みです。
今後、Webサーバを構築するときは意識しないといけませんね・・・。
raspberry pi 3 でstretch その12

#概要
raspberry pi 3 でstretchやってみた。
固定ipやってみた。

#環境
Raspberry Pi 3 model B v1.2 element14
2017-09-07-raspbian-stretch


#設定
sudo nano /etc/dhcpcd.conf

```
interface eth0
static ip_address=192.168.1.7/24
```
sudo nano /etc/hosts

```
129.168.1.7    pi.com
```
#確認
sudo ifconfig

以上。
Azure の Translator Text API で翻訳できる言語を調べた


# 概要
翻訳サービスで利用できる言語は60 (*1) という情報があるが、パラメータで指定する言語キーの一覧を取得してみた。

*1 https://www.microsoft.com/en-us/translator/languages.aspx

# 実装

ポイント

- この記事と同じく、言語取得サービスに直接アクセスキーを渡す。
	- https://qiita.com/january108/items/532c22f25f5cee4510cc
- 結果はログ出力した

```js
'use strict';

var https = require('https');

getLanguagesForTranslate(function (token) {
    getLanguagesForTranslate(lang, function (translated) {
    	// 言語をログ出力
       console.log('LangsForTranslate : ' + lang);
    });
});


// 利用可能な言語キーを取得する
function getLanguagesForTranslate(token, callback) {

    const subscriptionKey = "アクセスキーを指定してください";
    var body = '';
    var options = {
        host: 'api.microsofttranslator.com',
        path: '/V2/Http.svc/GetLanguagesForTranslate',
        method: 'GET' ,  
        headers: {
              'Ocp-Apim-Subscription-Key': subscriptionKey
       }
    };

    var req = https.request(options, function (res) {
        res.setEncoding('utf8');
        res.on('data', function (chunk) {
            body += chunk;
        }).on('end', function () {
        });
    }).on('error', function (err) {
        console.log(err);
    });


    req.end();

}

```

# 結果：利用可能な言語キー

- af
- ar
- bn
- bs-Latn
- bg
- ca
- zh-CHS
- zh-CHT
- yue
- hr
- cs
- da
- nl
- en
- et
- fj
- fil
- fi
- fr
- de
- el
- ht
- he
- hi
- mww
- hu
- id
- it
- ja
- sw
- tlh
- tlh-Qaak
- ko
- lv
- lt
- mg
- ms
- mt
- yua
- no
- otq
- fa
- pl
- pt
- ro
- ru
- sm
- sr-Cyrl
- sr-Latn
- sk
- sl
- es
- sv
- ty
- ta
- th
- to
- tr
- uk
- ur
- vi
- cy
シェルのエイリアスで環境変数を使うときはクォーテーションに気をつけよう

シェルのエイリアスで環境変数を使いたいときありますよね、多分。みなさんきっとあるでしょう。
`docker`をrunしてカレントディレクトリをマウントしてごにょごにょしたいときとか。長ったらしいコマンド打ちたくないんですみたいな。

僕も例に漏れず、実際にエイリアスをいくつか貼っていたんですが、エイリアスのクォーテーションによって意図した挙動になっていないことがありました。

## 例えば

例えばなんですが、zshで貼ってたこんなエイリアス。

```zsh
alias here='echo $PWD'
```

打ったらまぁ普通にカレントディレクトリが出ます。


```sh
$ here
/Users/ryosukes
```

これをダブルクォーテーションで括って名前を変えることにしました

```zsh
alias there="echo $PWD"
```

打ったらまぁ普通にカレントディレクトリが出ます。

```zsh
$ there
/Users/ryosukes
```

しかしディレクトリを掘って移動して実行すると

```zsh
$ mkdir ~/develop
$ cd ~/develop
$ there
/Users/ryosukes
```

おやおや。カレントディレクトリを出してくれません。

じゃあ`here`ではどうでしょう

```zsh
$ cd ~/develop
$ here
/Users/ryosukes/develop
```

ちゃんと出してくれますね。

## 何が起きてるか
あまり深くは挙動の調査を行なっていないのですが、シングルクォーテーションだと実行時に変数展開され、ダブルクォーテーションだとシェルのログイン時に変数展開されるぽいです。

`which` コマンドでエイリアスを確認するとわかりやすいです。

```zsh
$ which here
here: aliased to echo $PWD
$ which there
there: aliased to echo /Users/ryosukes
```

--- 


わかってしまえば「あぁそうだよねそりゃそうだ初心者かよ恥ずかしい」となるんですが、無駄にハマってしまったし今後も不意にやってしまいそうだと思ったので戒めのために残しておきたいと思います。
Jenkinsで複数ジョブを実行するプラグイン「Multijob plugin」

昔使っていたけど、Jenkins2の新機能「Pipeline」のせいで、検索順位が下がりまくって見つけられなかったので備忘録的に書いておく。Pipelineだとちょっと辛い。。という方、使ってみてください。

[Multijob+Plugin](https://wiki.jenkins.io/display/JENKINS/Multijob+Plugin)
YubiKeyの U2F 実装

# YubiKeyの U2F 実装の概要

会社のアドベントカレンダーに誘われて、変なこと書けないぞつらーい、と思ったのですが

「**最後に、あくまで個人の見解です** と書いとけばオールオッケー」

とと言われたので、緩いスタンスで書いていこうと思います。

## 自己紹介

普段は **YubiKey** を使ったセキュリティソリューションの開発や、調査、販売サポートなどをおこなったり、 [Twitterアカウントを作りなおしたり](https://twitter.com/watahani) しているエンジニアです。

## YubiKey とは

Yubicoが作っている セキュリティデバイスで、以下のような機能があります。

* FIDO U2F プロトコルによる2要素認証
* PIVの仕様に則ったスマートカード機能
* OpenPGP対応
* 各種標準OTPおよびYubico 独自のカウンタ方式の Yubico OTP


Qiita の記事を見てみると**LinuxのPam認証**で使ったり、**秘密鍵の管理**に使ったりという使い方が多いようですね。

* [YubiKey NEO で Linux でも ２段階認証しよう！](https://qiita.com/mopemope/items/779a5a4da734914b9cd0)
* [秘密鍵、管理してますか? YubiKeyで鍵の一元管理とSSH接続、２段階認証の高速化を試す](https://qiita.com/dseg/items/77d77467970b1b510285)

### U2Fの仕組み

Qiitaに各記事なので技術的なほうが良いと思ったので、今日は FIDO U2F の Yubico の実装について簡単に説明していきたいと思います。

FIDO U2F とは簡単に言うと電子署名を用いたチャレンジ＆レスポンス方式です。
詳しい解説は日本語だと以下のページが非常によくまとまっていますのでご参考に…。

[いまさらながらのFIDO U2F](http://blog.toke.jp/2015/11/fido-u2f.html)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/83984/2f52b4e8-860c-50f0-f9a3-112c11a15a88.png)

とどのつまり、各RP(サービス)ごとにキーペアを作って、署名検証しましょうということなのですが、 YubiKey の優れているところは各サービスごとの秘密鍵をデバイスに保存しないことです。

### YubiKey の U2F 実装

秘密鍵をデバイスに保存しないにもかかわらず、どうして各サービスごとに秘密鍵が作れるのでしょうか。

![](https://developers.yubico.com/U2F/Protocol_details/key_generation.png)
https://developers.yubico.com/U2F/Protocol_details/key_generation.png //404 not found...

上記の図は register 時の動作です。(画像が消えてます)
まずサービスにキーを登録する際に、 AppID（多くはドメイン）が YubiKey に渡されます。（青のラインです）
YubiKey は内部にある RNG(Random Number Generator)で作成した Nonce と AppID から **DeviceSecret**※ で HMAC を計算し、それを秘密鍵とします。

*※ DeviceSecret : YubiKey製造時に書き込まれるデバイス独自の秘密鍵*

つまりはこういうことです。

```math
Secret_{app} = HMAC(Secret_{device}, AppID + Nonce)
```

さて、作成された秘密鍵から公開鍵を作成すると **公開鍵** 、と **KeyHandle(NONCE+α 後述）** と共にサーバーに送ります。

つまりサーバーは以下の 2 つの情報を得ます。

```math
KeyHandle = Nonce + MAC_{app}\\
Public_{app} = GeneratePublicKey (Secret_{app})
```

認証時は Signリクエスト（Challenge + KeyHandle + AppID )がサーバーから送られてきます。
この際、**KeyHandle には Nonce が含まれている**ので、 AppID + Nonce + **DeviceSecret** で先ほど作成したものと同じ秘密鍵を作成できます。

```math
KeyHandle = Nonce + MAC_{app}\\
Secret_{app} = HMAC(Secret_{device}, AppID + Nonce)\\
Signiture = Sign(Secret_{app}, challenge)
```


それによってサーバーに保存された公開鍵で検証できる署名ができるというわけです。 

これらの処理はすべてYubiKeyの内部で行われるため、デバイスの秘密鍵でなく、アプリケーションごとの秘密鍵もデバイスの外にでることはありません。

ちなみに KeyHandle には赤のラインでは作成した HMAC(アプリケーションごとの秘密鍵 + AppID ) も含まれており、これは認証の際に、本当にこのキーで作成された公開鍵かを検証するときに使用されます）

```math
MAC_{app} = HMAC(Secret_{device}, AppID + Secret_{app})
```

自身のキーで作成された KeyHandle 以外が送られてきても安易に署名が行われないようになっているわけです。


### 謝罪

とまあ、完全にただ [Yubico のページ](https://developers.yubico.com/U2F/Protocol_details/Key_generation.html)を日本語訳しただけになってしまいましたが、前日に風邪ひいてしまって丸一日寝ていたので皆許してくれるかなあと思います。

**※あくまで個人の見解です**
Azure の Translator Text API  でテキスト翻訳する


# 文書
API ドキュメント
http://docs.microsofttranslator.com/text-translate.html


# 概要
- REST API 呼び出しである。（GET）
- 認証情報を渡す必要がある。２種類の方法がある
	- 1段階。
		- (1)翻訳サービスにアクセスキーを直接指定する
	- 2段階。
		- (1)アクセスキーを用いて 10分間有効なアクセストークンを生成
		- (2)翻訳サービスにアクセストークンを渡す
		- 短いインターバルで翻訳サービスを呼ぶ場合に性能面で有利と思われる。
- パラメータ概要
	- 認証情報
		- appid または Authorization を利用する場合、予めアクセストークンを取得し、"Bearer" + " " + "access_token"　形式で指定。
		- Ocp-Apim-Subscription-Key を利用する場合、アクセスキーを指定。
	- 翻訳対象のテキスト
	- 翻訳先の言語
	- 翻訳元の言語（オプショナル）
	- contentType（オプショナル）
	- category（オプショナル）
	- ＝＞ 詳しくは、API ドキュメントを参照のこと
		- http://docs.microsofttranslator.com/text-translate.html#!/default/get_Translate


# 実装

ポイント

- 翻訳サービスにアクセスキーを直接指定する方式を採用
- アクセスキーは、Azure の Translator Text API リソースの「キー」にて確認したものを設定
- 必須パラメータのみ設定


```js
var https = require('https');
var qs = require('querystring');

(function() {
    "use strict";
 
   	translate('こんにちは', function (translated) {
      	console.log("translated = " + translated);
    });

 })();


function translate(text, callback) {
 
	var subscriptionKey = "アクセスキー（１または２）を指定してください";

    var params = '&from=ja' +
            '&to=en' +
            '&text=' + qs.escape(text) +
            '&oncomplete=translated';
             
    var body = '';
    var options = {
        host: 'api.microsofttranslator.com',
        path: '/V2/Http.svc/Translate?' + params,
        method: 'GET',  
        headers: {
            'Ocp-Apim-Subscription-Key': subscriptionKey
        }
    };
    
    var req = https.request(options, function (res) {
        res.setEncoding('utf8');
        res.on('data', function (chunk) {
           body += chunk;
        }).on('end', function () {
            callback(body);
        });
    }).on('error', function (err) {
        console.log(err);
    });


    req.end();
}

```

# 参考

- Microsoft Translator APIを使ってみる
	- https://qiita.com/kemayako/items/21fe36005e6e729aff77
- Microsoft Translator テキスト API で、日本語を英語に翻訳するサンプル
	- https://qiita.com/TakeshiNickOsanai/items/a8039ba8d558f7c8a05e
コマンドラインでPython(Django)ファイルを実行する方法？

デバッグやスクリプトの解析につかえそうなやつ。
こんな感じでファイルが読み込めるみたい。

`python manage.py shell`

manage.pyに定義されているものを一通り読み込んでくれる状態で、Shellが実行する。

その後、必要なモジュールをimportコマンドで展開して、
適当な変数とかに入れてみるとかすると開発やりやすいみたいです。

実行するときは
`python manage.py runserver`
だから、こういう機能もあるんですね。
開発未経験者がWEBエンジニアを目指す-1

自分が学んでいることをしっかりと残すことで、多くのフィードバックがいただけることを信じて今日から始めてみました！
客観的に自分のこと見れるし、後から振り返られる良い場だと思い投稿をこれからしていきます！！

# 現在やっていること
・Progate (https://prog-8.com/) をひたすら利用中。
・わからなかったらすぐググる
・勉強中⇒HTML/CSS/PHP/Java
・Githubを通して友人と進捗の報告やどんな勉強をしているのか共有しようとしている。
## つまずいてること
・友人が私のプロジェクトにpushできない。(コラボレータは追加した、一応ssh認証キーの発行もしてみた)
・自分でcommitやpushがうまくされない。(ブランチは想定通りの結果になる)
・現在勉強中の言語を使ってどんなものを作ろうか、目標がない。(市場調査不足..)
⇒そもそも上記言語を使ってどんなことができて、どんなものが作れるのかを正しく理解してないと思った。
### 現時点での謎
・PHPのゲッター、セッターを学んだがピンと来てない
・そもそも学んでから作るのか、作りながら学ぶ方が良いのか
####最後に
学んだことわからないこと思ったこと考えたことなどを更新していきます。
Excelで正しく開けるcsvをpythonで作るサンプル

```py
import codecs
import csv

# ファイルの拡張子は.csv
csv_filename = '/tmp/hoge.csv'

# 先頭にBOMを記載
with open(csv_filename, 'wb') as f:
  f.write(codecs.BOM_UTF16_LE)

# utf-16-leで追加書き込み。フォーマットはTSV
with codecs.open(csv_filename, 'ab', encoding='utf-16-le', errors='replace') as f:  
  tsv = csv.writer(f, delimiter="\t")
  tsv.writerows([
    ['Excelで', '正しく', '開ける'],
    ['csvを', 'pythonで', '作る'],
  ])
```


参考
https://qiita.com/mashiro/items/0d0b9bbb0f4a6cca620c
Azure の テキスト翻訳 API の利用準備


Azure  の テキスト翻訳API （translator-text-api） を利用するための準備を行う。

大まかな流れは
1. Azure にサインアップ
2. Translator Text API へのサインアップ

# Translator Text API について知る

## Translator Text API のしごと
https://www.microsoft.com/en-us/translator/home.aspx

- クラウドベースの機械翻訳サービスである
- REST API 呼び出しで翻訳サービスを利用できる
- 2017/11時点で、読み書きできる言語は約60
	- https://www.microsoft.com/en-us/translator/languages.aspx
	- 元の言語は、自動的に検出されるらしい
- 【参考】音声を機会翻訳する Speech Transfer API もある

## 価格
https://azure.microsoft.com/en-us/pricing/details/cognitive-services/translator-text-api/


- 月間 2,000,000 文字までなら無料で利用できる




# 利用を開始する

## 	Azure 無料アカウントにサインアップ


### 何が無料？

- 無料製品を利用できる。利用する製品をアップグレードするまで課金されない。
- 有料製品を利用できる ¥20,500 のクーポン（有効期間1ヶ月）がついてくる


### サインアップする
https://azure.microsoft.com/ja-jp/free/

ウィザードに従って、以下の情報を設定する。

- 自分の情報（名前、メール、電話等）
- 電話による本人確認。
	- 電話またはテキストメッセージで確認コードを受け取り、入力
- クレジットカードによる本人確認
	- クレジットカード番号を登録
- 契約
	- 契約内容等に同意
	- アカウント利用への同意




## Translator Text API 無料試用版へのサインアップ

### 概要
Azure にサインインし、Translator Text API の新しいサブスクリプションを作成する

### 手順

1. Azure にサインインする
![スクリーンショット 2017-11-10 13.57.55.png](https://qiita-image-store.s3.amazonaws.com/0/27486/7d2ada8a-3d86-308c-4588-01a8ee876bfc.png "スクリーンショット 2017-11-10 13.57.55.png")


2. 「新規」＝＞ MarketPlace が開く
![スクリーンショット 2017-11-10 15.37.21.png](https://qiita-image-store.s3.amazonaws.com/0/27486/64f1e187-9846-79e3-d3a1-079fd1d87cc6.png "スクリーンショット 2017-11-10 15.37.21.png")

3. Translator Text APIを検索して選ぶ　＝＞　ライセンスに合意

4. リソースの情報を作成する＝＞少し待つとデプロイされた

- サブスクリプション：無料試用版
- 価格レベル：F0（月に最大200万文字までの翻訳）

![スクリーンショット 2017-11-14 12.21.41.png](https://qiita-image-store.s3.amazonaws.com/0/27486/55256f70-8e0e-3f90-77e8-7ecc4833b1d3.png "スクリーンショット 2017-11-14 12.21.41.png")

5.作成されたリソースの情報を確認する
（１）ダッシュボードから作成したリソースを選んで概要を確認する

![スクリーンショット 2017-11-10 16.25.41.png](https://qiita-image-store.s3.amazonaws.com/0/27486/dbce1b19-83fa-2a91-c441-94b0c7a95f3f.png "スクリーンショット 2017-11-10 16.25.41.png")


（２）API からアクセスする際に必要となるキー

- KEY1 と KEY2 の２種類があるが（見えないけど）、一つだけ使えばよい様子。

![スクリーンショット 2017-11-10 16.26.39.png](https://qiita-image-store.s3.amazonaws.com/0/27486/70c10db5-45b7-910f-ca05-53d03aa6c1a8.png "スクリーンショット 2017-11-10 16.26.39.png")




## 参考
@IT　:　翻訳系API「Translator API」の使い方と2017年2月現在のWatson、Google翻訳との違い (1/3)
http://www.atmarkit.co.jp/ait/articles/1703/02/news012.html
Androidのgradleでapkが出来上がったあとにタスクを実行する

## 目的

Androidのgradleでapkが出来上がったあとにタスクを実行する。

## 経緯

出来上がったapkをとあるサーバーにアップロードしたかった。

## 方法

project/app/直下のbuild.gradleを以下のように編集する。

```groovy

android {

    // 中略・・・

    task afterBuildSampleTask(type: Exec) {
    }

    afterEvaluate {
        // assemble[ビルドバリアント名].finalizedBy(afterBuildSampleTask)
        assembleProductionRelease.finalizedBy(afterBuildSampleTask)
    }
}
```

↑のサンプルではtype: Execを指定しているが特に意味はないです。
[初心者向け] 実務開始の前に知っておきたいAnsibleのこと


この投稿は、チュートリアルを終えて実務に入る前の人に知っておいて欲しいことをまとめています。
チュートリアルは終えている前提なので、基本的な実行方法などは省いています。
社内メンバー宛なので偏りがあるかもしれないですが、みなさまの役にも経てば幸いです。

## フォルダ構成を知る
変更を行う際は、既存のものはどこで何を書いているのかを知りましょう。
新規で作る際は、ansibleの公式サイトに書いてある [best practice](http://docs.ansible.com/ansible/latest/playbooks_best_practices.html#directory-layout) が参考になります

## 自分がやろうとしてることを確認する
開発環境で自分の仮想環境に対して実行する時以外は、自分がやろうとしていることをちゃんと理解してから実行しましょう。
「site.ymlが実はコメントアウトされてて、自分がやりたかったことが実行できなかった」なんてこともあるかもしれません。
（逆に、緊急対応でnginxの設定1行変えればいいだけなのに、site.yml全て実行してしまうのも考えものです。）

また、初めて本番環境に対して実行する時は、実行前にコマンドを確認してもらった上で、実行時にも横で見てもらうことをオススメします。

## ansible-vault
ansibleはインフラ構築のためにuser/passなどの秘匿情報を記載する必要があります。gitのprivate repositoryにあればパスワードが平文で書かれててもバレる可能性は低いでしょうが、一般的には暗号化していると思います。
その暗号化の際に使えるのがansible-vaultです。

既存のansibleをいじってる時、先頭行に`$ANSIBLE_VAULT;1.1;AES256`と書いていたら、それがansible-vaultで暗号化されたファイルです

```
ansible-vault edit （ファイル名）
```

として、パスワードを入力すれば、編集ができます

passwordを入力しなくても編集ができた人は、ansible.cfgに以下のようにパスワードファイルを指定する記述があるかと思います。
パスワードは厳重に管理しましょう

```:ansible.cfg
vault_password_file=~/.ansible_vault_password
```

## 複数台にansibleのtaskを実行している時の注意
本番環境に対してansibleを実行する時は対象のサーバーが複数台の時が多いと思います。
その際、僕自身がよく詰まるのは以下2点です

### 複数台のうち、1台が落ちても他のサーバーの実行は止まらない
ansibleを実行していると、エラーが起きたら実行が中断されます。
しかし、複数台のうちの1台が落ちていてもその他のサーバーへの実行はとまりません。
なので、無事終わったなぁと思って見てみると、実は途中で1台こけていて何が原因かわからなくなることもあります。
慌てず実行ログを見ましょう。

### 定義されてる変数が違う
複数台の場合は、定義されている変数が違います。（cloudだと、同じインスタンスのec2たてても、describeしてみると微妙に違うとかもありますよね）

そこで使えるのが[debug](http://docs.ansible.com/ansible/latest/debug_module.html) タスクです

```
- debug: var=変数名
```

で、その時の変数に何が入っているのかがわかります。

## 最後に

インフラ周りは影響範囲も大きいので、変更はくれぐれも慎重に。
新規の時は、動くか動かないか0/1の世界なので、既存の他サービスに影響与えないように実行対象にだけ注意して、ガンガンやればいいんじゃないかなぁと思います。

では、よいansible lifeを

## [初心者向け] 実務開始の前に知っておきたいシリーズ
[[初心者向け] 実務開始の前に知っておきたいSpreadSheetのこと](https://qiita.com/vankobe/items/5bcd2ca38f289bb9b98f)
[[初心者向け] 実務開始の前に知っておきたいGoogleAnalyticsのこと](https://qiita.com/vankobe/items/2ef45365c190d154103b)
[[初心者向け] 実務開始の前に知っておきたいWordPressのこと](https://qiita.com/vankobe/items/bc16ec597cf7cf37c348)
[[初心者向け] 実務開始の前に知っておきたいRailsのこと](https://qiita.com/vankobe/items/f7e7b2592fcb3c51988f)
twitter api の t.co を元のURLに戻す

TwitterAPIの返り値が、
http://yahoo.co.jp が http://t.co....になっていたりする。
もちろんURLすべて短縮されて返ってくる。

これじゃ画像かURLかもわからないので、元に戻す。


```

//一般的な search/tweets の結果
$res =  $this->client->get("search/tweets",$option);


foreach ($res as $key => $v) {


//            url を t.co から 元に戻す
            foreach ($v->entities->urls as $s) {
                $v->text = str_replace(
                    $s->url,
                    '<a href="'.$s->expanded_url.'">'.$s->display_url.'</a>',
                    $v->text);
            }

//            hashtagにリンクをつける
            foreach ($v->entities->hashtags as $s) {

                //https://twitter.com/freemanrepo
                $v->text = str_replace(
                    "#".$s->text,
                    '<a href="https://twitter.com/hashtag/'.$s->text.'?src=hash">#'.$s->text.'</a>',
                    $v->text);
            }


//            メンションにリンクをつける
            foreach ($v->entities->user_mentions as $s) {

                $v->text = str_replace(
                    "@".$s->screen_name,
                    '<a href="https://twitter.com/'.$s->screen_name.'">@'.$s->screen_name.'</a>',
                    $v->text);
            }


//            メディアのURLをt.co から戻す
            if(!empty($v->entities->media)){
                foreach ($v->entities->media as $s) {
                    $v->text = str_replace(
                        $s->url,
                        '<a href="'.$s->media_url_https.'">'.$s->display_url.'</a>',
                        $v->text);
                }
            }


            
        }



```

これでURLがすべて綺麗に戻されて帰ってきます。
https://syncer.jp/Web/API/Twitter/Snippet/3/

にはindicesを使う方法が書いてありますが、
文字列検索置換のが楽なので、今回はこの方法で行います。
Angular jasmine 使い方メモ

# はじめに
Angularでユニットテストを作成したときに使用したjasmineの使い方をメモしていきます。

# alertが表示されることをテスト
```
beforeEach(() => {

 　// アラートの監視
 　spyOn(window, 'alert');
});

it('〇〇な場合、対応するアラートを表示するべきである', () => {

    // テストを実行
    component.testSample();

    // テスト結果検証
    expect(window.alert).toHaveBeenCalledWith('エラー');
});

it('〇〇な場合、アラートを表示するべきでない', () => {

    // テストを実行
    component.testSample();

    // テスト結果検証
    expect(window.alert).not.toHaveBeenCalled();
});
```
# protected privateな関数が呼び出されているかをテスト
```
let component: CsvJsonParseDemoComponent;
let fixture: ComponentFixture<xxxComponent>;

beforeEach(() => {
    fixture = TestBed.createComponent(xxxComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
});
describe('xxxComponent', () => {
   describe('testSample1', () => {
      it('testSample1を実行した場合、testSample2関数を呼ぶべきである', () => {
          // testSample2を監視
          spyOn((component as any), 'testSample2');
          // テストを実行
          component.testSample1();
      　　// テスト結果検証
     　　 expect((component as any).testSample2).toHaveBeenCalled();
    });
   }
}
```

# 固定の戻り値を返却
```
spyOn((component as any), 'testSample1').and.returnValue('引数');

// 非同期の場合
spyOn((component as any), 'testSample1').and.returnValue(Promise.resolve('引数'));
```

# 戻り値がObservableで、delayを使用している関数のテスト

```
// 例として作成した関数
getContentsAsObservable(): Observable<any> {
   // 1秒後にhogeした内容を返す
   return Observable.of(~~ hoge ~~).delay(1000);
}
```

```
import { fakeAsync, tick,　discardPeriodicTasks } from '@angular/core/testing';

it(`テストしてみよう`, fakeAsync(() => {
  component.getContentsAsObservable()
   .subscribe((result) => {
     expect(result).toEqual('~~ hoge ~~');
  });
  tick(1001);
　discardPeriodicTasks();
}
```
discardPeriodicTasks()を呼ぶことでfakeAsync 中で残っている不要なタスクを終了します。
呼ばないと以下のエラーが出るので注意。

```
Error: 4 periodic timer(s) still in the queue.
```

# [Uncaught NetworkError: Failed to execute 'send' on 'XMLHttpRequest']エラーが発生したときの対処法

以下のコマンドで実際のエラーを吐かせる。

```
$ ng test -sm=false
```
JavascriptでラージファイルのMD5計算

# JavascriptでMD5計算する方法
webpackを使用していればビルトインのモジュールを使用することで、大体は事足ります。
[こちら](https://qiita.com/minodisk/items/24e253bb9f2313621a6b)を参考にどうぞ。


が、5GBくらいのファイルをMD5計算したいと依頼された場合は対処しきれなくなります。
`crypto`モジュールがエラーを起こしてくれます。
どうやら、メモリをどか食いする模様・・・

[このライブラリ](https://github.com/emn178/js-md5)を使用すれば解決できました。
 `npm`も対応しているので便利。
以下を参考にどうぞ。

```javascript
import md5 from 'js-md5';

/**
 * 入力されたファイルに対してMD5を計算して取得
 * @property {Object} file Fileオブジェクト
 */
getMd5(file) {
  const hash = md5.create();
  const chunkSize = 1000; // 一度に読み取るサイズを指定
  let offset = 0; // 読込開始位置
  let blockRead = null;

  // 分割されたファイルの読み込み関数
  const readContent = (evt) => {
    const result = new Uint8Array(evt.target.result);

    if (evt.target.error) {
      // エラー処理を記述・・・
    }

    offset += result.length;
    hash.update(result);

    if (offset >= file.size) {
      // 計算結果表示
      console.log(hash.hex());
    } else {
      blockRead(offset);
    }
  };
  // 再帰読込関数
  blockRead = (_offset) => {
    const blob = file.slice(_offset, chunkSize + _offset);
    const fileReader = new FileReader();
    fileReader.onloadend = readContent;
    fileReader.readAsArrayBuffer(blob);
  };

  // ファイル読み込み開始
  blockRead(offset);
}
```
saveAllはsaveAssociatedのラッパーだからあえてこちらを使う必要も無いと思っていたが

CakePHPは公式ドキュメントが詳しく書かれているので良いですね。
たとえばhasOneの関係を持つ二つのテーブルのデータを保存するときは、モデル名をキーにした配列でsaveAllまたはsaveAssociatedすればよいのです。
>saveAll は saveMany と saveAssociated のラッパーです。 このメソッドはデータ内容をみて、 saveMany か saveAssociated のどちらを使うのかを決定します。 データの添字が数値であれば saveMany を、それ以外は saveAssociated を呼び出します。
>
>このメソッドは、前に説明した2つのメソッド (saveMany と saveAssociated) と互換性があり、 同じオプション引数をとります。場合によって、 saveMany または saveAssociated を 使ったほうがいいこともあります。

なるほど、じゃあsaveAssociatedすると決まっているコードであればそっちを使ったほうがわかりやすいですね。

で、CakePHPにはsaveするときに自動でvalidationしてくれる機能が付いているのですが、とりあえずvalidationだけをしたいときがあります。
そういうときの方法も書いてありますね。
> 複数のモデルのバリデーションを行うには次のアプローチを使います:

> ```php
> if ($this->ModelName->saveAll(
>     $this->request->data, array('validate' => 'only')
> )) {
>   // データは有効
> } else {
>   // データは無効
> }
> ```

なるほど、では

```php
$this->ModelName->saveAssociated(
    $this->request->data, array('validate' => 'only')
)
```
でも良さそうですね！ ラッパーだし、同じオプション引数を取るらしいですからね！


ダメでした。

'validate' => 'only'のときの分岐はsaveAll内にしか書いてありませんでした。

おい！！！！



'validate' => 'only'を使いたいときはsaveAllで書きましょう。
Delphi Starter で TLang を使って国際化

これは [Delphi Advent Calendar 2017](https://qiita.com/advent-calendar/2017/delphi) の 6 日目の記事です。

Delphi では Starter も含め、[TLang](http://docwiki.embarcadero.com/Libraries/Tokyo/ja/FMX.Types.TLang) を使って、言語にあわせた文字列を表示させることができます。
TLang の言語デザイナを使用して言語と表示する文字列を追加するだけです。

サンプルを使って解説します。
今回作成するアプリケーションでは
「TextLang」 と設定した文字が日本語OS環境だと「てきすと」
「ButtonLang」と設定した文字が日本語OS環境だと「ぼたん」
と表示します。

## サンプル作成・実行

1. FireMonkey フレームワークを使うので、ウェルカムページの「マルチデバイスアプリケーション(Delphi)の新規作成」をクリックするか、メニューから「ファイル|新規作成|マルチデバイスアプリケーション - Delphi 」を選択して、設計画面を開きます。
2. フォーム上に TLable と TButton を置き、それぞれの Text プロパティを TextLang, ButtonLang と設定します。
3. フォーム上に TLang を置き、ダブルクリックして「言語デザイナ」を起動します。
![qiita001.png](https://qiita-image-store.s3.amazonaws.com/0/164551/1f268b3e-8fb3-106d-1cd6-3fab2aa13d52.png)

4. TLabel および TButton の Text プロパティに設定した文字列が既に追加されています。
5. 文字コード (ja) を入力して [追加] ボタンをクリックします。
![qiita002.png](https://qiita-image-store.s3.amazonaws.com/0/164551/d7ec760d-c8db-8ab2-aed4-3e27872a995a.png)

6. ソースの対訳を入力します。
![qiita003.png](https://qiita-image-store.s3.amazonaws.com/0/164551/7d98e4c3-efc7-bcc1-3647-7f6580e1f9ef.png)

7. もうひとつ言語 (en = 英語)を追加しています。
![qiita004.png](https://qiita-image-store.s3.amazonaws.com/0/164551/61ce89de-2cfb-000d-60ca-f8672d2a3a7d.png)

8. そのまま実行すると AutoSelect プロパティが True なので、現在動作している OS の言語を判断して日本語文字列が表示されます。
![qiita005.png](https://qiita-image-store.s3.amazonaws.com/0/164551/6c71e482-02c9-33ca-2790-9ef0b18b2f64.png)

9. AutoSelect プロパティを False にして、Lang を en と固定すると、英語文字列が表示されます。
![qiita006.png](https://qiita-image-store.s3.amazonaws.com/0/164551/4341bdde-7cec-7c73-fd24-52ecf8d47afe.png)


コード１行も書いていないんですよ。

##言語コードについて
TLang に追加する文字コード（言語コード）は ISO 639 を適用しています。
[コード一覧](https://ja.wikipedia.org/wiki/ISO_639-1%E3%82%B3%E3%83%BC%E3%83%89%E4%B8%80%E8%A6%A7)の 639-1 にある２桁のコードを使います。
日本は jp ではなくて ja なのです。
RubyでGoogleplayのレシートを照合する

# APIに必要なもの($ANDROID_CLIENT_IDとかに代入する)を揃えたら、実行すればいけるはず。
```ruby
# アンドロイドのレシートチェック
def check_receipt_for_android
  def fetch_receipt_for_android(product_id, purchase_token, token)
    require 'net/http'
    require 'net/https'
    require 'uri'
    require 'json'

    # path = "https://www.googleapis.com/androidpublisher/v2/applications/#{$ANDROID_PACKAGE_NAME}/purchases/products/#{product_id}/tokens/#{token}"
    path = "https://www.googleapis.com/androidpublisher/v1.1/applications/#{$ANDROID_PACKAGE_NAME}/inapp/#{product_id}/purchases/#{purchase_token}?access_token=#{token}"

    uri = URI.parse path
    https = Net::HTTP.new(uri.host,uri.port)
    https.use_ssl = true
    https.verify_mode = OpenSSL::SSL::VERIFY_NONE

    headers = {}
    headers["accept"] = "application/json"
    headers["content-type"] = "application/json"

    # 参考: https://stackoverflow.com/questions/7346398/nethttp-failure-to-access-google-docs-list-data-api
    https.start do |http|
      return http.get(uri.request_uri, headers).body
    end
  end

  # main
  # gemfile => gem 'google-api-client', '~> 0.8.6'
  require 'google/api_client'

  client = Google::APIClient.new(
    application_name:    '適宜',
    application_version: '1.2.3',
  )

  client.authorization = Signet::OAuth2::Client.new(
    token_credential_uri: 'https://accounts.google.com/o/oauth2/token',
    audience:             'https://accounts.google.com/o/oauth2/token',
    scope:                [],
    # https://www.eisbahn.jp/yoichiro/2011/10/oauth2-0_google-api.html
    client_id:     $ANDROID_CLIENT_ID,
    client_secret: $ANDROID_CLIENT_SECRET,
    refresh_token: $ANDROID_REFRESH_KEY,
  )

  p client.authorization.access_token #=> nil

  client.authorization.refresh!

  product_id = "product_id"
  purchase_token = "xxxxxxxxxxxx.xx-xxxx-kRhDk04x2ahVCKPxCDYAnxuxxxW1FX5kn8rEZf66d7BpItG411lyUr-xxxxxxxxxxxxxnBaDPZakoUBhUliHrbzwOT1ZoLvP-5uy7Fxii3DsxxxxxxMHf-n_N3c-ozSgxxxJ-LUXxx-bxxxf1Tw"
  receipt = get_android_refresh_token(product_id, purchase_token, client.authorization.access_token)

  pp JSON.parse(receipt, {symbolize_names: true})
end
```
[Unity][Android]VideoPlayerでカクつく問題への対応

#はじめに
Unity 5.6 から [Video Player component](http://forum.cocos.com/t/extensions-extensionexport-h-no-such-file-or-directory/39310) が追加されました。
MP4などのムービーを簡単に全画面で流したり、テクスチャに貼り付けて再生できたりできる便利なコンポジションなのですが、
こちらも使っている際にぶつかった現象について備忘録も兼ねてまとめておきます。


#開発環境
Unity 5.6.3f1 (64-bit)


#現象
VideoPlayerでムービーを再生するとAndroid端末で動画がカクつく。
iOS端末やUnityシミュレーター上ではカクつかない。

現象が起きたのは音声ありMP4だったのですが、
・ムービー素材のビットレートやフレームレートを下げたり無音に変えたりしましたが変化なし。
・VideoPlayerコンポジションの設定を弄り回しましても変化なし。
という状態でした。


#原因
マルチスレッドレンダリング設定が有効になっているとカクつくようです。
こちらの設定はiOSにはないため、Androidのみで起きていたわけです。
恐らくレンダリングとムービーのデコードを別スレッドで制御しているため、
お互いに待ちが発生してカクつく原因になっているのではないかと予想されます。


#対応方法
マルチスレッドレンダリングを止めてやる。
Unityエディタ上の[Edit]->[Project Settings]->[Player]の[Android]タブ内に、
[Other Settings]->[Multithreaded Rendering]という項目があるので、チェックを外してやる。
![Unityエディタ画面.PNG](https://qiita-image-store.s3.amazonaws.com/0/75533/6e545e6f-a6db-5e9b-146d-dfb18d735e6c.png)


#最後に
こちらの原因に行き着くのに半日近く掛かってしまいました。
Unityを使い慣れていないというのもありますが、理屈を考えて調査するのは大事だなと思いました。
gradleのビルドスクリプトで外部ライブラリを使う

## 概要

gradleのビルドスクリプトのプログラムで外部ライブラリを使う方法です。
*<font color="red">ライブラリをプロジェクト自体で使う場合の dependencies に設定するのとは違います。</font>*

## 経緯

gradleでビルドするとき、最終的なwarファイルやapkファイルを作る直前にソースコードの一部を編集した上でビルドしたい場合や、ビルド後にとあるサーバーと通信して成果物をアップしたい時に、ビルドスクリプトをgradleファイル内に書くと思いますが、デフォルトで用意されているgroovy、またはjavaのライブラリでは書くのが面倒臭く、外部ライブラリを使いたかった。

## 方法

```groovy
import org.json.JSONArray
import org.json.JSONObject
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserException
import org.xmlpull.v1.XmlPullParserFactory

buildscript {
    repositories { mavenCentral() }
    dependencies {
        classpath 'org.json:json:20090211'
        // https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
        classpath group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5'
    }
}
```

ポイントは、<font color="red">buildscript の dependencies に classpath で設定する</font>(設定値はhttps://mvnrepository.com/ からコピーできる値でよい)のと、<font color="red">importを自前で書く</font>ということです。
これでimportしたクラスを使えます。

↑本当に普通な内容でした。。。

ハマったのは、classpath で設定しただけじゃ、自動ではコード補完候補に出てこないということでした。
java.ioとかであれば、自動で候補に出てくるし選んだら自動でimportも補完してくれるので、そのノリで書いたらダメでした。
Unity WebGLでのVideoPlayerがうまく再生できないとき

#VideoPlayerが動かない!!
たぶんこのページを開かれたということは、WebGLでvideoPlayerがうまく動かなくてお悩みのことだろうと思われます。
結論だけ書くと

###ネット上に動画ファイルを置いて、urlから開いて
###VideoPlayerのロードを待つスクリプトを書きましょう!!

#なぜこのような事態が起きるか
まず、Unity 5.6からある、VideoPlayerはMP4ファイルを読み込んでくれる神機能ですが
マルチプラットフォーム対応の際どうしても対応状況に差が出てしまっているようです...
###Videoclipを埋め込んだ時に再生できない問題
どうやら仕様らしいです、あきらめましょう
([ここに書いてある](https://forum.unity.com/threads/unity-5-6-0b4-issues-with-video-player-in-webgl.452092/)、ドキュメント見忘れたって書いてあるけどそんな記述あったかなぁ...)
###Urlから開いても再生されない問題
本来仕様ではローディングが終わってから再生されるはずなんですが、どうやらバグっているのかその前に開こうとしてエラーをはいてる感じでした。
なので、追加でスクリプトを書きましょう

```csharp:VideoLoader.cs
[SerializeField] string url;
#if UNITY_WEBGL
    void Start()
    {

        var videoPlayer = GetComponent<VideoPlayer>();
        videoPlayer.source = VideoSource.Url;
        videoPlayer.url = url;
        videoPlayer.prepareCompleted += PrepareCompleted;
        videoPlayer.Prepare();
    }
    void PrepareCompleted(VideoPlayer vp)
    {
        vp.prepareCompleted -= PrepareCompleted;
        vp.Play();
    }
#endif
```
こんな感じで書いて、VideoPlayerにアタッチしてくださいこれでおそらく動きます。
全てのファイルの中からGrepする。


###ファイルの中のテキストを一括で検索する。

```
find ./ -name "*.py" | xargs -I {} grep 'キーワード' {}
```

###ファイル名も表示する場合。
```
find ./ -name "*.py" | xargs -I {} sh -c 'echo {}; grep "キーワード" {}'
```

###ディレクトリの警告がうるさいので…。
```
find ./ -type f -name "*.py" | xargs -I {} sh -c 'echo {}; grep "キーワード" {}'
```

xargsとかだいたい忘れちゃいます。
《Git》GitLabにコミットしたら、FTPでサーバにアップロードする自動化を１分で行う方法。


GitLabがビルトインしているGitLabCIを使うと、`.gitlab-ci.yml` というファイルの設置だけで、とても簡単にデプロイの自動化を実現できます。

Git環境での作業効率化／自動化の、誰でも取り組めるTipsです。





## １分でやりたい簡単なデプロイの自動化

要件は、

1. マスターブランチにコミット
2. リモートにプッシュ
3. サーバーにアップロード

ということです。




## .gitlab-ci.ymlを設置する

レポジトリのルートに `.gitlab-ci.yml` というファイルを追加します。やることは、このファイルの設置と書き換えのみなので、１分くらいでデプロイの自動化を実現できますね。


```yaml.gitlab-ci.yml

variables:
  HOST: "example.com"
  USERNAME: "yourName"
  PASSWORD: "yourPass"
  LOCAL: "./your/dist/dir"
  SERVER: "./your/public_html"

deploy:
  script:
    - apt-get update -qq && apt-get install -y -qq lftp
    - lftp -c "set ftp:ssl-allow no; open -u $USERNAME,$PASSWORD $HOST; mirror -R $LOCAL $SERVER --parallel=10"
  only:
    - master

```

### .gitlab-ci.ymlを書き換える

それぞれの環境に合わせるために、`variables` の項目を任意のものに書き換えます。`LOCAL` はレポジトリのデプロイしたいディレクトリ、`SERVER` はサーバーへのパスを記述します。

このファイルをマスターにコミットすると、GitLabCIが動くようになります。GitLabのデフォルトの設定で、`.gitlab-ci.yml` の有無で、GitLabCI が動くようになっています。

ここでは、[lftp](https://lftp.yar.ru/) というツールをインストールし、それを利用してサーバに接続しています。`mirror` にいろいろなオプションを渡すことで、アップロードを制御できます。

* [lftp(1)](https://qz.tsugumi.org/man_lftp.html)


これで、必要なことは終わりです。





## ログとか見たい

デプロイのログは、GitLabの任意のレポジトリの中で、サイドバーの「CI/CG」 / 「Pipelines」から辿ることができるので、詳細を確認することができます。

ログから走らせたジョブをリトライをする、などの操作もできます。何かエラーが発生したときは、メールで通知が届くようになっています。





## 参考

* [Configuration of your jobs with .gitlab-ci.yml](https://gitlab.com/help/ci/yaml/README)
* [lftp(1)](https://qz.tsugumi.org/man_lftp.html)


GitLabCIは、いまのところ無料で利用できます、、GitLab素敵ですよね。












おわります。
なぜGemfileを更新した際にdocker-compose buildし直さなければならないのか

[こちらの記事](https://qiita.com/mom0tomo/items/eb8ac53f86a4ac6c09e7)で 「docker-composeを使ったRailsアプリ開発では、Gemfileを更新したときbuildしなおす必要がある」 ということがわかったのですが、理由が腑に落ちなかったので調べました。

## buildとupの違い
### up
`$ docker-compose up`
**コンテナを作成して起動する**コマンドです。
既にコンテナが起動中の場合、コンテナを再起動します。

このコマンドは、docker-compose.ymlを更新した場合は差分をキャッチして設定や利用するイメージを変更してくれます。


### build
`$ docker-compose build`

「web」や「db」など、docker-compose.ymlに記述されている **サービスのbuildを実行**します。
　ymlにimage:が書かれている場合はそのイメージをリモートからpullします。既にリモートにイメージがpullされている場合はそちらを利用します。
　imageが書かれていない場合は、buildに書かれているパスのDockerfileを参考にしてイメージをbuildします。


## Gemfileを更新したするときにbuildし直す理由
　Gemfileを変更したときはイメージをbuildし直す必要があるようです。
　この理由は、Dockerfileを読んだらわかりました。

```:Dockerfile
1 FROM ruby:2.4.2
2 RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
3 RUN mkdir /myapp
4 WORKDIR /myapp
5 ADD Gemfile /myapp/Gemfile
6 ADD Gemfile.lock /myapp/Gemfile.lock
7 RUN bundle install
8 ADD . /myapp
```

　5行目でGemfileをADDしています。
　Gemfileを更新したときは、この部分をやり直す必要があったんですね...

## 参考
* [docker-compose コマンドまとめ | Qiita
](https://qiita.com/aild_arch_bfmv/items/d47caf37b79e855af95f)
* [Compose command-line reference](https://docs.docker.com/compose/reference/)


buildし直すのが面倒な場合、docker-compose.ymlに設定を記述して回避することもできるそうです。

* [docker-composeでRailsのGemを更新する時、docker buildするのを回避したい | Qiita](https://qiita.com/neko-neko/items/abe912eba9c113fd527e)
[jq] jqで特殊な文字(-, $など)を含むkeyでフィルタできないときの対処法 (If the key contains special characters)



例えば、keyにハイフン(`-`)が入っているとする。

```test.json
{
  "foo-bar": "valueA",
  "hoge-fuga": "valueB"
}
```

そのままjqすると、エラーになる。

```
$ cat test.json | jq '.foo-bar'
jq: error: bar/0 is not defined at <top-level>, line 1:
.foo-bar
jq: 1 compile error
```

# 対処法

[マニュアル](https://stedolan.github.io/jq/manual/)によると、

キーを`""`で囲めばフィルタできるようになる。

```
cat test.json | jq '."foo-bar"'
"valueA"
```


>If the key contains special characters, you need to surround it with double quotes like this: `."foo-bar"`, or else `.["foo-bar"]`.


# 参考

https://qiita.com/keigo1450/items/84e696f8be0761ed0e04
https://stedolan.github.io/jq/manual/
ConEmuでマウスオーバーしてもフォーカスを変更しないようにする設定

デフォルトだとマウスオーバーしたタブにフォーカスが移る。
画面分割をしていた場合に、意図しないタブにフォーカスが移って困っていた。
マウスオーバーではフォーカス移らないようにする設定。

## 設定箇所

####カテゴリ
Settings > Keys & Macro > Mouse

#### 設定項目
- [ ] Activate split/pane on mouse hover　※チェックを外す

## 環境
ConEmu 170910
今夜どうにかしたいSeabornの見た目

完全に自分用のメモ。

    sns.set_style("white") # 大まかな見た目を変える。詳しくはリンク1
     sns.set_context("notebook", font_scale=1.7) #  大体のサイズとか用途（論文用とか、発表用とか）とかを決める。フォントのサイズを一括変換するのもここ。詳しくはリンク2
    #plt.rcParams["figure.figsize"] = 12, 9 # 12インチx9インで出力
    #plt.rcParams["figure.dpi"] = 200 # 出力時の解像度
    plt.rcParams["savefig.dpi"] = 500 # 保存時の解像度


参考にさせていただいたurl
http://kg15m.hatenablog.com/entry/2016/07/31/140643

リンク1
https://seaborn.pydata.org/tutorial/aesthetics.html
リンク2
http://seaborn.pydata.org/generated/seaborn.set_context.html
Kapow(Bizrobo)で分岐を実行する

# Kapow(Bizrobo)で分岐を実行する

## 目標
Kapow(Bizrobo)を使ってシナリオの分岐を行う

## 方法
今回分岐を実施するために最低限利用するアクション(Step)は二つ

1. Try_Step
2. Test_Variables

上記に加えて今回は無事分岐が成功したかを確認するため、```Write Log```と```Assign Str Result```を使って確認します。

## 流れ
シナリオ作成の流れは下記のようになります。

1. ```Assign Str Result```で分岐の条件となる文字列を設定します
2. ```Try_Step```を用意し、その設定で「Error Handling」タブの「Then」の部分を```Skip Following Steps```に設定
3. 上の分岐に```Test Variables```を用意し、「Action」のタブから「Conditions」に```StrResult="分岐1"```のようにあらかじめ1で設定した変数(StrResult ※1)が```分岐1```ならという条件を作成し、「If」の部分を```no Conditions are Satisfied```、「Do」の部分を```As Specified Under "Error Handling"```に設定
4. 適宜分岐結果が分かるように```Wrirte Log```を挟む

※1 今回の変数名は適当。

## 作成結果
下記のように作成しました

![分岐.png](https://qiita-image-store.s3.amazonaws.com/0/139291/78029a8c-5d25-9144-74fe-9e873ca739c1.png)

「Debug」のタブから、テスト実行し、```Assign Str Result```の部分で変数：```strResult```の中身を分岐1にするとシナリオフローの上の処理が、それ以外ならシナリオフローの下の処理が流れます。
マルチGPU環境で、計算に使用するCUDAデバイスを選択する

GPUが複数刺さった計算機でKeras（Tensorflow backend）を使おうとしたところ、
Tensorflowが全GPUのVRAMを全て確保しようとするために、他の計算が回らなくなって困った。
GPU1枚だけを専有するように指定する方法でハマったのでメモしておく。

# ソリューション

環境変数のCUDA_VISIBLE_DEVICESで指定できる。
kerasやtensorflowをimportする前に宣言すること

```
import os
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" 
os.environ["CUDA_VISIBLE_DEVICES"] = ""
```

例：nvidia-smiから見てGPU ID = 0のGPUを使用する場合は

```
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
```

# その他試したことなど
with文で with tf.device('/gpu:0'): などと書いた後で処理を記述する方法はうまくいかなかった。
KerasやTensorflowをimportした時点で全てのメモリが確保されてしまう。

## 環境
Ubuntu 16.04 LTS
Nvidia Driver Version: 384.98
CUDA 8.0
Keras 2.0.9
Tensorflow 1.4.0
GTX1080Ti x2

# 参考になった情報
 [Can keras model run on specific device?](Can keras model run on specific device?)
GnuPGで暗号化されたファイルをcronで定期的に復号する

# GnuPGとは

GnuPG の機能については [The GNU Privacy Guard](https://www.gnupg.org/) に書いてある。
>GnuPG allows to encrypt and sign your data and communication, features a versatile key management system as well as access modules for all kinds of public key directories.

GnuPGは<b>データの暗号化・署名</b>そして通信を可能にします、また色々な種類の公開鍵のための接続モジュールであるとともに多目的の<b>鍵管理システム</b>をその特徴としています。

これもネット上では何度も言われていそうだが、GnuPGには元となる規格PGP(Open PGP: [RFC4880](https://www.ietf.org/rfc/rfc4880.txt) )が存在する。GPGはPGPの実装である。

# 暗号化・復号

暗号化・復号の方法は他にいい記事があるので、それをチェックする

* [PGPを利用してファイルを暗号化する](https://qiita.com/MiyaseTakurou/items/03f6809ec314ce45d3f2)
* [GnuPG を使って暗号化したり署名したりする](http://pochi.usamimi.info/linux/gnupg.html)

# Cronでの復号

## /etc/crontab を編集

* `HOME` を実行ユーザのホームに変えると、パスが通って楽になる
* Cronのログは何もしないと残らないので、標準および標準エラー出力を適当なところにリダイレクトするといいようです

```diff
# vim /etc/crontab

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
-HOME=/
+HOME=/root

# あとは以下のように適当に実行するシェルを指定
# 毎日10時30にrootユーザで/root/decrypt.sh以降のコマンド実行
+30 10 * * * root /root/decrypt.sh /root/input.gpg >>/tmp/gpg.log 2>>/tmp/gpg-err.log
```

## 復号用のコマンドをシェル化

オプションのおおよその意味

* `-vv` 出力の詳細化
* `--no-tty` 端末で開くわけじゃないので設定する
* `--batch` 対話型のコマンドだと途中で処理が止まってしまうので、これを設定して何も聞かれないようにする
* `--passphrase-file` GPGの秘密鍵のパスフレーズをここに記載するする


```diff
+#!/bin/bash
+INPUT=${1}
+OUTPUT=${INPUT%.*}.zip
+echo "Input file: ${INPUT}"
+echo "Output file: ${OUTPUT}"
+/usr/bin/gpg -vv --no-tty --batch --passphrase-file /root/.gnupg/passphrase.txt --output ${OUTPUT} --decrypt ${INPUT}
```
metalsmithでmetadataを一括指定する方法

静的サイトジェネレータ(ここではmetalsmith)というのはそこまで頻繁にビルド用のコードを書かないせいか、どうしても毎回同じところでハマったりする。ここではmetadataを一括指定する方法を考える。

私が多く採用しているのはmetalsmith-collectionsでcollectionsを作成し、metalsmith-collection-metadataでmetadataを追加するというパターン。

## metalsmith-collections について

metalsmith-collectionsというのはmetalsmithではかなりよく使う重要なプラグインで、他のプラグインがこのプラグインに依存していたり、あるいは追加した `collections` を利用したりするものがわりとよくある。metalsmith-collection-metadataもそうしたプラグインのうちの一つ。

metalsmith-collectionsがどういうものかというのは[READMEを見てもらえれば](https://www.npmjs.com/package/metalsmith-collections)わかると思うので、詳細な解説はここではしないが、簡単に説明すると、blogのpostsのようなものを作るときのために使うような日付順によるソートや、その前後記事のデータなどを含めたデータ一式を揃えてくれるものという認識でだいたい問題ないと思う。

blogでいうとpagerであるmetalsmith-paginationというプラグインもmetalsmith-collectionsに依存しているので、metalsmith-collectionsはそうした**ある一連のコンテンツを生成する**ために重要なプラグインであることがわかる。

metalsmith-collectionsにはmetadataを追加する機能がある用に見えるが、以下の二点に注意する必要がある

- metadataはcollectionsに追加されるデータにのみ追加される
- metadataはすべて `metadata` というkey以下に設定される

つまり、blogの記事それぞれにmetalsmith-layout用の `layout: post.pug` のようなmetadataを追加するような用途では使うことができない。

## metalsmith-collection-metadata

metalsmith-collection-metadataはその名の通り、作成したcollectionを指定してmetadataを追加するプラグイン。

- https://www.npmjs.com/package/metalsmith-collection-metadata

このプラグインは指定したcollectionを持つすべてのファイルに対してmetadataを追加する。

## 他の一括メタデータ追加プラグイン

- https://www.npmjs.com/package/metalsmith-writemetadata
- https://www.npmjs.com/package/metalsmith-filemetadata

公式ではmetalsmith-writemetadataをプッシュしてるけど、metadataの追加という観点のみで考えると機能過多で(テストもないし)あんまり好きではない。試してはないけどもcollectionsの特定collectionをjsonとしてoutputできるような設定があるので、その機能がほしい場合では便利なんだと思う。

metadataの追加だけで使うのであればmetalsmith-filemetadataなんだけど、metalsmith-collectionsを使うにしてもmetalsmith-branchを使うにしても`pattern`の設定がいずれも重複するのがちょっとモヤモヤっとする。

大体一括でメタデータを指定したいケースというのはその一括指定したいファイル群でcollectionを作ることがほとんどので、metalsmith-collection-metadataがまず最優先で、もしそうでない場合の候補としてmetalsmith-filemetadataというのが今のところ自分としてはベストの解。
HerokuでMySQLセットアップ


HerokuでMySQLを使う方法について紹介します。

* インストール

```bash:
# Install
heroku addons:add cleardb:ignite --app ${app_name}

# Install結果の確認
heroku addons --app ${app_name}
```

* 接続情報確認

```bash:
# AppのConfig確認
heroku config --app ${app_name}

# MySQLの接続情報は下記ように表示される
CLEARDB_DATABASE_URL: mysql://ユーザ名:パスワード@サーバ名/データベース?reconnect=true
```

* 接続 

MySQL Workbench/Sequel Proを使って、databaseにアクセス


※ 参考サイト
http://www.ownway.info/Ruby/heroku/how/management/database/cleardb