OmniAICreator/Qiita-1.07M huggingface dataset:
C#でBuilderパターン(effective java)

## コンストラクタの引数が多い

Studentクラスは名前と誕生日を必須の情報として持っていて、オプションでニックネームがついている。
こんなクラスを使いたいと思いました。

```c#
var taro = new Student("太郎", new DateTime(1990, 1, 1));
var sachiko = new Student("幸子", new DateTime(1990, 1, 1), "さっちゃん");
```

必須２個と任意１個の引数だからまだいいけど、増えてくるととても大変になります。
そして任意のパラメータ分のオーバーロードを書きたくない。



## メソッドチェーンで書きたい

コンストラクタを呼ぶときにパラメータを順次設定するメソッドを呼び出したいですね。

```c#
var taro = Student.Builder.Instance
                .SetName("Taro")
                .SetBirth(new DateTime(1995, 4, 18))
    			.SetNickname("タロ")
                .Build();

var sachiko = Student.Builder.Instance
                .SetName("幸子")
                .Build();  // 誕生日をセットしていないのでコンパイルエラーにしたい
```

SetNameとSetBirthは必須だがSetNicknameは呼ばなくてもbuildしたい。
これは以下のコードで実現できます。

```c#
public class Student
    {
        public string Name { get; }
        public DateTime Birth { get; }
        public string Nickname { get; }

        private Student(Builder builder)
        {
            Name = builder.Name;
            Birth = builder.Birth;
            Nickname = builder.Nickname;
        }

        public interface IHasName
        {
            IHasBirth SetName(string name);
        }

        public interface IHasBirth
        {
            Builder SetBirth(DateTime birth);
        }

        public sealed class Builder : IHasName, IHasBirth
        {
            internal string Name { get; private set; }
            internal DateTime Birth { get; private set; }
            internal string Nickname { get; private set; } = "";
            
            public static IHasName Instance
            {
                get { return new Builder(); }
            }

            private Builder() { }

            public IHasBirth SetName(string name)
            {
                Name = name;
                return this;
            }

            public Builder SetBirth(DateTime birth)
            {
                Birth = birth;
                return this;
            }

            public Builder SetNickname(string nickname)
            {
                Nickname = nickname;
                return this;
            }

            public Student Build()
            {
                return new Student(this);
            }
        }
    }
```

StudentとBuilderクラスのコンストラクタはprivateにしてあるので、Instanceを介さないとインスタンス化できません。
InstanceからはIHasNameが返るのでSetName以外は呼べません。
そしてSetNameからはSetBirthしか呼べません。
SetBirthからはSetNicknameもできるし設定せずにインスタンス化もできます。

そしてStudentインスタンスはreadonlyなフィールドだけを持つので、どこかで変更されることもありません。必要に応じてメソッドを追加していきましょう。

## 参考

[Builderパターン（Effective Java）](https://qiita.com/hatt0519/items/dd349a2d0a835c5c819b)

[なんぞこれ。コンストラクタパラメータが異常に大杉る･･･。バカなの？死ぬの？そういう場合はBuilderパターンを検討してみよう。](http://zecl.hatenablog.com/entry/20091117/p1)
Rustのジェネリクスとトレイトを使ってみる

Rust勉強中。
ジェネリクスとトレイトという概念を学びはしたものの、いまいち使い所が腑に落ちていないので、簡単なサンプルを書いてボトムアップ的に理解してみようという話。

# まずは普通のコード

サンプルとして、2つの数字を受け取って同じ値ならtrueを、そうでなければfalseを返す関数を考えてみる。これはもちろん普通に動く。

```rust
fn is_equal(a: i32, b: i32) -> bool {
    if a == b { 
        true
    } else {
        false
    }   
}

fn main() {
    println!("{}", is_equal(1, 1)); // true
}
```

# ジェネリクスを使ってみる

上記では2つの数字を数値（i32）の型で受け取ったが、文字列（\&str）として受け取っても比較できるようにしたい。数値だろうが文字列だろうが数字は数字じゃないか、という安易な考え方だ。
こういうときにジェネリクスを使うと、とてもスッキリ書くことができる。

```rust
fn is_equal<T: Eq>(a: T, b: T) -> bool {
    if a == b {
        true
    } else {
        false
    }
}

fn main() {
    println!("{}", is_equal(1, 1)); // true
    println!("{}", is_equal("1", "1")); // true
}
```

Eqトレイトを実装している型であれば何でも受け付けますよ、という宣言にすることによって、数値の「1」も文字列の「"1"」も同じ関数で比較できるようになった。Eqトレイトの詳細な定義は公式ドキュメントなどに任せるとして、とりあえずは「同じだったら同じと言えます！」という属性を持っている、くらいに考えればいいのではないだろうか。数値と文字列は、直感的にもそういった属性を持っていそうだ。

[Wikipedia](https://ja.wikipedia.org/wiki/ポリモーフィズム)によると、こういった書き方を「パラメトリックポリモーフィズム」とか、「ジェネリックプログラミング」とか言ったりもするらしい。

# トレイトを使ってみる

ここまでで、数値も文字列も同じ感覚で比較することができた。では、数値と文字列の比較はできないだろうか。

```rust
fn main() {
    println!("{}", is_equal(1, 1)); // true
    println!("{}", is_equal("1", "1")); // true
    println!("{}", is_equal(1, "1")); // ★これも比較したい
}
```

今のis_equalでは、数値も文字列も比較することができるが、それはあくまで「数値としての値」と「文字列としての値」をそれぞれ比較しているに過ぎない。ここでやりたいのは、数値だろうが文字列だろうが、「数字」として比較することだ。どんな型だろうが統一された形式の結果を取り出せる、という独自の属性を数値と文字列に持たせ、それぞれのやり方を定義しよう。ここでは結果をi32に統一する。
トレイトを使うことにより、異なる型に共通の属性を持たせることができる。


```rust
trait Calculatable {
    // 結果を取り出すことができますよ、という属性。
    // この属性を持つには、その属性を持ちたい型がresultという
    // メソッドを実装している必要がある。
    fn result(self) -> i32;
}

impl Calculatable for i32 {
    fn result(self) -> i32 {
        self // 数値はそのまま返す
    }
}

impl Calculatable for &str {
    fn result(self) -> i32 {
        self.parse().unwrap() // 文字列は変換して返す
    }
}

fn is_equal<T: Calculatable, U: Calculatable>(a: T, b: U) -> bool {
    if a.result() == b.result() {
        true
    } else {
        false
    }
}

fn main() {
    println!("{}", is_equal(1, 1)); // true
    println!("{}", is_equal("1", "1")); // true
    println!("{}", is_equal(1, "1")); // true
}
```

これで数値も文字列も「数字」として比較することができるようになった。

最初、関数の宣言は`is_equal<T: Calculatable>(a: T, b: T)`という書き方でもいけるかなと思ったが、これはコンパイルエラーになる。トレイトの条件は同じでも、内部ではちゃんと違う型として渡されているようだ。（しかもそれをコンパイラが見つけられている。）

このような書き方は「アドホックポリモーフィズム」とか言ったりするらしい。

# 注意

ジェネリクスは考え方で、ジェネリクスを「使う」という言い方は正確でないかもしれない。もう少しちゃんと言うと、型パラメータとトレイト境界を設定して関数をジェネリクスにする、とかかなぁ。

トレイトを説明するのに「属性」という言葉を用いたが、「属性」という言葉はRustの他の概念を説明するときに使われたりもするので、トレイトの説明に用いるのはあまりよろしくないかもしれない。あくまでイメージとしてとらえて下さい。

言葉は難しいですね。

# まとめ

ジェネリクスとトレイトを使うことにより、値の型によらない直感的な比較を行う関数を作ることができた。
出来上がったmain関数を見ると、なんだかプログラミングを習いたてのときにやってしまいそうな書き方だと思った。特にCとかを書いていると、どうしても型というものを意識するようになるが、Rustでは型を意識する必要のないインターフェースを作ることができる。もちろんそのような関数の裏側を実装するには型に対する理解が不可欠ではあるのだが、流れを理解しやすいコードを書くという観点では、大きな意味をもつのではないだろうか。
VSCodeでサーバー建ててファイル一式で納品の案

HTML/JSをサーバー動作でスタンドアロン納品したいときにVSCodeでLiveServerして簡易サーバーするメモ
XAMMPとかApache入れるなど結構大変なので。
他にいい方法あるとうれしい

###VSCodeをZip形式でダウンロード
https://code.visualstudio.com/download
![NoName_2020-2-19_10-12-35_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48015/27ee2d61-d64d-e70b-0455-54c0570c91af.png)

###新規環境として認識

dataディレクトリを追加すると新しい環境として認識するので、既存で利用中のVsCodeとい分けて設定が可能

![NoName_2021-5-11_10-20-56_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48015/396973ce-e6eb-3164-2245-87cb2ad11702.png)

###拡張機能をダウンロード
右下の方にダウンロードできるところあり

####Live Server
https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer
![NoName_2020-2-19_17-20-17_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48015/f815a17c-de7d-6e8a-9934-ac6c05ac68dd.png)

####Japanese Language Pack for Visual Studio Code
https://marketplace.visualstudio.com/items?itemName=MS-CEINTL.vscode-language-pack-ja
![NoName_2020-2-19_17-20-37_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48015/66119968-8dbc-90c0-be2f-c8ad65469f15.png)

###VSCodeに拡張機能をインストール

日本語化してLiveサーバーな状態
dataフォルダつくるとPCにインストしたVSCodeの設定を読み込まなくなるので便利でした
![NoName_2020-2-19_17-23-44_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48015/3ff24891-d872-e9f3-1815-70e91eacf583.png)

###参考サイト

Visual Studio CodeをオフラインPCで使用する
https://qiita.com/mekemeke421/items/98d5a3e2f2cc7517a6ab
Tensorflowで指定したインデックスのテンソルを抜き出す

# どういうことをしたいか

行列から各行から異なる列の値を取り出したい（パターンA)

```math
A = (a_{ij}) \in \mathbb{R}^{N\times M} \\
index = b_i \in \{1,\cdots,M\}^N \\
A[index] = a_{ib_i}
```

もしくは逆に各列から異なる行の値を取り出したい（パターンB）

```math
A = (a_{ij}) \in \mathbb{R}^{N\times M} \\
index = b_j \in \{1,\cdots,N\}^M \\
A[index] = a_{b_j j}
```

具体例（パターンA）

```math
A=\left(\begin{matrix}
  1 & 2 & 3 \\
  4 & 5 & 6 \\
  7 & 8 & 9
\end{matrix}\right) \\

index=\left(\begin{matrix} 2 & 1 & 0 \end{matrix}\right) \\

A[index] = \left(\begin{matrix} 3 & 5 & 7 \end{matrix}\right)
```



# TensorFlowでの実装

以下のコードで行列AからIDXで指定された値を抜き出せる。

パターンA用

```python
# A : 行列
# IDX : index (dtype=tf.int32, int32でない場合はキャストが必要になることがある)
_IDX = tf.concat([tf.range(A.shape[0])[:,tf.newaxis], IDX[:,tf.newaxis]], axis=1)
subA = tf.gather_nd(A, _IDX)
```

パターンB用

```python
# A : 行列
# IDX : index
_IDX = tf.concat(IDX[:,tf.newaxis], [tf.range(A.shape[1])[:,tf.newaxis]], axis=1)
subA = tf.gather_nd(A, _IDX)
```

### 簡単な解説

gather_ndは第一引数のテンソルから第二引数で指定された座標の値を抜き出して返す関数。
tf.rangeで生成したテンソルとindexをconcatすることで、抜き出したい座標を生成し、それをgather_ndに渡すことで各行(or 列)からindexで指定された値を抜き出すことを実現している。
[Android] IntentServiceでstopService()は使えない

IntentServiceでstopService()が使えないということを備忘録として残しておく。

##作りたかったもの
ActivityからIntentServiceを通してサーバに通信し、opPause()が呼ばれたら通信キャンセルするプログラム。
ActivityのonPause()は以下のように実装していた。

~~~java
    @Override
    protected void onPause() {
        super.onPause();
        stopService(intent);
    }
~~~

しかし、onPause()を呼んでも通信が最後まで行われた。


##ネット上のサンプル
上記の実装をしたのはネット上に
>
IntentServiceはstopService()かstopSelf()を明示的に呼ばなくてよい。
終了させたいときは呼んでもよい。

と書いてあったからである。（どのサイトだったかは忘れた…）

しかし、公式リファレンスには「呼ばなくてよい」ではなく「呼ぶべきじゃない」と書いてあった…
>
This method is invoked on the worker thread with a request to process. Only one Intent is processed at a time, but the processing happens on a worker thread that runs independently from other application logic. So, if this code takes a long time, it will hold up other requests to the same IntentService, but it will not hold up anything else. When all requests have been handled, the IntentService stops itself, so you should not call stopSelf.
This method may take several seconds to complete, so it should only be called from a worker thread.

https://developer.android.com/reference/android/app/IntentService

（ただしstopSelf()は呼ぶべきじゃないとだけ書いてあり、stopService()についてはわからないが、おそらく同様じゃないかなぁと思っている）




##代替案
onPause()内でboolean型変数をtrueにして、それがtrueの時は異なる処理をすればよい。
注意していただきたいのは、サービスを途中停止できないことである。IntentServiceはonHandleIntent()が呼ばれると、渡されたタスクを全て処理するまで終了しないので、キャンセルする手段が見つからない。（あるかもしれないが、私の知るところではない）

もしどうしてもキャンセルしたかったら、
AsyncTaskを使う、Serviceクラス（フォアグラウンドなので通信はできない）を使うなどが考えられる。

##感想
今回は「**ネットのサンプルを信じすぎた**」ので、「**公式を読む**」ということも心掛けたい。
というかこっちのほうが重要である。
【SORACOM】新発売のGPSマルチユニットを起動しSORACOM Harvestと接続してみた

#目的

あと先着30名に靴下のプレゼントとのことでしたので、届いてさっそくやってみた記事を書きます！（デブサミ2020のSORACOM玉川さんの公演で発表された新製品がとても面白そうでしたので、その場で発注しました）
##開封の儀
![00.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136929/b350b9ac-fe9a-a276-8c50-cbb260d2becf.jpeg)

納品されたものは以下の通りです。
・GPSマルチユニット本体　1台
・SORACOM SIMカード　1枚
・UBS typeBケーブル　1本
・KYOCERAの説明所　1冊（今回は使いませんでした）

##注意
京セラさんのデバイス用説明書がついておりますが、***SORACOMのセットアップでは使いません。***
***USBドライバのインストールも不要です。***
~~紙の説明書を読んでからやる昭和の癖が抜けない。~~

##SIM挿入
ユニットの上部にnanoSIMカードのスロットがあります。
![02_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136929/108a3b47-35d8-86fd-c41a-8f64d6a1e535.jpeg)

![01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136929/ddc3f5b6-aced-a742-7861-98508fdf3e21.jpeg)

向きを気を付けてSIMを挿入します。

##Getting Started with GPS マルチユニット SORACOM Edition
以下、こちらの公式マニュアルに沿ってセットアップします。

[GPS マルチユニット SORACOM Editionを使用して、定期的に位置情報を送信する
](https://dev.soracom.io/jp/start/gps_multiunit_location/#console)

###SMI受け取り確認
Menu＞発注　から注文履歴が確認できますので、「受け取り確認」をクリックするとSIMの受け取り確認が完了します。
###SIM、Group設定
「ステップ 2: GPS マルチユニットのデバイス設定を行う」に従って、GPS マルチユニットをHarvestに連携します。

ここで私は手順書にない、下記のような送信間隔設定を行いました。
通信料金を削減するためですが、期間設定のTOを2019年に設定してしまったため、受信できずに多少手間取りました。
~~ケチって失敗なんてダサい~~
![2020年2月19日キャプチャ設定３_定期設定ミス.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136929/8cfd6ad4-df91-9234-6c8c-eb33e76ea25b.png)

###送信データ確認
Menu＞ガジェット管理＞GPSマルチユニット＞デバイスを選択し「データを確認」をクリック
にて送信されたデータが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136929/4ac2afdd-9e15-3a2d-1d35-9fe589df35a0.png)

これにて起動確認完了です。

#利用料金
こちらに関しては月末に料金請求が着次第Updateしたいと考えております。
データ通信料およびHarvestの利用料金の概算見積は公式QAに記載があります。
[GPS マルチユニット SORACOM Edition　よくある質問](https://dev.soracom.io/jp/gps_multiunit/faqs/)

#今後について
自分の携帯の位置情報と、GPSマルチユニットがどれくらい離れているか確認できるサイトを作ってみようと考えております。

#参考資料
###[GPS マルチユニット SORACOM Editionを使用して、定期的に位置情報を送信する](https://dev.soracom.io/jp/start/gps_multiunit_location/#console)
###[KYOCERA GPSマルチユニット説明書](https://dev.soracom.io/jp/gps_multiunit/what-is-gps_multiunit/)
###[GPS マルチユニット SORACOM Edition　よくある質問](https://dev.soracom.io/jp/gps_multiunit/faqs/)
サイドナビのリンクを開くと、そのナビだけ色が変わる。

# サイドナビの色を変化させる。
サイドナビでナビをクリックすると、ナビの色が変化して、今開いているナビがわかるようにする。


## 処理の作成

```ruby:application_helper.rb

module ApplicationHelper
  def active_class(link_path) # (link_path)にrake routeの_pathを記載する。
    "active" if request.fullpath == link_path
    # もしも開いたページのURL（request.fullpath）が、指定の（link_path）と同じ場合、"active"になる。
  end
end
```

## classを付与させる

```haml:html.haml
%li{class: "#{active_class(users_path)}"}
// application_helper.rbで作成した処理により、activeが付与する。
// 指定したリンク以外では、activeは付与しない。
// この例の場合、users_pathのため、users#showのページを開くとナビの色が変化する
```

これで、完成

## おまけにHTMLとSCSS

```haml:haml

%ul.list-group
  %li{class: "list-group-item #{active_class(user_path)}"}
    = link_to "", user_path, class: "nav-list__link"
    %p マイページ
  %li{class: "list-group-item #{active_class(new_product_path)}"}
    = link_to "", new_product_path, class: "nav-list__link"
    %p コンテンツ
```

```scss:scss
.list-group{
  width: 250px;
  &-item{
    position: relative;
    /* li全体をaタグにする。 */
    a{
      text-decoration: none;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
    }
    &::after{
        /* 矢印 */
        position: absolute;
        top: 40%;
        right: 13px;
        content: '';
        width: 8px;
        height: 8px;
        border-top: 2px solid #ccc;
        border-right: 2px solid #ccc;
        -webkit-transform: rotate( -50%);
        -webkit-transform: rotate( -50%);
        transform: rotate(45deg);
        transition: all .2s;
      }
      &:hover{
        background: #fafafa;
        &::after{
          right: 9px;
          border-color: #333;
        }
      }
    /* 今開いているページのナビは、色を変化 */
    &.active{
      background: #EEEEEE;
      font-weight: bold;
      border-color: #3333;
      color: #212529;
      &::after{
        border-top: 2px solid #333333;
        border-right: 2px solid #333333;
      }
      .nav-list{
        &__link{
          text-decoration: none;
          font-weight: bold;
          color: #333333;
          font-size: 14px;
        }
      }
      &:hover{
        background: #EEEEEE;
      }
    }
  }
}
```
ローカルで動作するチャットボットの構築（その①：ローカル接続テスト）

# シリーズ概要
Microsoft Bot Framework を使用することでTeams、Slack、Lineなどのチャットアプリに簡単に接続することができます。今回はローカルPCで起動しているチャットボットアプリケーションをTeams上で使用する方法をご紹介します。
（注）この記事ではBot Frameworkを使用したチャットボット開発そのものは対象外です。

---

# 本記事の概要

まずはローカル環境でBot Frameworkで問題なくボットが応答できることを確認します。

---

# 準備と環境
* Azureの有効なサブスクリプション
* Bot Framework対応チャットボット
* [Bot Framework Emurator](https://github.com/microsoft/BotFramework-Emulator)

---

# 1. AzureでアプリケーションIDとパスワードを発行する

BotFrameworkの利用には、Azure上でアプリ用のID、パスワードを発行する必要があります。

## ① Azure portal 「アプリの登録」より新規アプリを登録します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339006/f17e7e80-3188-0078-0968-75cf8db063c8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339006/09b3b8b1-b12f-d3b8-31e1-c4413275168f.png)

## ② ブレード「証明書とシークレット」よりクライアントシークレットを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339006/e58c2cca-86ce-73b3-363f-44cce6c7bbc7.png)

## ③ 上記で取得したID、パスワードを作成済みのチャットボットの認証設定してください

---

# 2. Bot Framework Emurator

## ① 起動と接続

Bot Framework Emuratorを起動し、File > Open Bot を起動し、接続情報を入力後[Connect]を押下します
※ここでは、localhost:1080で起動しているチャットボットに、BotFrameworkが要求するAPI(api/messages)に接続してます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339006/8b8f7d6d-0319-2610-2fbd-959db0944d7a.png)


正常に接続できれば起動しているチャットボットのメッセージが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339006/556e666a-a2e2-c9a8-0b2e-c9956ffe1a79.png)

---

# まとめ
ローカル（オンプレミス）環境でチャットボットを起動・運用するための1つ目の手順としてBot Framework Emurator を使用した接続確認を行いました。

次の記事 -> [その②：Azure上で接続テスト](https://qiita.com/rei-yamamoto/items/e5a8df8bb8f015170da2)
【Nuxt】 JavaScriptロジックのまとめ方

# 前置き
- 私はこうしています、という内容です。
- こうすべきと言う話ではないので、ご意見・ご感想をいただければ幸いです。

# 現状の課題
- v-ifに具体的な条件式が書かれている状態
- 特定のデータを参照するためにアクセスする方法が複雑
- APIを改修せずにフロントエンドのロジックでどうにかする必要がある

```vue
// 具体的な条件式が書かれている
<div v-if="offer.stage === 40"></div>

// 複雑な構造のオブジェクト
<div>{{ deta[0].delivery.arrivalAddressData }}</div>
```


# 基本方針
- ロジックを純粋なJS（TS）ファイルに定義する。
- .vueファイル内で上記定義したロジックをインポートして使う

# ロジックの定義方針
## 巨大なcommon.jsを作らない（重要）
1ファイルにいろんなロジックを詰め込みすぎないために…

- 概念（ドメイン）ごとにファイルを分割して定義する
 - 例：ユーザー名、データの状態、など
 - DBのカラム名単位
 - DBのテーブル単位（1つのテーブル全体である情報を表している場合）

## plugin配下にフォルダを作ってまとめる

```:フォルダ構成
/plugins
  /serviceUtils
    /offer
      - offerType.js
      - price.js
      ...
    /entry
      - entryInfo.js
    ...
```

# 定義方法
- 必要な関数・定数を定義
- メソッド単位でもまとめてでのインポートもできるように、名前付きエクスポート、デフォルトエクスポートを設定する
- 基本的に構成は同じだが、名前付きエクスポートの方は定数をエクスポートする場合、別途名前空間を切っても良いかも。

```js:sample.js
const isNuxt = value => value === 'Nuxt'
const isVue = value => value === 'Vue'

export {
 isNuxt,
 isVue
}

export default {
 isNuxt,
 isVue
}
```

# 使い方
## インポート
page, component, layout配下のそれぞれの.vueファイル内でimportして使う

```js
// メソッド単位
import { isNuxt } from '~/plugins/serviceUtils/sample'

// まとめて
import sample from '~/plugins/serviceUtils/sample'
```

## methodsで使う
必要に応じて使い分ける

1. methodsに定義する
1. データを渡した状態で実行する
1. 独自ロジックの一部として使用する

```js

methods: {
 // そのまま使う場合は
 isNuxt, 
 isVue() {
   // 同じ名前で使用するが、ページ内の何らかのデータを渡した状態で実行したい場合
   return isVue(this.data)
 },
 // ロジックの一部として使用する場合
 myFunc() {
   const isOk = isVue()
   ...
 }
}
```

```vue
<!-- v-for内の分岐などで、HTML上で引数を渡したい・渡すしかない場合 -->
<div v-if="isVue(data)">Vue</div>

<!-- HTML上で引数を渡す必要がない場合 -->
<div v-if="isVue()">Vue</div>
<div v-else-if="isNuxt()">Nuxt</div>
```

## computedで使う
状態判定をしたい場合など。

```js
computed: {
  isNuxt() {
   return isNuxt(this.data) // dataが書き換わるたびに判定が切り替わる
  }
}
```

メソッドで定義した場合と違い、使う時にカッコを使わなくなる

```vue
<div v-if="isNuxt">Nuxt</div>
```

# メリット
- thisを使う必要がなくなる
- ロジックを集約できる
- TS化しやすい
  - やろうと思ったらできるなぐらいの認識だったが、試しにTS化してみたら簡単にできた。
  - ファイル全体をTS化する必要があるが、行数が少ない状態で別れているので、段階的に移行しやすい。
  - ピュアなJSなので、TypeScript公式の知識だけで移行できる（Nuxt,Vue独自の概念を使う必要ない）
- そのファイルでのみ使えるプライベートメソッドを定義して使える（後述）
  - 影響範囲が限られているのでリファクタリングしやすい
- 公開するメソッドと非公開のメソッドを制御できる

# プライベートメソッドの使用例

```js
// private
const find = (data, str) => data.find(v => v.key === str)
const findNuxt = data => find(data, 'nuxt')
const findNuxt = data => find(data, 'vue')

// public
const getName = (data) => {
  const nuxt = findNuxt(data)
  const vue = findVue(data)
  return nuxt || vue || ''
}

// 外部に公開しているのはgetNameのみ
export {
  getName
}

export default {
  getName
}
```

# 比較
## 普通に定義
```js
methods: {
  isNuxt(data) {
    return data === 'nuxt'
  },
  ...
}
```

# インポートする場合
```js:その1
import { isNuxt } from '~/plugins/serviceUtils/sample'

methods: {
  isNuxt,
  ...
}
```

```js:その2
import { isNuxt } from '~/plugins/serviceUtils/sample'

methods: {
  isNuxt(data) {
    return isNuxt(data)
  }
  ...
}
```
[やってみた]Jetson nano Docker Compose インストール

sudoなしでdockerコマンドを実行可能にする
(設定を反映するために再ログイン)

```
$ sudo usermod -aG docker $USER
$ exit
```

Docker Composeのインストール

```
$ sudo apt install -y curl

$ python --version
Python 2.7.15rc1

$ sudo apt update -y

$ curl -sSL https://bootstrap.pypa.io/get-pip.py | sudo python

$ pip --version
pip 20.0.2 from /usr/local/lib/python2.7/dist-packages/pip (python 2.7)

$ sudo apt-get install -y libffi-dev python-openssl libssl-dev

$ export DOCKER_COMPOSE_VERSION=1.24.0

$ sudo pip install docker-compose=="${DOCKER_COMPOSE_VERSION}"

$ docker-compose version
docker-compose version 1.24.0, build 0aa5906
docker-py version: 3.7.3
CPython version: 2.7.15rc1
OpenSSL version: OpenSSL 1.1.1  11 Sep 2018
```
kaggle资料整理


#大赛经验分享

はじめてのKaggle（kaggle①）
https://qiita.com/sudominoru/items/0290b09c6a9cfabd7d20

Kaggle&天池比赛经验
https://blog.csdn.net/qq_35571554/article/details/84850323

Kaggle，天池 等数据比赛经验总结
https://blog.csdn.net/qq_24598387/article/details/85113010


分分钟带你杀入Kaggle Top 1%
https://zhuanlan.zhihu.com/p/27424282

数据(机器学习/深度学习)竞赛平台——Kaggle
https://blog.csdn.net/g11d111/article/details/77164074

Kaggle 首战拿银总结 | 入门指导 (长文、干货）
https://blog.csdn.net/jdbc/article/details/72468001


#Sklearn

使用sklearn做单机特征工程
https://www.cnblogs.com/jasonfreak/p/5448385.html

使用sklearn优雅地进行数据挖掘
https://www.cnblogs.com/jasonfreak/p/5448462.html

Python之Sklearn使用教程
https://blog.csdn.net/XiaoYi_Eric/article/details/79952325


【手把手教你】玩转机器学习 Sklearn
https://blog.csdn.net/ndhtou222/article/details/100148295

#PyTorch

PyTorch 入門！人気急上昇中のPyTorchで知っておくべき6つの基礎知識
https://www.codexa.net/pytorch-python/

深度学习之PyTorch实战（1）——基础学习及搭建环境
https://www.cnblogs.com/wj-1314/p/9830950.html

深度学习之PyTorch实战（2）——神经网络模型搭建和参数优化
https://www.cnblogs.com/wj-1314/p/9838866.html

深度学习之PyTorch实战（3）——实战手写数字识别
https://www.cnblogs.com/wj-1314/p/9842719.html

详解 MNIST 数据集
https://blog.csdn.net/simple_the_best/article/details/75267863

#其他
统计学常用概念：T检验、F检验、卡方检验、P值、自由度
https://blog.csdn.net/mydear_11000/article/details/51576564

【決定版】年間１万人が学ぶ「心理学NLPとは？」NLPが仕事、人生、人間関係で使える理由
https://life-and-mind.com/aboutnlp-4590

深度学习 （人工神经网络的研究的概念）
https://baike.baidu.com/item/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/3729729

深度学习详解
https://baike.baidu.com/tashuo/browse/content?id=d4c4e5133c22d037e28f6be7&lemmaId=3729729&fromLemmaModule=pcBottom

机器学习加深了“知识”和“理解”之间的鸿沟
https://baike.baidu.com/tashuo/browse/content?id=d0746a7dd140e7e3262632ee&lemmaId=3729729&fromLemmaModule=pcBottom

深入学习卷积神经网络（CNN）的原理知识
https://www.cnblogs.com/wj-1314/p/9754072.html


深度学习专栏（hanbingtao）
深度学习基础（1）——感知器
https://www.zybuluo.com/hanbingtao/note/433855

零基础入门深度学习(3) - 神经网络和反向传播算法
全代码实现手写字体识别（不用现有类库pytorch,numpy）
https://www.zybuluo.com/hanbingtao/note/476663

爬虫福利一
https://blog.csdn.net/PY0312/article/details/100744842

爬虫福利二
https://blog.csdn.net/PY0312/article/details/101087356
ターミナルでTCP/UDP(osc)ネットワーク通信(Mac)


## HTTPリクエスト
#### Get

	$ curl http://localhost:8080

#### Put	

	$ curl http://localhost:8080 -X PUT

#### Post

	$ curl http://localhost:8080 -X Post

## TCPでのメッセージ送受信
#### TCPでメッセージ送信

	echo "hoge" | nc  127.0.0.1 8080

#### TCPで受信待ちする

	$ nc -l 8080

#### TCP受信したらレスポンスを返す

	$ (echo "HTTP/1.0 200 Ok"; echo; echo "Hello World") | nc -l 8080




永続的にTCPで受信待ちする

	$ while true; do (echo "HTTP/1.0 200 Ok"; echo; echo "Hello World") | nc -l 8080; done

## UDPでのメッセージ送受信

#### UDPでメッセージ送信

	$ echo "hoge" | nc -u 127.0.0.1 8888

#### UDPで受信待ちする

	$ nc -u -l 8888


## OSCでメッセージ送受信 (oscer使用)
aikeさんの[oscer](https://github.com/aike/oscer)がマルチプラットフォームで使用できてとても使いやすい
#### ダウンロード
	
https://github.com/aike/oscer

#### OSCでメッセージ送信

	$ oscer localhost 10000 /dummy
	$ oscer 192.168.1.10 12000 /hello 10

#### OSCで受信待ちする

	$ oscer receive 10000
axiosでリロードできなかったつまずき

# 現象
初め下のコードを書いていたところ、200が返ってきているにも関わらず、ページがリロードされない現象に悩まされました。

```javascript
axios.get('/user')
  .then(location.reload())
  .catch(error => alert("失敗しました。"));
```

# 解決
結論、javascriptの書き方が違っていたようです。

```javascript
axios.get('/user')
  .then(res => location.reload())
  .catch(error => alert("失敗しました。"));
```
create-react-appが公式にreduxテンプレートを公開した件

Reactを触ったことがあるみなさんならご存知のcreate-react-appですが、公式にReduxのテンプレートを公開したようです

<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">I&#39;m excited to announce that:<br><br>🔥🔥The official Redux template for Create-React-App is now available! 🔥🔥<br><br>To use it:<br><br>npx create-react-app my-app --template redux<br><br>Thanks to <a href="https://twitter.com/benlorantfy?ref_src=twsrc%5Etfw">@BenLorantfy</a> for putting the template together!<br><br>Release notes:<a href="https://t.co/gdRbgZGAPS">https://t.co/gdRbgZGAPS</a></p>&mdash; Mark Erikson (@acemarke) <a href="https://twitter.com/acemarke/status/1229576493153603585?ref_src=twsrc%5Etfw">2020年2月18日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

使い方は簡単
`npx create-react-app {app_name} --template redux`
templateにreduxをしてあげるだけで使えちゃいます

# 通常のcreate-react-appとの差分

普通の`create-react-app`コマンドで作成したときと何が違うのか一部抜粋してみました

まずは起動してみると...

[redux templateトップページ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308296/3e695970-f0eb-d41e-1f31-6b83c9ad3f5d.png)

カウンターアプリのサンプルが表示されていますね

## package.json

通常のcreate-react-appから追加でインストールされているモジュールは

- @reduxjs/toolkit
- react-redux

の２つでした

## ディレクトリ構造

`src`以下のディレクトリ構造は以下のようになっています

```
src
├── App.css
├── App.js
├── App.test.js
├── features
│   └── counter
│       ├── Counter.js
│       ├── Counter.module.css
│       └── counterSlice.js
├── index.css
├── index.js
├── logo.svg
├── serviceWorker.js
├── setupTests.js
└── store.js

```

大きな違いとしては、カウンターのサンプルが`features`以下に作成されています

また、`store`が始めから作成してあり、`index.js`の`Provider`に既に登録されています

```src/index.js
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
```

カウンターアプリも含め基本的に全て`Hooks`と`Functional Component`で書かれていました

# typescript対応

現在はまだ公式から`typescript`に対応したものは公開してないようです
でも近いうちに公開されるはず...

補足ですが、
`npx create-react-app {app_name} --typescript`
は廃止予定らしいので
`npx create-react-app {app_name} --template typescript`
を利用しましょう

# リンク
> github release note
> https://github.com/reduxjs/cra-template-redux/releases/tag/v1.0.0
laradoc環境作成でmysql接続でつまずいた話

# laradock環境にて：：ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock'

## 事象
```
php artisan migrate
```
上記コマンドを流すと、タイトルのエラーが発生。。。

いやぁまいったな。。。。

とりあえずググるか。。。

### 某記事１　DB_HOST=localhostとしてください。

ふむふむやってみよう。。。

数十秒後

できねぇな、、、

### 某記事２　DB_HOST=127.0.0.1としてください。

ほんとか。。！？

数十秒後

やっぱりできんやないかい。。。

## 解決策
どうやら立ち上がっているコンテナに紐付けられている
HOSTにしなければいけないみたい。。。
なるほどね。
ってことで下記手順

プロジェクト配下で

```
docker-compose exec mysql /bin/bash
```
下記で一番下に出てきたIPをDB_HOSTに記載！

```
cat /etc/hosts
```

んで改めてmigrateコマンド実行するとうまくいきました！！！

いやぁまいったね。。。
今までのものが動きません。apt　install　xvfd

2020年2月19日
忙しくて、正月から放置していましたが、強化学習シリーズで作ったcolaboratoryは動きません。
pyvirtualdisplayとxvfbのどちらかに問題が生じているようですが。
試してダメだった人は、他を当たってください。

2020年2月21日
!apt update
の後に、
!apt install xvfd
すると通るみたいです。
Numpyについて

# 当記事の目的

- 自分はデータエンジニアを目指しており，その中でデータサイエンスの知識も必要になると考え，機械学習についても学習しています．
その中で，Pythonのライブラリの中の一つである**Numpy**, **Pandas**, **Matplptlib**を学習中です．
- 当記事では，**Numpy**について，自分の学習結果をまとめます．

# Numpyのメリットとは？

### リスト型変数を行列のように扱える

Pythonのデフォルトのリスト型変数は行列ではありません．機械学習のようなビッグデータを扱う場合，行列計算を行いたくなる場合が多々あります．
そこで，**numpy.ndarray**クラスを使用します．このクラスは行列のように振舞います．

### 高速計算が可能になる

Python単独で使用した場合，お世辞にも計算が早いとは言えません．機械学習のようなビッグデータを扱う場合，高速な計算が求められます．
そこで，**Numpyライブラリ**を使います．Numpyは中身がC言語で書かれているため，高速な計算が可能です．

### コードが見やすくなる

前述したように行列計算が可能になるため，forループを行列の内積などで表せるようになるため，コードがすっきりします．

# Numpyの書き方

### Numpyライブラリの呼び出し

```Python
# import library
>>> import numpy as np
```
慣例的に，呼び出したライブラリを**np**と宣言し，*np.ndarray*のように使用します．

### 行列の宣言

まずは１*3行列を作ってみましょう．

```Python
# 1 * 3行列
>>> np.array([1, 2, 3])
array([1, 2, 3])
```

*array([1, 2, 3])*が出力されました．次にこの結果の型を調べてみましょう．

```Python
# 1 * 3行列
>>> type(np.array([1,2,3]))
numpy.ndarray
```
これは*numpy.ndarray*クラスであることがわかります．すなわち，np.arrayメソッドを用いて行列（ndarrayクラス）を宣言したい場合は以下のように書きます．

**np.array( *list_for_declaration* ) 　　# list_for_declarationはリスト型**

このリストの次元数を増やすと行列の次元数も同様に増加します．

```Python
# 2 * 3行列
>>> list_for_declaration = [[1, 2, 3],
                            [4, 5, 6]]
>>> np.array(list_for_declaration)
array([[1, 2, 3],
       [4, 5, 6]])

# 3 * 3行列
>>> list_for_declaration = [[1, 2, 3],
                            [4, 5, 6],
                            [7, 8, 9]]
>>> np.array(list_for_declaration)
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

# 2 * 3 * 4行列
>>> list_for_declaration = [[[1, 2, 3, 0],
                             [4, 5, 6, 0],
                             [7, 8, 9, 0]],
                           [[-1, -2, -3, 0],
                            [-4, -5, -6, 0],
                            [-7, -8, -9, 0]]]
>>> np.array(list_for_declaration)
array([[[ 1,  2,  3,  0],
        [ 4,  5,  6,  0],
        [ 7,  8,  9,  0]],

       [[-1, -2, -3,  0],
        [-4, -5, -6,  0],
        [-7, -8, -9,  0]]])
```

簡単ですね！次にいきましょう

### 行列の要素の確認

まず確認用行列を作ります

```Python
# 2 * 3 * 4行列
>>> list_for_declaration = [[[1, 2, 3, 0],
                             [4, 5, 6, 0],
                             [7, 8, 9, 0]],
                           [[-1, -2, -3, 0],
                            [-4, -5, -6, 0],
                            [-7, -8, -9, 0]]]
>>> array_1 = np.array(list_for_declaration)
```
- 次元数の確認

```Python
# 2 * 3 * 4行列
>>> array_1.ndim
3
```
- 要素数の確認

```Python
# 2 * 3 * 4行列
>>> array_1.size
24
```

- 行数，列数の確認

```Python
# 2 * 3 * 4行列
>>> array_1.shape
(2, 3, 4)
```

よく使用するのは上記３つで，全て*ndarray*クラスの要素であり，メソッドではないので*size()*のようには書きません．
Node.jsで動画変換処理(fluent-ffmpeg)

# 目次
- [概要](#概要)
- [環境構築](#環境構築)
- [fluent-ffmpegの使い方](#fluent-ffmpegの使い方)

***

# 概要
Node.jsをサーバとして利用した時に、動画加工処理の最適な方法は何かを調査する。
有名どころでは、ffmpeg。

## 参考
Node.jsでffmepgを使って動画からサムネイル/静止画を生成する
https://qiita.com/nasbi_suganuma/items/222cd894e09b7c5e9652
  
それFFmpegで出来るよ！  **ffmpeg自体の説明と操作**
https://qiita.com/cha84rakanal/items/e84fe4eb6fbe2ae13fd8

# 環境構築
## Macでのffmpegのインストール（時間がかかる）  

```
brew install ffmpeg
```

※こんなエラーが出たので、  
**Error: Permission denied @ dir_s_mkdir - /usr/local/Frameworks**  
  
ディレクトリを作成し、権限与えて、もう一度インストール！ 成功！

```
sudo mkdir /usr/local/Frameworks  
sudo chown $(whoami):admin /usr/local/Frameworks
```

### Winでのffmpegのインストール 参考
【windows】FFmpegをインストールする手順
https://fukatsu.tech/windows-ffmpeg

## fluent-ffmpegをインストール

```js

npm install fluent-ffmpeg
```

# fluent-ffmpegの使い方

難しいことをしないなら、 以下の記述だけで完了なので、結構簡単。

```js
ffmpeg(入力ファイルパス).output(出力ファイルパス)
``` 

もし、mp4を元にAVI形式を作成し、ついでにサムネイルも作成する場合は、以下のような記述になります。

```js
const filePath = `${__dirname}/../static/MovieFiles/${id}/`

ffmpeg(`${filePath}movie.mp4`)
  .output(`${filePath}movie.avi`)
  .on('end', () => {
    // ここに処理完了後の処理記述
    console.log('Processing finished !')
  })
  .screenshots({ // これはサムネイル作成の記述
    count: 1,
    folder: filePath,
    filename: 'thumbnail.jpg',
    size: '150x150'
  })
```
【Riot.js】propsとstate

[Riot.js](https://riot.js.org/ja/documentation/)の``props``と``state``についてまとめていきます。
まずはコードと結果から。
* 環境構築については[こちら](https://qiita.com/wafuwafu13/items/d40f3f972a4e8b702f78)


```index.html

<!doctype html>

<html>
  <head>
    <title>Riot practice</title>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
  </head>

  <body>

    <app></app>

    <script src="app.riot" type="riot"></script>
    <script src="https://cdn.jsdelivr.net/npm/riot@4/riot+compiler.min.js"></script>

    <script>
      riot.compile().then(() => {
        riot.mount('app', {
          title: 'propsのタイトル',
        })
      })
    </script>
  </body>
</html>
```

```html:app.riot
<app>
  <h3>{ props.title }</h3>

  <h3>{ state.title }</h3>

  <style>
     h3 { color: green }
  </style>

  <script>
    export default {
      onMounted() {
        console.log('マウントされました。')
        // this.state.title = 'stateのタイトル' DOMは更新されない
        this.update({
          title: 'stateのタイトル'
        })
      }
    }
  </script>
</app>
```

結果

<img width="609" alt="スクリーンショット 2020-02-19 15.28.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/40f066c1-69cf-6361-6a61-51ab38a8440a.png">

## ``props``

コンポーネントの初期プロパティを受け取けとっている。


- immutable data (不変のデータ)
- passed in from parent (親から渡される)
- can't change it (変更不可)
- can be defaulted & validated (デフォルト値の設定と検証が可能)

## ``state``

``this.props`` 属性がフリーズされている間は、``this.state ``オブジェクトは完全に変更可能であり、手動または ``this.update()``メソッドを使用して更新する。

- mutable data (可変のデータ)
- maintained by component (コンポーネントによって保持)
- can change it (変更可)
- should be considered private (プライベートであるべき)


## カウントアプリの作成

ボタンを押したら1増えるという単純なアプリを作成する。
**1増える**ということは、**状態が変わっている**。
よって、``state``を使う。


```html:app.riot

<app>
  <p>カウント：{ state.count }</p>
  <button onclick={ plusCount }>+1</button>

  <script>
    export default {
      state: {
        count: 0
      },
      plusCount() {
        this.update({
          //count: this.state.count++  なぜか増えない
          count: this.state.count += 1
        })
      }
    }
  </script>
</app>
```

``state``で値を保持し、``this.update()``で1増やす。


##### 補足
- ``this.state.count++``しても値は増えなかった。。。
- ``plusCount()``内に``console.log(this)``を置いた結果↓
<img width="725" alt="スクリーンショット 2020-02-19 16.14.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/bae8618f-3ff1-837e-3dd3-3822c8d0e2d6.png">
クラウドサービスでおかしいと思ったら確認する障害情報URL

#Overview

先日Node.jsのパッケージマネージャーであるnpmに障害が発生し、Google Cloud Functionsへのデプロイが1時間程度できなくなった。
もしかしてローカルのパッケージフォルダ壊れた？と思って、再インストールを実行したらそれもエラーとなり何もできない状態に:scream:
ということで、(私が使っている)各サービスの障害情報をまず確認しなくてはということでURLをまとめることにしました。

Slack自体の障害時を除けば、SlackにRSSフィードを追加するのがいいのではないでしょうか？
https://slack.com/intl/ja-jp/help/articles/218688467-Slack-%E3%81%AB-RSS-%E3%83%95%E3%82%A3%E3%83%BC%E3%83%89%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B

dblmktさんがツイートするアカウントを作られているようなので、併せて載せておきます。

#Body

##Slack

https://status.slack.com/
https://twitter.com/SlackStatus

##GitHub

https://www.githubstatus.com/
https://twitter.com/githubstatusjp

##AWS

https://status.aws.amazon.com/
https://twitter.com/awsstatusjp

##Azure

https://status.azure.com/ja-jp/status
https://twitter.com/azurestatusjp

##GCP

https://status.cloud.google.com/
https://twitter.com/gcpstatusjp

##Firebase

https://status.firebase.google.com/

##npm

https://status.npmjs.org/
https://twitter.com/npmstatus

##Google Analytics

https://www.google.com/analytics/status#hl=ja

##G Suite(Gmail、Googleドライブ等)

https://www.google.com/appsstatus#hl=ja&v=status
【Laravel】循環的複雑度を可視化するためにphpmdを入れた話

Qiitaでトレンド入りしていた下記の記事を読んで
循環的複雑度を可視化し、強制的に改善させるにLaravelにphpmdを導入しました

[プログラムの可読性を上げるための条件分岐を減らす方法7個](https://qiita.com/ddtaka/items/b178358ebc5b38c6906a)
[循環的複雑度について](https://qiita.com/yut_arrows/items/16749e02313109071338)

# phpmdのinstall
composer.jsonにphpmd/phpmdを追加する

``` composer.json
    "require-dev": {
        "phpmd/phpmd": "*"
    },
```

$ composer update

インストールが完了しました。


次にphpmdのルールファイル作成します

``` phpmd.xml
<?xml version="1.0"?>
<ruleset name="Custom_PHPMD">
    <description>Custom ruleset PHPMD</description>
    <rule ref="rulesets/codesize.xml" />
    <rule ref="rulesets/controversial.xml">
        <!-- 判定から除外: 変数名がキャメルケースかどうか -->
        <exclude name="CamelCasePropertyName" />
        <exclude name="CamelCaseParameterName" />
        <exclude name="CamelCaseVariableName" />
    </rule>
    <rule ref="rulesets/design.xml" />
    <rule ref="rulesets/unusedcode.xml" />
    <rule ref="rulesets/naming.xml">
        <!-- 判定から除外: 変数名の長さ -->
        <exclude name="LongVariable" />
    </rule>
</ruleset>
```

```
$ php vendor/phpmd/phpmd/src/bin/phpmd ファイル名 text phpmd.xml
```
とやれば実行できます

毎回このコマンドを書くのは面倒なので
まとめてartisanコマンドに追加しました。

# artisanコマンド作成
$ php artisan make:command PhpmdCommand

``` :app/Console/Commands/PhpmdCommand.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class PhpmdCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'phpmd {file_path}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'phpmd';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $phpmd = base_path('vendor/phpmd/phpmd/src/bin/phpmd');
        echo shell_exec('php '.$phpmd.' '.$this->argument('file_path').' text 
 phpmd.xml');
    }
}

```

$ php artisan phpmd ファイル名
で毎回チェックできるようになりました。

でも修正ファイルを毎回手動で確認するのも面倒なので、
commitする際にチェックさせて、エラーがあったらcommitさせないようにしようと思います。
けっこうチェック厳しいですが、これなら絶対複雑度は下がりますよね。

# git hookの設定
.git/hooks/pre-commit

``` :.git/hooks/pre-commit

IS_ERROR=0
for file in `git diff --cached --name-only && git diff --name-only`
do
    echo $file
    ERROR_MSG=`php artisan phpmd $file`
    if  [ "$ERROR_MSG" != "" ]; then
        echo $ERROR_MSG
        IS_ERROR=1
    fi
done

if [ $IS_ERROR -eq 1 ]; then
    echo ""
    echo "Please resolve the error"
fi
exit $IS_ERROR
```

git commit するたびにエラーを指摘されて大変ですが、
命名規則の徹底や複雑度改善がされていい感じですね。
今後ほかのサイトにも導入してみようと思います

以下を参照して修正予定
[phpmdのルール一覧](https://qiita.com/rana_kualu/items/097db09f711fe15eddb7)
[githooksのpre-pushを共有してレポジトリを健全に保つ](https://medium.com/@astatsuya/githooks%E3%81%AEpre-push%E3%82%92%E5%85%B1%E6%9C%89%E3%81%97%E3%81%A6%E3%83%AC%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%82%92%E5%81%A5%E5%85%A8%E3%81%AB%E4%BF%9D%E3%81%A4-7156def39b64)
GAS// メールを自動取得するスクリプト

#★Gmailに届いたメールを自動取得したい
毎日届く数百通のメールの中から、特定のルールのメールを自動取得したい。というニーズがありました。
マウスの動きを効率化するとか、意味不明な運用が正となってしまう前にスクリプトで自動化しました

##▼スクリプトの動き
1.Gmailから特定の件名のメールを取得する
2.メールをシートに展開する
3.ある程度必要な情報は列ごと
4.同じメールは取得しないようにする
5.定期的に動かす

##1.シートを指定する
```
const sh = SpreadsheetApp.getActiveSpreadsheet();
const ss = sh.getSheetByName("Mails");
const sheet = ss.activate();
```
複数のシートのどこに行くかわからないので、**Mails**シート固定になるようにした。なんだか冗長

##2.同じメールを取得しないようにする配列
```
const mIDs = sheet.getRange(2, 1, sheet.getLastRow()-1).getValues();
```
１列目のメールIDを`getRange`する。値がないとエラーになる。Lastrowが0になるので。何行か文字入れておけばOK

<details><summary>getID関数</summary><div>

``` function:getID
function getID(){
  const threads = GmailApp.search('from:test@example.com subject:"メールの件名" newer_than:1d');

  for(var i=0; i<threads.length; i++){
    var thread = threads[i];
    var mails = thread.getMessages();
    for(var j=0; j<mails.length; j++){
      var mail = mails[j];
      var date = Utilities.formatDate(mail.getDate(), 'Asia/Tokyo', 'yyyy/MM/dd');
      var time = Utilities.formatDate(mail.getDate(), 'Asia/Tokyo', 'hh:mm');
      var body = mail.getBody();
      var subjects = mail.getSubject();
      var tID = fetchData(body,'pre','\r');
      var tName = fetchData(body,'pre','\r');
      var tReason = fetchData(body,'pre','\r'); 
      var mID = mail.getId();
      Logger.log(mID , check_mID(mID));
      if(!check_mID(mID)){
         sheet.appendRow([mID,date, time,body,tID,tName,tReason]);
    }
  }
}
}
```

</div></details>


`GmailApp.search('from:test@example.com subject:"メールの件名" newer_than:1d')`
Fromアドレス、件名、１日前より新しいメールを検索

>日（d）、月（m）、年（y）で期間を指定して、それより古いメールか新しいメールを検索します	
older_than:
newer_than:
https://support.google.com/mail/answer/7190?hl=ja

`mail.getDate()`　すると日時を取得してしまうので、`Utilities.formatDate`で日付と時間に分割


## check_mID関数
１列目に取得しているメールIDを配列に読み込んで、IDを照合する。Someを使ってBooleanを返す

```function:check_mID
function check_mID(mID){
  var check_mID = mIDs.some(function(arr,i,mIDs){
    return(arr[0] === mID);
  });
  return check_mID;
}
```

##fetchData関数
メール本文から指定の範囲を抜き出す

```
function fetchData(mailbody,pre,suf){
  var reg = new RegExp(pre+'.*?'+suf);
  var results = mailbody.match(reg)[0]
  .replace(pre,'')
  .replace(suf,'');
  return results;
}
```
2020/3/10追記　pre/sufが存在しない場合にエラーで止まるので、try~catchを追加
##定期的に動かす
GASのトリガー機能を使用。うまくいきそうかな
ナイーブツリーにおける任意階層にある複数ノード配下の末端ノードを1クエリで全て取得する

# 目的
- ナイーブツリーで構成されている多階層テーブルにおいて
- 任意の階層に所属しているノード群(= 親ノード)に所属している末端ノードの一覧を
- 親ノードとの関連が分かるように
- 1クエリで

取得したい。

つまり

| 親ノードid | 末端ノードid |
| --- | --- |
| 3 | 20 |
| 3 | 21 |
| 3 | 22 |
| 4 | 25 |
| 4 | 26 |
| 4 | 27 |

みたいな結果を取得したい。

# 環境
MySQL 8~

MySQLだと8系以降でしか再帰クエリが使えないため。
他DBMSでも再帰クエリが使えれば同じことはできるはず。多分。

# 前提のテーブル構造

tableName: naive_tree

| id | parent_id | depth | is_leaf |
| --- | --- | --- | --- |
| プライマリ | 親id | 階層 | 末端ノードならtrue |

# 再帰クエリについて
ざっくり。

```sql
-- ここから再帰クエリ。`temporary_table_name`という名前で、hoge, fuga, piyo, ...の構造を持つ一時的なテーブルを作成する
WITH RECURSIVE <temporary_table_name> (<hoge>, <fuga>, <piyo>, ...) AS (
    -- ここから非再帰項
    -- 最初に実行され、再帰項を実行するベースデータを取得する
    SELECT <hoge>, <fuga>, <piyo>, ... -- 上記で定義したものと同じ構造である必要がある
    -- ここまで非再帰項

        UNION ALL -- 非再帰項と再帰項それぞれで取得できた結果をつなげる

    -- ここから再帰項
    -- 非再帰項の取得結果をベースに実行される
    SELECT <hoge>, <fuga>, <piyo>, ... -- 上記で定義したものと同じ構造である必要がある
    FROM <temporary_table_name> WHERE <condition> -- 一時テーブル自身(temporary_table_name)を使う
    -- ここまで再帰項
)
-- ここまで再帰クエリ
SELECT *
FROM temporary_table_name
```

# クエリ
```sql
SET @target_parent_depth = 1; -- 階層数を指定

WITH RECURSIVE tree(id, parent_id, depth, is_leaf, target_depth_parent_id) AS (
    -- 指定された階層のレコードを全て取得
    -- 自分自身が親なのでtarget_depth_parent_idは0としておく
    SELECT id, parent_id, depth, is_leaf, 0 as target_depth_parent_id
    FROM naive_tree
    WHERE id IN (
    	SELECT n.id
    	FROM naive_tree n
    	WHERE n.depth = @target_parent_depth
    )
      UNION ALL
    SELECT
    	n2.id,
    	n2.parent_id,
    	n2.depth,
    	n2.is_leaf,
    	(
    		CASE
	    		WHEN n2.depth = @target_parent_depth + 1 THEN n2.parent_id
	    		ELSE t.target_depth_parent_id
    		END
    	) as target_depth_parent_id
    	-- ここがキモ
    	-- JOINされたレコードが非再帰項で取得された階層の「次の」階層だった場合には、JOINされた側のレコードが持つparent_idを使う。
    	-- それ以外のケースでは、JOIN元のレコードのtarget_depth_parent_idをそのまま使う。
    FROM tree t
    INNER JOIN naive_tree n2 ON t.id = n2.parent_id
)
SELECT
	t.id,
	t.target_depth_parent_id
FROM tree t
WHERE t.is_leaf = 1 AND target_depth_parent_id != 0 -- 末端ノードであり、かつ親レコードではないことを条件とする
```
Javascriptで改行したら下に伸びるテキストボックスをつくる

#はじめに

読んで字の通り、可変テキストボックスを実装する関数をつくってみました。
改行するごとに下へ下へと枠が伸びてゆくので、見栄えはよくなるかも。


#コード
仕組みとしては、改行文字（\n）の数を数えて、改行文字 ✕ 一行分の高さ ＋ もともとの高さ　となるようにした感じ。
パソコンは改行そのものも「改行という名の文字」として認識しているので、そこを突いてやればいいというわけだ。

なお、CSSは適用されているスタイルをブラウザから自動取得してくる仕組みになっている。
わざわざJsを書き換えてやらずとも、使いまわすことができるというわけだ。


```javascript:javascript

function afeed(element){
	if(element.tagName == 'TEXTAREA'){

		// 行の高さとpadding値を取得する。IEやSafariなど、ブラウザによって必要な関数が異なるので、or（||）で３パターン分取れるようにしてある。
		var stylelists = window.getComputedStyle(element, null) || element.currentStyle || document.defaultView.getComputedStyle(element, '');

		// １行あたりの高さ。
		if(stylelists.getPropertyValue('line-height') === "normal"){
			var line_height = 1.2 * stylelists.getPropertyValue('font-size').replace(/px/g , "");
		}else if(Number.isNaN(stylelists.getPropertyValue('line-height'))){
			var line_height = stylelists.getPropertyValue('line-height').replace(/px/g , "");
		}else{
			console.log("エラー！line-heightが不正な値です。");
		}

		// 高さの初期値。
		var firstheight = Number(element.offsetHeight) - stylelists.getPropertyValue('padding-top').replace(/px/g , "") - stylelists.getPropertyValue('padding-top').replace(/px/g , "");


		element.style.height = firstheight + 'px';
		element.style.resize = 'none';

		var line_length;
		var result_height;
		element.addEventListener('input', function(){

			// 改行文字の個数を取得
			if(element.value.match(/\n/g) === null){
				line_length = 0;
			}else{
				line_length = element.value.match(/\n/g).length;
			}

			// 見栄えの関係上、１つ以上改行があるときは文字のすぐ下に枠が来るようにする
			if(line_length === 0){
				result_height = firstheight;
			}else{
				result_height = ((line_length - 1) * line_height) + firstheight;
			}
			element.style.height = result_height + 'px';
		}, false);
	}else{
		console.log('Error: テキストエリアでないものに対して適用されています。');
	}
}

```

#Codepenを用いたサンプル

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="js,result" data-user="yomogenium" data-slug-hash="gOpMqwa" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="テキストエリア自動改行">
  <span>See the Pen <a href="https://codepen.io/yomogenium/pen/gOpMqwa">
  テキストエリア自動改行</a> by Yomogenium (<a href="https://codepen.io/yomogenium">@yomogenium</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>


#おわりに

間違いやわかりにくい箇所ありましたら、編集リクエストをお願いいたします。



#参考文献

https://amachang.hatenablog.com/entry/20070611/1181554170
【Markdown】markdownlintのconfigの設定方法

markdownlintの構文チェックが厳しい；；

なのでちょっと基準をちょっとゆるくしてみたお話。

といっても、ただ基準をtrueからfalseにしただけです笑

# markdownlintの導入

- [Visual Studio Code で Markdown 編集環境を整える](https://qiita.com/kumapo0313/items/a59df3d74a7eaaaf3137)
- [Markdownファイルを構文チェックする仕組み](https://qiita.com/peg/items/c2b93919a1d55ada47cf)

ここらへん見て入れましょう！

# configの設定

今回のmarkdownlintを使っている環境はVSCodeなので、その環境での設定方法を書きます。

まずはみなさんご存知のsetting.jsonを開きます。

開き方は
ctrl+comma （File -> Preferences -> Setting）で設定パネルを開いて、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561377/b66f0ef5-9f1f-8010-9473-11242b000bf9.png)

をクリックです。

あとは、setting.jsonに`markdownlint`と打っている間に勝手に補完してくれます。

```
"markdownlint.config": {

    }
```

こんな感じに。なんか便利ね。

あとはゆるくしたいルールをfalseに設定するだけです。

例えば、

```
# Some text

## Some text
```

`#`で示すヘッダーが同じだと

```
MD024/no-duplicate-heading/no-duplicate-header: Multiple headings with the same contentmarkdownlint(MD024)
```

な感じでヘッダーが同じですよと警告してきます。

文末の`(MD024)`が構文チェックのルールの項目ID的なやつです。

`(MD024)`をfalseにすれば、そのルールに従う構文チェックが実行されなくなります。

```
"markdownlint.config": {
    "MD024": false
    }
```

こんな感じ。

ルールの設定は全てがbooleanでできるわけではないので、

公式で確認してみてください。

- [markdownlintのルール一覧](https://github.com/DavidAnson/markdownlint/blob/v0.19.0/doc/Rules.md#md025)
python3.7+pipenvの環境をUbuntu16.04(VirtualBox)に構築する



16.04のpythonバージョンはデフォルトで3.5.2であり、3.6以上はソースコードからinstallする必要があります。そのやりかたをまとめました。()の中はおよその作業時間です。

## OSの更新 (50分)
割とこれを最初にしていないために後々しんどくなることが多いです。
以下のコマンドでOSを更新してください。

```update.sh
sudo apt update -y
sudo apt upgrade -y
sudo apt dist-upgrade -y
sudo apt autoremove -y
sudo apt autoclean -y
```
もし、途中で以下のような画面がでたら

一番上の「インストールする」を選んでください。
![00003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587912/7ca2eebf-a7c2-071b-07a7-438de245951e.png)
## pythonのインストール(8分)
今回はpython3.7.0をソースコードからmakeしてinstallします。

```shell:pythonのinstall 
curl -O https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tgz
tar xvfz Python-3.7.0.tgz
cd Python-3.7.0/
./configure --prefix=/usr/local/python370 --with-ensurepip
sudo apt install libffi-dev
make
sudo make install
```

## pipenvのinstall(5分)
pipenvをインストールするまえにpipをinstallします。

```shell:pipenvのinstall
sudo apt install python-pip
sudo apt install python3-pip
sudo pip3 install pipenv
```

## pipenvの動作確認(3分)
実際にpipenvで仮想環境を構築します。
`pipenv --python [pythonのパス] install`でプロジェクト配下に仮想環境をつくります
そして`pipenv shell`で仮想環境に入ります

```shell-session:pipenvの動作確認
mkdir py_check
cd py_check
pipenv --python /usr/local/python370/bin/python3 install
pipenv shell
```
そしてスクショのようになっていたら成功です。
![00020.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587912/e33b2eae-ead8-01ae-ad7c-d5f69a206e9b.png)

```shell-session:バージョン確認
python --version

#実行結果
Python 3.7.0
```
## 参考記事
[ubuntu 16.04でPython3.7を使う](https://qiita.com/kei0425/items/6b84938db2c22186fdbc)
[pyenvで3.7系のインストールに失敗したときのメモ](https://qiita.com/hitochan777/items/941d4422c53978b275f8)
[やってみた]Jetson nano カメラ編

# カメラ接続

## カメラの接続
フラットケーブルの基盤接続面をヒートシンク側に向けて接続。

## 接続状況の確認
以下のコマンドで接続状況を確認できる

```
$ ll /dev/video0
crw-rw----+ 1 root video 81, 0 Feb  9 21:27 /dev/video0
```

また、v4l2-ctlコマンドでカメラのデバイス情報を確認できる

```
$ sudo apt-get -y install v4l-utils
```

## (注意)使用できるカメラに制限がある
そのまま流用できるのはRaspberryPi用カメラV2。

```
$ v4l2-ctl --list-devices
vi-output, imx219 6-0010 (platform:54080000.vi:0):
        /dev/video0
```

DonkeyCarで使用されていたカメラは赤外線カメラのようで認識しなかった。

```
$ v4l2-ctl --list-devices
mmal service 16.1 (platform:bcm2835-v4l2):
        /dev/video0
```

## 撮影

```
$ nvgstcapture

j+returnでjpg保存
ctrl+cで終了
```
TwilioでBundleSidに紐付いたAddressSidの見つけ方

:::note alert
2023年5月1日を持ちまして、株式会社KDDIウェブコミュニケーションズのTwilioリセール事業が終了したため、本記事に記載されている内容は正確ではないことを予めご了承ください。
:::

<font color='red'>現在は管理コンソールのBundleSidの詳細画面で、住所データのSID（ADから始まる文字列）を確認することができるのでこの記事は不要です。</font>

# はじめに

みなさん、こんにちは。
KDDIウェブコミュニケーションズのTwilio事業部エバンジェリストの高橋です。
今回は、先日から日本の電話番号の購入の際に必須化が始まったBundleSidとAddressSidに関しての、ちょっとしたTipsをご紹介します。

# BundleSidとAddressSidの紐付け

BundleSidとAddressSidは紐付いています。<font color="red">←これ重要</font>
そして、電話番号を購入するときは、それぞれが紐付いた状態で指定をしないとエラーになります。

管理コンソールから電話番号を購入する場合は、BundleSidを選択することで、自動的に紐付いているAddressSidがリストに出てくるため、特に意識をしなくても問題ないのですが、APIを使って番号を買う場合は、BundleSidとAddressSidをそれぞれ指定しなくてはならないので、どのAddressSidがどのBundleSidに紐付いているかを知る必要があります。
しかし管理コンソール上では、Bundlesの一覧を見ることもできるし、Addresses（住所）の一覧を見ることもできるのですが、それぞれがどれに紐付いているのかを知るすべがありません。

# BundleSidに紐付いたAddressSidを調べる方法

以下の手順で特定のBundleSidに紐付いているAddressSidを知ることができます。

- まずは管理コンソール上の**電話番号（Phone Numbers）**の**Regulatory Compliance**の**Bundles**を選択します。
- 調べたいBundlesを選択します。
- 画面をスクロールすると、**SUPPORTING DOCUMENT & SID**というセクションが見つかるはずなので、その一覧の中から登記簿謄本（法人の場合）のデータを探します（クリックすると登録する画像が確認できます）。
- 見つかったドキュメントのSID（RDから始まる文字列）を探してメモしておきましょう。
- 次にコマンドプロンプトを開きます。
- 以下のCurlコマンドを実行します（RDから始まる文字列を先程メモしておいた値に変えて、AccoutSidとAuthTokenもご自分の環境に合わせてください）。

```sh
curl -X GET 'https://numbers.twilio.com/v2/RegulatoryCompliance/SupportingDocuments/RDXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' \
-u ACxxxxxxxxxxxxxxxx:your_auth_token
```

実行結果に**attributes**という配列がありますが、この中に表示されているAddressSid（ADから始まる文字列）がBundleSidに紐付いているものです。

# まとめ

APIで電話番号を購入する場合だけでなく、電話番号サブアカウント間で移動させる場合なども、移動先のBundleSidとAddressSidが必要になります。
管理コンソール上から確認ができればよいのですが、現時点では確認ができないので、ぜひ困った時は思い出してください。

---
### Twilio（トゥイリオ）とは

https://cloudapi.kddi-web.com
Twilioは音声通話、メッセージング（SMS/チャット）、ビデオなどの 様々なコミュニケーション手段をアプリケーションやビジネスへ容易に組み込むことのできるクラウドAPIサービスです。初期費用不要な従量課金制で、各種開発言語に対応しているため、多くのハッカソンイベントやスタートアップなどにも、ご利用いただいております。