OmniAICreator/Qiita-1.07M huggingface dataset:
警告:MSB3277が出た時の対処法メモ


[警告 : 同じ依存アセンブリの異なるバージョン間での競合が見つかりました。](
https://msdn.microsoft.com/ja-jp/library/bb383993.aspx)
との警告が少し前に出たのでその時行った対処法をまとめます。

![2.png](https://qiita-image-store.s3.amazonaws.com/0/199752/469024cc-eee0-f26e-9f40-3e350771db9f.png)

# 前提
今回のケースでは、ソリューションをメインとなるプログラムのコード(以下、コード側)のプロジェクトとそれのテストプロジェクト(以下、テスト側)から構成されています。
また、テスト側のプロジェクトをスタートアッププロジェクト、つまりプライマリとして設定しています。
また、テスト側のプロジェクトはコード側のプロジェクトに依存しています。

 - ソリューション
    -  テスト側のプロジェクト(プライマリ)
    -  コード側のプロジェクト
 
(上記：ソリューションの構成イメージ)

# 1.メッセージの通りに出力を詳細にする(Optional)

まずは警告メッセージの通りにログの詳細を上げて問題箇所がわかるようにします。
[ツール]→[オプション]からVSのオプションを表示します。続いて[プロジェクトおよびソリューション]→[ビルド/実行]から[MSBuild プロジェクト ビルドの出力の詳細(V)]を"詳細"にセットします(下図)。
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/199752/d7f7c2ca-ec12-1366-f3c6-73f0ab046d65.png)

# 2.詳細になったビルド出力から問題箇所を探る

もう一回ビルドをかけるとたくさんのメッセージが表示されるので[出力]ウィンドウの内容を"MSB3277"で検索すると

```txt:検索結果
C:\(中略)\Microsoft.Common.CurrentVersion.targets(1987,5): warning MSB3277: 同じ依存アセンブリの異なるバージョン間で、解決できない競合が見つかりました。これらの参照上の競合は、ログの詳細度が詳細に設定されている場合にビルド ログにリストされます。
```

ここから上に向かって辿ると

```txt:問題の箇所
"Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed" と"Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed" の間で競合が発生しました。
プライマリであるため、"Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed"が選択されました。"Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed"はプライマリではありませんでした。
```

...最初この文章を見たとき、一瞬なんのことがよくわかりませんでした。
要約すると、

 - テスト側 Newtonsoft.Json(9.0.0)  (プライマリ)
 - コード側 Newtonsoft.Json(10.0.0)

「同じライブラリがバージョン違いで存在しているので警告を出しました。
今回はプライマリの方を選んでビルドしました」とのことです。

# 2.5. 問題箇所を確認する

今回のケースではプライマリ側のNewtonsoft.JsonがMicrosoft.Extensions.DependencyModel(1.1.0)から参照されていたので[そのバージョンのNugetのページ](https://www.nuget.org/packages/Microsoft.Extensions.DependencyModel/1.1.0)をチェックします。
するとDependenciesがNewtonsoft.Json (>= 9.0.1)ということがわかりました。
これならテスト側のバージョンを10.0.0以上にすれば問題が解消できそうです。


# 3. 問題となった側のNugetライブラリを最新にする

NugetからNewtonsoft.Jsonをインストールし、再度ビルドしたところ、
![1.png](https://qiita-image-store.s3.amazonaws.com/0/199752/c9b0bf9c-d7f8-c25e-5b8f-da4d985e8154.png)

警告が消えました！よかった！


# まとめ
 - 警告が出たときはメッセージを読む
    - 状況に応じて、出力のレベルを上げる
 - 競合しているライブラリのバージョンを見比べる
    -  それに依存するライブラリの条件も確認する
 - プライマリ側のライブラリを最新化し、再度ビルドする

# 関連リンク

 - https://blogs.msdn.microsoft.com/yingqin/2015/02/13/build-warning-msb3247-and-msb3276-and-msb3277/
KotlinからJavaクラスを参照するとビルド時にUnresolved refarenceが発生する場合がある

# app/src以下でsymbolic linkは利用しない方が良いというお話

## 前提：Flavor間のコード参照にSymblic Linkを利用していた

Android Studioでアプリ開発をしていて、本番用とサンドボックス用とでサードパーティーのSDKライブラリを切り分ける必要があった際に、
Flovorを利用してビルドを分けて、sandboxもproductの同じコードを利用するので、コードの参照をシンボリックリンクを利用して行っていた

```:app/build.gradle
android {

 (省略)

 Flavors {
    product {}
    sandbox {}
  }

 (省略)

}
```

``` sh:app/src
% ln -s product sandbox
% ls
  product
  sandbox -> product
```
こんな感じにすると、AndroidStudio上で正常に動作して、project treeもflavor名でちゃんと表示されます。

## しかし、KotlinでSymbolic Link先のJavaクラスを参照するとビルド時にエラーが発生します。

で、少し時間が経過して、
Javaで書いていたプロジェクトでしたが、機能の追加では新規部分をKotlinで記述することになりました

この為KotlinからJavaのクラスを参照する必要もあり、
flavorの指定をsandboxにした場合、Symbolic Link先のJavaクラスを参照することもあるのですが、
Android Studio上では正常に参照され、補完もされたはずなのに・・・

``` sh:error
Unresolved reference: packagehoge
Unresolved reference: classmoge
```

ビルド時にこんな感じのエラーが発生します。

Javaのみ、Kotlinのみのコード構成だと、なんの問題もありません。
KotlinからJavaのクラスを参照しようとすると発生するようです。

## 解決方法: ちゃんとsourceSetsを利用しましょう

横着せずにちゃんと設定しましょう

```:app/build.gradle
android {

 (省略)

 Flavors {
    product {}
    sandbox {}
  }

 (省略)

  sourceSets {
    sandbox {
      sandbox.manifest.srcFile 'src/product/AndroidManifest.xml'
      sandbox.assets.srcDirs += 'src/product/assets'
      sandbox.java.srcDirs += 'src/product/java'
      sandbox.res.srcDirs += 'src/product/res'
    }
  }

 (省略)

}

```

上記設定を行うことで、Symbolic Linkを利用した参照が無くなり、無事にビルドが通るようになりました。
AWSでSSLを利用するなら、AWS Certificate Managerが断然便利。


#AWS Certificate Managerとは
AWSのサービスに対して利用可能なSSL/TLSサーバ証明書サービス（2048bit、SHA-256）
SLの取得、管理、設置が全て無料で行うことが可能。
加えて自動更新されるので期限切れを気にすることもありません。

#AWS Certificate Managerの特徴
- ACMの主な特徴は以下の通り。
- AWSサービスに対しての利用のみ可能
- 費用は無料
- 有効期間13ヶ月
- ドメイン認証
- CloudFrontかELBにて利用可能

上記の通りACMで発行される証明書の認証方法はドメインの使用権有無のみを確認するドメイン認証です。
認証方法は他に組織認証証明書、EV証明書がありますが、ドメイン認証はこの中でも一番ライトなタイプの証明書です。
#Chromeにおけるシマンテック証明書の無効化の動き

以前からChromeにおけるシマンテック証明書の無効化の話がありましたが、
シマンテックのCA事業売却に伴い、シマンテック証明書の無効化スケジュールをGoogleが発表しました。

詳細は[公式ブログをご参照ください。](https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html)


2017年から段階的に証明書が無効となりますが、約1年後の2018年秋頃には
シマンテックCAが発行したすべての証明書は信頼できないものとして取り扱われます。
今後証明書を取得する際はシマンテックは避けた方が良さそうですね。

#SSL推奨化の動き。サイトのHTTPS化でSEOが優遇される！？

2014年には、HTTPS化されたWebサイトをSEOの評価として優遇するといったことがgoogleで発表されました。
今の所必須要件ではないので急いで導入する必要はなさそうですが、今後HTTPS化を検討しなければいけない時が来るかもしれません。

現状ACMで取得可能な証明書はドメイン認証のもののみですが、無料・自動更新・導入も手軽にできるACMを使わない手はありませんね。
【 Python 】ローカル → S3へファイルをアップロードする手順 ( boto3 )

#はじめに
boto2を使って、ローカルストレージにあるファイルをアップロードするQiita記事はよく見かけるが、
boto3を使ったものがなかなか見つからなかったので、公式サイトを参考に実装したものを貼っておく。

#開発環境
Python 3.6.1
pip 9.0.1

#手順
- パッケージインストール
- Configファイル設定
- 実装 (pythonソースコード)

# パッケージインストール
boto3(AWS SDK for python)

```
$ pip install boto3
```

コマンドラインよりAWSのサービスを操作するためのパッケージも併せてインストールしておく。

```
$ pip install awscli
```

# Configファイル生成 

アクセスキー、シークレットキー、リージョン等をConfigファイルに書き込む。
下記コマンドを実行し、後は対話型にデータを入力していけばホームディレクトリ配下にファイルが生成される。

<font color ="red">__※ boto2では、ソース上よりAWSアクセスキー、シークレットキーを読み込んでいたが、
boto3では、Configファイルから上記2つキーを取得する。__</font>


```
$ aws configure
```

```
AWS Access Key ID [None]: xxxxxxxxxxxxxxxxxxxxxxx
AWS Secret Access Key [None]: xxxxxxxxxxxxxxxxxxx
Default region name [None]: xxxxxxxxxxxxxxxxxxxxx
Default output format [None]: xxxxxxxxxxxxxxxxxxx
```

生成されるファイル(2つ)

```~/.aws/credentials
----------------------------------------------
[default]
aws_access_key_id = ACCESS_KEY_ID
aws_secret_access_key = SECRET_ACCESS_KEY
----------------------------------------------
```

```~/.aws/config
----------------------------------------------
[default]
region = [xxxxxxxxxxxxxxxxx]
output = [xxxxxxxxxxxxxxxxx]
----------------------------------------------
```

ホームディレクトリに生成され、boto3実行時もホームディレクトリの上記ファイルを読みに行っているので、
.awsのディレクトリを移動させるとエラーが発生するので注意。

botocore.exceptions.NoCredentialsError: Unable to locate credentials

もし移動させると、上記のようなエラーが発生する。
まぁ、普通の人は移動させないんだろうけど。。。

# 実装 (Pythonソースコード)

```py

# -*- coding: utf-8 -*-

import sys
import threading

import boto3

# boto3 (.aws/config)
BUCKET_NAME = 'YOUR_BUCKET_NAME'

class ProgressCheck(object):
    def __init__(self, filename):
        self._filename = filename
        self._size = int(os.path.getsize(filename))
        self._seen_so_far = 0
        self._lock = threading.Lock()
    def __call__(self, bytes_amount):
        with self._lock:
            self._seen_so_far += bytes_amount
            percentage = (self._seen_so_far / self._size) * 100
            sys.stdout.write(
                    "\r%s / %s (%.2f%%)" % (
                        self._seen_so_far, self._size,
                        percentage))
            sys.stdout.flush()


def UploadToS3():
    # S3Connection
    s3 = boto3.resource('s3')
    s3.Object(BUCKET_NAME, 'OBJECT_KEY (S3)').upload_file('UPLOAD_FILE_PATH (lOCAL)')

UploadToS3()  
  
```

__OBJECT_KEY (S3)__ : <font color="red"> S3でのオブジェクトキーを設定する。</font>
__UPLOAD_FILE_PATH (lOCAL)__ : <font color="red">アップロードするローカルファイルのパスを設定する。</font>

#終わりに
気が向いたら、boto2でのアップロード方法との比較も書きたいと思います。
最後までお読みいただき、ありがとうございました。

何か誤り、アップデート事項ございましたらご指摘お願いいたします。
Ansible | インベントリファイルの基本

# ホストの指定

## インベントリファイルの作成

適当な名前でインベントリファイルを作る。

```:inventory.txt
example.com
```

## 実行

「インベントリファイル」と「実行対象」を指定して、コマンドを実行する。
( ` --list-hosts` はホストの一覧を表示する )

```
ansible -i [インベントリファイル] [実行対象] --list-hosts
```


ここではインベントリファイルに書いたホスト ( `example.com` ) を直接、実行対象として指定する。

```
$ ansible -i inventory.txt example.com --list-hosts
```

ファイルにもホストを書いて、コマンドでもホストを指定する。
なんだか二度手間なような気もするが、とりあえず気にしないでおく。

## 結果

```
$ ansible -i inventory.txt example.com --list-hosts
    example.com
```

## ちなみに

インベントリに書かれていない対象(ホスト)に対しては、コマンドを実行できない。

```
$ ansible -i inventory.txt none.com --list-hosts
No hosts matched
```

# グループの指定

最初のケースだとほとんど意味がないが、グループを指定することでインベントリファイルが重宝する。
グループAとグループBにホストをまとめてみる。

```:inventory.txt
[groupA]
first.example.com
second.example.com
third.example.com

[groupB]
forth.example.com
fifth.example.com
sixth.example.com
```

## 実行

それぞれグルーピングされているのが分かる。

```
$ ansible -i inventory.txt groupA --list-hosts
    first.example.com
    second.example.com
    third.example.com
$ ansible -i inventory.txt groupB --list-hosts
    forth.example.com
    fifth.example.com
    sixth.example.com
```

## グループのグループを作る

グループをグループ化することが出来る。
ここでは「グループA」と「グループB」をまとめた「グループC」を作ってみる。

```:inventory.txt
[groupA]
first.example.com
second.example.com
third.example.com

[groupB]
forth.example.com
fifth.example.com
sixth.example.com

[groupC:children]
groupA
groupB
```

## 実行

```
$ ansible -i inventory.txt groupC --list-hosts
    first.example.com
    second.example.com
    third.example.com
    forth.example.com
    fifth.example.com
    sixth.example.com
```

# 環境

- ansible 1.9.6








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Truffleでデプロイ時にエラー

truffleでデプロイ時にコンソールで下記のようなエラーがでる場合があります。

```
Error encountered, bailing. Network state unknown. Review successful transactions manually.
Error: The contract code couldn't be stored, please check your gas amount.
```

上記のエラーの原因をそのまま鵜呑みにして調べても、
abstractのcontractをデプロイしているからだとか、そんな感じなんですが、

自分がハマった原因はデプロイするcontractのconstructorで、

```
require(_startBlock >= block.number);
require(_endBlock >= _startBlock);
require(_rate > 0);
require(_wallet != 0x0);
```
みたいなところがあって、requireが満たせておらず、上記のエラーが出てデプロイできてませんでした。

悲しいハマり方。。。
でももうちょっと良いエラーログ出してほしいものだ。。。
Oracleで個人的によく使うコマンド その1

個人的にOracleでちょいちょい使うコマンドや、ちょっとした時にパッとコピペできると楽なコマンドをまとめておく。

ある程度まとめたらコマンドの種類別に少し整理しよう･･･

------------------------

##インスタンス作成時に設定したコンポーネント構成を確認
```sql:
SELECT comp_name
	  ,version
	  ,status
FROM dba_registry
ORDER BY 1;
```

##どのユーザー所有のテーブルかの確認
```sql:
col OWNER for a30
col TABLE_NAME for a30

SELECT owner
	  ,table_name 
FROM dba_tables 
WHERE table_name='テーブル名';
```

##表に紐づく索引と索引が貼られているカラムの確認
```sql:
col COLUMN_NAME for a30

SELECT table_name
	  ,index_name
	  ,column_name 
FROM user_ind_columns
WHERE table_name = 'テーブル名';
```

###テーブルの列に設定されたコメントを取得するSQL
```sql:
SELECT column_name
	  ,comments
FROM user_col_comments
WHERE table_name = 'テーブル名'
```

##SIDとSERIAL#の確認系

###SIDとSERIAL#の確認
```sql:
SELECT s.username
	  ,l.sid
	  ,s.serial# 
FROM v$lock l,v$session s
WHERE l.sid=s.sid 
ORDER BY 1;
```

###OS上のPIDからのSIDとSERIAL#の確認
```sql:
SELECT s.username
	  ,s.sid
	  ,s.serial#
	  ,s.program
	  ,p.spid
	,s.status
FROM v$session s,v$process p
WHERE p.addr=s.paddr 
	AND spid='PSコマンドで確認したPID';
```


##ユーザと実行中のSQLのIDの確認
```sql:
SELECT distinct s.username
	           ,s.sid
	           ,s.serial#
	           ,q.sql_id
	           ,s.status
FROM v$session s,v$sql q
WHERE s.sql_id=q.sql_id 
	and s.username IS NOT NULL
ORDER BY q.sql_id;
```

###SQL文自体も確認する場合
```sql:
SELECT distinct s.username
	           ,s.sid,
	           ,s.serial#
	           ,q.sql_id
	           ,s.status
	           ,q.sql_text
FROM v$session s,v$sql q
WHERE s.sql_id=q.sql_id 
	AND s.username IS NOT NULL
ORDER BY q.sql_id;
```

##処理の進捗状況確認
```sql:
SELECT sid
	  ,serial#
	  ,username
	  ,opname
	  ,(sofar/totalwork)*100 as WIP --進捗度(%)
	  ,time_remaining
	  ,to_char(start_time, 'YYYY/MM/DD HH:MI:SS')
FROM v$session_longops
WHERE username = 'ユーザー名'
	AND time_remaining !=0;
```

##接続ユーザ所有のパッケージなどを確認
```sql:
SELECT object_type
	  ,created_status
	  ,status,oject_type
FROM user_objects
WHERE object_type IN ('PROCEDURE','FUNCTION','PACKAGE','PACKAGEBODY');
```

##ディレクトリ・オブジェクトの確認
expdp/impdp使ってないとすぐに忘れる･･･

```sql:
SELECT * FROM dba_directories;
```

## 表領域毎に表領域割当制限を付与する
```sql:
ALTER USER ユーザー QUOTA サイズ ON 表領域名;
```
### 表領域割当制限の確認
```sql:
select username,tablespace_name,max_bytes from DBA_TS_QUOTAS;
```
Libertyのバージョンが知りたい


Libertyのバージョンが知りたくなったら、こう調べる。
[本家サイト](https://www.ibm.com/support/knowledgecenter/ja/SSEQTP_8.5.5/com.ibm.websphere.wlp.doc/ae/rwlp_command_productinfo.html)を見て、コンソールでコマンド実行しても、`bash: productInfo: command not found`と怒られてしまったあなた。

`liberty/bin`の下に`productInfo`は存在します。ので、そこで実行しましょう。

``` 
$ ./productInfo version
製品名: WebSphere Application Server
製品バージョン: 17.0.0.1
製品エディション: BASE_ILAN
```
【GoogleAppsScript】ログ出力(デバッグ目的)

Google Apps Script にて、ログを出力する方法です。
今回は、デバッグをするという目的で、GAS内でログを出力、見る方法です。

#Loggerクラスを使う
参考：[Class Logger](https://developers.google.com/apps-script/reference/base/logger)
Loggerクラスを使うことで、ログを出力することができます。

###log(data)
引数のdataをそのまま出力します。

```js
Logger.log('apple');
// 「apple」と表示されます
```

###log(format, values)
formatして値を出力します。
formatの中には`％s`というプレースホルダーを使うことができ、値は可変で渡すことができます。

```js
Logger.log('I like "%s".', 'apple');
// 「I like "apple".」と表示されます

Logger.log('I like "%s" and "%s".', 'apple', 'red');
// 「I like "apple" and "red".」と表示されます
```

#Logを閲覧する
出力したログをGAS上で閲覧します。
スクリプトを実行後に、GAS画面の左上の「表示」>「ログ」で、ログを見るためのビューが表示されます。
(もしくは Ctrl + Enter でも表示できます)
![log.png](https://qiita-image-store.s3.amazonaws.com/0/45528/1e133155-1fd7-03e0-3b74-bdce2e639d01.png)

![view.PNG](https://qiita-image-store.s3.amazonaws.com/0/45528/c7a0758c-d917-b145-8141-993f287e6daa.png)

スクリプト実行後いちいち開かないといけないのですが、これでログを出力、見ることができるようになります。
Windows 10 でインターネットショートカットをスタートメニューにピン留めし、登録したサイトのファビコンを表示する

## はじめに

Windows 10 になって、デスクトップ上のインターネットショートカットをドラッグ＆ドロップでスタートメニューへ追加できなくなった。また、Windows 10 から推奨のブラウザは Microsoft Edge になり、従来の Internet Explorer のようにインターネットショートカットは作成できなくなりました。

ここでは、①Windows 10 環境下で従来のようなインターネットショートカットを作成する手順と、②作成したインターネットショートカットをスタートメニューにピン留めする手順を解説します。


## 手順

### ①Windows 10 環境下で従来のようなインターネットショートカットを作成する

1. インターネットショートカットを作りたいページを Microsoft Edge で開きます。
> ex.) ```http://localhost/```
1. 画面右上にある「・・・」アイコンを押下し、「**Internet Explorer** で開く」を押下します
1. 先ほど開いたページが Internet Explorer で開かれます
1. ページ内を右クリックし、表示されたコンテキストメニューから「**ショートカットの作成**」を押下します
1. 「***この Web サイトへのショートカットをデスクトップに作成しますか？***」と問われるので「**はい**」ボタンを押下します
1. デスクトップにインターネットショートカットが作成されます
1. アイコンが意図したものになっていない場合、インターネットショートカットを右クリックし、「**プロパティ**」を押下します
1. 「**アイコンの変更**」ボタンを押下します
1. 「**参照**」ボタンを押下します
1. 任意のアイコンを選択し、「**開く**」ボタンを押下します
1. 「**OK**」ボタンを押下して「アイコンの変更」画面を閉じます
1. 「**適用**」ボタンを押下します
1. 「**OK**」ボタンを押下して「プロパティ」画面を閉じます
1. インターネットショートカットのアイコンが変更されたことを確認します
1. インターネットショートカットの作成が完了しました


### ②作成したインターネットショートカットをスタートメニューにピン留めする

1. Windows アイコンからスタートメニューを開きます
1. 歯車のアイコンを押下し、「**設定**」を開きます
1. 「**個人用設定**」を押下します
1. サイドバーから「**スタート**」を選択します
1. 「**スタートメニューにアプリの一覧を表示する**」「**最近追加したアプリを表示する**」が「**オン**」になっていることを確認します
1. エクスプローラーで「```C:\ProgramData\Microsoft\Windows\Start Menu\Programs```」を開きます
1. 先ほど作成したインターネットショートカットを「```C:\ProgramData\Microsoft\Windows\Start Menu\Programs```へコピーします
1. 再びスタートメニューを開きます
1. 「**最近追加されたもの**」のところにインターネットショートカットが表示されていることを確認します
1. スタートメニュー上のインターネットショートカットを右クリックし、「**スタートにピン留めする**」を押下します
1. 「**スタート**」にインターネットショートカットが表示されます


以上
iPhone Xをネイティブ解像度から判定する

iPhone Xだけを判定したい場合があると思います。
ベストプラクティスではないかもしれませんが何かありましたら教えてください。


* iOS 11以降であることを前提としています。
* `nativeBounds`(iOS 8.0, *)を見ているのでiPhone XがDisplay Zoomモード(存在するかは未確認)であっても対応可能です。
* ポートレイトモード、ランドスケープモードの両方に対応しています。



# Swift

## グローバル変数


```swift
let is_iPhoneX: Bool = {
    guard #available(iOS 11.0, *),
        UIDevice().userInterfaceIdiom == .phone else {
            return false
    }
    let nativeSize = UIScreen.main.nativeBounds.size
    let (w, h) = (nativeSize.width, nativeSize.height)
    let (d1, d2): (CGFloat, CGFloat) = (1125.0, 2436.0)
    return (w == d1 && h == d2) || (w == d2 && h == d1)
}()
```


# Objective-C

## UIDeviceカテゴリ

```objc:UIDevice+Extension.h
@import UIKit;

@interface UIDevice (Extension)
+ (BOOL)is_iPhoneX;
@end
```

GCDを用いて初回1度だけ判定してstatic変数に格納しています。

```objc:UIDevice+Extension.m
#import "UIDevice+Extension.h"

@implementation UIDevice (Extension)

+ (BOOL)is_iPhoneX
{
    static BOOL result = NO;
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (@available(iOS 11.0, *)) {
            if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
                CGSize nativeSize = UIScreen.mainScreen.nativeBounds.size;
                CGFloat w =  nativeSize.width;
                CGFloat h =  nativeSize.height;
                CGFloat d1 = 1125;
                CGFloat d2 = 2436;
                result = (w == d1 && h == d2) || (w == d2 && h == d1);
            }
        }
    });
    
    return result;
}

@end
```

命名規則に反して`is_iPhoneX`としていますが、iPhoneが含まれる変数や関数をキャメルケースでつなげるとき悩みますね。

使う時

```objc:ViewController.m
#import "UIDevice+Extension.h"
...

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    if (UIDevice.is_iPhoneX) {
        NSLog(@"is iPhoneX");
    }
    else {
        NSLog(@"is not iPhoneX");
    }
}
```

## マクロ & インライン関数

`nativeBounds`が使えるiOS 8以降を前提にしています。


```objc
NS_INLINE BOOL checkScreenSize (CGFloat d1, CGFloat d2) {
    CGSize nativeSize = UIScreen.mainScreen.nativeBounds.size;
    CGFloat w =  nativeSize.width;
    CGFloat h =  nativeSize.height;
    return (w == d1 && h == d2) || (w == d2 && h == d1);
}
#define IS_IPHONE          (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_OS_11_OR_LATER  (UIDevice.currentDevice.systemVersion.floatValue >= 11.0)
#define IS_IPHONE_X        (IS_IPHONE && IS_OS_11_OR_LATER && checkScreenSize(1125, 2436))
```

参考: :link: [How can I detect whether a user has an iPhone 6 Plus in standard or zoomed mode?](https://stackoverflow.com/a/26150089/3283039)



# Display Zoomモードの判定
iPhone 6から導入された機能で、小さい文字などが見えにくい人のために設定アプリの「画面表示と明るさ」「拡大表示」から解像度を一回り下げることができます。実機で確認できるようなのでiPhone Xも対応しているかは不明です。

このとき`UIScreen.mainScreen.bounds`の値が変更されてしまいますが`UIScreen.mainScreen.nativeBounds`は不変です。

`UIScreen.mainScreen.scale`と`UIScreen.mainScreen.nativeScale`の値が違っていたらDisplay Zoomモードであると判断できます。`scale`ではなく`nativeScale`の方が変化します。


```swift:swift
if (UIScreen.main.scale != UIScreen.main.nativeScale) {
    // display zoom mode
}
```

```objc:objc
if (UIScreen.mainScreen.scale != UIScreen.mainScreen.nativeScale) {
    // display zoom mode
}
```
gstreamer備忘録


個人的備忘録のため随時追記

動作はDebian GNU/Linux (amd64, stretch)で確認

# エレメントの情報

`gst-inspect-1.0`でエレメント一覧が表示されるのでgrepでテキトウに探す。

```bash
$ gst-inspect-1.0 | grep 264
videoparsersbad:  h264parse: H.264 parser
uvch264:  uvch264src: UVC H264 Source
uvch264:  uvch264mjpgdemux: UVC H264 MJPG Demuxer
x264:  x264enc: x264enc
typefindfunctions: video/x-h264: h264, x264, 264
libav:  avmux_ipod: libav iPod H.264 MP4 (MPEG-4 Part 14) muxer
libav:  avdec_h264: libav H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 decoder
libav:  avenc_h264_omx: libav OpenMAX IL H.264 video encoder encoder
rtp:  rtph264pay: RTP H264 payloader
rtp:  rtph264depay: RTP H264 depayloader
```

詳しく見たい場合は

```bash
$ gst-inspect-1.0 x264enc
(長いので省略)
```

指定できるプロパティは、Element Propertiesに記載される

```
Element Properties:
  name                : The name of the object
                        flags: 読み込み可能, 書き込み可能
                        String. Default: "x264enc0"
  parent              : The parent of the object
                        flags: 読み込み可能, 書き込み可能
                        Object of type "GstObject"
(以下略)
```

受け取り可能なデータはPad Templates>SINK templateに、吐き出されるデータはPad Templates>SRC templateに記載される

```
Pad Templates:
  SRC template: 'src'
    Availability: Always
    Capabilities:
      video/x-h264
              framerate: [ 0/1, 2147483647/1 ]
                  width: [ 1, 2147483647 ]
                 height: [ 1, 2147483647 ]
          stream-format: { (string)avc, (string)byte-stream }
              alignment: au
                profile: { (string)high-4:4:4, (string)high-4:2:2, (string)high-10, (string)high, (string)main, (string)baseline, (string)constrained-baseline, (string)high-4:4:4-intra, (string)high-4:2:2-intra,
 (string)high-10-intra }

  SINK template: 'sink'
    Availability: Always
    Capabilities:
      video/x-raw
              framerate: [ 0/1, 2147483647/1 ]
                  width: [ 16, 2147483647 ]
                 height: [ 16, 2147483647 ]
                 format: { (string)Y444, (string)Y42B, (string)I420, (string)YV12, (string)NV12, (string)Y444_10LE, (string)I422_10LE, (string)I420_10LE }



```

# gst-launch-1.0 でいろいろ

## 一番簡単な例

```bash
$ gst-launch-1.0 videotestsrc ! autovideosink
```

![Screenshot from 2017-09-14 13-53-01.png](https://qiita-image-store.s3.amazonaws.com/0/39647/a397f846-99a1-38ea-c37d-e70a80f98284.png)

## H264にエンコードしてデコードして表示

```bash
$ gst-launch-1.0 -v videotestsrc ! x264enc ! avdec_h264 ! videoconvert ! autovideosink
```

## [RTP](https://ja.wikipedia.org/wiki/Real-time_Transport_Protocol)で動画をストリーミング

送り側

```bash
$ gst-launch-1.0 -v videotestsrc ! x264enc ! rtph264pay ! udpsink host=127.0.0.1 port=5005 sync=false
```

受け側

```bash
$ gst-launch-1.0 -v udpsrc port=5005 ! application/x-rtp,media=video,encoding-name=H264 ! queue ! rtph264depay ! avdec_h264 ! videoconverter ! autovideosink
```
## フレームレートを変える

`videorate`を使用する


```bash
# 30fps
$ gst-launch-1.0 filesrc location=/path/to/movie.mp4 ! decodebin ! videorate ! video/x-raw,framerate=30/1 ! autovideosink
```
uGUIのImageでPixelsPerUnitを変更した時の動的な処理

# はじめに
uGUIで詰まったことがあったので、備忘録として初投稿です。
uGUIでUI画像のPixel数が大きすぎてPixelPerUnitを変更することがあると思います。
その時にwidth/heightとの関係性を残したいと思います。

# PixelsPerUnitとは？

PixelsPerUnitとは、ワールド空間の1単位分のpixel数になります。
デフォルトは100に設定されています。

![PixelsPerUnit.png](https://qiita-image-store.s3.amazonaws.com/0/106605/4b02ab78-b959-12e7-278a-8d8e519cf3ca.png)

上のようにSpriteのインスペクタから変更することができます。

#どんな時に使うの？

今回はUIをスライスして上の部分を固定化したい時に変更しました
あらかじめSpriteのインスペクタから固定化したい部分を設定しておきます。

![9-Slice.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/106605/b9d24836-3dd8-bdbf-8adb-b7d722155bf6.gif)

![PixelsPerUnit.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/106605/393d879d-940c-3b4f-d284-38a0f4991cef.gif)

上のように固定化したい部分の幅を変更したい場合、
PixelsPerUnitを変更するのが有効だと思います。

#スクリプトから動的にUIを変更する

PixelsPerUnitはReadOnlyのため、動的に変更することはできないようです。
ただ、PixelsPerUnitを変更した時に、UIの配置を動的に処理することはできます。

```C#:UIScript.cs
using UnityEngine;
using UnityEngine.UI;

public class UIScript : MonoBehaviour {

	void Start () 
    {
        // PixelPerUnitを取得
        float pixelPerUnit = GetComponent<Image>().sprite.pixelsPerUnit;

        // 子のRectTransformを取得
        var titleRectTrans = transform.Find("Title").gameObject.GetComponent<RectTransform>();

        // 子のTitleの高さを変更
        titleRectTrans.sizeDelta = new Vector2(0, 237.0f * (100 / pixelPerUnit));
	}
	
}
```

今回はUIの上部の大きさに合わせてTextの大きさを変更しています。
使用した画像は1920*1371の大きさで、上部の白い部分は上から237pxの範囲になります。

注意が必要なのは、1px当たりのwidth/heightは
100 / PixelsPerUnit
になる点です。

100[width] = 1[unit]
100[height] = 1[unit]
になっているせい？なのか、

100[width/unit] / PixelsPerUnit[px/unit] = 1px当たりの横幅[width/px]
100[height/unit] / PixelsPerUnit[px/unit] = 1px当たりの縦幅[height/px]
となるようです。（分かり辛かったらすいません。）

余談ですが、RectTransformのsizeDeltaにwidth/heightが格納されていています。
今回使ったTextのRectTransformは横幅をStretchしているため、横幅に0を代入しています。

#最後に
たまたま数字を入れて計算したところ分かった結果なので、
もし間違っていたらコメントをいただけると嬉しいです。
UniRxを用いたSerialHandler

Unity + Arduinoな構成のインスタレーションを作ることになり、その際UniRxを採用して詰まったことのメモです。

## TL;DR
* `Thread` 内では `ReactiveProperty` のValueを更新できない(イベントの購読が出来ない)
* その対策として、一度メンバ変数に値を渡し、`ObserveEveryValueChanged`と `ToReadOnlyReactiveProperty` を用いることで、間接的に `ReactiveProperty` にすることにした。

## Thread内ではReactivePropertyのValueは更新できない
通常Arduinoの値をSerialから読み取る際、メインスレッドの速度に影響が出ないよう、 `Thread` を用いてそのThread内でSerialの読み取りを行います。
その読み取った値を `ReactiveProperty` として扱いたくこのような処理を書きました。

```csharp:SerialHandler.cs
// 説明用のため、細かいところは省略してあります。

private ReactiveProperty<string> _sensorMsg = new ReactiveProperty<string>();
public IReadOnlyReactiveProperty<string> SensorMsg { get { return _sensorMsg; } }

void Awake () {
  _serialPort = new SerialPort (_portName, _baudRate, Parity.None, 8, StopBits.One);
  _serialPort.Open();

  _thread = new Thread (Read);
  _thread.Start();
}

private void Read () {
  while (_isRunning && _serialPort != null && _serialPort.IsOpen) {
    try {
      _sensorMsg.Value = _serialPort.ReadLine();
    }
    catch (System.Exception e) {
      Debug.LogWarning (e.Message);
    }
  }
}
```

しかし、このまま `SensorMsg` を購読しようとすると、実行時にエラーとなり、値を受け取ることは出来ません。
これはThread内では、UnityのAPIを実行できないという性質によるものかと思われます。

## `ObserveEveryValueChanged` を使用する
Thread内で更新できないものはどうしようもないので、一度メンバ変数に値を渡すことにしました。
その上で、 `ObserveEveryValueChanged` というUniRxの関数を使うことにしました。
この `ObserveEveryValueChanged` は任意のクラスオブジェクトの変更をストリームに変換できる事のできる関数です。
こちらの関数と、 そのストリームをreadonlyな `ReactiveProperty` に変換する、 `ToReadOnlyReactiveProperty` を使って処理を書きました。

## 完成したコード

```csharp:SerialHandler.cs
using System.Collections.Generic;
using System.IO.Ports;
using System.Threading;
using SimpleJSON;
using UniRx;
using UnityEngine;


public class SerialHandler : MonoBehaviour {
  [SerializeField] private string _portName;

  private SerialPort _serialPort;
  private Thread _thread;
  private bool _isRunning;

  private int _baudRate = 115200;

  private string _sensorMsg;

  public IReadOnlyReactiveProperty<string> SensorMsg { get; private set; }

  void Awake () {
    _serialPort = new SerialPort (_portName, _baudRate, Parity.None, 8, StopBits.One);
    _serialPort.Open();

    _serialPort.DtrEnable = true;
    _serialPort.RtsEnable = true;
    _serialPort.DiscardInBuffer();

    _isRunning = true;

    _thread = new Thread (Read);
    _thread.Start();

    SensorMsg = this.ObserveEveryValueChanged (x => x._sensorMsg)
      .ToReadOnlyReactiveProperty();
  }

  private void Read () {
    while (_isRunning && _serialPort != null && _serialPort.IsOpen) {
      try {
        _sensorMsg = _serialPort.ReadLine();
      }
      catch (System.Exception e) {
        Debug.LogWarning (e.Message);
      }
    }
  }

  public void Close () {
    _isRunning = false;

    if (_thread != null && _thread.IsAlive) {
      _thread.Join();
    }

    if (_serialPort != null && _serialPort.IsOpen) {
      _serialPort.Close();
      _serialPort.Dispose();
    }
  }
}
```
Realtime Databaseのルールで指定したKey名のみ許可するやり方

初投稿です。
お手柔らかにお願いします。
Realtime Databaseのルールで指定したKey名のみ許可するやり方を紹介します。

## 意図しないKeyが追加される可能性のあるルール
以下にRealtime Databaseのルールがあります。
※バリデーションの確認なので全ての権限を許可しています。

```json
{
  "rules": {
    ".read": true,
    ".write": true,
    "users": {
      "$userUid": {
        ".validate": "newData.hasChildren(['name','age','gender'])",
        "name": { ".validate": "newData.isString()" },
        "age":  { ".validate": "newData.isNumber()" },
        "gender": { ".validate": "newData.isString()" }
      }
    }
  }
}
```
`userUid`の子には`name`と`age`と`gender`が存在します。
`userUid`の子のKey名には`name`と`age`と`gender`のみを許可するようにしたいです。
ただしこの状態だと`userUid`の子に`hobby`などを追加できてしまいます。

## ではどうするのが良いのか？
この場合は以下の通りにルールを追加します。

```json
{
  "rules": {
    ".read": true,
    ".write": true,
    "users": {
      "$userUid": {
        ".validate": "newData.hasChildren(['name','age','gender'])",
        "$other": { ".validate": false },
        "name": { ".validate": "newData.isString()" },
        "age":  { ".validate": "newData.isNumber()" },
        "gender": { ".validate": "newData.isString()" }
      }
    }
  }
}
```

`$other`が作成された時、常にバリデーションがfalseになるためエラーになります。
これで`hobby`を作成しようとしてもエラーとなります。


より安全なバリデーションを構築してFirebaseライフを楽しみましょう！
他の方法でもできるよ！って場合はコメントください。
一般ユーザアカウントを匿名ユーザ化する

# 概要
一般ユーザアカウントのパスワードを削除し、匿名ユーザ(anonymous user)化してみた。

# 手順

## 1.指定のアカウントのパスワードを削除する
```
[root@localhost]# passwd -d <username>
Removingpassword for user <username>
passwd: Success
```

# 匿名ユーザとは

> 　システムが使う認証なしの特殊なアカウント。Windowsではマシンがドメイン・コントローラからユーザー・アカウントの一覧を取得するときなどに使われる。セキュリティ上問題があると指摘されることが多い。また，Internet Information Server/Servicesは，不特定多数のユーザーからのアクセスのために，OSに専用のユーザー・アカウントを登録する。こちらも匿名ユーザーと呼ばれる。
[出典元:ITPro Windows用語辞典より] (http://itpro.nikkeibp.co.jp/article/Keyword/20070209/261643/?rt=nocnt)
@includeの中のcalc()の中で変数を呼び出したい

これを

```
.hoge {
  height: 32px;
  min-width: 32px;
  @include css3(border-radius, 16px);
}
```

↓こうしたい場合

```
$size: 32px;
.hoge {
  height: $size;
  min-width: $size;
  @include css3(border-radius, $sizeの半分);
}
```


`@include`　の中で `calc()` を使ってこう↓書いてもだめで、

```
.hoge {
  height: $size;
  min-width: $size;
  @include css3(border-radius, calc( $size / 2));
}
```

`@include`　の中で `calc()` を使うならこう↓書くといいみたい

```
.hoge {
  height: $size;
  min-width: $size;
  @include css3(border-radius, calc( #{$size} / 2));
}
```

一年に一回ぐらい検索してる気がするのでメモ。。。
コードで理解するReact入門

とりあえず手を動かしてざっくりReactを理解する。

## create-react-app
Reactアプリの開発に必要な環境をコマンド一発で構築するツール

エディターはVisual Studio Code

```
create-react-appをnpmでインストール。　OSにnodeインストールしてる前提

$ npm install -g create-react-app

$ create-react-app hello-world(アプリ名)

$ cd hello-world

$ npm start
```
ブラウザでアプリが表示されてるのを確認。

　　　　↓

まだ何もいじってないApp.jsはこんな感じのはず
<img width="630" alt="スクリーンショット 2017-09-14 12.05.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/132777/66ac5f22-b68b-07e1-eb50-b06317406039.png">

　　　　↓

Hello Worldに書き換える。
なぜかstate.nameのはずが、state.whoになってるけど気にせんと進む。
<img width="499" alt="スクリーンショット 2017-09-14 12.11.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/132777/d3f1a0eb-d0a4-b611-80cb-6e796f4d06d0.png">

　　　　↓

propsを渡す
<img width="654" alt="スクリーンショット 2017-09-14 12.50.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/132777/9051ab46-a83d-3187-fe28-b0d504eb2334.png">

　　　　↓

stateを変更する処理を追加。
<img width="737" alt="スクリーンショット 2017-09-14 12.32.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/132777/692d99c4-7917-5943-494f-f3bc655ddd88.png">

　　　　↓

stateに配列データを追加し、リストデータを表示。
<img width="733" alt="スクリーンショット 2017-09-14 12.58.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/132777/c25a11b8-a229-a7ca-9398-f49ddcc6d9ba.png">
LINE@に友達登録した人のアクセス元を特定(トラッキング)する方法


#誰得の記事なのか

- LINE@へ友達登録してくれた人がどこから来たのか特定し、効果測定したい人
- LINE@に友達登録させてくれた人に対してインセンティブを付与したい人


#概要
色々やり方はあるのですが、一番ポピュラーな方法としてCookieを用いたトラッキング法をご紹介します。
ブラウザでCookie食わせた後に突き合わせて特定するという原始的な手法です。
ブラウザを使わないFingerPrintとか、もっとクールな方法があったら是非コメント欄などで教えて欲しいです :bow:

#OSごとの仕様の違い

### iOS版LINE
- LINEのQRコード機能で画像読み取り、LINE以外のURLだった場合、LINE **<font color="Red">内</font>** WebブラウザでQRコードのURLを開く。
- LINE内メッセージでURLを選択すると、LINE  **<font color="Red">内</font>** WebブラウザでURLを開く。

### Android版LINE
- LINEのQRコード機能で画像読み取り、LINE以外のURLだった場合、LINE **<font color="Blue">外</font>** WebブラウザでQRコードのURLを開く。
- LINE内メッセージでURLを選択すると、LINE  **<font color="Red">内</font>** WebブラウザでURLを開く。

iOS版とAndroid版で挙動が異なるため、単純なやり方ではうまくいきません。
解決策として、URLクエリにopenExternalBrowser=1をつけることで、強制的に外部ブラウザを使用させ、UAやCookieを扱うことができます。


#やり方

###1.Cookie食わせ用PHPを作成する

```php:SetCookie.php

<?php
$set_id = $_GET['id'];
setcookie('id', $set_id);

//$_SESSION['id'] = $set_id;//SESSIONもセットしておくとよりbetter
//ここらへんでUserAgentやIPとってDBに保管しておくとよりbetter

//LINE友達登録用URLにリダイレクト
$line_friend_url = "https://line.me/R/ti/p/hogehoge";
header("Location:" . $line_friend_url);

```


###2.Cookie食わせ用PHPのQRコードを作成する
[デザインQRコードジェネレーター](https://www.unitag.io/qrcode)を使うとそれっぽくなります。
[goo.gl](https://goo.gl/)等の短縮URLを経由させるとよりbetter.
![qrcode.jpg](https://qiita-image-store.s3.amazonaws.com/0/189055/633182ca-fef1-3e37-8597-a08ead222014.jpeg)

###3.Cookie取得用PHPを作成する

```php:GetCookie.php

<?php
$get_id = $_COOKIE['id'];
print "君は{$get_id}のフレンズなんだね！";

```


###4.Cookie取得用PHPをLINEから踏ませる
URLが見えてしまうとアレなので、UriTemplateActionBuilderなどを使ってButtonでリンクさせるとよりbetter.


```php:LineBot.php

	function do_get_cookie()
	{
		$url = "https://hoge.com/GetCookie.php?openExternalBrowser=1";//openExternalBrowser=1が重要

		$actions = array(
			new \LINE\LINEBot\TemplateActionBuilder\UriTemplateActionBuilder("ボタン", $url),
		);

		$title = "　タイトル";
		$message = "メッセージ";
		$thumbnail = NULL;

		$button = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\ButtonTemplateBuilder($title, $message, $thumbnail, $actions);
		$messageBuilder = new \LINE\LINEBot\MessageBuilder\TemplateMessageBuilder($message, $button);
		$response = $this->bot->replyMessage($this->replyToken, $messageBuilder);

	}

```



#FAQ
###Q.[LINE Login](https://business.line.me/ja/services/login)使えばいいんじゃね？
とも思ったのですが、審査が厳しいってのとUserにLoginさせる手間が煩雑ということで断念しました。

###Q.ProfileのpictureUrlをユニークキーにしたらいいんじゃね？
とも思ったのですが、 [LINEで画像登録していないUserの場合レスポンスJSONに含まれない仕様](https://devdocs.line.me/ja/#bot-api-get-profile)のため、断念しました。

###Q.UserAgentとIPあれば十分じゃね？
とも思ったのですが、精度を求めるとやはりCookie方式がいいかなと思い、断念しました。
在 Android 中避免打開登入畫面後，按系統的返回鈕可以把登入頁面關掉

## 問題

有一個 MainActivity 為主畫面，
當使用者沒有登入的時候，會透過 Intent 在上面疊一個 LoginActivity
接著按下系統的返回按鈕會回到 MainActivity

## 預期

在 MainActivity 是被設定成要登入才可以觀看這樣的先決條件之下，
當 LoginActivity 出來之後，按返回鍵應該是會回到手機的桌面去

## 解決辦法

在 LoginActivity 裡面，加上一個 callback 實作即可：

```kotlin
override fun onBackPressed() {
    moveTaskToBack(true)
}
```

## 參考

- https://stackoverflow.com/a/26492794/1583560
日本語ファイル名との闘い： Rubymine, AWS CLI, Docker for Windows (1) - AWS CLI


３部作

1. AWS CLI （この記事）
2. Rubymine (次に書く)
3. Docker for Windows (その次に書く)

# AWS CLI で s3 にファイルあげるときに日本語のファイル名でエラー

以下のような感じのエラーが出たりしたとき

```text
UnicodeEncodeError: 'utf-8' codec can't encode 
```
とか

```text
Please check your locale settings.  The filename was decoded as: ANSI_X3.4-1968 On posix platforms, check the LC_CTYPE environment variable.
```
#### ざっくり手順
1. たぶんそれはpython2 だから python3 にあげる
2. やり直す
3. さらに失敗し、それはファイル名が utf-8 ではなく sjis なのかもしれないとする

#### CentOS6の場合

1. python3 へ
    
    ```shell-session
    $ yum install python34 # もしくは yum search python | grep 3 ぐらいで探す
    $ yum install python34-setuptools # これは easy_install 使うため
    ```
    この時点で easy_install が２つか３つになってる
    
    ```shell-session:たとえばこんな感じ
    -rwxr-xr-x 1 root root 323 11月 12 09:38 2010 /usr/bin/easy_install
    -rwxr-xr-x 1 root root 331 11月 12 09:38 2010 /usr/bin/easy_install-2.6
    -rwxr-xr-x 1 root root 334 10月 11 00:17 2016 /usr/bin/easy_install-3.4
    ```
    
2. やりなおす
    
    ```shell-session
    $ aws s3 うんたら
    ```
    
3. それでだめなら言語設定ちゃんとする
sjis なら以下のような感じで
    
    ```vim:/etc/sysconfig/i18n
    LANG="ja_JP.sjis"
    LC_CTYPE="ja_JP.sjis"
    SUPPORTED="ja_JP.sjis:ja_JP:ja"
    SYSFONT="latarcyrheb-sun16"
    ```
    ここで使えるロケールは以下でチェックできる
    
    ```shell-session
    $ locale -a
    ```
    sjis はなかったので、以下のような感じで追加
    
    ```shell-session
    $ localedef -f SHIFT_JIS -i ja_JP ja_JP.SJIS
    ```

参考

* [Filename encoding errors](https://github.com/aws/aws-cli/issues/1368)
ネット＆スマートフォン・コマース 2017

# MUJI（DIGITAL）MARKETING　
（株）良品計画
　　Web事業部長　
　　川名　常海

・Eコマース
・デジタル接点でのブランド理解を奨める

ver 1.0
・2000年からデジタルマーケティングに着手（300店舗）
　→店舗に来れない人がターゲット
　→店舗とWEBで仲が悪かった

ver 2.0
・業績が横ばいになっていた
・2003年から戦略変更
　40：60＝ネット経験あり：なし
　→なし＝商品チェックや新着情報確認
　店舗とネットが、補完関係・相乗効果
　店舗；接客、試食、商品確認
　ネット：全商品あり、24時間営業

［施策］
クーポン利用：メールにクーポン画像をはる
→ネットと店舗が仲良くなりだした：ネットが店舗に送客しているを店長が実感
※ネット商品を店舗で受け取れる
　→受け取り店舗の売上になる
　　実店舗で売ってないカテゴリ商品の売上がたつ

ver 3.0
2007年〜現在：SP発売（情報過多）
毎日接する3000の広告を覚えてる人はいない
購入者の行動が変わった：広告が届かない

モノが有りすぎてモノが選べない
→口コミやSNSの時代

SNS→WEB→店舗の時代
友人の評価→カタログ検索→来店・ネットで購入→満足度のツイート

★大事
なぜこの店にきたのか？なぜ買ったか？
売った後に商品を満足しているか？どんなライフスタイルに組み込まれているか？

全体のデータを１顧客としてのデータとしてみることが重要
→2013年　無地パスポートを開発
　→無地マイルで買った以上に行動情報を取得できるようにした
　　★無印と顧客の関係性を可視化した
　　　DL数　1,000万　アクティブ数700万（iosが2/3）
提示率18%　使用率28% ニュースコーナーが良く見られている＠フロム無地：20万
チェックイン数20% 平均チェックイン数4回/ユーザ　チェックイン後購買確率(同日中・同店舗)5%
チェックインは600M範囲可能
チェックイン分布を出店時のデータとして活用

商品詳細→購買のジャーニー
ネットで見てネットで購入３割　その後店舗で購入５割
→ネット一本の購入動線ではない
　お気に入りや店舗在庫をわかるようにする

発信・共感・話題化・確認・参加/結果を確認できるようなダッシュボードがある

『デジタル時代に求められるマーケティングのこと』
最適化することだけでない。
デジタル化された顧客課題解決のために、守備領域をリアルの接点にも拡張し『顧客にとって良い体験をつくる』というスタンスが重要。

# プロフェッショナルはここを見る！ ECサイト構築1000サイトの実績から見えてきた ECサイト売上UPのポイント！ 

（株）ecbeing　
企画制作本部 ディレクション第3部　
部長　藤井　和也

売上アップのために重視する指標
訪問数×注文率×客単価

1.接客　2.集客
優先順位を間違うと広告費の無駄

◾︎接客
実店舗と同様に商品購入にためらっている問題を解消すること
探しやすく・買いやすく。
サービスと利便性。
自社の強みをしっかり意識して接客を徹底的に強化することが重要

[新潟　味のえん]
http://www.ajinoren.co.jp/shop/
初期購入のハードルを下げる
・お試しセットをつくる
　送料無料、価格600円

・こだわりの販売方法
詰め合わせ機能：ギフト対応
http://www.ajinoren.co.jp/shop/assort/manual.aspx

[ACE]
http://store.ace.jp/shop/default.aspx
・検索カテゴリの工夫
泊数から探す

・欲しいものリストに追加する＝お気にいり機能
ネーミングを変えるだけで機能使用率が43%アップ

[4℃]
http://4c-bridal-online.jp/shop/
・サンプルリング貸し出しサービス

[SHIPS]
http://onlineshop.shipsltd.co.jp/shop/default.aspx
・店舗在庫を表示
・特定店舗の在庫検索

◾︎集客
購買意欲の高いユーザを連れてくることが大切
自然検索、リスティング広告

リスティング広告の最適化について

・指名系ワード
指名系ワードに出稿するにも意図があればよい
広告効果を社内アピールしたい場合
他社広告が表示される場合

[住商ブランドマネジメント]
ファイラー
指名系キーワードの広告は出稿していない

[グラニフ]
購入有無によって広告の出し分け
未購入者のみ広告表示　検索流入120%を達成

・NGワード
購買意欲をまったくないユーザを連れてくる

[コウダイ]
取り扱いないアニメタイトル　ジクソーパズル

[アマガサ]
地域名 JELLY BEANS

# 勝てるECサイトのGoogleアナリティクス活用法 ～受注率等の数値の正しい捉え方とチーム運営への活かし方～
キイロ（株）
代表取締役 
行廣　昌彦

レジュメあり

MEMO
単品通販は、新規とリピートの施策を考えるチームが違う
↓作ったのでよろしく
https://siteanatomy.com/
qshape - 何か異常な状態の時にさくっとメールサーバの配信状況を確認＋メール一括で削除


メールサーバにメールがたまってそうな時(inodeがどどっと増えたり)に便利、grepしたりしなくて済む。

CentOS 6 では以下でパッケージをインストールできる。base repoなので特にリポジトリ追加という不要。

```shell-session
$ yum install postfix-perl-scripts
```

![qshape.PNG](https://qiita-image-store.s3.amazonaws.com/0/54494/ece997a5-c904-bd59-9772-07617969c08d.png)

詳しくは [Postfix ボトルネック分析](http://www.postfix-jp.info/trans-2.1/jhtml/QSHAPE_README.html#deferred_queue)

---

### 対処

**MailDir**形式 で スパムが大量に届いたとか、送信できませんでしたメールが大量にたまっていたら
もしくは、メール以外でも大量のファイル消すときとか

```shell-session
$ /bin/rm -rf /<メールディレクトリ/ new/*
```
だとファイル数によっては死ぬので（引数大杉問題： <code>/bin/rm: Argument list too long</code> ）

```shell-session
$ find /<メールディレクトリ＞/ > filelist.txt
$ vim filelist.txtd
```

```bash:filelist.txt
# vim上で :%s;^;rm ;g して、以下みたいに成形する
rm mailfile1
rm mailfile2
```

```shell-session
$ cd  /<メールディレクトリ＞/ 
$ sh ~/filelist.txt
```

以下のようなコマンドでも出来るけど、リストのファイル作ることで一度目チェックしたり、場合によってはさらに条件で絞り込んで削除とかが楽。
（消しちゃいけないものまで消さないように）
```shell-session
find **** | xargs rm
```
クラスタ構成下で共有ディレクトリ上のログファイルをローテートする

# はじめに
クラスタ構成下の複数台のLinuxサーバにて、
共有ディレクトリ上のログファイルをローテートする方法について。

# 背景
とある一日に複数回cronで実行するシェルがあり、
共有ディレクトリ上に実行結果のログを出力していたのですが、
こいつが稼働後数年経っているにも関わらず、ローテートされないままえらいことになっていました。

確かに1回1回のログの量は大したことがないのですが、
毎日複数回実行されるため、それが365日×数年分ともなれば、まさに塵も積もれば何とやら。

本来であればログのローテートなんかは、
/etc/logrotate.d/の中に設定ファイルを書いてlogrotateにやってもらうのが一番手っ取り早いのですが、
何せサーバが複数台のクラスタ構成になっているため断念。

シェル自体の修正も検討したのですが、
何せ動けばいいや的な思想で書かれたアレなクオリティだったため、
下手に修正しちゃうと火傷しかねないということもあり断念。

幸いにしてクラスタ構成下でアクティブなサーバを判定する方法はあったので、
手動でローテートするシェルをこさえた上で、全部のサーバのcronに仕込んで、
アクティブなサーバ上でのみローテートを実行するというやり方に落ち着き・・・・・・そうです。
（この記事を書いてる時点ではまだ100％決まってなかったりするのですが）

# ローテートシェルの書き方
ローテートシェルの書き方については @Kuchitama さんの [自前でログローテートする](http://qiita.com/Kuchitama/items/a72558bd95197ce73a67) という記事を参考にさせていただきました。ありがとうございます。

```shell-session
#!/bin/bash

# 対象ディレクトリ
LOGDIR="/xxx/log"

# 対象ログファイル
FILES="xxx.log yyy.log"

# ログ保存期間
ROTATE=14

DATE=`date +%Y%m%d`

for file in ${FILES}
do

    # 既に当日のローテートファイルが作成されている場合は処理を行わない
    if [ ! -e ${LOGDIR}/${file}.${DATE}.gz ]; then

        /bin/cp -p ${LOGDIR}/${file} ${LOGDIR}/${file}.${DATE}
        /usr/bin/gzip ${LOGDIR}/${file}.${DATE}

        # 対象ファイルを空にする
        if [ $? = 0 ];then
            /bin/cp /dev/null ${LOGDIR}/${file}
        fi

        # 指定した期間以前のファイルを削除する
        /usr/bin/find ${LOGDIR}/${file}.* -mtime +${ROTATE} -exec /bin/rm {} \;

    fi

done
```

基本的には参考にさせていただいた記事内のシェルを元に書いていますが、
アクティブサーバの切り替わり等や切り替わりに伴う手動でのシェル実行などを考慮して、
既に同じ日付のローテートファイルが作成されている場合には、
ローテート処理を実行しないようにしています。

**9/20追記
この書き方だとroot以外のユーザで実行した場合にファイル・ディレクトリの権限の影響をモロに受けるので、
必要に応じてcpコマンドの前にsudoを付けるなど気を付けてください。**

# cron側の設定
```shell-session
* * * * * アクティブ判定シェル.sh > /dev/null 2>&1 && ローテートシェル.sh > /dev/null 2>&1
```

&&は「左側の式の終了ステータスが0だった場合に右側の式を実行する」なので、
アクティブサーバ判定用のシェルでアクティブなら終了ステータス0を渡すように書けば、
上記のようなcronの書き方でいけます。
うっかり&1個で書いちゃうとただの並列処理になってしまうので要注意。

環境によって判定するシェルの書き方なんかは変わってくると思うので省略しますが、
例えばアクティブなサーバのみネットワークに接続されているウォームスタンバイな環境なら、
ping飛ばしてその戻り値で判断するとか色々やり方はあるかと思います。

# おわりに
一つ一つのログは小さくとも、
稼働後は時間の経過とともにどんどんディスク容量を食っていくので、
システム構築時に稼働後のことも考慮してローテートなどを組み込むかどうか検討しましょうというお話。
~~ただこちらが稼働3年で見積もって構築したシステムを平気で10年以上稼働させるユーザなんかザラにいるからなぁ~~
Plesk覚書【随時追記】


GMOクラウドのALTUSでPlesk付きのCentOSを利用していて分かったことメモ。
基本的にはPleskの仕様まとめです。
Pleskライセンスの種類によって管理画面の構成なども違うので、上位版ではまた違うかもしれません。

# 環境
OS：CentOS 7.2 64bit with Plesk12.5 20161101
Pleskライセンス：Web Admin Edition(10ドメイン)

# ウェブサイトとドメイン
ドメイン数はライセンスによって上限が違う。(10,30,無制限)
ドメインーサブドメインの関係の場合デフォルトではサブドメイン名のディレクトリがメインドメインスペース内にできる。
サブドメイン作成時にドキュメントルートを`/httpdocs`にすればファイルを共有できる。
サブドメインとして作成したドメイン名はメールアドレスとしては利用できないので、メールアドレスを使い分ける必要がある場合はドメインとして作成する必要がある。
この場合でもウェブスペースとして既存のものを選択すればファイル共有が可能

# データベース
まずはドメインを選択してその中にデータベースを作成していく。
ドメインを選択せずにDBを作成することはできない。
ドメインに関連付けることができるが関連付けなくても接続は可能。
(↑ここの違いは検証してないです)
他ドメインのDBにもプログラムによる接続は可能。
phpMyAdminでの閲覧は当該ドメインの中からしか不可。

# エラーログ
** 基本は`/var/log`内に格納される**

|--|格納場所|
|--:|:--|
|Web系[^web]|/var/www/vhosts/ドメイン名/log/error_log|
|Plesk系|/usr/local/psa/var/log|
|システムエラー|/var/log/message|
|PHP(fpm利用)|/var/log/plesk-php＊[^ver]-fpm/error_log|
|PHP(OSデフォルト利用)|/var/log/php-fpm/error_log|
[^web]:ここのログはPlesk管理画面から確認できる
[^ver]:＊部にはPHPのバージョンが入る(PHP5.6なら56)

# 各種アプリケーションのインストール
基本的にドメイン下にインストールされる

# アプリケーションとしてconcrete5をインストール

普通にインストールしようとしたらできなかったのでメモ

## mcrypt入ってないよ＼(^o^)／
って言われるのでいれる。
https://support.plesk.com/hc/en-us/articles/213925125-How-to-install-the-php-mcrypt-module-

CentOS7.2なので

`# yum install epel-release`
`# yum install php-mcrypt`
`# /usr/local/psa/bin/php_settings -u`
`# systemctl restart httpd`


＞ツールと設定　＞一般設定（PHP設定)　で該当PHPの拡張にmcryptがあってチェックが入ってればmcryptのインストールは完了

そのあとアプリケーションからconcrete5のインストールボタンを押せばOK(　´∀｀)bｸﾞｯ!

# メールをトリガーにしてプログラムを動かす(PHP)
## php@example.com あてのメールを /var/www/vhosts/example.com/script/mail.php　で処理したい！
### メールアドレスを作成
pleskの管理画面からメールアドレスを作成する。
ユーザは実在する必要はないので、顧客パネルへのアクセスのチェックは外す

### 該当メールアドレスをユーザに割り当て
ここでのユーザは　/etc/aliases　で利用するためのもの
pleskユーザとの関連はなし
ここではユーザ名を　trigger　として設定
`# vim  /var/spool/postfix/plesk/virtual`
```
example.com anything
php@example.com trigger
```

### virtual.dbを更新する
`# postmap /var/spool/postfix/plesk/virtual`

これをしないと
` warning: database /etc/postfix/virtual.db is older than source file /etc/postfix/virtual`
とかって怒られてしまったのでｗ

### aliasでPHPを指定
`# vim /etc/aliases`
```
trigger:  |"/usr/bin/php -q /var/www/vhosts/example.com/script/mail.php"
```

`# newaliases`
`# systemctl restart postfix`

### updateに注意！
おそらくアップデートが原因だと思うのですが、いつの間にかaliasesが解除されてました。。。
存在しないアドレス宛てのメールを該当アドレスに転送させてトリガーにしていたのですが、aliasesが解除されていたのを修正したら「存在しないメールアドレスです」というバウンスメールが。。。
そこの設定さっきPlesk管理画面でやったぞ？？となりながら試行錯誤。
結果、エイリアスの設定等をすべて終わらせて、`postfix reload`の後で改めて管理画面から設定したところ反映しました(　´∀｀)bｸﾞｯ!
Kaggle - Data Science Bowl 2017上位陣リンク一覧

KaggleのData Science Bowl 2017[^1]の上位陣リンク一覧です．

## [1位] Document and code of the grt123 team 

- Name: Liao
- Kaggle Discussion: https://www.kaggle.com/c/data-science-bowl-2017/discussion/32555
- Writeup: https://github.com/lfz/DSB2017/blob/master/solution-grt123-team.pdf
- Code: https://github.com/lfz/DSB2017
- Qiita Memo: https://qiita.com/namakemono/items/d1cf8605db38389a316e

## [2位] 

- Names: Julien & Daniel 
- Kaggle Discussion 1: [Very quick 1st summary of julian's part of 2nd place solution.](https://www.kaggle.com/c/data-science-bowl-2017/discussion/31551)
- Kaggle Discussion 2: [Documentation + code 2nd place.](https://www.kaggle.com/c/data-science-bowl-2017/discussion/32544)
- Code(Daniel): https://github.com/dhammack/DSB2017/
- Writeup(Daniel): https://github.com/dhammack/DSB2017/blob/master/dsb_2017_daniel_hammack.pdf
- Code(Julien): https://github.com/juliandewit/kaggle_ndsb2017/
- Writeup(Julien): http://juliandewit.github.io/kaggle-ndsb2017/
- Qiita Memo: http://qiita.com/namakemono/items/499e5f90865d3d69ef38

## [7位] 7th Place short overview.

- Name: Köhler
- Kaggle Discussion: https://www.kaggle.com/c/data-science-bowl-2017/discussion/31576
- Qiita Memo: http://qiita.com/namakemono/items/f565028e5a87066c8fa0


## [9位] 9th place solution - Deep Breath 

- Name: Vansteenkiste
- Kaggle Discussion: https://www.kaggle.com/c/data-science-bowl-2017/discussion/31548
- Writeup: https://eliasvansteenkiste.github.io/machine%20learning/lung-cancer-pred/

## [16位] docker from 0.465 team

- Name: Dong
- Kaggle Discussion: https://www.kaggle.com/c/data-science-bowl-2017/discussion/31583
- Code: https://github.com/aaalgo/plumo


## [209位] My code - 2D & 3D Segmentation U-Net's & Classification CNN's + XGB

- Name: Rosinski
- Kaggle Discussion:https://www.kaggle.com/c/data-science-bowl-2017/discussion/31608
- Code: https://github.com/Wrosinski/Kaggle-DSB
- Qiita Memo: http://qiita.com/namakemono/items/a9b5e440b94d20cbe00f

## References

[^1]: Kaggle, [Data Science Bowl 2017](https://www.kaggle.com/c/data-science-bowl-2017), 2017.
Rake 12.1.0で導入された did you mean 対応を試す

Rake 12.1.0で導入された did you mean 対応を試します。

* Rakefile

```ruby
desc "hoge"
task "hoge" do
  puts "hoge"
end

desc "hige"
task "hige" do
  puts "hige"
end

desc "foo"
task "foo" do
  puts "foo"
end
```

* 実行結果

```sh
$ rake -T
rake foo   # foo
rake hige  # hige
rake hoge  # hoge
$ rake foo
foo
$ rake fooa
rake aborted!
Don't know how to build task 'fooa' (see --tasks)
Did you mean?  foo

(See full trace by running task with --trace)
$ rake hege
rake aborted!
Don't know how to build task 'hege' (see --tasks)
Did you mean?  hige
              hoge

(See full trace by running task with --trace)
```

## 雑感
べんり

## 外部資料
* [Rake 12.1.0 をリリースした - HsbtDiary(2017-09-12)](https://www.hsbt.org/diary/20170912.html#p01)
* [Added did you mean to rake by xtina-starr · Pull Request #221 · ruby/rake](https://github.com/ruby/rake/pull/221)
* [スペルミスでエラーが出たら、正しい名前を教えてくれる gem を作った - Qiita](http://qiita.com/yuki24/items/feb72ee1f280434d5a5f)
* [Ruby | did_you_mean gem でスペルミスを検出＋ did_you_mean gem のコードリーディング - Qiita](http://qiita.com/tbpgr/items/835b3ac168304cba9b7b#_reference-6860fadc9851c9849ade)
gzip のやり方

普通に文字列 (string) から gzip を生成するやり方
エラーハンドリングは省略

```
import (
  "bytes"
  "compress/gzip"
)

func makeGzip(body string) []byte {
  var b bytes.Buffer
  gw := gzip.NewWriter(&b)
  _, err := gw.Write([]byte(body)); if err != nil {
    ...
  }
  gw.Flush()
  gw.Close()
  return b.Bytes()
}
```
gw.Close() はファイルストリームのクローズみたいな挙動ではなく, 
gzip のフッターデータ書き込みなので defer 等で最後に回そうとすると
不正なデータになってしまうので注意. (とりあえず解凍はできない)
Close() は Flush() の処理を含んでいるかもしれませんが自信がないです.
ActiveAdminで二重にnestしたフォームを書く

[ActiveAdminでhas_oneのassociationに対するnestしたフォームを作る](http://qiita.com/setoyama-precena/items/d47a00bb3344fe4b10dc)
に続き、ActiveAdminネタ。二重にネストしたフォームは普通にActiveAdminでも書けます。

親モデルParent、子モデルChild、孫モデルGrandChildが以下のように定義されているときに、

```ruby
class Parent < ActiveRecord::Base
  has_many :childs # childの複数形はchildrenだけど、無視
  accepts_nested_attributes_for :childs, allow_destroy: true
end

class Child < ActiveRecord::Base
  belongs_to :parent
  has_many :grand_childs
  accepts_nested_attributes_for :grand_childs, allow_destroy: true
end

class GlandChild < ActiveRecord::Base
  belongs_to :child  
end
```

二重にネストしたフォームは以下のように書けます。ただし、当然ながら、 `accepts_nested_attributes_for`が正しく設定されていないと、内部的に呼ばれる`new_record?`のところでnilが起因するエラーが出ます。

```ruby:/admin/models/parent.rb
ActiveAdmin.register Parent do
  form do |f|
    f.inputs "子モデルの編集"
     f.has_many :childs do |child|       
       child.input :hoge

       child.has_many :grand_childs do |grand_child|
         grand_child.input :moge
       end
     end
    end
  end

end
```
【UE4】継承を用いた複数NavMeshの分類方法

##はじめに
UE4上ではNavMeshを複数使い分けることで、敵やNPCが侵入不可のエリアを作成したり、敵の種類によって棲み分けを行うことが可能となります。

##作成/設定方法
以下の記事に基本的な設定方法が記載されています。
[【UE4】ナビゲーションシステムのSupportedAgentsについて](http://qiita.com/Dv7Pavilion/items/625eeeb1885fe8d76f20)

##確認事項
基本的な設定が終わったらUE4上部メニューから 「編集」>「プロジェクト設定」でプロジェクト設定ウィンドウを開き、左のメニューから「エンジン」>「ナビゲーションシステム」を開いてください。

今回は「Supported Agents」にある自身で設定したTypeの "Navigation Data Class" と "Preferred Nav Data" を以下の状態に設定しています。この自身の設定に沿うように配置しているキャラクターの「Movement Capability」項目にあるプロパティ群と一致するかの確認も行ってください。

![ini.PNG](https://qiita-image-store.s3.amazonaws.com/0/36899/ff669b42-1cdf-2cf9-630a-68a2b13e1565.png)

ここで、上記の記事に従った通りに設定を行っていれば、とりあえず複数NavMeshの分類対応は行えると思います。

ですが、例えば、同じ大きさ且つ同じ動きが可能なNPCと敵がいたとしたら、上記パラメータでの分け方だけだと不十分な可能性があります。この場合に、Typeに適用している "Navigation Data Class" と "Preferred Nav Data" のRecastNavMeshクラスを継承したカスタムRecastNavMeshクラスにすることによって実現可能かと思われます。具体的な作成方法は以下の通りです。

##RecastNavMeshのカスタムクラス作成

確認後、これらの横にある虫眼鏡アイコンを押下し、UE4エディタ上の「コンテンツブラウザ」を確認してください。おそらく、「エンジンC++クラス」>「Engine」>「Classes」>「AI」>「Navigation」というパスで表示されていると思います。そのコンテンツブラウザを開いている状態から、左上の新規追加ボタンを押下してください。
![コンテンツブラウザ.PNG](https://qiita-image-store.s3.amazonaws.com/0/36899/1f2c1402-cf0a-1c0c-d1f0-e1235f3fcd82.png)


プルダウンメニューが開かれるので、そこから"新規C++クラス..."を選択します。すると、「C++クラスを追加」というウィンドウが開かれます。このウィンドウの左上部にある、"全てのクラスを表示"というチェックボックスにチェックをしてください。検索ボックスとすべてのクラスが表示されたら、検索ボックスからRecastNavMeshを検索し、選択状態にしておきましょう。

選択ができたらそのまま次の画面へ進んでください。
![newC++class.PNG](https://qiita-image-store.s3.amazonaws.com/0/36899/d82390ab-3027-ac8a-50c8-f23d86454ff1.png)


次に「新規 Recast Nav Mesh に名前を付ける」という画面が表示されるので、任意で "ファイル名" と "パス" を編集してください。編集後はそのままクラスを作成して頂いて問題ありません。

クラス作成後は先ほどの「ナビゲーションシステム」から見ることができる「Supported Agents」の任意Typeの "Navigation Data Class" と "Preferred Nav Data" を先ほど作成したカスタムRecastNavMeshを適用してください。また、それに伴い、配置しているキャラクターの「Movement Capability」項目にあるプロパティ群とも一致させるよう設定してください。

ここまで設定が完了したら、あとは念のため一度UE4上でビルドを行い、想定通りにキャラクターが動いているか確認をしてみましょう。もしも、うまく動作していない場合、作成したNavMeshをあちこち移動させたり編集を行うことで参照がどこかに残ってしまっている可能性があります。その場合は、一度エディタの再起動を行うか、再度UE4上でビルドを行うか、マップ上に配置しているNavMeshを一旦作成しなおす等を行ってみてください。

以上。