OmniAICreator/Qiita-1.07M huggingface dataset:
Nagios管理画面に表示されるホスト・サービスをユーザーごとに制限する

# 前提
+ Nagios 4系でしか試していません
+ 管理画面へのログインはBasic認証で制限しています

# やりたいこと
管理画面のログインユーザーごとに、表示されるホスト・サービスを制限したい

# 設定方法
+ **contact_name**と同じユーザー名でBasic認証ユーザーを追加する

# 詳細
## 管理画面の表示権限オプションについて
ログインユーザーの権限に関する設定は *cgi.cfg* で以下のようなオプションで設定されている

+ **authorized_for_all_hosts**
+ **authorized_for_all_host_commands**
+ **authorized_for_all_services**
+ **authorized_for_all_service_commands**
+ **authorized_for_read_only**

**authorized_for_all_*** とあるとおり、オプションにユーザーを定義すると、
全てのhost、serviceが管理画面に表示される。
このほかに個別ユーザーアクセス権限を制限するオプションが見当たらなかったため、
ユーザーごとに表示可能なhost、serviceの制限は出来ないものと思っていた

## contact_name
``define contact{}``で設定されている、通知先名の定義です。
Basic認証にこの定義で設定したユーザー名で登録すると、管理画面にログインできます。
表示されるのは、この``contact_name``が通知先として設定されている host、service のみとなります

## コマンド実行の制限
**authorized_for_read_only**と同じように、コマンド実行を制限したい場合は
``define contact{}``で **can_submit_commands** を ``1`` とします。
省略時は ``0`` なので、コマンド実行可能な状態となっています。
通知先定義ごとの設定のため、同じユーザーで host、service のコマンド実行可否を分けることは出来無そうです

## contactgroup_nameでは制限できない？
**contactgroup_name**にの設定値をBasic認証ユーザーに追加したところ
ログイン可能だが、1つも host、service が表示されない状態となった。
おそらく、Basic認証の承認だけで、Nagios側の権限のあるユーザーとして認識されない状態と思われます。
Pythonの環境構築メモ(Anaconda,biopython)

#0_始めに
研究室でPythonを使うことになったので生物系に必要そうなパッケージをインストールしようと思った
調べてみるとデータ分析系のパッケージは大体Anacondaにあるらしいのでそれを入れることにした
また,FASTAファイルを読み込みたかったのでBiopythonを入れた。

使用した環境は下に
OS:Widows 10 Home
Anaconda3: 5.0.0


#1_Anacondaをインストールする
まず,Windows向けのインストーラを以下からダウンロードした
自分はPython3.6versionの64bit版をダウンロードした。
https://www.anaconda.com/download/

ダウンロード後,インストーラーを起動し,インストールを完了させる。
この時,インストール先の場所を記録しておくといい（はず）

以下のサイトを参考にするといいと思います
http://pythondatascience.plavox.info/python%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/python%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB-windows

#2 Pythonのパスを通す
コマンドプロンプトを開き,pythonの実行を確認してみる
![image.png](https://qiita-image-store.s3.amazonaws.com/0/143479/bfeebc79-3397-acf8-3b48-5b014ebbc408.png)
こんな感じで表示されればOK, 

|Anaconda ,Inc|の文字がない場合PythonとAnacondaのパスが通っていないので,以下を参考にパスを通す.自分の場合C:\ProgramData\Anaconda3

https://www.pythonweb.jp/install/setup/index1.html

#3_biopythonをインストールする
Anacondaのなかにbiopythonは入っていないみたいなので追加したい。
プロキシ存在下の場合は,.condarcファイルを作成し,プロキシを設定する必要がある(学内回線なら必須）。
また,学内回線につなぐ際にidとpasswordが必要な場合,
http://ユーザID:パスワード@プロキシアドレス:ポート番号
というように記述する必要がある

https://qiita.com/mishan88/items/2f9e1c5e9e2572ba8a36 を参考にするとよい。

その後CortanaなどでAnacondaNavigatorを検索し,管理者権限で起動
（管理者権限で起動しないと書き込みができないのでエラーになる。）

起動後,Enviromentを選択,installedをNotinstalledに変更し検索欄にbiopythonを入力,
パッケージにチェックを入れると右下にApplyが出現するので実行。


#4_エディタについて
Pythonを実行するエディタについてだが,
anacondaをインストールした際についてくるjupyternotebookでもよさそう
AnacondaNavigatorから起動できる
CloudFormationでクロスアカウントなVPCPeeringを構築する

# 概要
別アカウントのVPCとVPCピアリングを行う際のCFnの書き方と、ロールの設定方法について。
なお同一アカウント内でのVPCピアリングだとロール無しでスルッと行ける。

# やり方
## ざっくり
1. 前提としてピアリングを行うVPCは各アカウントで用意してあること
2. VPCPeeringを受け入れる(accepter)アカウントでクロスアカウント許可用ロールを用意
3. VPCPeeringをリクエストする(requester)アカウントでVPCPeeringリクエストを送信
4. 完了

## ロールの用意
### テンプレート
```acceptrole.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: Accept VPC Peering Role
Parameters:
  AcceptAccountId:
    Type: String

Resources:
  AcceptVpcPeeringRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: 'AcceptVpcPeeringRole'
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Action: 'sts:AssumeRole'
            Principal:
              # ここで複数アカウントを指定することも可能
              AWS: !Join
                - ''
                - - 'arn:aws:iam::'
                  - !Ref AcceptAccountId
                  - ':root'
      Policies:
        - PolicyName: 'AcceptVpcPeering'
          PolicyDocument:
            Statement:
              - Effect: Allow
                Action: 'ec2:AcceptVpcPeeringConnection'
                # 適宜許可を行いたいVPCを設定
                Resource: '*'

```

### 実行コマンド
```bash
$ aws cloudformation create-stack \
    --stack-name accept-vpcpeering-role \
    --template-body file://acceptvpcpeeringrole.yaml \
    --parameters ParameterKey=AcceptAccountId,ParameterValue=000000 \
    --capabilities CAPABILITY_NAMED_IAM \
    --profile=accepter # profileは適宜
```

## VPCPeeringの作成
### テンプレート
```vpcpeering.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: VPC Peering
Parameters:
  VpcId: 
    Type: String
    Default: 'vpc-xxxxxxxxx'
  PeerOwnerId:
    Type: String
    Default: '000000000000000'
  PeerVpcId:
    Type: String
    Default: 'vpc-xxxxxxxxx'
  PeerRoleArn:
    Type: String
    Default: 'arn:aws:iam::000000000000000:role/AcceptVpcPeeringRole'
    
Resources:
  VpcPeering:
    Type: "AWS::EC2::VPCPeeringConnection"
    Properties:
      VpcId: !Ref VpcId
      PeerOwnerId: !Ref PeerOwnerId
      PeerVpcId: !Ref PeerVpcId
      PeerRoleArn: !Ref PeerRoleArn
      Tags:
        - Key: Name
          Value: 'TestPeering'

```

### コマンド
```bash
$ aws cloudformation create-stack \
    --stack-name vpcpeering \
    --template-body file://vpcpeering.yaml \
    --profile=requester # profileは適宜
```
node.js Express4.Xで middlewareとしてasync function

#　なんか出来るっぽい

async functionはawaitしない場合Promiseオブジェクトが返却されます。
普通のfunctionとは違うので、どうなるか気になったので調べてみた

express-generatorで生成されるapp.jsに対して
以下の様にasync function を使ったミドルウェアを追加しても
next()が生きていてその後の処理に進んでいた。

```app.js

app.use(async function(req ,res ,next){
  console.log("async func")
  next() 
})

app.use("/"....)
```
結論、どんな形でもnext()が呼ばれればいいのかな？
UbuntuにBluetoothで接続したヘッドセットがA2DPプロファイルを適用するための設定

# はじめに

以前は問題なかったんですが、いつのまにかUbuntuにBluetoothで接続しているヘッドセットがA2DPプロファイルでなくHSP/HFPプロファイルしか適用できなくなっていました。いろいろと調べた結果、A2DPプロファイルが適用できるようになった設定です。

# 環境

Ubuntu 16.04です。ちなみに、それまで14.04でしたが、もしかしたら16.04に上げれば直るかも、と期待してバージョンアップしましたが変わらなかったので、少し真面目に調べました。

# 現象

「すべての設定」から「サウンド」を選択して「出力」タブで「サウンド出力デバイスの選択」からBluetoothで接続しているデバイスを選択すると、「プロファイル」のメニューで以下の2つを選択できるようになります。

- High Fidelity Playback(A2DP Sink)
- Headset Head Unit (HSP/HFP)

HSP/HFPが設定されていたので、これをA2DP Sinkに変更して「スピーカーのテスト」をしてもステレオになりませんし、「サウンド」画面を閉じてから開くとHSP/HFPに戻っていました。

Bluetoothマネージャーを起動してBluetoothで接続しているデバイスを右クリックして「オーディオプロファイル」からHigh Fidelity Playback(A2DP Sink)を選択すると、

```
Failed to change profile to a2dp_sink
```
というエラーメッセージが画面の下に表示されてプロファイルが変更されませんでした。

# 変更点

いろいろと検索した結果、以下のリンク先に書かれていたコメントを見つけました。

[Bluetooth Speaker not doing A2DP Ubuntu Gnome 17.04](https://askubuntu.com/questions/934381/bluetooth-speaker-not-doing-a2dp-ubuntu-gnome-17-04/935972)

どうやらGnome Display Manager(GDM)がpulseaudioのBluetooth接続を有効にしているのが問題で、それを無効にすればいい、ということのようです。

GDMのpulseaudioを無効にする設定が以下の通りです。

1. /var/lib/gdm3/.config/pulse/default.paをテキストエディタでオープンします。私の環境には、そもそも該当するファイルがなかったので作成しました。ファイルの作成およびオープンにはroot権限が必要です。

1. 以下の内容を追加します。

```default.pa
#!/usr/bin/pulseaudio -nF
#

# load system wide configuration
.include /etc/pulse/default.pa

### unload driver modules for Bluetooth hardware
.ifexists module-bluetooth-policy.so
  unload-module module-bluetooth-policy
.endif

.ifexists module-bluetooth-discover.so
  unload-module module-bluetooth-discover
.endif
```

エディタを閉じてOSを再起動するとA2DPプロファイルに切り替えられるようになりました。
Laravelをサブディレクトリで動かす on Apache2.4PHP7.0

※ 2018/6/25 assetについて追記しました。

# 目的
https://qiita.com/darum/items/b4841e031dca46b8c138
こちらで作った環境を使って、以下のようなアドレスでLaravelアプリにアクセスするように設定を行う

アドレス
http://192.168.1.10/laraapp/
※ 自宅環境なので、DNSなしです

# 前提条件
Laravbelアプリは出来上がっている（完成といかなくても、ローカルで動作確認済み）

# 事前作業
/home/me/laravel にデプロイ済み
※ モダンなデプロイ方法はいっぱいあると思いますが、こちらについては別途

# 作業
## Apache2.4 の設定

```/etc/httpd/conf/httpd.conf
Alias /laravel /home/me/laravel/public
<Directory "/home/me/laravel/public">
        AllowOverride All
        Require all granted
</Directory>
```
Apacheを再起動

## public/.htaccessの編集
```
    RewriteBase "/laravel/" # 追加

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^laravel/(.*) /%1 [L,R=301] #編集
```

## アセットを使うとき
hoge.blade.php
```
    <script src="{{ asset('app.js') }}"></script>
```
asset() を使ってファイルを指定する必要がある。

[バージョンニング](https://readouble.com/laravel/5.5/ja/mix.html#versioning-and-cache-busting) を利用している場合は、mix()も使用して、

```
    <script src="{{ asset(mix('app.js')) }}"></script>
```
remarkで作ったスライドをPDF出力する方法

みなさんは[remark](https://github.com/gnab/remark)をご存知でしょうか？

こちらはMarkdownでスライドを生成できる便利なライブラリです。

このremarkで作ったスライドをPDFに出力する簡単な方法をご紹介しようと思います。

## 出力方法

remarkで作ったスライドをPDFにするとき、一番簡単そうなのはCSSに

```css
@page {
  size: 1210px 681px;
  margin: 0;
}

@media print {
  .remark-slide-scaler {
    width: 100% !important;
    height: 100% !important;
    transform: scale(1) !important;
    top: 0 !important;
    left: 0 !important;
  }
}
```

を追加してchromeの印刷からPDF出力するという方法です。

4対3にしたいときは`size: 908px 681px;`とすればOKです。

> 参考：[Export to PDF · Issue #50 · gnab/remark](https://github.com/gnab/remark/issues/50#issuecomment-223887379)
Xcodeで Could not load the "" image referenced from... が出た時の解決法

事象
---
XcodeでStoryboardを使ってUIButtonを配置して、そのボタン用の画像を指定しました。でもなんか画像が気に入らないなー。やっぱりこの画像に変えよーっと。という感じで画像を変更しました。
さて動かしてみるとコンソールに

```
Could not load the "hoge.png" image referenced from... 
```

と出て、ボタンが表示されない。

色々試行錯誤した結果、

解決法
---
1. 画像（上記例だとhoge.png)を削除する。
2. ボタンも削除する。
3. 画像のファイル名を変えて（例えばhogeNew.png) File->Add Files
.. で読み込む。
4. StoryBoardで新しくボタン(UIButton)を配置し、ボタンのAttributeで画像(hogeNew.png)を指定する。


原因（推測）
---
UIButtonのAttributeのImageに画像を指定した後、その画像ファイルを削除し、ButtonのAttribute設定はそのままにしたのが原因かも。
お作法としては、まずButtonのAttributeを変更して、その後に元の画像ファイルを削除するのが正解かもしれません。
Hashable

Hashableプロトコルのリファレンスの意訳です。

# 概要
この型は整数のハッシュ値を提供します。

`Hashable`プロトコルに準拠する型は辞書のキーや集合で使うことができます。標準ライブラリの多くの型はデフォルトでHashableです。独自の型もHashableにできます。

関連する値をもたない列挙型を定義すると自動的にHashableになります。
他の独自の型でもhashValueプロパティを加えることでHashableにできます。

ハッシュ値はhashValueプロパティによって決まり、比較の際、互いが等しいときにハッシュ値は等しくなります。つまり、aとbが同じであるとき、a.hashValue == b.hashValueです。しかし、逆は必ずしも真ではありません。等しいハッシュ値が必ずしも互いが等しいとは限りません。

### 重要な点
ハッシュ値は異なるプログラムの実行において等しい値を保証していません。
ハッシュ値を将来の実行にそなえて保存しないでください。

#Hashableプロトコルに準拠する

集合で独自の型を使いたい場合や、辞書のキーとして使用する場合、hashValueを定義することでHashableへの準拠を追加してください。

HashableプロトコルはEquatableプロトコルを継承していますので、等号演算子('==')関数を追加する必要があります。

 例として、 `GridPoint`型というボタンのグリッドにおける場所を記述する型を考えてみましょう。
 
`GridPoint`型の最初の宣言は次のとおりです：

```swift
     // A point in an x-y coordinate system.
     struct GridPoint {
         var x: Int
         var y: Int
     }
```


ユーザーが今までタップしたグリッドの位置のセットを作りたいとします。
GridPointはまだHashableでないので集合のElementとしてはまだ使えません。
Hashableに準拠するためには'=='演算子関数と'hashValue'プロパティを加えます。

```swift
     extension GridPoint: Hashable {
         var hashValue: Int {
             return x.hashValue ^ y.hashValue
         }

         static func == (lhs: GridPoint, rhs: GridPoint) -> Bool {
             return lhs.x == rhs.x && lhs.y == rhs.y
         }
     }
```

この例での'hashValue'プロパティはグリッドのxとyのハッシュ値をビットごとのXOR演算子('^')を用いて結合しています。'^'演算子は２つの整数を1つの整数に結合する一つの方法です。

 - 注：集合と辞書のパフォーマンスはハッシュ値に依存します。ハッシュ値がそれらに関連する要素とキーの衝突を最小化します。

GridPointをHashableプロトコルに準拠させたので、タップされたグリッドポイントの集合を作成することができるようになりました。

```swift
     var tappedPoints: Set = [GridPoint(x: 2, y: 3), GridPoint(x: 4, y: 1)]
     let nextTap = GridPoint(x: 0, y: 1)
     if tappedPoints.contains(nextTap) {
         print("Already tapped at (\(nextTap.x), \(nextTap.y)).")
     } else {
         tappedPoints.insert(nextTap)
         print("New tap detected at (\(nextTap.x), \(nextTap.y)).")
     }
     // Prints "New tap detected at (0, 1).")
```
TensorFlowの学習を始めた時によく調べ直すメソッド

# はじめに
絶賛記事追記中です（17/10/18)

# 変数・定数など
## tf.constant
* 定数

## tf.variable
* 変数

## tf.placeholder
* データが格納される予定地
* 出力結果などをここに放り込む

# 活性化関数
## tf.nn.relu
* 活性化関数
* 0より大きい時に活性
* x = (y <= 0.0) ? 0.0 : y;

# 損失関数
## tf.reduce_mean
* 自分のモデルと実データの差異に対応するコスト
* 平均を計算する関数
* 学習結果の正解率を出すのなどに使用

# 計算
## tf.square
* 二乗をとる

# 最適化クラス
## tf.train.RMSPropOptimizer
* 収束値に近づいた後、目的関数はほとんど同じ値に留まる。
 * [参考](https://qiita.com/cnloni/items/ad7dcb7521b936d9fc18)

# 出力整備
## tf.nn.softmax
* 0~1の結果にする

# 分類分からず
## tf.matmul
* 行列積
* matrix multiplicationからきている

## truncated_normal
* 正規分布かつ標準偏差の2倍までのランダムな値で初期化
* stddev：正規分布の標準偏差を指定する。1.0で標準正規分布

# その他調べている時によく見かける旧メソッド
* tf.audio_summary -> `tf.summary.audio
* tf.contrib.deprecated.histogram_summary -> tf.summary.histogram
* tf.contrib.deprecated.scalar_summary -> `tf.summary.scalar
* tf.histogram_summary -> tf.summary.histogram
* tf.image_summary -> tf.summary.image
* tf.merge_all_summaries -> tf.summary.merge_all
* tf.merge_summary -> tf.summary.merge
* tf.scalar_summary -> tf.summary.scalar
* tf.train.SummaryWriter -> tf.summary.FileWriter

[TensorFlow の "AttributeError: 'module' object has no attribute 'xxxx'" エラーでつまづいてしまう人のための移行ガイド](https://qiita.com/shu223/items/ef160cbe1e9d9f57c248)
Qiitaの記事の画像のサイズを変えてみた

#はじめに
Qiitaで画像を投稿する際に画像サイズや表示位置を変更したいと思いましたので
こちらの記事を備忘録として残します。

##全画面表示

通常画像をアップロードする場合は以下の手順になるかと思います。
1. 投稿ページにアクセス
2. エディタから載せたい画像をドラッグアンドドロップ、もしくは画像を選択

この場合は以下のように横いっぱいに大きく表示されます。
![代替テキスト](https://qiita-image-store.s3.amazonaws.com/0/207972/60eadf64-4856-23e0-daea-21ded748e209.jpeg)

##サイズを変更
全画面表示版は以下のような記載になっているかと思います。
`![代替テキスト](https://qiita-image-store.s3.amazonaws.com/0/207972/60eadf64-4856-23e0-daea-21ded748e209.jpeg)`

上記をimgタグにして、width を追加し任意の値を設定します。
`<img src="https://qiita-image-store.s3.amazonaws.com/0/207972/60eadf64-4856-23e0-daea-21ded748e209.jpeg" width=50%>`

結果
<img src="https://qiita-image-store.s3.amazonaws.com/0/207972/60eadf64-4856-23e0-daea-21ded748e209.jpeg" width=50%>

小さくなりました！

■参考サイト
https://qiita.com/hkusu/items/1ba2de200f731e5ef374
GoogleスプレッドシートのSUMIFS関数、全角と半角を区別しない疑惑。

# ちょっと戸惑ったのでメモ
データをスプレッドシートで集計していたところ、同じデータを同じように参照していると思ったら
集計結果が違って戸惑ったことがあったので、記録しておきます。

# 関数たち
## COUNTIF関数
![countif.PNG](https://qiita-image-store.s3.amazonaws.com/0/129038/3b42e9cf-e4b8-7216-87cb-05bbc0dbc121.png)
"banana"のかずは　3つですね。

## COUNTIFS関数
![countifs.PNG](https://qiita-image-store.s3.amazonaws.com/0/129038/490702b7-b47e-e642-3949-1808e5a6e7e5.png)
こちらも、"banana"は　3つですね。

## SUMIF関数
![sumif.PNG](https://qiita-image-store.s3.amazonaws.com/0/129038/c4967d7e-afb0-355b-1b91-fe7863f9ae3b.png)
"banana"のよこの　すうじのわは　3ですね。

## SUMIFS関数
![sumifs.PNG](https://qiita-image-store.s3.amazonaws.com/0/129038/d485109f-620e-3b11-a302-22fc3c59219d.png)
"banana"のよこの　すうじのわは　4ですか……？

# SUMIFS関数は全角と半角を区別しない
っぽいです。
Google AnalyticsのPV数について集計していると、
全角英数のURLが紛れ込んでいて、
サイトで確認した結果とSUMIFS関数での集計結果が違うという問題が発生しました。


# 全角と半角を区別してSUMIFS関数を使う方法
私の頭では思いつきませんでした。
ﾀﾞﾚｶﾀｽｹﾃｰ

# 仲良くしていきたい
それでもやっぱりスプレッドシートは便利なので、仲良く付き合っていきたいですね。
viエディタ操作方法(初心者向け)

# viエディタ

A4サイズで操作方法をまとめてみました。
これを印刷して、キーボードの手前の机上に置けば、
少しでも体得の効率を高められるかな、と。
![20171017 viエディタ -(CC-BY).png](https://qiita-image-store.s3.amazonaws.com/0/60782/22421e52-ccaa-155d-ee75-9534d186c450.png)
新しくCSVファイルを利用せざるを得ないときのチェックリスト

CSVは誰かがフォーマットを厳密に定義してるわけでないので、認識相違が多めです。
以下のような部分を考えましょう。

|ポイント|例|メモ|
|:-----------------|:------------------|:------------------|
|改行コード| <ul><li>CR+LF(Windows主流)</li><li>LF(Unix主流)</li></ul>|CRLFが無難。|
|文字コード|<ul><li>UTF-8</li><li>CP932</li><li>Shift_JIS</li><li>EUC-JP</li></ul>|WindowsでもUTF-8がおすすめ。<br>UTF-8が主流だからというのは当然として、特にVistaからJIS第三第四水準文字がUnicodeで入力できるので入力値に存在する可能性がある。<p>文字コード決めの考慮点<ul><li>JIS第三第四水準文字を利用するか</li><li>Windowsの場合は拡張文字を利用するか</li><li>emojiはどうか</li></ul></p>まず使わないがShift_JISやEUC-JPも2004版で第三第四水準相当になる。|
|区切り文字|<ul><li>カンマ</li><li>タブ</li></ul>|項目にカンマが含まれる可能性があるのでタブのほうがおすすめ。<br>またスプレッドシートではタブの方が扱いやすいのもポイント。|
|ヘッダー|<ul><li>あり</li><li>なし</li></ul>|合意しておくこと。あったほうが内容確認時に便利|
|途中の空行|<ul><li>あり(完全に空）</li><li>あり（カンマだけ）</li><li> なし</li></ul>|プログラム上でおかしくなる可能性|
|最終行|<ul><li>改行つける</li><li>改行つけない</li></ul>|プログラム上でおかしくなる可能性|
|項目内改行|<ul><li>あり</li><li>なし</li></ul>|なるべくなしにしたい。ありの場合で Excelを使ったとき、項目内改行の改行コードはCRである。|
|空データ|<ul><li>ありえる</li><li>なし</li></ul>|CSVというより一般常識。あとファイル作るか作らないかも。ヘッダーも注意。|
|記号、制御文字|<ul><li>入ってくる</li><li>入ってこない</li></ul>|これも常識|
|ユーザーがExcelでみたり操作するか|<ul><li>する</li><li>しない</li></ul>|様々なExcelトラップがある。0はじまり文字列の0が表示上消えたり、勝手に日付として解釈したり。<br>そのためユーザーに良い開き方を教えたり項目内容を工夫したりする必要がある。|
|項目をダブルクオートでくくるか|<ul><li>くくる</li><li>くくらない</li></ul>|くくる場合はさらに考える事が<ul><li>一部項目だけくくる</li><li>ダブルクオート内のダブルクオートはどうするか</li><li>シングルクオートでくくる</li><li>項目が空データの場合はくくるかくくらないか</li></ul>|

ファイルは結合度が高く、データ連携としては原始的です。
そもそもCSVで渡す必要性を考えつつ、素直に作りましょう。
BetaFlight OSDもスロットルグラフ表示してみた


#BetaFlight OSD

- [MWOSD](https://qiita.com/osaruda/items/cc15fe7f51f158713003)とは異なり、フライトコントローラーのCPUが直接描画を行うのでレスポンスに優れる。
- MCMフォントフォーマットは[MWOSD](https://qiita.com/osaruda/items/cc15fe7f51f158713003)と共通だが、後半部分に起動ロゴビットマップを使用しているので、0xF0〜のコードを使用できない。コンパスを使用した矢印表示はあまり必要ないので、そのエリアをフォントマップに使用してみた。
- BetaFlightのファームウェア本体を改造するため、ビルド後の改造ファームをフライトコントローラーに描き込む必要がある。
- BetaFlightは3.2.0をosd表示のみ改造した。
- フォントセットは、プリセットのすべてのフォントに対しグラフ表示部分0x60〜12文字分を書き換えているものを用意。

## Macでビルド環境を構築する

- 普通にDeveloper Toolsインストールする。最近はAppStoreよりXcodeをインストールするだけでOKみたい。
- ARMのSDKをインストールする。BetaFlightのソースを解凍したディレクトリでコマンド一発で終了

```bash
$ cd betaflight-x.x.x
$ make arm_sdk_install
```

- ターゲットを選択してビルドする。

```bash
$ make TARGET=hogehoge
```

## コード

osd.c

```C
    case OSD_THROTTLE_POS:
        buff[0] = SYM_THR;
        buff[1] = SYM_THR1;
        int throttle_per = (constrain(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX) - PWM_RANGE_MIN) * 100 / (PWM_RANGE_MAX - PWM_RANGE_MIN);
#ifdef THROTTLE_GRAPH
        throttle_per = throttle_per / 2; //0-50
        throttle_per = throttle_per>48 ? 48 : throttle_per; //0-48、まぁ95%以上なら100%扱いでいいだろう。
        int cur1 = throttle_per<12 ? throttle_per : 12; throttle_per = throttle_per<12 ? 0 : throttle_per-12;
        int cur2 = throttle_per<12 ? throttle_per : 12; throttle_per = throttle_per<12 ? 0 : throttle_per-12;
        int cur3 = throttle_per<12 ? throttle_per : 12; throttle_per = throttle_per<12 ? 0 : throttle_per-12;
        int cur4 = throttle_per<12 ? throttle_per : 12;
        buff[2] = 0x60 + cur1;
        buff[3] = 0x60 + cur2;
        buff[4] = 0x60 + cur3;
        buff[5] = 0x60 + cur4;
#else
		tfp_sprintf(buff + 2, "%d", throttle_per);
		//constrainで、lowとhigtの設定した値範囲の中の初手一を返す。
		//おそらく1070-1950くらいがデータとして返る。それをパーセンテージ表示に直してtfp_sprintfしている。
#endif
        break;
```

##ダウンロード
![222.png](https://qiita-image-store.s3.amazonaws.com/0/207772/54540c4a-c0bf-0a34-9f8f-50b190aaca61.png)

[BetaFlight（スロットル表示改）ファームウェアダウンロード](https://www.dropbox.com/sh/ac74x6wa165zd5g/AADB7dUW4Jy7vaWsRtG_06TKa?dl=0)

- 3.2.0 -> 3.2.1 はバグフィックスのみとのこと。osd.cの改変はありませんでしたのでそのま移行。
- 3.2.1 -> 3.2.2 OSD関係もいくつか修正があるみたいですね。FULL_CIRCLEって何だろう・・・
- 3.2.2 -> 3.2.3 
- 3.2.3 -> 3.2.4 
- 3.2.4 -> 3.2.5 & 3.3.0 RC1
- 3.3.0 RC1 -> 3.3.0 RC2 OSD関係は変更無し
- 3.3.0 RC2 -> 3.3.0 RC3 OSD関係の修正あり
- 3.3.0 RC3 -> 3.3.0 & ButterFlight 3.4.2 （clarity.mcmをフォントセットに追加）
- 3.3.0 -> beta 3.3.1 & butter 3.5.0
- 3.3.1 -> beta 3.3.2 & butter 3.5.1RC2
- 3.3.2 -> 3.3.3 w/ RSSI Graph
- 3.3.3 -> 3.4.0 RC1 -> 3.4.0 RC2
- 3.4.0 RC2 -> 3.4.0 RC5 -> 3.4.0
- 3.4.0 -> 3.4.1 & 3.5.0
- 3.5.0 -> 3.5.1
- 3.5.1 -> 3.5.2
- 3.5.2 -> 3.5.3
- 3.5.3 -> 3.5.4
- 3.5.4 -> 3.5.5
- 3.5.5 -> 3.5.6 & 4.0.0 RC1
- 3.5.6 -> 3.5.7 & 4.0.0 RC2
- 4.0.0 RC2 -> 4.0.0 RC4
- 4.0.0 RC4 -> 4.0.0 RC6
- RC6 -> 4.0.0
- 4.0.0 -> 4.0.1
- 4.0.1 -> 4.0.2
- 4.0.2 -> 4.0.3
- 4.0.3 -> 4.0.4 
- 4.0.4 -> 4.0.5
- 4.0.5 -> 4.0.6

![BF_date.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207772/d66fde48-c64e-87b3-5623-40e2f2cfe178.png)
ファームウェアとコンフィグレーターのリリース日付相関関係も纏めてみた。
■ ありえない日付をIF関数で確認 ☆

#■ ありえない日付をIF関数で確認 ☆

**=IF(ISERR(DAY(B1)),"あり得ない日付です。","OK")**

![IF関数_01.jpg](https://qiita-image-store.s3.amazonaws.com/0/196323/bb95c4b9-1460-76d1-8af7-37e761237789.jpeg)
mongo コマンド一覧

### mongoコマンド一覧

##db確認コマンド
＞ show dbs
admin     0.078GB
crowidb   0.078GB
local     0.078GB
searchdb  0.078GB
test      0.078GB
test_db   0.078GB

##DB切り替え
＞ use crowidb

##コレクション一覧確認
＞show collections
attachments
bookmarks
comments
configs
pages
revisions
searchwords
system.indexes
updateposts
user
users
words

#DB確認
> db.pages.find()
{ "_id" : ObjectId("XXXXXXXXXXXXXXXXXXXXXXX")...........以下省略

#DB詳細確認(2017年10月1日の日報のみ抽出)
＞ db.pages.find({path: "/user/yamada/日報/2017/10/01"})

＞ db.users.find( {name:'山田 太郎'} )
{ "_id" : ObjectId("58fa23767ffd2fbb09ef557d"), "password" : "e740e6904141efbcc221e183d50267dcbed95920eb214dc2f94bf587bc44e87d", "email" : "yamada@test.jp", "username" : "yamada", "name" : "山田 太郎", "admin" : true, "createdAt" : ISODate("2017-04-21T15:21:26.581Z"), "status" : 2, "__v" : 0, "apiToken" : "CzkEzDxllZ9ZPbvJsw/W21XrhNLQd7pbpM5IxMB0eGY=" }

＞ db.users.find().forEach(function(user){print (user.username + "," + user.name);})
test,てすと
test1,てすといち
test2,てすとに
※function(user)←変数

#DB削除
pages
＞ db.pages.remove({path: "/user/yamada/日報/2017/10/17"})

user
＞ db.users.remove( {name:'ぱち'} )
WriteResult({ "nRemoved" : 1 })
Laravel artisanコマンドでエラーが出る時の対処法

Laravelをアップグレードした際などに出るエラーでartisanコマンドが動かなくなる時があります。この記事では、その時の対処法を紹介します。

## 問題

artisanコマンドを入力した際にこのようなエラーが出る。

```
[Symfony\Component\Debug\Exception\FatalErrorException]         
Trait 'Illuminate\Console\AppNamespaceDetectorTrait' not found  
```

## 対策

このエラーは次のように use 宣言を変更することで対処できます。

> 直接Illuminate\Console\AppNamespaceDetectorTraitを使用しているのであれば、代わりにIlluminate\Console\AppNamespaceDetectorTraitを使用するようにコードを更新してください。
[アップグレードガイド 5\.4 Laravel](https://readouble.com/laravel/5.4/ja/upgrade.html)

```diff
// vender\laralib\l5scaffold\src\Makes\MakeController.php
- use Illuminate\Console\AppNamespaceDetectorTrait;
+ use Illuminate\Console\DetectsApplicationNamespace;
```

## 参考

https://readouble.com/laravel/5.4/ja/upgrade.html
http://am1tanaka.hatenablog.com/entry/2017/02/14/142601
DockerでTOMCATを立てる

## TOMCATの起動

```bash
docker run -d -p 8000:8080 tomcat:8.0
```

## ベーシック認証の有効化

docker環境に入り

```bash
bash -c "clear && docker exec -it nostalgic_mestorf bash"
```

vimをインストール

```bash
apt-get update
apt-get install vim
```
tomcat-users.xmlを編集

```bash
vim /usr/local/tomcat/conf/tomcat-users.xml
```

以下を追加

```
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<user username="admin" password="password" roles="manager-gui,manager-script" />
```

これで`admin` `password`でログインできるようになります。


## 再起動して設定を有効化

```bash
docker restart {コンテナ名}
```

127.0.0.1:8000にアクセスしてログインできれば設置完了
ClojureのビルドツールLeiningenがJava9で動かない件の対策

#動かない
Java9を入れて、leinを起動すると・・・
![Screenshot from 2017-10-18 09:48:33.png](https://qiita-image-store.s3.amazonaws.com/0/9582/10ac3082-abde-40ec-e0af-14d5ff32d557.png)

ｷﾞｬｱｯ！

ぐぐると本家でもスレッドが伸びていました。

Java 9 incompatibility - technomancy/leiningen - GitHub
https://github.com/technomancy/leiningen/issues/2149

Java9におけるProjecgt Jigsawの影響でsun.miscに大規模な改修が入りその影響？
という事みたいですが、よく分かりませんでした。

#対策

leinをアップデートします。
`$ lein upgrade 2.8.0-RC1`

これだけで動くらしいのですが私の場合は動かなかったので
leinスクリプトを開いて204行目付近にある

```bash:lein
if [ "$LEIN_SKIP_BOOTCLASSPATH" = "" ]; then
     BOOTCLASSPATH="-Xbootclasspath/a:$LEIN_JAR"
fi
```
をコメントアウトすると動きました。

![Screenshot from 2017-10-18 09:58:25.png](https://qiita-image-store.s3.amazonaws.com/0/9582/74a1e6b5-d426-a8f5-bd83-91c6eb828817.png)

今のところちゃんと動いています。

環境は
OS: elementaryOS Freya (ubuntu 14.04LTS)
Java: Java(TM) SE Runtime Environment (build 9+181)
です。

めでたしめでたし:raised_hand:
Mac OS Xの管理者パスワードをリセット

Mac OS X Snow Leopardの管理者のパスワードを忘れてしまったのでリセットしてみた。まずはcommand + Sでシングルユーザモードでbootし、以下の作業を行う。ログイン後、キーチェーンアクセスをリセットしておく。

```lang:sh
:/ root# /usr/bin/sw_vers -productName
Mac OS X
:/ root# /usr/bin/sw/vers -productVersion
10.6.8
:/ root# /sbin/fsck -y
:/ root# /sbin/mount -uw /
:/ root# passwd alice
Changing password for alice.
New password: 
Retype new password: 
:/ root# sync
:/ root# reboot
```
アルゴリズムイントロダクション 章末問題1

# 本記事の概要

[概要はこちら](https://qiita.com/miumiu0917/items/4073be8aaba2eea58c33)

第一回の記事を参照ください。
さっそく回答していきます。
（第一回の記事でも申し上げましたが、私の回答は正解ではないですし、間違ってる可能性大！です。）

# 章末問題1

##1-1

*以下の表の各関数$f(n)$と時間$t$に対して、アルゴリズムが問題を解くのに$f(n)$マイクロ秒かかるとき、$t$時間でとくことができる最大の問題サイズ$n$を求めよ。*

$\log n$合ってないかも…
天文学的過ぎる…
2分探索ってソートされてるデータであればどんなに大きくても現実的な時間で探索が可能ってことなんですかね。

|   |  1秒   |  1分  | 1時間  | 1日数 | 1月数 | 1年数 | 1世紀 |
|---|---|---|---|---|---|---|---|
| $\log_2 n$  | $1.0 \times 10^{301000}$  | $1.0 \times 10^{1806000}$  | $1.0 \times 10^{108360000}$  | $1.0 \times 10^{2600640000}$  | $1.0 \times 10^{78019200000}$ | $1.0 \times 10^{949233600000}$ | $1.0 \times 10^{949233600000}$ |$1.0 \times 10^{94923360000000}$ |
| $\sqrt{n}$  |  $1.0 \times 10^{12}$ | $3.6 \times 10^{15}$  | $1.296 \times 10^{16}$  | $7.465 \times 10^{21}$  | $6.718 \times 10^{24}$ | $9.941 \times 10^{26}$ | $9.941 \times 10^{30}$ |
| $n$  | $1000000$  | $6.0 \times 10^7$  | $3.6 \times 10^9$  | $8.64 \times 10^{10}$  | $2.592 \times 10^{12}$ | $3.153 \times 10^{13}$ | $3.153 \times 10^{15}$ |
| $n\log_2 n$  | $62764$  | $2801417$  | $1.333\times10^8$  |  $2.755 \times 10^9$ | $7.187 \times 10^{10}$ | $7.976 \times 10^{11}$ | $6.861 \times 10^{12}$ |
| $n^2$  | $1000$  | $7745$  | $60000$  | $293928$  | $1609968$ | $5615692$ | $56156922$ |
| $n^3$  | $100$  |  $391$ | $1532$  | $4420$  | $13736$ | $31593$ | $146645$ |
| $2^n$  |  $19$ | $25$  | $31$  | $36$  | $41$ | $44$ | $51$ |
| $n!$  | $9$  | $11$  |  $12$ | $13$ | $15$ | $16$ | $17$ |

#次回
実際のアルゴリズムのコストについて解析していきます。
KerasのRNNを触ってみる②

## はじめに

この記事は、[前回](https://qiita.com/kento1109/items/b37dd38c18b0575363d5)の続編です。
導入部分は前回を参照いただければと思います。

前回はSimpleRNNを
今回は、LSTMを使ってモデルを作ります。

#### １）モデル構築

学習データの作成部分は前回と同じなので割愛します。
今回は、LSTMクラスを使うので、モデル構築部分は下記のようになります。
（SimpleRNNがLSTMになっただけ）

```py
model = Sequential()
model.add(InputLayer(batch_input_shape=(None, maxlen, in_out_dims)))
model.add(
    LSTM(units=hidden_dims, return_sequences=False))
model.add(Dense(in_out_dims))
model.add(Activation("linear"))
model.compile(loss="mean_squared_error", optimizer="rmsprop")
```

#### ２）学習

ここも前回と同じです。
LSTMはSimpleRNNよりパラメータが多いので、時間がかかります。。

```py
callbacks = []
# Early-stopping
callbacks.append(EarlyStopping(patience=0, verbose=1))
# CSVLogger
callbacks.append(CSVLogger("LSTM_history.csv"))
# fitting
history = model.fit(X_train, y_train, batch_size=100, epochs=100, validation_split=0.1, callbacks=callbacks)
```

#### ３）結果の確認

誤差がSimpleRNNの時よりも減っています。（3.29 → 0.87） 
![image.png](https://qiita-image-store.s3.amazonaws.com/0/204732/94a0fca5-5d25-a19e-5e7e-cb7607209910.png)

*61回で打ち切り

#### ４）教師データとの比較
前回と同様に訓練データの値と比較してみます。
（SimpleRNNも再掲します。）

| precdict(SimpleRNN) | precdict(LSTM) |true |
|:-:|:-:|:-:|
| [17.03078651] |  **[ 20.04093552]** |[ 22]
| [14.13138199]  | **[14.27271557]**  |[14]
| [ 11.11346722] | **[11.31826878]**  |[11]
| [7.76618958]  | **[7.15918827]**  |[7]
| [6.90901232]  | **[5.99405384]** |[6]
| [ -1.77918458]  | **[0.28667003]**  |[0]

一行目の値が22にグッと近づきました。（まだ2離れてますが。。）
その他もちょっと誤差が小さくなっています。

とりあえず、これでLSTMの基本の確認はこれで良しとします。
【Visual Studio】Unity におけるゲーム開発でも使用できるオススメの拡張機能の記事16選

<div align="center"><img src="https://cdn-ak2.f.st-hatena.com/images/fotolife/b/baba_s/20170928/20170928225255.png"></div>

# 備考

この投稿は自分のブログの記事の転載になります
http://baba-s.hatenablog.com/entry/2017/10/03/100000

# はじめに

http://baba-s.hatenablog.com/entry/2016/06/29/100000

去年、Visual Studio のオススメの拡張機能を<span style="color: #ff0000">35個</span>まとめた記事を公開しましたが、
この一年で新たに使ってみて良かったと感じた<span style="color: #ff0000">16個</span>の拡張機能の使い方をまとめました

すべて無料で、かつ Unity におけるゲーム開発でも使用できるため
興味がある拡張機能はぜひ使ってみて頂ければと思います

また、ここで紹介している拡張機能は <span style="color: #ff0000">Visual Studio 2015</span> で動作することを確認しています

# 拡張機能

1. [関数の保守性や複雑度を見ることができる「Microsoft CodeLens Code Health Indicator」](http://baba-s.hatenablog.com/entry/2017/10/02/110000_8)
1. [行末の空白をハイライトで表示できる「BlackSpace」](http://baba-s.hatenablog.com/entry/2017/10/02/110000_7)
1. [複数行を選択して一行にまとめられる「JoinLines」](http://baba-s.hatenablog.com/entry/2017/10/02/110000_3)
1. [空白行の縦幅を縮小して表示できる「Line Press」](http://baba-s.hatenablog.com/entry/2017/10/02/110000_10)
1. [Ctrl + / でコメントを切り替えられる「Toggle Comment」](http://baba-s.hatenablog.com/entry/2017/10/02/110000_11)
1. [閉じ括弧にコードブロックに関する情報を追加できる「CodeBlockEndTag」](http://baba-s.hatenablog.com/entry/2017/10/02/110000_5)
1. [ソリューションエクスプローラーでファイルのパスをコピーできる「Copy as Path」](http://baba-s.hatenablog.com/entry/2017/10/02/110000_2)
1. [Ctrl + 0, Ctrl + 0 でズームをリセットできる「Reset Zoom」](http://baba-s.hatenablog.com/entry/2017/10/02/110000_14)
1. [シンタックスハイライトをサポートする言語を追加する「Syntax Highlighting Pack」](http://baba-s.hatenablog.com/entry/2017/10/02/110000_1)
1. [ソリューションエクスプローラーに表示されるファイルアイコンを追加する「File Icons」](http://baba-s.hatenablog.com/entry/2017/10/02/110000_9)
1. [#region の折りたたみを無効化する「I Hate #Regions」](http://baba-s.hatenablog.com/entry/2017/10/02/110000)
1. [Ctrl + マウスホイールによるズーム機能を無効化する「Disable Mouse Wheel Zoom」](http://baba-s.hatenablog.com/entry/2017/10/02/110000_13)
1. [5 ボタンマウスの「進むボタン」「戻るボタン」を使えるようにする「Mouse Navigation」](http://baba-s.hatenablog.com/entry/2017/10/02/110000_4)
1. [ファイルを UTF-8 BOM 付きで保存できる「ForceUTF8 (with BOM)」](http://baba-s.hatenablog.com/entry/2017/10/02/110000_6)
1. [改行コードを LF（Unix） に統一できる「Trim line ends on save」](http://baba-s.hatenablog.com/entry/2017/10/02/110000_12)
1. [ウィンドウ全体に好きな背景画像を表示できる「MoeIDE」](http://baba-s.hatenablog.com/entry/2017/09/27/100000)
GoogleのPWA Roadshowの話(2)

[前回](https://qiita.com/MurakumoA/items/57330f8d90a7da3f3b29)はPWAとは何かということをまとめてみました。
今回はPWAを構成する４つのキーワードの１つ、**Integrated**についての話をまとめてみます。

スライドは以下を参照
https://goo.gl/ESUahe

# Chapter2:Integrated Experiences
## Integratedとは
Integratedとは、ここではWebを意識させないという意味になります。
つまり、Webアプリケーションをホーム画面に表示させることにより、ブラウザからページに接続するということをユーザに意識させずにWebアプリケーションを利用できるようにします。

## ホーム画面の追加
現在、８０％のユーザがアプリをホーム画面に追加し、よく使うものをまとめたり、見た目を良くしたりというように好きなように配置しています。
Webアプリケーションもホーム画面にURLをブックマークするという利用はできましたが、名前を変えられない、オフラインでは使えないなどの制約がありました。
しかし、それらの問題を解決する手段としてWeb App Manifestがあります。

### Web App Manifest
Webアプリケーションマニフェストは、各HTMLページからリンクしてブラウザにアプリケーションについての情報を伝えるJSONファイルです。
以下のようなコードをHTMLに埋め込みます。
`<link rel="manifest" href="/manifest.json">`

JSONファイルの内容は以下のようになっています。
<pre><code>{
    "name": "CNET Tech Today",　　　　 　　　　　　　　　　・・・　起動画面での名称
    "short_name": "Tech Today",　　　　　　　　　　　　　　・・・　ホーム画面での名称
    "icons": [{　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　・・・ ホーム上でのアイコン
    "src": "icon-512x512.png",
    "sizes": "512x512",
    "type": "image/png"
    }, {...}],
    "start_url": "/index.html",　　　　　　　　　　　　　　　・・・ 開始するURL
    "display": "standalone",　　　　　　　　　　　　　　　　　　　　　・・・　表示プロパティ（例ではNative Appのように表示）
    "orientation": "portrait",　　　　　　　　　　　　　　　　　・・・ 画面の向き
    "background_color": "#FF0000",　　　　  　・・・ 起動画面の背景色
    "theme_color": "#FF0000"　　　　　　　　　　　　　　　　　　　　　・・・ マルチタスク画面の色
}</pre></code>
細かい仕様は以下のURLをご覧ください。
https://w3c.github.io/manifest/#display-modes


### ホーム画面追加の通知
ホーム画面に追加をするときは、ブラウザ側からホーム画面に追加することを提案してくれます。
ブラウザから通知される基準は、サイトを何回訪れたか、何分使用したか等、ブラウザによって異なります。

#### ※Google Chromeの場合の条件
- Web App Manifest（name、short_name、start_url、192x192以上のアイコン、表示プロパティは必須）
- Offline support(Service Workerがあること)
- Engaged User(ユーザがサイトに関心があること(何度も訪れていること？)→スパムと間違われないように)

## Web Payment
現在、Webショッピングは６６％がWebサイトから行われております。
しかし、モバイルからのコンバージョン率はPCからのコンバージョン率の３分の１となっております。
理由としては、モバイルから決済に必要な情報（名前、住所、電話番号、配送方法など）を入力するという手間の大変さが挙げられます。
そこで、モバイルからのコンバージョン率を上げるために、チェックアウトの流れや支払いを簡単にする必要があります。

### Autofill
ブラウザ側で入力する要素を判断し、自動入力をします。
しかし、画面ごとに要素は異なるため、誤った入力をしてしまう可能性があります。
autocomplete属性を使うことで、ブラウザが要素を判断する必要がなくなります。
以下のように、属性を追加するだけで使用することができます。
<pre><code>\<label for="frmNameCC">Name on card\</label>
\<input name="ccname" autocomplete="cc-name">

\<label for="frmCCNum">Card Number\</label>
\<input name="cardnumber" autocomplete="cc-number">

\<label for="frmCCCVC">CVC\</label>
\<input name="cvc" autocomplete="cc-csc">

\<label for="frmCCExp">Expiry\</label>
\<input name="cc-exp" autocomplete="cc-exp"></code></pre>

その他のオートコンプリート属性は下のURLをご覧ください。
https://goo.gl/5mLti2


### Payment API Request
Webショッピングの支払い情報の入力を標準化するためのAPIです。
Payment API Requestはブラウザから提供するもので、これを使用することでサイトは独自の入力フォームを用意する必要がなく、ユーザに入力フォームを提供することができます。
しかし、このAPIはあくまで入力フォームを提供するだけであり、決済処理を行うわけではありません。
決済処理は、APIから渡されるJSON形式の入力情報を使用して個別に実装する必要があります。

# おわりに
ここでは、Webアプリをホーム画面に追加する方法とWebショッピングの支払い情報の入力に関する話をまとめさせていただきました。
ホーム画面に追加するというキモの部分が、１ファイルの用意と１文の埋め込みで実現できるというのは衝撃的です。
次はReliable（信頼性）の話をまとめたいと思います。
SendGridでCurlコマンドを使ってメールを送信する

# 準備
* SendGridのアカウントを作成する（Azureを使用している場合はAzureポータルからも可能）
* SendGridのポータル画面でAPI Keyを作成する（メール送信権限ありにする）

# 実行
API Keyと宛先アドレスの箇所を書き換えて以下のコマンドを実行する。

```bash
curl --request POST \
  --url https://api.sendgrid.com/v3/mail/send \
  --header 'Authorization: Bearer API-KEY-HERE' \
  --header 'Content-Type: application/json' \
  --data '{"personalizations": [{"to": [{"email": "TO-ADDRESS-HERE"}]}],"from": {"email": "example@example.com"},"subject": "Hello, SendGrid!","content": [{"type": "text/plain", "value": "Hi!"}]}'
```

# 参考
* [cURL Examples for Common Use Cases - SendGrid Documentation | SendGrid](
https://sendgrid.com/docs/Classroom/Send/v3_Mail_Send/curl_examples.html)
Excelを排他ロックせずに簡単に開く方法

# はじめに

編集するつもりのないExcelファイルを開いてゆっくりと内容を確認したいとき，普通に開いてしまうと排他ロックがかかってしまい，編集したい人が困ってしまうことはいまだによくある光景かと思います．（それで適当な名前のコピーファイルが量産されたり．．．）
「読み取り専用を推奨する」に設定しておく手もありますが，ファイルごとに設定する必要があるのでおっくうです．
そんな中，お手軽に排他ロックせずに簡単に開く方法を見つけたのでメモです．

# 右クリックから「新規」

開きたいファイルを右クリックのコンテキストメニューから「新規」を選ぶと，元ファイルの内容をコピーしつつ新規ファイルとしてエクセルが立ち上がってくれます．
これで無駄にファイルをロックすることもなく，間違って意図せず編集して上書き保存したりすることも防ぐことができます．
もちろんExcelの他にWordなどでも同様です．

![excel.png](https://qiita-image-store.s3.amazonaws.com/0/45310/1bf9eada-f808-6715-e10b-ca9d4e5ee9d1.png)

これ知ってちょっと嬉しかったので，お困りの方はどうぞ．
Vue 2.5 のコンポーネントのメンバーに型を追加する


## 前提
今まではVueとTypeScriptの組み合わせだと `vue-class-component` を使うというのが定石だったけど、Vue 2.5ではコンポーネントの型定義が大きく改善されたおかげで、TypeScriptでも `vue-class-component` を使わずに普通の方法でコンポーネントを書けるようになった。

[やってくるVue2.5でのTypeScriptの変更](https://jp.vuejs.org/2017/09/23/upcoming-typeScript-changes-in-vue-2.5/)

つまり、こんな感じで書いたとすると、各functionの中でちゃんと `this.foo`、`this.bar`、`this.baz` にアクセスすることができる。(もちろん、それぞれの型も正しく認識される)

```ts
import Vue, { VNode } from "vue";
export const MyComponent = Vue.extend({
  name: "MyComponent",
  props: {
    foo: String
  },
  computed: {
    bar() { return this.foo.toUpperCase(); }
  },
  methods: {
    baz() { console.log(this.bar); }
  },
  render(h): VNode {
    return h("div", { on: { click: this.baz } }, this.foo);
  }
});
```

`vue-class-component` を使うなら、こんな感じになる。

```ts
import Vue from "vue";
import component from "vue-class-component";

@component({
  props: {
    foo: String
  },
})
export class MyComponent extends Vue {
  get bar() {
    return this.foo.toUpperCase();
  }
  baz() {
    console.log(this.bar);
  }
  render(h) {
    return h("div", { on: { click: this.baz } }, this.foo);
  }
}
```

## 本題
さて、`props`、`data`、`methods`、`computed` については型が導出されるようになったけど、ほかにもいろいろと型をつけたい部分が出てくることがある。

例えばVuexを使うなら `MyStore` 型の `$store` をメンバに追加したいと思うかもしれない。
もしくは、テンプレート内のdiv要素に `ref="box"` を指定しているなら、 `$refs` の型が `{ box: HTMLDivElement }` であることを明示したいと思うかもしれない。
他にも、 `$scopedSlots` のスロット名や引数を型を明示したいとかもある。

`vue-class-component` を使っていればこういうのは単にメンバーを追加すればよかった。

```ts
import Vue from "vue";
import component from "vue-class-component";
import { MyStore } from "./store";

@component({ /* 略 */ })
export class MyComponent extends Vue {
  $store: MyStore;
  $refs: {
    box: HTMLDivElement
  }
  /* 以下略 */
}
```

じゃあ `Vue.extend` で同じことがしたければどうすればいいの？という話

## 解決策

こんな感じのメソッドを用意する

```ts
import Vue from "vue";
import { VueConstructor } from "vue/types/vue";

export function vueWith<T>(): VueConstructor<Vue & T> {
    return Vue as any;
}
```

で、こう

```ts
import Vue, { VNode } from "vue";
import { MyStore } from "./store";

export const MyComponent = vueWith<{
  $store: MyStore,
  $refs: { box: HTMLDivElement }
}>().extend({
  name: "MyComponent",
  methods: {
    onClick() {
      console.log($refs.box.innerHTML);
    }
  }
  render(h): VNode {
    return h("div", { ref: "box", on: { click: this.onClick } }, this.$store.state.message);
  }
});
```

もっといい方法があれば教えてください。
npm run testするときはnpmログを切ったほうがいい

# 結論
`npm run test --silent`

# 背景
`vue init webpack`コマンドによってプロジェクトを作成し、インストールしていくと(テスト関連のインストールを無効にしてなければ)、karmaによる単体テストとnightwatchによるE2Eテストがインストールされます。
テストはそれぞれ、`npm run unit`、`npm run e2e`で実行でき、`npm run test`を使うと両方連続で実行できます。

しかし、テスト結果にエラーがあると結果の後に以下のような表示がでてしまいます。

```
npm ERR! Windows_NT 10.0.15063
npm ERR! argv "C:\\Program Files (x86)\\Nodist\\v-x64\\8.2.1\\node.exe" "C:\\Program Files (x86)\\Nodist\\npmv\\4.0.5\\bin\\npm-cli.js" "run" "unit"
npm ERR! node v8.2.1
npm ERR! npm  v4.0.5
npm ERR! code ELIFECYCLE
npm ERR! vue@1.0.0 unit: `cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the vue@1.0.0 unit script 'cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the vue package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs vue
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls vue
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     C:\xampp\htdocs\vue\npm-debug.log

npm ERR! Windows_NT 10.0.15063
npm ERR! argv "C:\\Program Files (x86)\\Nodist\\v-x64\\8.2.1\\node.exe" "C:\\Program Files (x86)\\Nodist\\npmv\\4.0.5\\bin\\npm-cli.js" "run" "test"
npm ERR! node v8.2.1
npm ERR! npm  v4.0.5
npm ERR! code ELIFECYCLE
npm ERR! vue@1.0.0 test: `npm run unit && npm run e2e`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the vue@1.0.0 test script 'npm run unit && npm run e2e'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the vue package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     npm run unit && npm run e2e
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs vue
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls vue
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     C:\xampp\htdocs\vue\npm-debug.log
```

npm ERR!ってでてるのでシステムエラーかとも思うんですが、よく見るとテストのコマンドのところで、Exit status 1ってなっているのが原因のようです。
まあ、テスト失敗してるんだからExit status 1 でいいのではないかと思います。
そう考えると、この表示が邪魔。

そういう時は`--silent`オプションをつけるとnpmのログを切れます。
成功してた時に出てた余計なWARNINGとかも消えて表示がすっきりします。
Viewを高さ指定で上端に配置しSafe Areaの外側も同じ色にする

# はじめに

独自のナビゲーションバーを実装しているアプリで以下の条件でiPhoneX対応していました。

* iPhoneXとその他でNavigationBarのStatusBarを除いた高さは同じにしたい
* StatusBarとNavigationBarは同じ色にしたいが背景色のためだけに追加のViewは置きたくない
* コードによって端末やバージョン判定、StatusBarの高さの取得などはできるだけしたくない

指定した高さのViewをSafe Areaの上端に配置すると外側まで色が変わってくれるのが理想です。

UIToolBarは、Safe Areaぴったりに配置するとSafe Areaの下まで背景色がついてくれます。
![toolbar.png](https://qiita-image-store.s3.amazonaws.com/0/66520/c0081b9c-fae9-6ef8-b592-b183f43f6650.png)
（左：Safe Areaから1だけ上にずれてる状態　右：Safe Areaにぴったり）

しかし、ただのUIViewは空気を読んでくれませんでした。

![スクリーンショット 2017-10-18 3.43.38.png](https://qiita-image-store.s3.amazonaws.com/0/66520/6a5a2415-75e9-5dc7-2091-2ced9d9e0ad1.png)
（A. Safe AreaのTopに高さ44のViewを配置）

![スクリーンショット 2017-10-18 3.46.12.png](https://qiita-image-store.s3.amazonaws.com/0/66520/3f2c00c3-5468-1885-9298-7538ab21bee2.png)
（B. SuperViewのTopに高さ44のViewを配置）

Safe Areaからの高さを設定する場合にはStatusBarの背景色をどう描画するかを解決する必要があります。
SuperViewからの高さを設定する場合にはStatusBarの高さの違いによるViewの高さの違いを解決する必要があります。

Safe AreaのTopからの高さを指定しつつ、SuperViewからSafe Areaまでの間も描画できれば目標が果たせそうです。

# 解決策

設置したいViewの高さをxとして、ViewのTopをSuperView.Top、BottomをSafe Area.Top - xに設定することで実現します。
以下に手順を説明します。

## 1. ViewをSuperView.TopとSafe Area.Bottomの間に設置する

![スクリーンショット 2017-10-18 4.47.32.png](https://qiita-image-store.s3.amazonaws.com/0/66520/34fb2a27-788a-3d57-05cd-67d7addbc677.png)

* LeftとRightはSafe Areaに対して0に設定する
* TopはSuperViewに対して0に設定する(Safe Areaになっていないか確認)
* BottomはSafe Areaに対して0に設定する(ここで設定されるのはSafe Area.Bottom)

![スクリーンショット 2017-10-18 4.56.10.png](https://qiita-image-store.s3.amazonaws.com/0/66520/d682dd6c-b984-4a02-5de8-a13333458643.png)



## 2. BottomをSafe Area.BottomからSafe Area.Topに変更する

![スクリーンショット 2017-10-18 4.59.02.png](https://qiita-image-store.s3.amazonaws.com/0/66520/ff67233c-cb4d-dd28-d12a-440b11b5a2f6.png)

* BottomからTopに変更することで、ViewがSafe Areaより上側だけに描画される

## 3. Safe Area.TopからのConstantを0からViewの高さに変更する

![スクリーンショット 2017-10-18 5.04.39.png](https://qiita-image-store.s3.amazonaws.com/0/66520/fb2ab7ab-8d63-bf73-71d3-f8d099f615f8.png)

* 上端に設置したいViewの高さを指定する(マイナスにすることに注意)

## 4. 完成

![スクリーンショット 2017-10-18 5.42.25.png](https://qiita-image-store.s3.amazonaws.com/0/66520/d418a6ec-60f4-de28-3682-fede2bcc0e64.png)

# 環境

* Xcode 9.0
* iOS 11.0

# サンプル

この方法を利用した擬似NavigationBarと、それを下端に応用した擬似ToolBarのサンプルです。
[https://github.com/ninten320/PseudoNavigationAndToolBar](https://github.com/ninten320/PseudoNavigationAndToolBar)

![PseudoNavigationAndToolBar.png](https://qiita-image-store.s3.amazonaws.com/0/66520/a49ede43-8c10-7fed-ecdc-48b8810c4d14.png)
Actions on Google AppをSimulatorでテスト中に、206エラーが出た



[Actions on Google App、Dialogflowで初めてのアプリを作るチュートリアル](https://developers.google.com/actions/dialogflow/first-app
)をやっていて、単純なミスでハマったのでメモ

### エラーがでた場所


![スクリーンショット 2017-10-18 4.00.22.png](https://qiita-image-store.s3.amazonaws.com/0/173392/2c0bfdc3-2d62-0cbf-c65d-7ddc68f2340b.png)

```
          "code": 206,
          "errorType": "partial_content",
          "errorDetails": "Webhook call failed. Error: 400 Bad Request"
```


おかしいなー、日本語じゃダメなのかなーと思いつつ、
原因を調べていたらこちらがヒット、どうやら英語でも起きる模様。
https://discuss.api.ai/t/webhook-request-timeout-206-error/4656/9
生成されたJSONがおかしいのでは？プログラマさんに見てもらいなよ、という会話をしている。。そこで、さきほどローカルからfirebaseにデプロイしたjsのコードをみてみる。

/sillynamemaker/functions/index.js
![スクリーンショット 2017-10-18 4.09.16.png](https://qiita-image-store.s3.amazonaws.com/0/173392/f32d8ad3-158b-f6b5-c1f4-cd3f022e9be5.png)

あっ、8行目、、
// a. the action name from the make_name Dialogflow intent
const NAME_ACTION = 'make_name';　:point_left:**これ、IntentsのActionにも指定しないとアカン奴じゃないの？**




![スクリーンショット 2017-10-18 4.13.57.png](https://qiita-image-store.s3.amazonaws.com/0/173392/c7b9182f-051c-4470-6faf-27cdd924397e.png)

記入して、再度、「Integrations」＞「Google Assistant」＞「UPDATE DRAFT」を実行し、さらにsimulatorを開いているブラウザをリロードしたところ、ちゃんと動くようになりました。


![スクリーンショット 2017-10-18 3.56.05.png](https://qiita-image-store.s3.amazonaws.com/0/173392/36905875-904c-dae8-3da6-595ed06a3346.png)



[チュートリアルの 
Define your conversation's grammar
9.Enter make_name for it's name and click SAVE.](https://developers.google.com/actions/dialogflow/first-app#define_your_conversations_grammar)
にも書いてあったのに見落としていました。



哀しみ。。。
意味もわからずコピペしてたのが敗因でした。
次からはちゃんと意味を把握してからコピペしようと思います。

以上！
StoryboardのCustomClassにInnerClassを指定

swiftにはmodule単位でしかnamespaceの概念がないので、インナークラスで乗り切りたくなることがよくある。
Storyboardで指定するクラスをインナークラスにするためには工夫がいるのでその手順をメモ

## 環境
- xcode 9.0
- swift4

## 手順

### ソースコードの調整
```swift:Staff.swift
class Staff {
  // namespace用なので中身はなし
}
```

```swift:StaffViewController.swift
// RunPhaseのCompileSouresで必ずStaff.swiftより後になるように設定すること

extension Staff {

  // 括弧の中はstoryboardから指定するときの名前を入れる(なんでも良い)
  @objc(StaffViewController)
  class ViewController: UIViewController {
    // 何かする
  }
}
```

### Storyboard上の操作

UIViewController > CustomClass > Class、無理やり「StaffViewController」と指定する。
保管も出ないし、「UIViewController > CustomClass > Module」がNoneに変わるがそれで良い。(「Inherit Module From Target」に戻すとUnknown Classで落ちる)

----

投稿してから気づいた。
ViewControllerのときはうまくいくけれども、Viewのときはダメみたい…。
が、そもそもViewのサブクラスに「namespaceで区切りたいようなドメイン固有のロジック」をもたせたいとおもわないので不便はなかったのである。
AndroidのHttpURLConnectionでjsonの取得

#AndroidでHttpURLConnectionを用いたjson(XML)取得
今回はHttpURLConnectionを用いて、サーバからデータの取得を書いてみようと思います。

##HttpURLConnection
HttpURLConnectionはAndroidアプリ開発におけるHTTP周りのクラスです。
では、簡単にHTTP通信の接続から

```java

public String getGET() throws IOException {
        final int CONNECTION_TIMEOUT = 30 * 1000;
        final int READ_TIMEOUT = 30 * 1000;

        URL url = new URL("あなたのhttp_urlを代入してください");
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(CONNECTION_TIMEOUT);
        conn.setReadTimeout(READ_TIMEOUT);

        conn.setRequestMethod("GET");
        conn.connect();
        int statusCode = conn.getResponseCode();

        if(statusCode == HttpURLConnection.HTTP_OK){
            StringBuilder result = null;
            //responseの読み込み
            final InputStream in = conn.getInputStream();
            final String encoding = conn.getContentEncoding();
            final InputStreamReader inReader = new InputStreamReader(in, encoding);
            final BufferedReader bufferedReader = new BufferedReader(inReader);
            String line = null;
            while((line = bufferedReader.readLine()) != null) {
                result.append(line);
            }
            bufferedReader.close();
            inReader.close();
            in.close();

            return result.toString();
        }

        return null;
    }
```

また、以下のタイムアウトを設定することで自動で接続を切断してくれます。

```java
conn.setConnectTimeout(CONNECTION_TIMEOUT);
```

Cookieの情報を加えたい場合は以下を入れてください。

```java
conn.setRequestProperty("Cookie", cookies);
```

InputStreamからテキストを読み込めば、jsonやxmlなどのデータ取得できます。

次に、このHttpURLConnectinoを実行するために、AsyncTaskを利用します。

```java:HttpTask.java
public class TestHttp extends AsyncTask<Void,Void,Void> {
    @Override
    protected Void doInBackground(Void... params) {
        try {
            getGET();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

```

あとは以下を実行したいところに記述するだけです。

```java
HttpTask httpTask = new HttpTask();
httpTask.execute();
```

##最後に
Androidアプリに精通している人ともっと知り合いたいです。
Actions on Google Appを作るときローカルでFirebase initしても何故かfunctionsがインストールされなかったのでメモ


Actions on Google Appを作るための公式チュートリアル通りに進めていたのだが、
自分の環境ではコマンドが1個足りなかったのでメモ



### 自分の環境
Mac OS : バージョン 10.12.5
node : v6.11.4


### 問題の箇所

Actions on Google App
Dialogflowで初めてのアプリを作るチュートリアル
https://developers.google.com/actions/dialogflow/first-app

後半の方の「Build fulfillment」 の項目で、ローカルマシンにfirebase tootlsをインストールする時、

```
firebase init 
```

![スクリーンショット 2017-10-18 0.06.24.png](https://qiita-image-store.s3.amazonaws.com/0/173392/17a9dd31-e04f-47ac-652a-7db3306aa70e.png)

にて、「Function」（下から３行目）を指定するだけでは、
sillynamemaker/functions/以下の一式はインストールされず
sillynamemaker/functions/package.jsonも
sillynamemaker/functions/index.jsも無かった。

調べたらfunctionsのインストール用の別のコマンドがあった。

```
firebase init functions
```

実行してみたところ、sillynamemaker/functions/以下の一式が無事にインストールされた。
自分の環境が何かおかしいのかもしれないが、同じことが起きた時のためにメモっておくでやんす。

以上
大学生の僕がゼロからWebエンジニアになった話 - 1年生 -

僕は高校生まで体育会系で、それまで全然勉強もせず走ってばかりいました。

そんな僕は大学では引退し、そしてエンジニアに生まれ変わりました。

それまでのプロセスと、現在の心境を書きます。

将来何をやりたいか決まっていない、あるいはエンジニアに興味がある人に
読んでいただければと思います！

## 大学1年生

僕が入った学部は、情報系ではありましたが、社会系とか心理学とか色々学べるところでした。

入学当時から情報系に興味があったわけではありません。

とにかく、指定校推薦で入学した僕は、大学の授業についていくのが精一杯で、
サークルにも部活にも入らずカフェにこもって独学で高校の課程をやりながら、
ひたすら授業の予習復習をやっていました。

***

後期に入り、僕は授業でプログラミングに出会いました。
やったのは **Visual Basic** です。

他の科目と違って、プログラミングの授業は
ほとんどの人が初心者だったので、僕も比較的対等に戦えました。

授業後半に課題が出され、終わった人から帰っても良いという制度だったので、
予め勉強しておいて、課題を誰よりも早く解いて
ドヤ顔で退出するのが快感だった思い出があります。

ある日、その授業で、 Visual Basicと、今までの内容を踏まえて
各自電卓を実装してこいという課題が出されました。

ただの電卓でよかったのですが、僕はそれではつまらないと思い、
自分で調べながらこんなものを作りました。w

![image.png](https://qiita-image-store.s3.amazonaws.com/0/138750/009f3f05-e9e4-057d-4808-59c023caa7ea.png)

教授に「何作ってんの？ww」って笑われて、でもそれが嬉しくて、
何か自分でオリジナルのモノを作るということに楽しさを覚えました。

***

大学のプログラミングの授業は他にもありましたが、
理工系ではないので、基本的な内容ばかりです。

でも、1年生の僕はそれでも新しい知識ばかりで、
**HTML/CSS**も授業で初めて触れました。

タグで囲んで、スタイルを書いて、確認。
簡単なページを作るところまでを一通りやりました。

しかし、僕は納得できませんでした。

**「どー見てもぐぐって出てくるサイトと違うやん！！」**

当時サンプルで作った数十行のコードなので
かなり殺風景になるのは当たり前でしたが、
本物のサイトで、画像が動いたり、メニューがにょきって出てきたり、
自分のものとは次元が違いすぎて不満でした。

そこで僕は、そのあと自分で色々調べて、 **JavaScript**を知りました。
初めて `alert()` を発動させた時、
**おぉ！！ あれってこう出すんか！！** って一人で感動してました。w

授業では扱われませんでしたが、
適当にいい感じのサイトを１つ見つけて、それを自力で再現して遊びました。
初心者だった当時はかなり勉強になったと思います。

「なるほど、こういうことか！！w」

Webサイトの表面に関してはそこで何となく納得できました。

大学の授業は出会うきっかけに過ぎず、
基本的には自分の勝手な興味->自己満足の流れで知識を集めていた気がします。
（それは今も変わりません。）

***

次回、2年生にて
本格的にプログラミングの分野に自分を向けることになります。。

[大学生の僕がゼロからWebエンジニアになった話 - 2年生 -](https://qiita.com/uenoryo/items/3dee9aa3e4878e887d20)
Gradle Wrapper で Flyway 付き SQL 配布ファイルを作る

# 背景
* Gradle 4 + MySQL 5.7 + Spring Boot 1.5 で開発
* 勤務先はシンクライアントに近い環境。社則で毎日退社前に個人PC上のデータを消す必要がある　(アプリは別)
    * → マイグレーションツール必須
* どうせならステージング環境等のDBマイグレーションも開発に使っているものと同じツールを使って省力化したい
    * でも Spring Boot + flyway-core の強制自動マイグレーションは怖い

→ サーバ用の SQL 配布アーカイブに、Flyway タスクのみを入れた build.gradle を足してみます。

# サーバに配布する build.gradle
```groovy
plugins {
    id 'org.flywaydb.flyway' version '3.2.1'
}
// java プラグインを入れないと JDBC ドライバの dependencies を解決してくれない
apply plugin: 'java'

flyway {
    url = 'jdbc:mysql://localhost/foo'
    user = xxx
    password = xxx
}
flywayClean.enabeld = false // 誤爆防

repositories {
    jcenter()
}
dependencies {
    runtime group: 'mysql', name: 'mysql-connector-java', version: '5.1.44'
}
```
展開して `./gradlew flywayMigrate` で SQL を適用できます。
なお Gradle のキャッシュは `$HOME/.gradle` に入ります。

# サーバ用 SQL 配布アーカイブを作成するための Gradle タスク
tarball は `build/distributions/` 以下に作成されます。

```groovy
task sqlDist(type: Tar) {
    compression = Compression.GZIP
    archiveName = "${baseName}-sql-${version}.tar.gz"

    // SQL files
    into('src') {
        from 'src'
        include 'main/resources/db/migration/**'
    }

    // Gradle Wrapper
    into('/') {
        from 'config/flyway'
        include 'build.gradle'
    }
    into('/') {
        from '.'
        include 'gradlew'
    }
    into('gradle') {
        from 'gradle'
    }
}
```