OmniAICreator/Qiita-1.07M huggingface dataset:
Sourcetreeでのリモート・リポジトリブランチの作成方法

Git初心者です。

下記リンクのリモートリポジトリのブランチ作成では、上手く作成出来なかったため、備忘録として対応を記載します。

https://laraweb.net/environment/1687/
https://teratail.com/questions/68283

2名(repo_a, repo_b, だけでブランチを共有して作業する場合を想定します。リモートリポジトリは、origin/masterとします。

repo_aでまず、ローカルにブランチを作成します。左側の自分のブランチdevを右クリックし、push先→originとします。
プシュ:repo_aが上部に見え、ローカルブランチとしてdev, リモートブランチが空白になります。

この空欄にdevを入れます。そうすると、左側の雲のリモートのorigin>を開くと、dev, masterが見えます。

現時点での作業ブランチはdevなので、masterとは切り離されて作業が出来ます。これをターミナルをクリックすると
(dev)になっている事が分かります。git remote -vと打つとoriginでありながら、(dev)の状況である事が分かります。

この時点で、devでの編集、コミット、プッシュした情報は、リモートリポジトリのブランチdevに保存されます。

そこで、repo_bに移ります。repo_aと同様にセットします。pullします。これで、全く同じ編集したページが取得されます。

何かコメントがあれば訂正致します。
BlockWriteプロシージャは転送ブロックとその数の組み合わせ

データ構造が動的配列となっているデータをファイルに書き込む場合、
System.Writeプロシージャは使えない（第1引数は型ありファイル変数）ため、
System.BlockWriteプロシージャ（第1引数は型なしファイル変数）を使うことになります。
ただ、そのときいろいろ罠に陥りました。
...というか、ちゃんとヘルプを読んでなかっただけ。

その1。
System.BlockWriteの第3引数には
「ファイルに書き込むデータのサイズ」
ではなく、
「ファイルに書き込む転送ブロック（Rewriteプロシージャでサイズを指定できる）の数」
を指定します。
つまり、ファイルに書き込むデータサイズは結果として
　転送ブロックサイズ×第3引数値
となります。

その2。
BlockWriteは書き込みたいデータのサイズを知らないので、第3引数指定したブロック数分書き込みます。
だから転送ブロックサイズと書き込むブロック数を正しくしないと、できたファイルの後ろにゴミが入っていたり、あるいは書き込みたいデータの後ろが切れたりしてしまいます。

その3。
書き込みたいデータのサイズが転送ブロックサイズより小さいと例外になるようです。
つまり、128byteでちまちまと何度もファイル書き込みするくらいなら、転送ブロックを大きくして1回で書き込んでやれと早合点して、Rewriteプロシージャ第2引数に適当な転送ブロックサイズを指定すると失敗するってことです。

★結論。
BlockWriteではなく、TFileStreamを使った方が簡単でした。
既存のソースでBlockWriteを使っていたものだから、それに囚われておりました...
Rustで設定情報をstructで持ちまわす

# 目的
プログラム全体で使いたい設定情報を1つのstructに定義して持ち歩きたいです。actix-webあたりだとWebDataとして各ハンドラーから参照できるようになります。
デフォルト値をもちつつ、値の変更は環境変数で行うものとします。
DBの接続先はテストかどうかで向き先を変えてみます。

# プログラム

```rust:config.rs
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Config {
    pub pg_url: String,
    pub redis_url: String,
    pub db_retry_count: u64,
    pub db_retry_delay: u64,
}

impl Config {
    pub fn new() -> Self {
        let db_host = get_env_str("DB_HOST", "localhost");
        let pgport = get_env_str("PGPORT", "5432");
        let postgres_user = get_env_str("POSTGRES_USER", "user");
        let postgres_password = get_env_str("POSTGRES_PASSWORD", "password");

        // まず本番環境の値を探して、なければテストかどうかで開発かテストを判定
        let postgres_db = get_env_str(
            "POSTGRES_DB",
            &if cfg!(test) {
                get_env_str("POSTGRES_DB_TEST", "test")
            } else {
                get_env_str("POSTGRES_DB_DEV", "development")
            },
        );
        Self {
            pg_url: format!(
                "postgres://{}:{}@{}:{}/{}",
                postgres_user, postgres_password, db_host, pgport, postgres_db
            ),
            redis_url: get_env_str("REDIS_URL", "redis://localhost:6379"),
            db_retry_count: get_env_value("DB_RETRY_COUNT", 3),
            db_retry_delay: get_env_value("DB_RETRY_DELAY", 2),
        }
    }
}

// 文字列の値を取得
fn get_env_str(key: &str, default_value: &str) -> String {
    match ::std::env::var(key) {
        Ok(val) => val,
        Err(_) => default_value.to_string(),
    }
}

// 文字列以外の値を取得
fn get_env_value<T>(key: &str, default_value: T) -> T
where
    T: std::str::FromStr + Copy,
{
    match ::std::env::var(key) {
        Ok(val) => val.parse().unwrap_or(default_value),
        Err(_) => default_value,
    }
}


```
最速でinitを呼ぶ

[Goアドベントカレンダー](https://qiita.com/advent-calendar/2019/go)の穴埋め投稿です。

他の初期化処理に先駆けて、真っ先に何かをやりたいことってないですか？ありますよね？

# initの呼び出し順序

Go処理系の実装依存であって、仕様はないのですが、Python同様Goは主要実装が仕様なところがあるのでこれに従って説明します。ググるといろいろ情報が出てきます。

[Package initialization and program execution order](https://yourbasic.org/golang/package-init-function-main-execution-order/)

* mainパッケージの初期化
  * 自身のパッケージの前にimportされているパッケージを初期化
  * パッケージは1度にひとつずつ初期化される
  * パッケージレベルの変数は宣言順に初期化される
  * 最後に自分の中のinitが呼ばれる
* 最後にmain関数を呼ぶ

ここに書いてない情報としては、パッケージ内部の順序というのはファイル名の順序で規定されます。あと、init関数はパッケージ内部に同名関数をいくつも定義できますが、複数ある場合もパッケージ内部の順序（ファイル名順→ファイル内宣言順）で呼ばれます。

# 最速で呼ぶには

最速のファイル名を定義して、その中からimportして、その中にロジックを書くのが最速ということです。最速なのはゼロドットゴーです。

```go:0.go
package main

import _ "github.com/shibukawa/fastest"
```

これのためにわざわざリポジトリを作るのはあれなので、fastestサブフォルダを作ってgo.modでreplaceでそういうパッケージがあるように見せかけます。

```:go.mod
module fastest_test

go 1.13

replace github.com/shibukawa/fastest => ./fastest
```

これが最速で呼ばれるコードです。

```go:fastest/fastest.go
package fastest

import "log"

func init() {
    log.Println("最速で呼ばれるinit")
}
```

これで最速でなにかやりたいときはバッチリです！まあ実装するのがツールやらライブラリならgo.modのreplaceはやらなくても良くて、そのパッケージのサブパッケージで指定すれば良いですね。今回はコードジェネレータで置き場所が事前に決まらない、みたいなユースケースで解法を考えたのでreplace使っています。
Windows10 Ruby2.6でRubyOnRailsインストールメモ

![](https://badgen.net/badge/icon/Windows 10?icon=windows&label=) ![](https://badgen.net/badge/Ruby/2.6/red)
Windows10だと良く失敗するので。
なんかWebpacker必須になったため面倒くさくなった。

#(1)Rubyをインストール

安定版の2.6あたりをWindows用のInstallerでいれる。
https://rubyinstaller.org/
なんか途中で立ち上がる黒い画面のRubyInstaller2と書いてあるやつに対しては、「1」と入力後Enter

終わるともう一回出るのでEnterで終える。
#(2)NodeJSをインストール

https://nodejs.org/ja/
LTS版を入れておけばよい
#(3)Yarnをインストール
https://yarnpkg.com/lang/ja/docs/install/#windows-stable
入れる。
#(4)Railsをインストール
コマンドプロンプトを立ち上げて


```
gem install rails
```

多分うまくいく。

#(5)Railsのプロジェクトを作る
プロジェクトを作りたいフォルダに移動します。そしてコマンドプロンプトで

```
rails new プロジェクト名
```

実行します。
SQLite関連のエラーが出たら、(6)へ、
Webpacker関連のエラーが出たら(7)へ
失敗しなかったら(8)へ飛ぶ

もし、よくわからないなら(6)へ。

#(6)SQLiteをいれる
コマンドプロンプトで

```
 gem install sqlite3 -v '1.4.1'
```
と実行する。
※もし失敗したら、
https://www.sqlite.org/download.html から、SQLiteをダウンロードして、Rubyのインストールしたフォルダの中のbinフォルダに「sqlite3.dll」をコピーしてコマンドを再実行する。

#(7)Webpackerをいれる
先ほどのプロジェクトフォルダの中で実行する！
※フォルダを移動するには、コマンドプロンプトで

```
cd プロジェクト名
```

フォルダの移動ができたら、再びコマンドプロンプトで

```
bundle install
```

すんなりwebpackerがインストールされるはず。

#(8) サーバーを立てる
先ほどのプロジェクトフォルダの中で実行する！

```
rails s
```
サーバーが立つ。
その後、ブラウザを開いて、アドレスバーに「localhost:3000」と打って、トップページが出たら終わり。

もしうまくいかなかったら、

```
bundle install
```
を再実行する。それでもエラーが出たら、エラーが出た項目を手動インストールする。

動くといいね
ゆるコンというゆるいコンサルについての会

# はじめに

https://connpass.com/event/157781/
テストの勉強会でおみかけするかおりっとさんが主催の、コンサルでうまく言語化したいという悩みを解決するようなゆるい会に参加してきましたので自分なりのまとめ。

テストやQAという立場でコンサルとは関係ないのだけど、最近、品質レベルやらチームビルディングやらいろいろと（社内の）コンサルに近いなぁっと思っていたところですし、社外コンサルの人が入ってきたときには現場の悲惨さをうまく表現できていないのかなぁっと思い、そもそも人と話すのが上手ではないので同じ悩みを感じているということで参加してました。

twitter のハッシュタグ
 [#ゆるコン](https://twitter.com/search?q=%23%E3%82%86%E3%82%8B%E3%82%B3%E3%83%B3&src=typed_query)



# 言語化したい
テスト手法（HAYST法）などを教えたが間違った使い方をしてモヤモヤするなどコンサルでいろいろと悩んでいらっしゃるようで、かおりっとさん曰く、『言語化できると世の中よくなる』
（よくなるってことは、何か問題点を解決ができる？）


# コンサルのタイプ

* 要求があってスコープを切って問題点を解決するタイプ
* 全てをお任せするタイプ

コンサルしてもらう側がどう発注するのかによって変化する

# コンサルテーションのゴール

『コンサルテーションを始めるときにゴール（方向性）を決めるのか？』という話では

* ある程度決めておくが、実施しているうちにゴールが変わる場合がある
* 松竹梅で決めておく

コンサルテーションすると組織（経営、開発現場、QAなど）や役職によってゴールが異なるため調整して、それぞれの立場で達成すべきことを説明する。


# コンサルタントのタイプ
コンサルタントの種類として以下のような種別がある

* 何かを売る（手法やISOなど）
* ツールの導入
* 何かを一緒に作る
* 問題を解決する

# コンサルタントへの感情
日本の組織的には閉鎖的のため、おおむねコンサルタントが入ることを嫌がる。
コンサルが現場入ると、総スカンになるときがある

* 閉鎖的で組織の流動性が少なく記憶が失敗した記憶が強い
* 手八丁口八丁の人もいるので、よく思われていない節もある

海外ではコンサルタントというか知恵、知識を外部から取り入れる（時間を買う）という文化


# コンサルテーションを成功させるには
コンサルタントの人が何かを成し遂げることはなく、クライアントがやる気がなければ、どんなコンサルが入っても失敗する


最初から何か効果を感じさせるのは難しいが最初に導入しておいて契約が終わった時に、そのシステム（知識なども含めて）が利用できなくなる損の感覚があるとコンサルタントが入ったことがよかったことに気付く（最初は実績作り）

# コンサルをするときに気を付けること

コンサルのキャッチコピーは同じなので、どれを選んでいいかわからない
それを体系化しないとわからないので手法などで説明をする。

手段解決型（道具で解決しようとする）で問題がどこにあるかはっきり言ってくる型が多いが、その組織や体制などをよく観察していかを考える

* 問題の再定義をして本質を見抜くこと
* 組織の方向性とあっているか

本当のことをいうと「逆鱗に触れる人」、「納得して同意し協力する人」がいる。

長い計画（コンサル）の場合、小さい成果が見えなくなりやすい。
習慣を変えるなどのコンサルは達成感が難しい（家庭教師型コンサル）

現場に入って問題が何かを考えて、その問題を解決する手法をえらぶが重要

意図がないコンサルはよくない。どういう組織にしたいかなどのビジョンがないといけない


# 質疑応答など

* コンサルが親離れする時期はあるのか

ある問題が解決しても、次の問題がある
ある時期を置いて再度コンサルに入って状況を確認する

* どういう人にコンサルすればいいのか

モチベーションが高い人に対してアプローチをする
低い人を救い上げようと思わない


* 問題を認識してもらう技術

組織が暗黙の目標について観察して、達成できないと嫌なことを考える
そうすると、影（本当の）の目標が見えてくる


# 最後に
コンサルタントの人は、様々な知識が（深く）必要だし、技術だけではなく人間力も必要なんだなと学んだ。
そして観察することも大事で、そういう話を聞いて[「五ゲン主義」](https://www.kaizen-base.com/contents/kall-42423/)が大事なのかなと感じた。

QAという立場で製品品質というか業務改善（製造ラインの改善）をしていく上でのヒントがあったと感じたところであるが、どう説明していこうかとか悩むところである。
arrayOfNullsでgenericsが使用できない

# `arrayOfNulls`でgenericsが使用できない
```kotlin
class Test<T> {
    val arr: Array<T?> = arrayOfNulls<T>(1)
}
```
上のコードは，以下のようなエラーメッセージと共に，コンパイルエラーとなる，
"Cannot use  'T' as reified type parameter. Use a class instead."

エラーメッセージ内にある`reified`とは。

## reifiedとはなにか？
### Type erasure
前提として，javaにおける`type erasure`を知っておく必要がある．
[Type Erasure in Java Explained](https://www.baeldung.com/java-type-erasure)

> Type erasure can be explained as the process of enforcing type constraints only at compile time and discarding the element type information at runtime.
> 
> Type erasureは，コンパイル時に型の制約をもたらし，ランタイム時には，要素の型情報を無くすような処理として説明できる．

リンク先のbaeldungに記載のコードをそのまま引用すると，
コンパイル時、

```java
public static <E> boolean containsElement(E [] elements, E element){
    for (E e : elements){
        if(e.equals(element)){
            return true;
        }
    }
    return false;
}
```
コンパイル後は以下の通り，上記のコードの`E`は，`Object`に変換される．
これにより，コンパイラは、コードの型の安全性を確保し、実行時エラーを防ぐ．

```java
public static  boolean containsElement(Object [] elements, Object element){
    for (Object e : elements){
        if(e.equals(element)){
            return true;
        }
    }
    return false;
}
```

見方を変えると，Type erasureにより，ランタイム時にジェネリクスの型情報は無くなってしまう．
kotlinでは，デフォルトの挙動として，
ジェネリクスの型引数に対する型チェックは許容されていない．
上述したように，ジェネリクスの型は，type erasureにより喪失するためである．

### reified
そこで．`reified`の登場である．
`reified`を使用することで，ランタイム時においても型情報を保持することができる．

これにより，以下のようなコードが書けるようになる．

```kotlin
inline fun <reified T> printIfSameTypeReified(a: Number) {
    if (a is T) {
        println(a)
    }
}

printIfSameTypeReified<Int>(3) // Prints 3, as 3 is Int
printIfSameTypeReified<Int>(4L) // Prints nothing, as 4 is Long
printIfSameTypeReified<Long>(5) // Prints nothing, as 5 is Int
printIfSameTypeReified<Long>(6L) // Prints 6, as 6 is Long
```

ジェネリクスの型`T`の情報を保持できるため，
コンパイラはコード内で型チェックをすることが可能となる．

## back to 'arrayOfNulls'

```kotlin
public fun <reified @PureReifiable T> arrayOfNulls(size: Int): Array<T?>

```

ここで、`arrayOfNulls`の定義を見てみると、
型引数`T`に`relified`が付与されており、一見ジェネリクスが使用できそうに見える。

が、`@PureRefiable`なるアノテーションが付いており、このコメントは以下の通りである。

```kotlin
/**
 * Specifies that the corresponding type parameter is not used for unsafe operations such as casts or 'is' checks
 * That means it's completely safe to use generic types as argument for such parameter.
 */
```

> キャストや`is`チェック等のunsafeな操作に使用されない型引数であることを指定する。
> つまり、引数としてジェネリクス型を完全に安全に使用できることを意味する。

この`@PureRefiable`が付いていることにより、
冒頭のエラーメッセージ
> "Cannot use  'T' as reified type parameter. Use a class instead."

が返ってきている。

## Misc
`@PureReified`なアノテーションが付与されているのは以下の関数

```kotlin
public inline fun <reified @PureReifiable T> emptyArray(): Array<T>
public fun <reified @PureReifiable T> arrayOfNulls(size: Int): Array<T?>
public inline fun <reified @PureReifiable T> arrayOf(vararg elements: T): Array<T>
```
Amazon EBSの種類でNextcloud の occ files:scan の速度を比較してみた

## はじめに
先般、[Nextcloud におけるファイルスキャン速度を比較してみた](https://qiita.com/S_Katz/items/4d599c7b632d95544d65) の記事を書きながら、「そういえば、ストレージの種類でもパフォーマンス変わるんじゃないか？」と思いたち、ざっくり検証してみることにしました。
今回は、Amazon EBS の種類で Nextcloud のファイルスキャンコマンド `occ files:scan` のパフォーマンスがどれほど変化するのかを確認してみました。

## 検証の条件

### Nextcloud サーバー環境
* Nextcloud アプリケーションのバージョン
    * Nextcloud: 17.0.1
* ミドルウェアのバージョン
    * PHP: 7.3
    * MariaDB: 10.4
* サーバー構成: Nextcloud 本体、データベース等を含めた1台のオールインワン。
* サーバー環境: AWS EC2(CentOS7、M5.large)＋EBS(500GB)

### 比較対象の EBS の種類
* EBS 汎用 SSD (gp2)　※IOPS:最大1,500
* EBS マグネティック　※IOPS:最大500
* EBS プロビジョンド IOPS SSD (io1)　※IOPS:最大3,000

※「スループット最適化 HDD (st1)」と「Cold HDD (sc1)」はルートボリュームに設定できないため今回は対象から除外しました。時間があったら環境をそろえるなどして改めて検証してみます。

### 検証ファイル/フォルダ数
* フォルダ数: 41,732
* ファイル数: 313,860
* 合計ファイルサイズ: 3,075 MB

### 検証方法
* テストファイル/フォルダ群を Nextcloud サーバの規定ディレクトリに配備し、 `occ files:scan [アカウント名]` コマンドでファイル/フォルダの同期を行う。
* テストは3回行って、実行平均時間で比較する。

## 検証結果
| |実行時間 (汎用 SSD)|実行時間 (マグネティック)|実行時間 (プロビジョンド IOPS SSD)|
|:-:|:-:|:-:|:-:|
|1|11分44秒|11分34秒|11分20秒|
|2|11分54秒|12分21秒|11分32秒|
|3|11分49秒|11分56秒|11分47秒|
|**平均**|**11分49秒**|**11分57秒**|**11分33秒**|

**※平均値としては、プロビジョンド IOPS SSD ⇒ 汎用 SSD ⇒ マグネティック の順という、まぁ期待通りの結果とはなりましたが、IOPS 性能を考えるとそれほど大きな違いとはなりませんでした。**

## 考察、あとがき
今回は、`occ files:scan` をシングルタスクで実行していることから、処理内容に対して IOPS 性能に余裕があり、大きな差が見えづらかったと考えます。
EBS のメトリック情報を見る限りでは、処理開始から前半は 高い IOPS 値でしたが、後半はそれほど IOPS 値が上がっておらず、ディスクI/Oが少ない小さな処理が続いていたと思われます。ここではおそらくデータベースにフォルダ/ディレクトリ情報をこまごま INSERT し続けているんだと思われます。

次の機会では、`occ files:scan` を多重実行してみて比較をしてみようと思います。

EBS の種類もいろいろあるため選択に迷うこともあるかと思います。とりあえず迷ったらいったん汎用 SSD を選択するのが無難だと思います。
で、性能試験してみて、IOPS が頭打ちになるような傾向となったら、

* SSD の容量を増やして IOPS 性能を上げる
* プロビジョンド IOPS SSD に変更してみる

といった対策になるでしょうか。

マグネティックは、容量単価はルートボリュームにできる種別の中では最安ですが、容量単価のほかに I/O 100万回単位の単価もプラスされますので、開発環境やちょっとした動作検証での用途で使う程度がおすすめですね。
JUnit5のParametrisedTestの@ValueSourceを使う

# 概要

このエントリは、JUnit5で単体テストを書くとき、パラメータを変えたテストを書くのを楽にしてくれる「ParametrisedTest」の「@ValueSource」を使用する方法を書きます。

[Enterprise電卓を作る Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ehw_calculator)の2日目のエントリです。

## 想定読者

- JUnit4には慣れているけれどもまだJUnit5のお便利機能を使っていない方。

# JUnit5のParametrisedTest

JUnit5は、JUnit4を大幅刷新したテストフレームワークです。ばっさり削除された機能もあれば、新たに追加になった機能もあります。

新たに追加になった機能の中に「[Parameterized Tests](https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests)」があります。これは、一つのテストケースの引数に対して、値の種類を様々に変えてパラメータとして渡すことで、簡単にテストが書けるような支援をしてくれるものです。

# 準備

ドキュメントによれば、Parameterized Testsを実行するには、「junit-jupiter-params」のアーティファクトを利用可能になっている必要があります。
このエントリでは、[SpringBoot](https://spring.io/projects/spring-boot)を使っており、テスト用にspring-boot-starter-testを使用していますが、この場合はspring-boot-starter-testを一行書いておくだけでjunit-jupiter-paramsへの依存関係も指定されています。

build.gradleに下記のような指定を入れています。
SpringInitializrを使うと、JUnit3やJunit4で書かれたテストを実行することをサポートする「junit-vintage-engine」は使用しない指定も入れてくれました。

```
dependencies {
	implementation 'org.springframework.boot:spring-boot-starter'
	testImplementation('org.springframework.boot:spring-boot-starter-test') {
		exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
	}
```

# @ValueSourceでテストを書いてみる

JUnitを書くとき、結果の確認には、読みやすさが好きなので「[AssertJ](https://assertj.github.io/doc/)」を使っています。build.gradleに下記の一行を追加しています。

```
	testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.14.0'
```

ValueSourceを使ったテストのソースの例を下記に示します。

```java

    @ParameterizedTest
    @ValueSource(chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'})
    public void push_single_success(char c) {
        DeskCalculator dc = new DeskCalculator();
        dc.pushChar(c);
        assertThat(dc.getCurrentValue()).isEqualTo(new BigDecimal(new String(new char[]{c})));
    }
```


このテストで対象としているDeskCalculatorクラスの「pushChar」メソッドは、下記の機能を持っています。

1. 数値("0-9"と".")を示すcharは入力し、内部バッファに保持する
2. それ以外は無視する
3. 内部の数値バッファはインスタンス内の文字列で保持する。外部から値を問われたときにはBigDecimalで返す。

テスト実行結果は下図のとおりです。10個分テストされていますね。

![コメント 2019-12-11 081737.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65002/25e00eea-88aa-8bef-cb11-214bd6a62d9a.png)


数値が入ることは上記でテストしましたが、2番目の動作を確認するため、次のテストも書きます。

```java
    @ParameterizedTest
    @ValueSource(chars = {'+', '-', '*', '/', 'A', '!', ' '})
    public void push_single_invalid_char_success(char c) {
        DeskCalculator dc = new DeskCalculator();
        dc.pushChar(c);
        assertThat(dc.getCurrentValue()).isEqualTo(BigDecimal.ZERO);
    }
```

上記2つの例で挙げたように、@ValueSourceの部分にパラメータを複数渡してあげることで、複数の値に対するテストが実行されます。

# おわりに

本エントリでは、JUnit5で追加となった「ParametrisedTest」について取り上げました。
ParametrisedTestは、@ValueSourceのほかにも、複数の引数を渡してあげる機能、CSVから値を読み込む機能なども提供されています。

このエントリで使用したコードは、GitHubにタグをつけて格納しています。https://github.com/hrkt/commandline-calculator/releases/tag/0.0.3
ecs-cli composeを使用してFireLensからDatadogへログを送信するYamlの記述方法

# TL;DR

`ecs-cli` コマンドでDocker Compose YamlからTaskDefinitionを生成してデプロイが可能です。
ですが、これを使ってFireLensを具体的にどう記述すればよいのか良い記事を見つけられなかったのでメモしておきます。
[公式のREADME](https://github.com/aws/amazon-ecs-cli)で完全に理解できなかった私のような人向けです。
ついでにDatadogの設定方法も記載しておきます。

## 記述方法

さくっと例を記載します。

```docker-compose.yaml
version: '3'
services:
  app:
    image: nginx
    ports:
      - "80:80"
# 以下がログ関連設定
## log driverにfirelensを指定
    logging:
      driver: awsfirelens
      options:
        Name: datadog
        apiKey: "hogehoge"
        dd_service: "app-service"
        dd_source: "nginx"
        dd_tags: "project:example"
        provider: "ecs"
# FireLens本体
  log_router:
    image: 906394416424.dkr.ecr.ap-northeast-1.amazonaws.com/aws-for-fluent-bit:latest
# FireLens自体のログはCloudWatchLogsへ出力
    logging:
      driver: awslogs
      options:
        awslogs-group: firelens-container
        awslogs-region: ap-northeast-1
        awslogs-stream-prefix: firelens
        awslogs-create-group: "true"
```

FireLensのイメージ取得レジストリはリージョンによって異なるので注意してください。


```ecs_params.yaml
version: 1
task_definition:
:
省略
:
  services:
    app:
      essential: true
# FireLens設定
    log_router:
      essential: true
      firelens_configuration:
        type: fluentbit
        options:
          enable-ecs-log-metadata: "true"
run_params:
:
省略
```

基本はこんな感じで動きます。
fluentbitの設定をS3から直接流し込めたりもします。その場合は `ecs_params.yaml` を下記のようにしてください。

```ecs_params.yaml
version: 1
task_definition:
:
省略
:
  services:
    app:
      essential: true
# FireLens設定
    log_router:
      essential: true
      firelens_configuration:
        type: fluentbit
        options:
          enable-ecs-log-metadata: "true"
# fluentbit設定ファイルをS3に配置して、そのarnを設定
          config-file-type: s3
          config-file-value: arn:aws:s3:::firelens/extra.conf
run_params:
:
省略
```

また、ecs-cliのバージョンが `1.15.1` の時に下記エラーが出ました。

```
When awsfirelens log driver is specified in log configuration, a firelens configuration object must be configured in one of the containers.
```

その場合はecs-cliのバージョンを上げてください。
少なくとも `1.17.0` では発生しなくなってます。

それでは良いECSライフを。
Railsチュートリアル 第12章 パスワードの再設定 - 前提

# 何をしていくか

「パスワードを忘れた」というユーザーのために、「パスワードの再設定」という操作ができるようにします。

## 「パスワードの再設定」とは

パスワードをダイジェストとしてRDBに保存している場合、ハッシュ関数の性質上、パスワードそのものを通知することはできません。そのため、「再設定」という操作が必要になります。大まかな手順は以下です。

1. パスワードを再設定するユーザーは、新たなパスワードをフォームに入力し、アプリケーションに送信する
2. アプリケーションは、1.で設定されたパスワードを元に新たにハッシュ値を生成する
3. 2.で生成したハッシュ値を、当該ユーザーの新たなパスワードダイジェストとしてRDBに保存する

## ユーザーの真正性を確認する方法

「第11章 アカウントの有効化」と同様の手順となります。

1. ユーザーは、パスワード再設定用リンクを受け取るためのメールアドレスをアプリケーションに送信する
2. アプリケーションは、パスワード再設定用のトークンとダイジェストの組を生成する
3. アプリケーションは、2.で生成されたパスワード再設定用ダイジェストをRDBに保存する
4. アプリケーションは、2.で生成されたパスワード再設定用トークンを含むURLを生成する
5. アプリケーションは、4.で生成されたURLを含むメールを作成し、1.で指定されたメールアドレスに送信する
6. ユーザーは、5.で送信されたメールに記載されたURLをクリックする
7. アプリケーションは、6.でクリックされたURL（トークン）と2.でRDBに保存されたダイジェストを比較し、ユーザーの真正性を確認する
8. アプリケーションは、ユーザーにパスワード再設定用フォームを返す

# 「第11章 アカウントの有効化」との類似点と相違点

## 類似点

今回実装する「パスワードの再設定」と、第11章で実装した「ユーザーの有効化」には、以下のような類似点があります。

* トークンとダイジェストの組を生成する
* トークンを含むURLを生成する
* ユーザーの登録メールアドレスにメールを送信する
* トークンを含むURLへの`GET`リクエストをトリガーとして認証を行う

## 相違点

一方で、以下のような相違点もあります。

* パスワードの再設定を実装する際には、既存のビューの変更を伴う
* ビューを2つ新たに実装する必要がある
    * パスワード再設定用メールを受け取るメールアドレスの入力フォーム
    * 再設定するパスワードそのものの入力フォーム

# モックアップ

上述「相違点」でビュー3つが登場しました。Railsチュートリアル本文においては、当該ビューのレイアウトについて、以下のモックアップが提示されています。

* [図 12.1 - 「forgot password」リンクのモックアップ](https://railstutorial.jp/chapters/password_reset?version=5.1#fig-login_forgot_password_mockup)
* [図 12.2 - 「forgot password」フォームのモックアップ](https://railstutorial.jp/chapters/password_reset?version=5.1#fig-forgot_password_form_mockup)
* [図 12.3 - パスワード再設定用フォームのモックアップ](https://railstutorial.jp/chapters/password_reset?version=5.1#fig-reset_password_form_mockup)
cron 実行時の環境変数の値を調べる

## cron 実行時の環境変数の値を調べる方法
- /usr/bin/env コマンドの結果をファイルに出力するよう crontab に設定する

## 現在の crontab をバックアップする

心配なら以下のコマンドなどでバックアップしておく。

```
$ crontab -l > ~/crontab.bak
```

## crontab に設定する内容を用意

例えば以下の場合は毎日23時59分に実行される設定で、env コマンドの実行結果をホームディレクトリの env.txt ファイルに出力するようになっている。

今回はこの内容を ~/crontab.txt ファイルに保存しておく。

```crontab.txt
59   23   1-31   1-12   0-6   /usr/bin/env > ~/env.txt
```

## crontab に設定する

以下のように crontab.txt ファイルの内容で crontab の設定を上書きする。

```
$ crontab ~/crontab.txt
```

crontab に設定されていることを確認する。

```
$ crontab -l
59   23   1-31   1-12   0-6   /usr/bin/env > ~/env.txt
```

## crontab が実行されるのを待つ

待つ。

## 結果を確認する

~/env.txt の内容を確認する。

例として以下の環境での確認結果を載せておく (アカウント名が alice の場合で、一部の値を改変したもの)。

### Debian GNU/Linux 9 (stretch) 

```
$ cat ~/env.txt
HOME=/home/alice
LOGNAME=alice
PATH=/usr/bin:/bin
LANG=ja_JP.UTF-8
SHELL=/bin/sh
PWD=/home/alice
```

### CORESERVER (GMOデジロック社のレンタルサーバ)

```
$ cat ~/env.txt
XDG_SESSION_ID=1707777
SHELL=/bin/sh
USER=alice
PATH=/usr/bin:/bin
PWD=/virtual/alice
SHLVL=1
HOME=/virtual/alice
LOGNAME=alice
XDG_RUNTIME_DIR=/run/user/10077
_=/usr/bin/env
```

### macOS Catalina 10.15

```
$ cat ~/env.txt
SHELL=/bin/sh
USER=alice
PATH=/usr/bin:/bin
PWD=/Users/alice
SHLVL=1
HOME=/Users/alice
LOGNAME=alice
_=/usr/bin/env
```

## crontab の設定を元に戻しておく

必要に応じて設定を戻す。

```
$ crontab ~/crontab.bak
```

## 参考資料
- [Man page of ENV](https://linuxjm.osdn.jp/html/GNU_coreutils/man1/env.1.html)
- [crontab \- Wikipedia](https://ja.wikipedia.org/wiki/Crontab)
Qiitaに投稿しようとすると「エラーにより投稿できませんでした。baseに投稿禁止の内容が含まれています。」とダイアログが表示されて失敗する

10月くらいから記事が投稿出来なくなった既存の記事の編集にも失敗する10月時点では［投稿する］をクリックしても無反応だったのが最近では「エラーにより投稿できませんでした。baseに投稿禁止の内容が含まれています。」とダイアログが表示されて失敗するようになった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/a60482cb-27cb-0fd9-31a5-cdc93de53151.png)

色々調べても全く何も分からなかったので[リクエストを送信]から

https://support.qiita.com/hc/ja/requests/new

以下内容で問い合わせをしてみたら

```
20_percent_coolerと申します(以下が自分のページです)

https://qiita.com/20_percent_cooler

10月から記事を投稿しようと[投稿する]をクリックしても投稿に失敗するようになりました
10月時点では無反応で何も返ってこなかったのですが今試すと
「エラーにより投稿できませんでした。baseに投稿禁止の内容が含まれています。」と
ダイアログが表示されて失敗しています
お手数ですがご確認頂けませんでしょうか
```

20分後くらいにサポートの方から「メールアドレスが@protonmail.comなのが原因だと思われるので他のドメインのメールアドレスに変えてみて」といった内容の回答があり試したら解消してこの記事も投稿出来ているはず
ServiceNowでString Typeの文字列長を調べる

Version: Newyork

# 適当に確認
ServiceNowでString Typeで文字列長40のColumnに値を入れます
![FireShot Capture 035 - bbb - Table - - ぽんぽこシステム - .service-now.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/4f09f66c-eab0-072d-50e4-011f63b56226.png)

ServiceNowで文字列長が40の場合40byteではなく40文字として扱われるようです全角は40文字まで入りました半角41文字は入りませんでしたまたUTF-8で4byte必要な文字は扱えないのか文字化けしました
![FireShot Capture 036 - bbbs - ぽんぽこシステム - .service-now.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/de309611-bc81-58ee-9faf-e3a2a20708a8.png)

4byte必要な絵文字も化けました
![FireShot Capture 037 - bbbs - ぽんぽこシステム - .service-now.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/182b0ff7-5b57-7e16-9800-76946a6fb8cd.png)

ServiceNowの文字コードはdefaultでutf-8だったと思いますDiagnostics Pageで確認するとDBはMaria5.6.21のようです

> Database overview
> Type mysql
> Version 5.6.21-MariaDB-log
> Driver mariadb-jdbc
> JDBC 1.1

因みにString Typeの最大文字列長は試したところMySQLのLONGTEXTの最大長(4,294,967,295)の半分の2,147,483,647文字の様です(2,147,483,648に変更しようとするとエラーが出ます)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/5a4c8405-5b13-1458-d86a-d2ca5ef69e48.png)

# Stringで256以上のmax lengthだとDB的にmediumtext型になるらしくて16,777,215 bytesまで入るらしい
あとすっごいびっくりしたのですがStringで256以上のmax lengthだとDB的にmediumtext型になるらしくて16,777,215 bytesまで入るらしいとIncidentのDescriotionとか4,000なので16,777,215 bytes入るはず

[Fields in ServiceNow accept string inputs greater than the sys_dictionary max_length value - Support and Troubleshooting]
https://hi.service-now.com/kb_view.do?sysparm_article=KB0685779

```
Fields in ServiceNow accept string inputs greater than the sys_dictionary max_length value.
 
This is expected behavior of the product.
 
When you create a string field in ServiceNow, the underlying column in database is created with a default data type based in part on the specified max_length value.
 
Small (40) = varchar(40)
Medium (100) = varchar(100)
Large (1000) = mediumtext
Extra Large (4000) = mediumtext
 
Any string field that is larger than varchar(255) is given the mediumtext data type. In the client, it will be represented as HTML textarea, instead of an HTML input. The maximum length of mediumtext is 16,777,215 bytes.
```

# ServiceNowでLength 40の項目に41文字以上の値でInsertするとエラーも出ずに40文字で切れて挿入される

最初この仕様にびっくりしました このSQLモードが指定されていないんだろうなと想像しています

https://dev.mysql.com/doc/refman/8.0/ja/sql-mode.html
> STRICT_TRANS_TABLES
> 
> 値を指定したとおりにトランザクションテーブルに挿入できない場合、ステートメントを中止します。 非トランザクションテーブルの場合、値が単一行ステートメントで発生するか、複数行ステートメントの先頭行で発生した場合、ステートメントを中止します。 詳細については、このセクションのあとの方で説明します。
ぼくのかんがえたさいきょうのアーキテクチャ ~ DDD on TEA ~ （概要編）

※この記事はポエムです。  -- テンプレ

## 3行前提

- Elm でコンポーネント化はページ単位がよき。他はなるべく分割すな（公式見解の曲解）
- でも分割しないと名前空間とか検索性とかがつらみ
- なんかいい方法ないの？

## 3行まとめ

- とりあえずオニオンアーキテクチャ
- View の名前空間も Msg で管理する（斬新）
- View は Model、Update、Msg とモジュールを分ける

**結局全てはトレードオフ**だから多少シンプルさを犠牲にしても、いい感じに関心を分離して保守性が上がらないか試行錯誤した結果、3行で「それ大丈夫？」ってなりそうな何かに辿り着きました←

最強と銘打ちましたが、これはコロンブスがそう思い込んでいたように、反対側のどこかに上陸しただけで、僕にとってのインドではないような気もします。

マサカリを貰うために投稿するみたいなものなので、ぜひ皆様のご意見をいただけらた嬉しいです。（ここまで保険）

## オニオンアーキテクチャとは

オニオンアーキテクチャについてはこちらの記事が好きです。

[[DDD]ドメイン駆動 + オニオンアーキテクチャ概略](https://qiita.com/little_hand_s/items/2040fba15d90b93fc124)

こちらがフラットにオニオンアーキテクチャを表した図と、クラスの例です。
（クラス ≒ Elmのモジュール）

> ![フラットにオニオンアーキテクチャを表した図](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F30489%2F817fe669-7e30-6e8c-e48a-f4098b05d94e.png?ixlib=rb-1.2.2&auto=compress%2Cformat&gif-q=60&s=e8f131a64de2719f87339afdd363a919 )
> DomainModel、Applicationが常に独立した形で書け、その単位で品質保証をすることができる
> （[DDD]ドメイン駆動 + オニオンアーキテクチャ概略 より引用）

この様に依存関係を整理すると、ドメインロジックとシステムロジックが分離できる他、その周りの色々もよしなに関心を分離できるよー。というのがオニオンアーキテクチャもしくは DDD です。（雑）

詳しくは上記記事とその関連記事などをご覧ください。

## Elm のコンポーネントとは

そもそも Elm でコンポーネント化って何よって方は、こちらの記事をまず読まれることをオススメ致します。

[Elm のコンポーネント論争とは何か](http://jinjor-labo.hatenablog.com/entry/2017/05/12/183154)

こちらも僭越ながら3行でまとめさせていただくと、以下の通りです。

- Elmでコンポーネント化は悪手（確信）
- ただ、うまくやっている例はある（[elm-mdc](https://github.com/aforemny/elm-mdc)）
- でも結局YAGNIの原則。コンポーネントは作らず**Viewの関数**で済まそう（結論）

確かになぁ...。

でもそうは言っても、オニオンアーキテクチャとかもあるしよしなに出来ないのかなぁ...？

と思ってしまったのが全ての始まりです。

下手に悩まず、[Elmガイド（日本語版）](https://guide.elm-lang.jp/)の通り実直に実装するのが吉なのは既知でしょうが、クソザコナメクジの僕は探求したい欲求を抑えられませんでした。


## 僕が辿り着いたもの

とりあえず適当に書いた謎の何かしらをどうぞ。

一応、UIとかAppとかの黒い枠でレイヤーを、赤い四角で Elm のモジュールを、線で依存関係をそれぞれ表しています。

上のモジュールが下のモジュールに依存しています。

ここではオニオンアーキテクチャを表した図と同じように、タスク管理アプリを例に書いてみました。

<img width="686" alt="ddd_on_tea.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174939/e17cdaea-f90a-2972-0cc1-7899ae6e198f.png">

ポイントは以下の通りです。

- App層 では Msg の代わりに Usecase を定義
- アプリケーション固有のロジック（App層）と、ドメインのロジック（Domain層）を分離
- UIの概要（UI.Page.xxx）と具体的なHtmlの実装（UI.Widget.xxx）を分離

## 力尽きました。

お疲れ様です。力尽きました。ごめんなさい。

何もわからないクソ記事になってしまいましたが、何かしら読み解いていただいた猛者がいらっしゃいましたら、ぜひコメントいただけるとモチベーションが上がります。

まとめの下記三点、おそらくそれぞれで１記事書けるくらい語りたいです。

**とりあえずオニオンアーキテクチャ**
→ 関数型言語であるElmに適用するために変えてる部分とその理由とか

**View の名前空間も Msg で管理する**
→ よく考えたら、それぞれのUIパーツって何かしらのユースケースに紐づいてるよな...
　（ロバストネス分析）
→ ユースケース ≒ Msg だから...とか

**View は Model、Update、Msg とモジュールを分ける**
→ View が依存する Widget が Msg（ ≒ ユースケース）に依存しちゃうから...とか

あとはここら辺も説明したいです。

- なぜ Widget?
- App層 が Infra層 に依存してるけどいいの？
- Widget が依存しているであろうあれこれはどう引き回しているの？

とか。

## おわりに

[Elm Advent Calendar 2019](https://qiita.com/advent-calendar/2019/elm)に皆様良質な記事をご投稿いただいている中、こんな適当な記事で大変申し訳ない気持ちでいっぱいです。

改めて自分がザコであることを認識しました😫😫😫

[Elm2 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/elm2) がガラ空きなので、そちらで解説編を書かせていただきます。（願望）

暖かく見守っていただけたら幸いです。🙇‍♂️
エンジニアチーム内で相互理解を深めるためにジョハリの窓をやってみた

この投稿は、[品川アドベントカレンダー2019](https://qiita.com/advent-calendar/2019/shinagawa)１１日目です。

# はじめに
最近ジョハリの窓を実施する機会があったのですが、意外とジョハリの窓の認知度が低いことが分かったのでこの場を借りて紹介したいと思います。
また、ジョハリの窓をやってみた感想も書きます。

## なぜジョハリの窓を実施したのか
所属している開発チームで、コミュニケーション不良によりチーム内の雰囲気が悪くなるという問題が時々発生している。
そこで、チームメンバー同士での円滑なコミュニケーションを実現するにあたってジョハリの窓が有効なのではないかと考え、実施しました。[^1]

# ジョハリの窓の紹介
## ジョハリの窓とは
> 自分が知っている「自分の特徴」、他人が知っている「自分の特徴」の一致・不一致を『窓のように見える４つの枠』に分類することで自己理解のズレに気づく、心理学ではよく使われているフレームワーク（手法）です。また、そのズレを一致させていくことで他人とのコミュニケーションを円滑にできると考えられています。
*（引用元: [ジョハリの窓で自己分析｜ポテクト](https://potect-a.com/utilization/johari_window/)）*

ジョハリの窓では、自己を以下の図のような４つの窓に分類します。
<img width="273" alt="スクリーンショット 2019-12-10 23.59.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541299/9c4ff161-8660-d921-fbf6-68d44ab75e0e.png">
「開放の窓」を広げることで自己開示が行われ、コミュニケーションが円滑になると考えられています。

ジョハリの窓は結果的に自己理解を深めることができるため、自己分析ツールとして就職活動や社員教育で取り扱われているのを見かけることもあります。

## ジョハリの窓の実施方法
ジョハリの窓のやり方については以下２つの記事がとても分かりやすかったので、ジョハリの窓を実施する際には参考にしてみてください。

　[ジョハリの窓で自己分析 ～概要、やり方、項目例、シート、アプリ、研修活用～](https://potect-a.com/utilization/johari_window/)

　[【心理学】ジョハリの窓とは？ ビジネス研修でのワークの手法など基本を解説！](https://www.kaonavi.jp/dictionary/johari/)

私が今回どのように実施したのかについては[後述します](#実施方法)。

# ジョハリの窓やってみた
## 実施方法
### 用意したもの
- 4つの窓が書かれたシート（1人1枚）
- 今回使用する[資質項目](#今回使用した資質項目)
- 白紙の紙（例えば、6人で実施する場合は1人6枚用意する）

### 手順
1. ジョハリの窓とは何かを参加者(6名)[^2]に説明
2. [資質項目](#今回使用した資質項目)から**自身**に当てはまるものを複数選択し、白紙へ記入
3. [資質項目](#今回使用した資質項目)から**相手**に当てはまるものを複数選択し、白紙へ記入（全員分の記入が終わるまで、これを繰り返す）
4. 3の手順で記入した紙を相手に渡す
5. 4の手順で受け取った紙に書かれている内容を元にして、4つの窓が書かれたシートを完成させる
6. 完成したシートを参加者全員で回し読みする
7. ~~ディスカッション~~[^3]

### 今回使用した資質項目
> 性格の要素19のポイント
①頭が良い
②発想力がある
③段取り力がある
④向上心がある
⑤行動力がある
⑥表現が豊か
⑦話し上手
⑧聞き上手
⑨親切
⑩リーダー資質がある
⑪空気が読める
⑫情報通
⑬根性がある
⑭責任感がある
⑮プライドが高い
⑯自信家
⑰頑固
⑱真面目
⑲慎重
*（引用元: [ジョハリの窓で自己分析｜ポテクト](https://potect-a.com/utilization/johari_window/)）*

## ジョハリの窓をやってみての感想
思っていたより参加者からのジョハリの窓へのウケは良かった。（面白かったという声がそこそこあった）
目的としていた円滑なコミュニケーションの実現にはまだ至っていないが、まずは今回完成した4つの窓が書かれたシートを元にチーム内での相互理解を深めていきたい。

## もしもう一度ジョハリの窓をやるなら
- ジョハリの窓を行う前にモチベーション曲線[^4]を利用した自己分析を行い、参加者同士でディスカッションする
- 資質項目の見直し（ストレングスファインダー[^5]の「34の資質」を使ってみたい）
- チーム内での資質の偏り分析

# おわりに
私自身ジョハリの窓についてしっかりと学んだわけではありませんが、この記事で少しでもジョハリの窓に興味を持ってもらえたら幸いです。

[^1]: とあるコミュニティで「チームビルディングでエニアグラムを使用した」という話を聞いたことが、ジョハリの窓をやってみようと思った発端。<br>エニアグラムとは何か知りたい方は[こちら](https://www.kaonavi.jp/dictionary/enneagram/)
[^2]: 人数は4〜8名程度推奨（私見）
[^3]: 時間切れのため、開放の窓を広げるためのディスカッションを行うことができなかった。
[^4]: [モチベーション曲線とは](https://shukatsusoken.com/self-analysis/motivation-curve/)
[^5]: [ストレングスファインダーとは](https://heart-lab.jp/strengthsfinder/)
【Unity】SerializeFieldの警告を削除する。

## 問題
以下のコードでは、値が初期化されていない旨の警告が発生する。

```csharp
    [SerializeField] private CardController cardPrefub;
```

> warning CS0649: フィールド 'GameManager.cardPrefub' は割り当てられません。常に既定値 null を使用します。

## 解決
```csharp
    [SerializeField] private CardController cardPrefub = default;
```
・default値を設定する。
・default値とは初期値を設定しなかった場合に割り振られる値。
　int なら 0, float なら0.0, objectなら null

大量の警告を一括解消する。(初期値が設定されていないものを対象。)
置換前 : (?=^[^=]+$)\[SerializeField\](.+)
置換後 :  \[SerializeField\]\1 = default;

# 参考サイト
[[SerializeField] 属性をつけていると、CS0649警告が出るようになった。消したい。](https://qiita.com/chocho/items/1633f56e57c4291f47cf)
React Native: コンポーネントで遷移したい

React Nativeで画面遷移するときは、`navigation`を使います
別の画面に遷移したいときは、画面のpropsに`{ navigation }`を渡して、`navigation.navigate('AnotherScreen')`のようにして遷移させます

が、これができるのは`screens`配下にある画面だけで、コンポーネントではできません

コンポーネントの中から画面遷移を呼び出したいときは、`react-native`の`withNavigation`関数を使います

### 手順

1. import する
2. export するときに `withNavigation` を使う

### サンプル

```react

import * as React from 'react';
import { View, TouchableOpacity } from 'react-native';
import { withNavigation } from 'react-navigation'; // ここ大事

const MyComponent = ({ navigation }) => {
  return (
    <View>
      <TouchableOpacity onPress={() => { navigation.navigate('MyScreen') }}>
         <Text>遷移するよ</Text>
      </TouchableOpacity>
    </View>
  )
}

export default withNavigation(MyComponent); // ここ大事
```

### 参考

https://reactnavigation.org/docs/en/connecting-navigation-prop.html
ConoHaで脳波解析をしてみるよ！

#はじめに
この記事は「[ConoHa Advent Calendar 2019](https://qiita.com/advent-calendar/2019/conoha)」の第10日目の記事です．急に10日目が空きになっていたので，今年も参加してみました．このConoHa Advent Calendarに参加されている皆さんは，もうさまざまな分野のスペシャリストで，いろんなことに取り組まれているので，実用的なネタは紹介しません．なので，ちょっと変わった使い方として，今回は，ConoHaを使って，生体信号の１つである脳波解析を簡単ですがしてみようと思います．

#脳波とは？
そもそも脳波ってご存じですか？　そうです，病院とかで検査されるやつですね．もしかしたら，お子さんがいらっしゃる方は，お子さんの検診で，脳波検査されたかもしれません．あれ，耳が聞こえているかチェックしているんですよ？（たぶん...）　赤ちゃんだと「聞こえてるよ！」って言ってくれないので...汗　ASSR(auditory steady-state response)とかで調べていただけると詳細がわかると思います．

定義的には，ヒトの脳波としては，脳の電気的活動（ニューロンの活動）を電極等を用いて計測したもののことです．ニューロンの活動で生じる電気活動を計測しています．なので，活動の副産物を計測しています．基本的には，頭皮に電極を設置して測定すればOKなのですが，そのままだと測定できないので，耳たぶや耳の後ろあたりに基準電極を設置して，頭皮に置いた電極と基準電極の電位差を測定します．それが，脳波として現れます．

ちょっと前までは，脳波計って最低数百万円したのですが，今では，EmotivとかOpenBCI（あえてリンクは貼りません笑）とか安価な脳波計も登場していて，個人のお金でも買うことができるようになってきました．お手軽ですね！　少し前のニコニコ超会議で，脳波ネコミミとかありました！　私は，これでも女性なので一応購入しましたが，着けるのは恥ずかしいですね笑

今回は，OpenBCIで脳波を計測したので，それをConoHaで解析して簡単に結果をお見せしようと思います．

使った脳波計の写真を載せておきます．ちょっと自作感あふれていますが笑

![IMG_20191209_181548.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311851/4b3f120d-71b0-9d9d-a152-6d0b1118787d.jpeg)

いくつかケーブルが刺さっているのは，基準電極用のケーブル2本と測定する電極の1本です．他にも刺さっていますが，それは画面表示したタイミングを記録するための機器のケーブルです．

#解析

では，実際に解析してみましょう．プログラムとかは公開しませんが，アルゴリズム程度は書こうと思います．

まず，ConoHaにログインします！

![001.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311851/1719e1e2-b567-1427-c48c-d368dfcb5d69.png)

実はけっこう古参のユーザー（だと思っている）なので，このコントロール画面でサーバーを立てて使っています．新しいのバージョンに移行する予定は今のところないです笑　このこのはちゃん「清楚・かわいい！」ぞ！

契約しているのは，メモリー2GBプランです．それで脳波が解析できるのかというと，なんとかなります．解析は，主にPythonをつかってやります．普段はWindowsを使っているのですが，相性が悪いのか設定が悪いのかで，Pythonがまともに機能しないので，ConoHaにLinuxサーバーを立てて使っています．そのほうが楽なので．

行った実験は，オドボール課題と呼ばれているやつで，高頻度の視覚刺激の中に，高頻度の視覚刺激と異なった低頻度の視覚刺激をランダムに順番に呈示して，低頻度の視覚刺激の数を数えてもらうものを実施しました．今回，高頻度刺激は，〇図形を，低頻度刺激は△図形として，△図形の数を数えてもらいました．そして，その最中の脳波を計測しました．**実験が上手くいくと，P300という特徴的な脳波が見られます．**

解析は，次の順で行いました．

１．△図形が呈示されたときの脳波を集めてくる（-200ms ～ 800ms の1秒間のデータを約20個）
２．バンドパスフィルタでノイズ除去を行う（電源ノイズ（50Hz or 60Hz）とかを除去）
３．きれいになったデータを足し合わせて平均化（専門用語：加算平均）

で完成です．これらはPythonで実装しています．

#結果

解析結果の画像を貼っておきます．

![1575928379420.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311851/258ee57e-81db-bc4b-188a-6fd0c70158b8.jpeg)

ちょっとノイズが入っているのですが，綺麗に出ました．縦軸は[μV]，横軸はデータ数を表しています．サンプリングレートを250Hzで計測したので，50データ数が，0.2秒になります．グラフの50データ数のところが，0秒（視覚刺激呈示のタイミング）になります．

150データ数の少し手前に大きな振幅が見られますが，これがP300です．きれいに特徴的な脳波が検出できました．そして，ConoHaでの解析も無事成功しています．計算に少し時間がかかりました...汗

#まとめ

かなり説明を飛ばしてしまいましたが，いかがだったでしょうか？　ConoHaのちょっと変わった使い方を紹介しました．脳波解析とかは，データ数によっては時間がかかることも多いので，低価格でサービスを利用できるConoHaはとてもお勧めです．自宅だとPCを何十時間もつけっぱなしとかちょっと怖いので...（燃えたらどうしようとか...）　なので，いつも重宝しています！　このはちゃん清楚・かわいいしね！（2回目！）

最近は，生体信号をAIに入力して解析・利用する例も増えてきていて，それを計測するツールも手軽に手に入るようになってきたので，ぜひ，1度やってみてはどうでしょうか？
UnityでglTFローダを作ってみたはなし

# はじめに
この記事は、[ドワンゴ Advent Calendar 2019](https://qiita.com/advent-calendar/2019/dwango)の11日目の記事です。

ドワンゴではniconicoの課金システムの開発をしています。
課金関係のことに触れられればよかったのですが、普段は趣味でUnity+C#を触っているため、
今回はそちらに関する記事です。
シンプルなglTFローダの作り方などを解説している記事はありますが、複雑なモデル描画まで行っている記事が見当たらず、
かなり苦戦したため書き残しておきます。ようは備忘録です。
Qiita記事はドワンゴに来る前に非公開記事として共有することにしか使ってなかったため、他記事に比べ読みづらいと思いますが生暖かい目で見守ってください。
# 何故やろうとしたか
VR向けアバターフォーマットであるVRMはglTFをベースとしているため、glTF自体に興味はあったが
触る機会がなく、ふわっとしか理解していなかったので、リファレンスを参考に自分で作ってみようと思いました。
(VRMのロード時間最適化したいといったのもありますが)。
# 実際にやったこと
## GLBの処理
GLBファイルのバイト配列をSpanにし、ヘッダ部分を `Slice` して `MemoryMarshal` でCastすることで構造体として扱いました。
Unityでも、 `System.Memory` をnugetから落としてくれば利用できるためぜひ使ってみてください。

```csharp
var headerSpan = glbSpan.Slice(0, Marshal.SizeOf<Format.GLBHeader>());
var header = MemoryMarshal.Cast<byte, Format.GLBHeader>(headerSpan)[0];
```

チャンクを処理する際も、 `MemoryMarshal` で処理することでほぼ処理速度を気にせず構造体配列として扱えます。
この時、フォーマットの種類である `JSON` or `BIN` の判定を、intとして処理することで1byteずつASCIIで判定することなく行えます(つまり、enumで判定できます)ので、フォーマット部はintで行うことをおすすめします。  

```
JSON: 0x4e4f534a
BIN:  0x004e4942
```

## glTFのJSON部処理
[mebiusbox/gltf(Github)](https://github.com/mebiusbox/gltf) で公開されている以下の画像を参考にパーサを実装しました。

![Quickreference](https://raw.githubusercontent.com/mebiusbox/gltf/master/glTF2_QuickRef_jp.jpg)
最初はglTFのjsonスキーマを読みながら実装をしていたのですが、このクイックリファレンスのおかげでかなり楽に行えました。
## メッシュ処理
メッシュには `Primitive` が配列として格納されているため、それをループで処理します。
`Primitive` = Unityで言うサブメッシュを表します。

先にvertex数分確保が必要ですが、Primitive1個目のPosition数*Primitive数で初期化しました。
ここでは、 `Position` と `Normal` 、 `TexCoord0` をこの基準で格納しています。
`Indices` はPrimitiveの数分のジャグ配列を初期化し、それぞれ格納しています。

実際にUnity上のメッシュにする際は、 `subMeshCount` に `Primitive` の数をセットし、 `SetTriangles` メソッドで `Indices` をセットしました。

```csharp
var umesh = new Mesh
{
	vertices = position,
	normals = normal,
	uv = texcoord0.ToArray(),
	subMeshCount = mesh.Primitives.Count
};

for (var i = 0; i < mesh.Primitives.Count; i++)
	umesh.SetTriangles(indices[i], i);
```

そのまま描画しようとすると座標系の違いにより左右反転して表示されるため、変換を行う必要があります。
ここで変換が必要なのは `Position` と `Normal` です(TangentはVRMの仕様上、含まれないため省いています)
単純にPositionのx座標を反転し、IndicesをVector3として見立てた状態での、X座標とZ座標を入れ替えることで行いました。
# 困ったこと
## 右手系座標を左手系座標へ変換する際のSpan<T>のパフォーマンス
Accessorの値配列を得るために、Span<T>を用いることで高速化しようとしましたが、書き換え時のパフォーマンスがよくありませんでした
(1000ループで約3000ns)
`MemoryMarshal.Cast` で `float` にキャストした後、該当位置に書き込みなども行いましたが、まったくパフォーマンスがよくならず、頭を抱えました。
結果としては、現在のUnityでの `.NET Standard` バージョンが `2.0` であり、ランタイムに最適化が入っていないことによるパフォーマンス低下であり、一度通常の配列として持ち、それをポインタ経由でいじることでパフォーマンスがよくなりました。
そのため、事前に一定のヒープを確保しておき、そこに保持することで高速化することが出来ました。

# まとめ
実際に自分の手でローダを作ってみることで、glTF自体や、Unityの描画周りなどを知ることができました。
車輪の再発明ではありますが、パフォーマンスチューニングを含む様々な知見を得られたため、かなりプラスでした。

まだ全体の実装が出来てないため、出来上がったらコード込みの詳細の記事を出そうと思います。
Power BIでの数値データの扱いの変更（Tableauとの比較）

## はじめに
　Power BIでデータを読み込んだときに行われる、型の自動認識、整数に認識されたフィールドをテキストに変換することについて、Tableauでの典型的な対応と比較しながら説明します。

## サンプルデータの内容

　超シンプルな「データ」というフィールドを持つ、下記のようなテーブルをサンプルデータとします。

| データ |
|--------|
| 1 |
| 2 |
| 3 |
| 2 |
| 1 |
| 1 |

## Tableauでのデータのエリア分け等
　Tableauでは、データの型とは**別**に、**メジャー**（数値等定量的な値）と**ディメンジョン**(名前、日付等定性的な値)の**エリア分け**や、役割として不連続、連続を青、緑の色分けで「ピル（錠剤）」（1つのフィールドがピル型なので俗称）を扱います。そして、メジャーとディメンジョンの入れ替えはドラッグ・アンド・ドロップでできます。（詳細:[ディメンションとメジャー、青と緑](https://help.tableau.com/current/pro/desktop/ja-jp/datafields_typesandroles.htm)）


　メジャーとして認識されたものは、シンプルにバーチャートにすると合計が表示されます。

![コメント 2019-12-11 032444.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/a27ea088-a134-fe2a-af5c-ee463e6824f2.png)

データのピルをディメンジョンに持っていって、、、
![コメント 2019-12-11 044712.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/de1dfb01-2d83-9d9b-0b19-d0f04ac3ca99.jpeg)


レコード数をカウントすると以下のような結果が得られます。

![コメント 2019-12-11 033159.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/503a0aee-31c8-bb0a-46f9-a3a63acfd173.jpeg)


参考までに左上の「#」の部分は、データの型を表しており、「数値（整数）」のままとなっています。ちょっと不思議ですが。

## <追記>Power BIでTableauと同様の扱いを行うには?

　私の本記事の初版に対して、12/11に貴重なコメントをいただきまして、同様の対応方法2点をいただきました。詳述いただいていますので文末のコメント欄をご参照ください。
　データの型そのものを変更して対応する、となりましたら次項を参照ください。

## Power BIでの型の変更は?

　Power BIではこのようなデータのエリア分け等はなく、メジャーは別な意味（[繰り返し利用できる "定義"](https://qiita.com/PowerBIxyz/items/94e171e05ef7beb83897)）なので、Tableauに慣れている人は注意が必要です。

　サンプルデータを読み込んだ時、自動認識で整数の型で認識されていたら、Σのマークが付いているので「数値として認識されて、合計されているんだな」とわかります。

![コメント 2019-12-11 040346.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/88427d14-4b84-178c-99da-d33ef901fc0e.jpeg)



　バーチャートにしてみると合計が表示されます。


　では、データを数値ではなく、テキストの区分のように考えて、その個数をカウントしたい、となった時は、上部の**「クエリを編集」**から、**Power Query エディター**を呼び出して、型の変更を行います。

![コメント 2019-12-11 033650.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/8c2c7481-e9e2-ae33-72bc-973731665d06.jpeg)


　変更しようとするとき、図のようなダイアログが表示されますが、

![コメント 2019-12-11 042736.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/f60f743b-6783-740b-1f9d-41f8e9fabc65.jpeg)


右下の**適用したステップ**について、最後の「変更された型」を上書きして置換するか、新たにステップを追加して変更するか、というもので、結果どちらも同じなので、**どちらでもOK**です。

　変更後に、データの個数をカウントするチャートを表示すると以下のようにうまくいきました。

![コメント 2019-12-11 045847.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/6d1a6505-06f8-3581-9266-232eeb4e1a10.jpeg)


## おわりに
　Tableauに慣れ過ぎると、操作感や用語、機能のあり方の違い等からPower BIに慣れるまで混乱するかしら、と思い書き記しました。参考にしていただけますと幸いです。
pyside:MEventMessageを使ったcallback

*この記事は　Maya Advent Calendar 2019 の14日目の記事になります。*

大変恐縮ですが参加させていただきます。

maya上で状態が遷移した時に何らかの処理を実行したい場合
scriptJobが定番ですが、よりシンプルで軽いOpenMaya.MEventMessageを使用してみます。

今回はpysideGUI上での使用方法について簡単に書いてみました。
選択したノードのタイプを見てラベルの文字を変更してみましょう。

###サンプルコード
meshをもつトランスフォームノードを選択した場合の処理と、異なるタイプが選択された場合の処理、
何も選択されていない場合の処理、それぞれ違うlabel textを表示させます。

```python

import pymel.core as pm
import maya.api.OpenMaya as om

from PySide2 import QtGui, QtWidgets, QtCore
from maya.app.general.mayaMixin import MayaQWidgetBaseMixin

class TestGUI(MayaQWidgetBaseMixin, QtWidgets.QMainWindow):
    windowName = 'testGUI'
    
    def __init__(self, parent=None):
        super(TestGUI, self).__init__(parent)
        if pm.window(self.windowName, q=1, ex=1):
            pm.deleteUI(self.windowName)
        
        #window settings
        self.setObjectName(self.windowName)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        self.setAttribute(QtCore.Qt.WA_AlwaysShowToolTips)
        self.setWindowTitle(self.windowName)
        self.setWindowFlags(QtCore.Qt.Window)

        self.initUI()
        self.setCentralWidget(self.mainWidget)
        self.connectCallback()

    def initUI(self):
        #UI初期設定
        self.mainWidget = QtWidgets.QWidget()
        main_vBoxLayout = QtWidgets.QVBoxLayout()
        self.mainWidget.setLayout(main_vBoxLayout)

        self.main_lbl = QtWidgets.QLabel('Select Mesh.')
        main_vBoxLayout.addWidget(self.main_lbl, alignment=QtCore.Qt.AlignCenter)     

    def closeEvent(self, event):
        #ウィンドウを閉じる際にcallbackを破棄
        om.MMessage.removeCallback(self.callback)

    def connectCallback(self):
        #callback作成
        self.callback = om.MEventMessage.addEventCallback('SelectionChanged', self.changeLabel)

    def changeLabel(self, *args, **kwargs):
        #選択したノードのタイプを判別してテキストを変更
        try:
            node = pm.selected()[0]
            if pm.nodeType(node.getShape()) == 'mesh':
                self.main_lbl.setText('Ready.')
                
            elif not pm.nodeType(node.getShape()) == 'mesh':
                self.main_lbl.setText('Must select mesh.')
            
            else:
                self.main_lbl.setText('Select Mesh.')
                
        except:
            node = None
            self.main_lbl.setText('Select Mesh.')

if __name__ == '__main__':
    gui = TestGUI()
    gui.show()
```

##実行結果
![ezgif-1-dbdf3615885d.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187969/1015aa49-c8b7-8ff7-4422-ac4617b86a03.gif)


テキストだけでなく様々なwidgetの状態切り替えもできますね。
短い内容でしたがご覧頂きありがとうございました。
【Unity】Grid Layout Groupに追加されたGameObjectをソートする

# Grid Layout Groupに追加されたGameObjectをソート

## 概要
ゲーム中のアイテムリスト、カードリスト等、ScrollViewなどでグリッドレイアウトは頻繁に使用されますが、これはUnity標準のコンポーネントであるGrid Layout Groupで解決することができます。
しかし、そういったリストの大半はソート機能が必要になる場合がほとんどです。
調べた限り、UnityにはのGrid Layout Group上に配置された子GameObjectをソートするような機能は、標準で存在しないようです。
本記事はGrid Layout Groupのソートについて、メモレベルで説明します。

Grid Layout Groupの使い方そのものについては、本記事の下部に記載している参考記事などをご参照下さい。


## 想定
Grid Layout Group(以降Contentと呼ぶ)に対して、以下ように、Prefabを子GameObject(以下セルと呼ぶ)として動的に生成、関連付けている。

```csharp
var childObj = Instantiate(/* セルのPrefab */); // セルを生成
childObj.transform.parent = contentObj.transform; // セルをContent配下に配置
```

この状態から昇順／降順にソートしたい、というシチュエーションを想定しています。

## やりかた
以下に雰囲気コードを示します。

```csharp
var childObjs = /* 何らかの方法でContent内のセル(GameObject)の一覧を取得 */;
var siblingIndexes = childObjs.Select(c => c.transform.GetSiblingIndex()).Reverse().ToArray();
for (var i = 0; i < childObjs.Count; i++) {
    childObjs[i].transform.SetSiblingIndex(siblingIndexes[i]);
}
```

## コード解説

1. セルをSelectし、全SiblingIndexを取得(GetSiblingIndex)します。
2. 前項で取得したSiblingIndexをReverseし、逆順のSiblingIndexを取得します。
3. セルを元の順番で順次参照し、前項のSiblingIndexをセット(SetSiblingIndex)します。

### 補足
ある階層に並列で配置されたオブジェクト、すなわち兄弟(Sibling)間のオブジェクトの表示順序は、Unityにより管理されるSiblingIndexによって決定されています。
このSiblingIndexは、例えばContent以下の兄弟オブジェクトの場合、Unityのエディタ上の見た目そのまま、Hierarchyの表示順に、0から順に振られています。
　
例:Hierarchyがこんな感じとした場合のSiblingIndex

```
...
 └ Content // ScrollViewのContentとか
　 ├ childObjA // 0
　 ├ childObjB // 1
　 ├ childObjC // 2
　 └ childObjD // 3
...
```

Grid Layout Groupの１セルの表示順（Hierarchyの配置順）はSiblingIndexにより決定しています。
ですので、セルのソートを反転したい場合は、現在のSiblingIndexを逆順で取得(GetSiblingIndex)し、
それを現在のセルの配置順に上書き(SetSiblingIndex)していくことでセルの表示順を反転させることができます。

例:すべてのセルのSiblingIndexをReverseしてセットし直した状態のHierarchy

```
...
 └ Content // ScrollViewのContentとか
　 ├ childObjD // 0
　 ├ childObjC // 1
　 ├ childObjB // 2
　 └ childObjA // 3
...
```

### 応用メモ
単純なソートは昇順／降順ソートは上記のように行うことができますが、
たとえば、セルであるGameObjectにスクリプトをアタッチし、そこに「種別」などの情報をもたせて、より複雑なソートアルゴリズムを適用できるでしょう。
今回例に示したソースはReverseを使用して単純反転させましたが、特にこれを使用しなければならないという事はありません。



## 参考資料

### Grid Layout Groupの使い方
https://qiita.com/t_Kaku_7/items/588fada25cf2d519589d
https://tech.pjin.jp/blog/2016/08/30/unity_skill_3/

### SiblingIndexについて
https://forum.unity.com/threads/order-of-elements-in-layout-groups.267668/
https://qiita.com/T_2/items/69c22e649441055d2329
perlのビルド/インストール方法

みなさんは、どのversionのperlをお使いだろうか。
perlは毎年、新しいstable versionがリリースされており、2019年12月現在、最新stable versionは5.30.1である。
perlは後方互換性にとても気を使っており、また新しいperlは細かなパフォーマンスチューニング、バグフィックスをたくさん含んでいる。よって、いつでも最新stable versionのperlを使うのがおすすめである。

おそらくOS付随のperlは最新のものではない。よって最新のperlを使おうとしたとき、自分でビルドしインストールする必要がある。
この記事ではperlのビルド/インストール方法について説明する。

## perlのビルド/インストール方法

はじめての方は敬遠しがちかもしれないが、実のところperlをビルドしインストールするのは驚くほど簡単である：

```
(A) $ wget https://www.cpan.org/src/5.0/perl-5.30.1.tar.gz
(B) $ tar xf perl-5.30.1.tar.gz
(C) $ cd perl-5.30.1
(D) $ ./Configure -Dprefix=$HOME/perl -Dscriptdir=$HOME/perl/bin -des -Dman1dir=none -Dman3dir=none -DDEBUGGING=-g
(E) $ make --jobs=8 install
```

これでperl 5.30.1をビルドし、`$HOME/perl`にインストールできる。かかる時間も4分程度である。

以下(A),(D),(E)について説明を加える。

## (A) perlのソースコードを取得

perlのソースコードは https://www.cpan.org/src/ から取得可能である。またこのページでperlの最新versionも確認できる。
なお、perlは `5.(偶数).x` がstable version, `5.(奇数).x` がdeveloper versionとなっている。たとえば、`5.26.3, 5.28.2, 5.30.1`はstable version、`5.27.5, 5.29.1, 5.31.6`はdeveloper versionである。
developer versionはperlのcoreを開発している人でない限り使うべきでない。
よって`5.(偶数).x`のstable versionのうち、もっとも新しいもの選ぶとよいだろう。

## (D) Configureオプション

このConfigureオプションが重要である。ひとつひとつ見ていこう。

### -Dprefix=(インストール場所)

インストールしたい場所に合わせて自由に設定する。なおperlの実行ファイル自体は `(インストール場所)/bin/perl` に配置されることになる。インストール後、環境変数PATHに `(インストール場所)/bin` を追加しておこう。

### -Dscriptdir=(インストール場所)/bin

これはあまりいい挙動だとは思っていないのだが、perlはいくつかのスクリプトを`/usr/local/scirpt`などグローバルなディレクトリにインストールしようとするかもしれない。これを抑止するために、明示的に`-Dscriptdir=(インストール場所)/bin`を指定しておこう。

### -des

本当は、このオプションは`-d`, `-e`, `-s`の3つにわかれる。特に`-d`は、すべての設定値をperlが推奨するデフォルトを使用する、の意味である。これを指定しないと、たくさんの(少なくとも最初は意味不明な)質問に答えないといけなくなる。
ということで`-des`は指定しておこう。

### -Dman1dir=none -Dman3dir=none

perlのドキュメントはpodという形式で書かれており、それは`perldoc`コマンドで参照可能である。よってman形式のドキュメントはほとんどの場合、必要ない。
これらのオプションはman形式のドキュメント作成、インストールを無効化するものである。いつでも指定しておくのがおすすめ。

### -DDEBUGGING=-g

いつかperlにデバッグ情報が入っていてよかったと思う日が来るかもしれない。
その日に備えてこのオプションを指定しておくのがおすすめである。


### -Duseshrplib

apache httpd mod_perlやnginx unitなどperlと動的リンクさせて動くソフトウェアがある。これらで使うperlをビルドしようと思っているなら必須のオプションである。
逆にいうとその予定がないのなら必要ないオプションである。

### -Duseithreads

perlのthread機能を有効にするオプションである。明確にthreadを使うコードがあるというとき以外は必要ない。

# (E) makeオプション

`--jobs`を指定すれば並列でビルドされ時間短縮になる。よって`--jobs=8`などを指定するのがおすすめである。
なお、古いperlは並列でビルドしようとすると失敗することがあるので注意が必要である。具体的には5.20.0未満だと失敗する可能性がある。


## おわりに

perlのビルド/インストール方法を紹介した。
perlをビルドしインストールするのは本当に簡単なので、是非自分でビルドし最新のperlを使うといいと思う。

## 変更履歴

* scriptdirオプションを追加。