OmniAICreator/Qiita-1.07M huggingface dataset:
CentOS7でcode-server を立ててみる、、いまさら？？　でも５分で実行できるよ

# code-server を立ててみる
いまさらなんですが code-server 立てて遊んでみました。これいいですね ブラウザで Visual Studio Code(以下vscode)が動くって言うのがね。ちなみに CentOS7 で動作確認しました。

# code-server ってなんぞや
上記に書いてあるとおりなのですが、Linuxサーバ側でこの code-server を起動すればブラウザ経由でファイルを編集することができます。また vscode のインターフェースを使用するので黒い画面に拒否反応ある人にはうってつけですね。
また各設定を正しくすれば、プログラム実行＆debugerできて便利そう（今回は、立ち上げるだけ）

# code-server を起動してみる
[リモートサーバー上でvscodeを動かしてブラウザからアクセスする ―code-serverのススメ](https://qiita.com/canonrock16/items/b043a996fe1175298207) を見ながら起動してみます。
docker入れるのが面倒だったのでバイナリファイルから実行してみます（笑）。

ドキュメントは英語ですが整備されています。
　・[Set up instance](https://github.com/cdr/code-server/blob/master/doc/deploy.md)
　・バイナリ 2020/2/21 時点で [2.1698-vsc1.41.1](https://github.com/cdr/code-server/releases) が最新のようです

非武装地帯 (DMZ)にいるのでパスワードなしで起動

```text
$ ./code-server ../ --auth=none
```

コマンドラインを見るとエラーなく起動している
![vscode_server_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/45b59958-c33b-d291-5026-8b41b5e18416.png)


# ブラウザからアクセスしてみる
![vscode_server_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/ba9c13fd-85a9-2e7e-ae5e-e3858ae6d374.png)


いい感じですね。これなら黒い画面が嫌とは言われない気がする。

# GLIBCXX_3.4.14 以上が必要なようです
CentOS6(2020/11/30 まで)だと libstdc++ ライブラリが古く比較的新しいソフトウェアを実行することができないようです。どうしてもCentOS6で…という方以外は、素直に新しいOSで実施した方がよいみたいです。
・[CentOS6 の libstdc++ を更新する](https://www.saintsouth.net/blog/update-libstdcpp-on-centos6/)

# 色々と便利そう
なんだかvscode本体よりバージョンが低いようで、拡張機能マネージャーからインストールできる拡張機能が制限されるようです。そう言ってもGUIで編集できるメリットは高いですね。
もちろんセキュアなサーバに入れて”だれだよ！このファイル変更したのは！”という使い方はしないでしょうが、viでファイル編集したり、windowsからsftpしたりするよりは効率がよさそうですね。

# 参考サイト
・[リモートサーバー上でvscodeを動かしてブラウザからアクセスする ―code-serverのススメ](https://qiita.com/canonrock16/items/b043a996fe1175298207) 
・[自宅サーバーで Docker + Nginx + code-serverを動かそうとした話](https://qiita.com/sskmy1024y/items/8f098f7faa36fc34608c)
#OpenCV　Sharpでメモリリークが起きる

本内容を利用した場合の一切の責任を私は負いません。

Matをusingしてるのに起きた。
(下記の公式サンプルでusingしてるためアンマネージ。
https://github.com/shimat/opencvsharp_samples/
)
検索したら下記が見つかって、自分はMat取得ではなくBitmap取得(Mat.ToBitmapメソッド)だから該当しないと思ったけど、Disposeしたら防止できた。
https://blog.mohyo.net/2015/03/1313/
てことで、Matから取得したアンマネージは全てDisposeした方がよさそう。
今更ながらWPFに置き換えてみる（1）

この前新しいノートPC買った。
レノボのX1。すこぶる快適なんですが、以前作ったツールアプリの表示が汚い。解像度の問題で仕方ないのはわかっているんですが何とかしたいと考えてWPFで作り直すことにします。
どうせ作り直すので、VBからC#に置き換えもやってみようかと。

---
#Forms版のボケ具合
現行のFORMはこんな感じ
![コメント 2020-02-21 195453.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590512/a67f6ba7-03c6-dc1d-df8c-41b45458c1c2.png)

↑超ボケボケ。ひどい。

機能は自分ツールなんであまりなく
・タイムカード代わりにPCの起動時間と終了時間を保存する
・常駐型アプリ
・NotifyIconの動的生成（数種類）
・時報表示
くらい。

いまさらWPFってのもあれですが自分用の備忘録として進めていきます。
#OpenCV　SharpのVideoCapture.IsOpenedメソッドがtrueにならない

本内容を利用した場合の一切の責任を私は負いません。

コンストラクタで動画ファイルを指定した場合。
Readメソッドで取得したMatも使用できない。
動画ファイルのファイル名が原因ぽい。
「🄬」が入っていると例外は発生しないが事象が起こる。
Unicodeのせい？？？と検索したら、既に下記で問題視されてるように見える。
https://github.com/shimat/opencvsharp/issues/342
で、更に追うと、下記から元のOpenCVの問題っぽく見え、チケットがクローズしてないのでまだ修正されてないのかも。
https://github.com/opencv/opencv/pull/13368
とりあえず、ファイル名を変えれば回避できる。
Eclipseのインストール～Java(PHP)の実行まで

#　この記事でできること
- Eclipseをインストールし、Javaが実行できる
- PHPを実行できる(XAMPPがインストール済みの場合)…長くなったので別記事：[EclipseでPHPを開発できるようにする - Qiita](https://qiita.com/niyute/items/9c07712dda830d14c767)

# ダウンロード
URL：https://mergedoc.osdn.jp/
▼特にこだわりもないので最新版を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256612/ab8b3e41-0177-bf36-4c09-d138de694664.png)

▼Python,XAMPPは既に入っているので今回はJava(FullEdition)を選択。1,5GBあるので気長に待つ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256612/d46c42e6-1c9d-d3f0-ae4c-b1a75d088017.png)

# 解凍～起動
▼ダウンロード完了後解凍。こんな感じになっているはず。[eclipse.exe]を実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256612/b7440103-7e7a-2399-4b42-4cf57d2e57df.png)

▼起動画面が出てくる。初回はキャッシュクリアのため1分ほど待つ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256612/81958ae3-f55e-fc5e-5656-869d6780fcdf.png)

▼ワークスペース(実際のソースとかを置くところ)を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256612/c65f21e1-3541-555f-6f71-f0b1e23e6d83.png)

▼ワークスペースの選択後IDEの画面が表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256612/bab85022-58f5-2127-5efd-109787df19df.png)

▼ワークスペースには[.metadata]フォルダだけがある状態
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256612/f0ad58f8-e85f-ec00-ee17-b44cdb3a9e91.png)

#Javaアプリの実行まで
▼Javaプロジェクトの作成を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256612/d5f473e6-3466-dc6b-795e-12ca4caf0f73.png)

▼プロジェクト名を入力し「次へ」（完了でもいいがせっかくなので覗いてみる）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256612/395bed2b-b26a-21fc-99eb-cced39fc76af.png)

▼ビルド設定。今回は特に触らずに「完了」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256612/27c6c365-dd47-daf6-1f84-5a86e465a745.png)

▼「module-info.javaの作成」なんのこっちゃ、、、。Java9の新機能らしい。とりあえず「作成」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256612/6a4d6277-afe1-e085-37a6-b9b9208cde37.png)

▼Javaプロジェクトが完成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256612/b800631d-1541-8027-265b-a188cf7d8e0a.png)

▼ソースを書くファイルを作成。画面左の「パッケージエクスプローラー」で右クリック→「新規」→「ファイル」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256612/66fe5159-6b13-e7cb-e394-7531a4933383.png)

▼ファイル名を入力し「完了」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256612/fd0f22d3-a1ec-c31b-b809-7607ad2e1855.png)

実際にコードを書く。
どうも「module-info.javaの作成」をしたばっかりにpackage宣言しないといけないようなので[hallowWorld]パッケージの宣言をする。実ファイルのディレクトリもIDEが自動で変更する。

```java:hellowWorld.java
package hellowWorld;
class hellowWorld{
  public static void main(String[] args){
    System.out.println("HelloWorld");
  }
}
```
▼コードを保存して実行。ソースファイルがアクティブな状態であれば画面上部の「実行」マークから実行できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256612/c5567a3a-e6e7-0696-8793-12d82de864b2.png)

▼実行結果がコンソールに出力されて終了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256612/f8fe868b-294f-2c78-d7b0-5150978c61a7.png)


以上
ChromeかFireFoxでURLを文字化けせずにコピペする

ChromeやFireFoxでURLに日本語文字が含まれるとき、URLをコピペしたら文字化けする。

<img width="494" alt="スクリーンショット 2020-02-21 16.24.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283603/24b1eab6-61f3-bc41-e90c-5e90e9e7c86b.png">

これは文字化けではなく、文字がエンコードされているから
エンコード：日本語→半角英数字・記号へ変換
デコード：半角英数字・記号→日本語へ変換

エンコード、デコードをしてくれるサイトがあります
→[URLエンコード・デコード](http://...https://tech-unlimited.com/urlencode.html)

しかし「別サイトを開かず、ブラウザで何とかならんか」という人向けの内容です。

# １）コンソールを開く
ChromeもしくはFireFoxのコンソール（デベロッパーツール）を開きます
<img width="1615" alt="スクリーンショット 2020-02-21 19.46.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283603/b2166c4f-6a39-1c04-64fd-bc17e78d6b20.png">


## ショートカット
ショートカットの方が早く開けます。ChromeもFireFoxも同じです。
macOS：`option` + `command` + `i` もしくは `F12`
Windows：`Ctrl` + `Shift` + `i` もしくは `F12`

# ２）コマンド
「コンソール（Console）」タブの画面で、下記のコマンドを入力してください

<img width="613" alt="スクリーンショット 2020-02-21 19.48.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283603/28028502-88b3-ea06-5834-4d6a12ddf7c4.png">


## URL取得 + デコード + クリップボードへコピー 
`copy(〜)`でクリップボードへコピー

```terminal
copy(decodeURI(location.href))
```

## URL取得 + デコード 
`decodeURI(〜)`でデコード

```terminal
decodeURI(location.href)
```

## URL取得 
`location.href`で開いてるページのURLを取得（※ただしエンコードされた状態）

```terminal
location.href
```

#まとめ
１）コンソールを開く：`F12`
２）コマンドを打ち込んでエンター：`copy(decodeURI(location.href))`

以上。

#こんな方法もありました。
[日本語の入ったURLをそのままコピーしたいとき](https://qiita.com/ntoreg/items/4a97304dd2861b64a8b6)
[ブラウザのURLをそのままコピペする方法](https://qiita.com/akm/items/e11a17261f7e1056382a)
【備えあれば憂い無し】ROSインストール済みのLiveUSBイメージをビルドするスクリプトを作った

![usb_hand_memory.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/c57f02d5-d015-d067-3afc-130f97f7a325.png)

追記：ROS2版も追加しました。（2020/02/28）

大会、商談など大事な時に限って、PCの調子が悪かったりバッテリーが切れたりして、ROSのデバッグが出来なかった。。。そんなことありませんか？
そんなとき、誰かのPCを使ってせめてrvizだけでも起動できれば、、、

ということで、
Dockerとchrootを使用してROS LiveUSBを作成するスクリプトを作ってみました。
[rdbox/utils/live\-ros\-builder at master · rdbox\-intec/rdbox](https://github.com/rdbox-intec/rdbox/tree/master/utils/live-ros-builder)

イメージの作成はとても簡単です。
特に作業環境を汚染しないことを意識しています。 （dockerとchrootを使用）

**備えあれば憂い無し**

## Get started
1. Requirement
   - Linux
   - Docker
   - `sudo`無しで`docker`コマンドが実行できるユーザ

   ```bash
   $ sudo gpasswd -a $USER docker
   $ sudo systemctl restart docker
   $ exit
   ```

2. リポジトリを取ってくる

   ```bash
   $ git clone https://github.com/rdbox-intec/rdbox
   $ cd rdbox/utils/live-ros-builder
   ```

3. ISOを作る
   - ROS1 (Melodic Morenia)

   ```bash
   $ make iso-ros1
   ```

   - ROS2 (Dashing Diademata)

   ```bash
   $ make iso-ros2
   ```

   - ROS1 & ROS2

   ```bash
   $ make iso-all
   ```


4. USBに書き込む  
   `dd`コマンドを使います。  
   <device>は、USBメモリのドライブパスです（例：/dev/sdc） 
   デバイス名は「sudo fdisk -l」で確認できます。

   ```bash
   $ sudo dd if=live-ros.iso of=<device> status=progress oflag=sync
   ```

## カスタマイズ
もしも、他のパッケージを追加でインストールする場合は`ListOfPackagesToInstall.txt`にパッケージ名を追加して下さい。

```bash
$ vi ListOfPackagesToInstall.txt
packageA
packageB
packageC
:
:
```

## 今後
ROS2とか需要があれば作ります。
追記：ROS2版も追加しました。（2020/02/28）

## 参考文献
[How to create a custom Ubuntu live from scratch \- ITNEXT](https://itnext.io/how-to-create-a-custom-ubuntu-live-from-scratch-dd3b3f213f81)
新卒webエンジニアの僕が実際使ったGitコマンド集

#Gitとは
wikipedia先生によると
>Gitは、プログラムのソースコードなどの変更履歴を記録・追跡するための分散型バージョン管理システムである。[wiki](https://ja.wikipedia.org/wiki/Git)

Gitは分散型バージョン管理システムといって、リモート（元のファイル）をローカルに落として編集できるんだなくらいに思っています。

##branch
- `git branch`<br>
ローカルブランチの確認

##clone

- `git clone クローンしたいリポジトリ`<br>
リモートリポジトリをクローンして<br>ローカルリポジトリを作る

##checkout
- `git checkout -b ブランチ名`<br>
ブランチの作成
- `git checkout ブランチ名`<br>
ブランチを切り替える

##fetch
- `git fetch`<br>
リモートリポジトリから最新情報をローカルリポジトリに持ってくる（更新はされていない）


##merge

*自分のブランチに他のブランチの更新を取り込む*

- リモートブランチにローカルブランチの更新を取り込みたい場合
`git merge 変更を加えたローカルブランチ名`
更新を取り込みたいリモートブランチにいる状態で実行する　　
　　 


- コンフリクトが起きて編集前にマージを取り消す場合
`git merge --abort`
　　
- コンフリクトが起きて編集後にマージを取り消す場合
`git reset --hard HEAD`
- コンフリクトが起きてリモートで上書きしたいとき

```
git fetch origin コンフリクトが起きたブランチ名
git reset --hard origin/コンフリクトが起きたブランチ名
```

##pull

*fetchとmergeを同時に行う*

- `git pull origin master`

ローカルのマスターにいる状態で実行するとリモートのマスターからの変更がローカルのマスターに組み込まれる

##add

*追加、変更したファイルをインデックス（commit候補）に加える*
※add単体での使用はしないため例は省略

##commit

*インデックスに登録してある変更対象をローカルリポジトリに反映*

- `git commit -am "コミットメッセージ"`<br>
addとcommitを同時に行い、メッセージも指定できる

##show

- `git show`<br>
最新コミット内容表示

##reset

- `git reset --soft`
コミットだけを取り消す（ローカルのワークディレクトリの内容は変更しない）

- `git reset --hard`
ローカルのワークディレクトリの内容も含め、コミットを取り消す

- `git reset --soft HEAD^`
直前の間違ったコミットを取り消す（「HEAD^」は、直前のコミットという意味を表すオプション）

[git pushを取り消す2つの方法](https://reasonable-code.com/git-push-cancel/)
##push
*ローカルブランチの変更をリモートブランチに反映*

- `git push origin ブランチ名`<br>
変更したローカルブランチにいる状態で実行すると指定したリモートブランチに変更を反映できる

##delete

- `git branch -d ブランチ名`
マージ済みのブランチのみ削除

- `git branch -D ブランチ名`
どんなローカルブランチでも削除できる

- `git push --delete origin ブランチ名`
リモートブランチを削除
※originはリモートリポジトリのこと

##stash
- `git stash`
変更を退避する


- `git stash save "message"`
メッセージをつけて退避

- `git stash list`
退避した作業一覧を見る

- `git stash apply stash@{0}`
退避した作業を戻す

- `git stash drop stash@{0}`
退避した作業を消す

- `git stash pop stash@{0}`
applyとdropを同時に行う


- `git stash clear`
退避した作業を全削除
『Unity C# 個人用メモ』オブジェクトをランダムな座標へ一定時間ごとに移動させる 

自分用メモ
わざと区切ってるけど全部１枚の流れ
###必要になる素材を作る
```
public class RandomIdou : MonoBehaviour
{
    //座標を再計算しても良いかの判定
    private bool bl = true;

    //移動先の座標
    private Vector3 pos;

    //x座標代入用
    private float x;

    //z座標代入用
    private float z;

    //移動する速度
    private float speed = 3f;

    //移動範囲計算用
    private int i = 5;
```
###初動用の座標を作る

```
    void Start()
    {
        //Randomな値を代入する
        x = Random.Range(-i, i);
        z = Random.Range(-i, i);
        
        //↑で出た値を座標に代入する
        pos = new Vector3(x, transform.position.y, z);
    }
```
###座標の移動と再計算

```
    void Update()
    {
        //移動するときの速度用
        float step = speed * Time.deltaTime;

        //座標をpos座標へstepの速度で移動させる
        transform.position = Vector3.MoveTowards(transform.position, pos, step);

        //座標の再計算を行ってよく、座標が目的地に着いた時
        if (bl == true && transform.position == pos)
        {
            //2秒後再計算を行う
            Invoke("Idou", 2f);
            //毎フレーム計算しない様に判定を変える
            bl = false;
        }
    }
```
###再計算用のメソッド

```
    void Idou()
    {
        //移動するときの値への減少率を計算
        float xp = 1f - System.Math.Abs(transform.position.x) / 5f;
        float zp = 1f - System.Math.Abs(transform.position.z) / 5f;

        //x座標が中心より大きい時（中央より右側へ行ったとき
        if (transform.position.x > 0)
        {
            //右側へ移動する範囲にのみ減少率を掛けRandomな値を計算する
            x = Random.Range(-i, i * xp);
        }
        //x座標が中心より小さい時(中央より左側へ行ったとき
        else
        {
            //左側へ移動する範囲にのみ減少率を掛けRandomな値を計算する
            x = Random.Range(-i * xp, i);
        }

        //y座標ver(以下略
        if (transform.position.z > 0)
        {
            z = Random.Range(-i, i * zp);
        }
        else
        {
            z = Random.Range(-i * zp, i);
        }

        //目的地座標posに計算結果の値を代入する
        pos = new Vector3(x, transform.position.y, z);

        //再計算をしてもよい判定を付ける
        bl = true;
    }
Golangのデータベース操作を雑多にまとめる

本当に雑多に走り書き、DBはsqlite3を用いる。

# テーブルの作成

```go
func main() {
    DbConnection,  _ := sql.Open("sqlite3", "./data.sql")
    defer DbConnection.Close()
    cmd := `CREATE TABLE IF NOT EXISTS person(
                name STRING,
                age INT)`
    _, err := DbConnection.Exec(cmd)
    if err != nil {
        log.Fatalln(err)
    }
}
```

# テーブルに挿入
```golang

func main() {
    DbConnection := sql.Open("sqlite3", "./data.sql")
    defer DbConnection.Close()
    cmd := "INSERT INTO person (name age) VALUES (?, ?)"
    _, err := DbConnection.Exec(cmd, "Nancy", 24)
    if err != nil {
        log.Fatalln(err)
    }
}
```

# テーブルを更新

``` golang

func main() {
    DbConnection := sql.Open("sqlite3", "./data.sql")
    defer DbConnection.Close()
    cmd := "UPDATE person SET age = ? WHERE user_id = ?"
    _, err := DbConnection.Exec(cmd, "1234)
    if err != nil {
        log.Fatalln(err)
    }
}
```

# テーブルからMultiple Selectし、結果をPerson構造体のスライスに詰める

DbConnection.Queryを使い、結果をrows.Next()でループを回す

```golang

type Person struct {
    Name string
    Age int
}

func main() {
    DbConnection := sql.Open("sqlite3", "./data.sql")
    defer DbConnection.Close()

    cmd := "SELECT * FROM person WHERE"
    rows, _ := DbConnection.Query(cmd)

    var persons []Person
    for rows.Next() {
        var p Person
        err := rows.Scan(&p.Name, &p.Age)
        if err != nil {
            log.Println(err)
        }
        persons = append(persons, p)
    }
}
```

# テーブルからSingle Selectし、結果をPerson構造体にする

DbConnection.QueryRowを使う。


```golang
func main() {
    DbConnection := sql.Open("sqlite3", "./data.sql")
    defer DbConnection.Close()

    cmd := "SELECT * FROM person WHERE age = ?"
    row := DbConnection.QueryRow(cmd, 28)

    var Person p
    err := row.Scan(&p.Name, &p.Age)

    if err != nil {
        // 条件を満たすものが見つからない場合
        if err == sql.ErrNoRows {
            log.Println("No row")
        // そういうわけではないがエラー
        log.Println(err)
    }
}
```

# テーブルからデータを削除

```golang
func main() {
    DbConnection := sql.Open("sqlite3", "./data.sql")
    defer DbConnection.Close()

    cmd := "DELETE FROM person WHERE user_id = ?"
    row := DbConnection.Exec(cmd, 1234)

    if err != nil {
        log.Fatalln(err)
    }
}
```

# クエリインジェクション対策
* valueは`?`でエスケープする
* ただし、table名は`?`で挿入できず、`%s`をplaceholderとする
Kotlin入門:定数とは

実際に読んでみて良かった書籍について情報を発信していますので、
よろしければ[Twitter](https://twitter.com/KaoruTojo_Novel)のフォローもお願いします。


※コメント閲覧推奨
※一般的に定数と言うとconstキーワードを使用した「コンパイル時定数」のことを指す。

##val命令

定数を宣言するにはval命令を使います。
以下を実行するとエラーになります。

```Kotlin
fun main() {
    val name = "山田"
    name = "鈴木"
    println(name)
}
```

ただし、配列を定数とした場合にはその要素は変更可能です。

```Kotlin
fun main() {
    var data = arrayOf(1,2,3)
①  data = arrayOf(11,22,33)
②  data[0] = 10
    println(data[0])
}
```

①では配列そのものを変更しようとしているのでエラーになります。

②では配列の要素を変更しようとしているのでエラーにはなりません。


###varとval

基本的にはvalの使用を推奨します。
というのも、コードを書いていく上では変数に再代入する局面があまり発生しないからです。

保守性の観点からvarの使用は非推奨です。
なぜならvarがあると、どこかで変更（再代入）されるかもしれない
可能性を考慮しながらコードを読み進めることになるからです。
再代入を想定していないならば、原則としてvalの使用を推奨します。
【Laravel】DBのレコードを元に生成したcsvのダウンロードを行うためのController

# やりたいこと
Controller内でデータを取得し、csvのレスポンスを生成して返すControllerを作成します。
どこかのストレージにすでに存在するcsvをレスポンスとして返すものとは少々異なります。

# 実装
## モデル
扱うデータ用オブジェクトは下記のものします。

```app\Models\Person.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Person extends Model
{
    protected $table = 'persons';

    protected $fillable = [
        'name',
        'age'
    ];
}
```

## ルーティング

リクエストをControllerにつなぎこみます。
ここは普通にGETリクエストを行う場合と同じやり方。

```routes/web.php
Route::get('/persons/download/csv', 'PersonController@download_csv');
```

## コントローラー
ここでレスポンスでcsvを返す処理を書きます。

```app\Http\Controllers\PersonController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Schema;
use App\Models\Person;

class PersonController extends Controller
{
    public function download_csv(Request $request)
    {
        $persons = Person::all();
        $persons = $persons->toArray();

        // 全カラム名を配列で取得
        $header = Schema::getColumnListing((new Person)->getTable());

        // レスポンスストリームにcsv用のデータを書き込み
        $stream = fopen('php://temp', 'r+b');
        fputcsv($stream, $header);
        foreach ($persons as $row) {
            fputcsv($stream, $row);
        }
        rewind($stream);
        $csv = str_replace(PHP_EOL, "\r\n", stream_get_contents($stream));
        $csv = mb_convert_encoding($csv, 'SJIS-win', 'UTF-8');
        $headers = array(
            'Content-Type'        => 'text/csv',
            'Content-Disposition' => "attachment; filename=persons.csv", // ファイル名
        );

        return Response::make($csv, 200, $headers);
    }
```

これで、 `/persons/download/csv` にアクセスすれば、csvがダウンロードされます。

# 参考記事
[横長のデータでも Laravel の CSV 出力を行うためには](https://qiita.com/moobay9/items/ed4c19b01d10c5db091b)
Laravel の言語ファイルを一発で配置する ライブラリ作った

以下のファイルだけだと、リマインダーメールなどは日本語化されないので、`ja.json`も配置するコマンドを作成しました。

- `Resources/lang/ja/auth.php`
- `Resources/lang/ja/pagination.php`
- `Resources/lang/ja/passwords.php`
- `Resources/lang/ja/validation.php`

GitHub

[https://github.com/ShibuyaKosuke/laravel-language-setting](https://github.com/ShibuyaKosuke/laravel-language-setting)

# laravel-language-setting

## インストール

```
composer require shibuyakosuke/laravel-language-setting --dev
```

## コマンド

`config/app.php` 先にプロジェクトの言語を設定しておきます。

```
'locale' => 'ja',
```

## 使用方法

### 言語ファイルのお配置

```
php artisan lang:setting ja
```

以下のようなファイルが配置されます。

- `Resources/lang/ja.json`
- `Resources/lang/ja/auth.php`
- `Resources/lang/ja/pagination.php`
- `Resources/lang/ja/passwords.php`
- `Resources/lang/ja/validation.php`

### 対応している言語のリストを表示する

```
php artisan lang:list
```

## 現在対応している言語

| language | locale |
|:--------:|:--------:|
| Japanese | ja |

## Contribution

他の言語ファイルをお持ちの方は、是非、プルリク送ってください。
Laravel requestのバリデーションをControllerで受け取りたいとき

どうしてもコントローラ側でバリデーションエラーを制御したかったときに実装した内容を備忘録として残します。

## バージョン
Laravel Framework 5.5.45
PHP 7.2.25 

## やったこと


```failedValidation``` を override して、Handlerに飛ばないようにします。
```getValidator```を実装して、インスタンスを返せるようにします。

```php:GetIndexRequest.php
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;

class GetIndexRequest extends FormRequest
{
  /**
   * リクエストに適用するバリデーションルールを取得
   *
   * @return array
   */
  public function rules()
  {
      return [
          'title' => 'required|max:255',
          'body' => 'required',
      ];
  }

    /**
     * 定義済みバリデーションルールのエラーメッセージ取得
     *
     * @return array
     */
    public function messages()
    {
        return [
            'title.required' => 'A title is required',
            'body.required'  => 'A message is required',
        ];
    }

    /**
     * @param Validator $validator
     */
    protected function failedValidation(Validator $validator)
    {
    }

    /**
     * @return  Validator  $validator
     */
    public function getValidator()
    {
        return $this->getValidatorInstance();
    }
}
```

Controller側で受け取ってみます。

```php:HogeController.php
public function find(GetIndexRequest $request)
{
    $validator = $request->getValidator();
    if ($validator->fails()) {
       // エラーが表示される
        echo $validator->getMessageBag()->first();
    }
}
```
自分用メモ Flutterでwidgetを親widgetいっぱいに引き伸ばす

#flutterのwidgetは子のサイズに合わせて縮むように出来ている

```dart

Card(
   color:Colors.blue,
   child:Text("ぴったり"),
)

```

![Screenshot_1582278302 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520648/c5324f17-4b67-d7df-49bb-d40c2a345b54.png)

これを親いっぱいに引き伸ばしたいけど、どこにもそんな引数がない！

###正解:SizedBox.expandを使う

```dart

Card(
   color:Colors.blue,
   child:SizedBox.expand(
      child:Text("ゆったり"),
   ),     
)

```

![Screenshot_1582278650 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520648/36fd5cbe-faed-5a76-8e77-4894a38645af.png)

###SizedBoxその他
SizedBoxは大きさを指定出来るWidget。デフォルトコンストラクタで呼び出しても引き伸ばし出来る。
width: と　height: にそれぞれdouble.infinityを設定。

```dart

SizedBox(
   width: double.infinity,
   height: double.infinity,
   child: Text("てにゅうりょく"),
)

```
avy-zapのハック

avy-zapというパッケージをご存知だろうか。
プログラムや文章を書いているときに「カーソル位置から"あの辺り"まで一気に削除したい」ときに有用なコマンドである。るびきち氏のブログにも紹介されている。

- [avy-zap.el : zap-to-char(M-z)をavy化して自然に拡張する](http://emacs.rubikitch.com/avy-zap/)

なおavy-zapパッケージのリポジトリは以下である。一度使ってみれば、細かい説明は必要ないほどに分かりやすい。

- https://github.com/cute-jumper/avy-zap

削除する際の挙動として、`kill-ring`に保存して後で再利用できる形（yankなど）で削除するか、保存せずに削除するかを選択できる。実際、変数`avy-zap-function`をカスタマイズし、

- kill-ringに保存して削除する場合は `(setq avy-zap-function 'kill-region)`
- そのまま削除する場合は `(setq avy-zap-function 'delete-region)`

のようにする。筆者はこれをシームレスに切り替えられたら面白いと考えたので、以下のコードを書いた。プレフィックスキー(C-u)をつけて呼び出すかどうかで上記の挙動を切り替えるものである。

```emacs-lisp
(require 'avy-zap)

(defun my-avy-zap-to-char-dwim (&optional prefix)
  "avy-zap-to-charの改良版。
プレフィックスをつけないと単なる削除。
プレフィックスをつけるとkill-ringに保存して削除。"
  (interactive "P")
  (message "char:")
  (if prefix
      (let ((avy-zap-function 'kill-region))
        (avy-zap-to-char))
    (let ((avy-zap-function 'delete-region))
      (avy-zap-to-char))))

(defun my-avy-zap-up-to-char-dwim (&optional prefix)
  "avy-zap-up-to-charの改良版。
プレフィックスをつけないと単なる削除。
プレフィックスをつけるとkill-ringに保存して削除。"
  (interactive "P")
  (message "char:")
  (if prefix
      (let ((avy-zap-function 'kill-region))
        (avy-zap-up-to-char))
    (let ((avy-zap-function 'delete-region))
      (avy-zap-up-to-char))))
```

適当なキーバインドをアサインするのも一興だろう。

```emacs-lisp
(global-set-key (kbd "M-Z") 'my-avy-zap-to-char-dwim)
(global-set-key (kbd "M-z") 'my-avy-zap-up-to-char-dwim)
```

以上
Kotlin入門:配列とは

実際に読んでみて良かった書籍について情報を発信していますので、
よろしければ[Twitter](https://twitter.com/KaoruTojo_Novel)のフォローもお願いします。


##配列を生成する方法
arrayOf関数に格納したい要素を列挙する。

```Kotlin
var data = arrayOf(0,1,2)
```

##空の配列

要素が空の配列を作成するには以下の通りになります。

```Kotlin
var data :Array<String?> = arrayOfNulls(3)
```

nullを代入することになるので要素型には?をつけます。
右辺にはarrayOfNulls関数です。

```Kotlin
var data :Array<要素型?> = arrayOfNulls(要素数)
```

##配列要素を取り出す

```Kotlin
fun main() {
    var data = arrayOf(1,1,1)
    data[1] = 10
    println(data[1])
}
```
実行すると結果は

```
10
```

になります。
forEachメソッドを使うと要素を順番に取り出せます。

```Kotlin
fun main() {
    var data = arrayOf(0,1,2)
①  data.forEach{println(it)}
}
```

実行すると結果は

```
0
1
2
```

となります。

①のitは予約変数と言います。
受け取る引数が一つの場合に受け取ることができます。
予約変数とはKotlinであらかじめ定義されている変数のことです。
イベントレポート（ITエンジニアの振る舞い方、キャリアパスについて）

自社で大手IT部長の方を招いてITエンジニアの振る舞い方やキャリアパスについての
パネルディスカッションを開催しましたので、内容を共有したいと思います。
※今回はSES事業に焦点を当てています

## 現場での振る舞い方
### 採用する立場から見た評価の基準
協力会社外部の方に対しては特定の領域が強いイメージを持っているが、
ネット系の現場（一つの案件がそれほど大きくない）なので社員との違いは意識していない
AWS資格は安心感ある

### どんな振る舞いが評価されるのか？
漏れなく正確に作業をすることが重要
＋アルファの提案ができる
周りと比べて圧倒的に目立つこと

### 質問したい時にタイミングを迷う
質問するときは時間を奪うという意識を持つ
何でも質問するのではなく、ググっても分からないことを聞く
ヘルプデスクであれば俊敏性も大事。現場特有のことは調べずに聞く

### 技術力ない上位者に技術のことを伝えるのが難しい
興味がない上位者に説明するのは難しい。
システムコール全てを調べさせられそうになった。
立場によって見るものが違う。相手目線で考えられるか。

### 大手IT部長の方自身の振る舞い方はどうだったか
上位者が何を考えているかについては常に意識していた。
分からなくても考える癖はつけていた。
全体像を意識していた。

### 長期勤務について
時間短くてもアウトプットは同等のものを出せるような工夫、効率化を目指す時代。

## キャリアパスについて
### どう考えていくか
マネジメント（PG⇒SE⇒PM）系もあるが、エキスパート系（スペシャリスト）もあり。
AWS資格は安心感ある！でも好きでやっている人にはかなわない。

エキスパートでなければPMやITILを目指すのもあり。
話を聞いただけでは理解できないので、プライベートでもITに触れることは大事
（AWSでWordPress開設など）

### キャリアパスの見つけ方
最初に建てたキャリアパスと今は違う。
30代半ばでようやく定まったと思う。
色々やってみたが、それぞれの経験が生かされていると感じる。

常に新しいものに触れていないといけないから興味を持てるかどうかが大事。

AWSとAzureは伸びてきているので、それぞれの仕組みを知るのは良いことだと考える。

## 自社プロジェクト紹介でのコメント
開発言語10個知ってるよりは１、２個でもこういうシステムを作ってきたという方が信頼性ある
技術情報はyou tubeで収集している、英語のyou tubeも見ている
情シス業務で得られることは多い

## 所感
現場での振る舞い方については、相手の目線に立った動き方ができるかが重要だと感じました。
キャリアについては計画立てたとしても変化が速いIT業界ではその通りになることは少ないので、
目の前のことに対して真剣に取り組むことが大事なのかなと思いました。
Tabelau初心者の入門メモ②

さて、昨日に引き続き今日もめもめもφ(..)メモメモ

#アナリティクスペイン関連
##１．傾向線
操作：
アナリティクスペインから傾向線をドラッグ

散布図とかラインチャートの時に使う。

##２．リファレンスライン
操作：
アナリティクスペインからリファレンスラインをドラッグ

定数線とか、平均や合計など集計値で線を引ける。
その上で、自身でみたいレコードを選択すると、選択したレコードにおける線が再描写されるため便利。

##３．ブレッドグラフ
サンプルにもともと入っているスーパーストアで作ってあるやつ。
![ブレッド.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589595/bea5f8df-a1c3-1307-cca7-95d2ed5e4b7a.png)
操作：
比較対象としたいメジャーのデータをマークの詳細にドラッグ。
アナリティクスペインから分布バンドを選択してドラッグ。（この際、セルを対象に。）
あとは例えばパーセントで100%、比較対象としたいメジャーを選択すれば完成。

いろんな形で使える。目標達成であれば予算を100%で設定すればいいだけ。
グラフの数を減らせるので、ビジュアル的に◎。
リファレンスラインと合わせるとなお良し。


##４．箱ひげ図
 ![箱ひげ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589595/881042e5-cecf-6bfa-65d1-2a117bfc9b2f.png)
操作：
メジャーを非集計で行か列にドラッグ⇒アナリティクスペインの箱ひげ図をビューにドラッグ⇒マークを丸に変更

分布と外れ値を見つけるのによく使うやつ。詳しい意味は調べてください。

##５．クラスター
操作：
アナリティクスペインからクラスターをドラッグ

グラフに入れると自動もしくは指定した数でクラスターにグループ分けしてくれる。
作成されたクラスターをデータペインにドラッグ＆ドラッグすれば、ディメンジョンとして保持も可能。あまり使うタイミングないかな・・・。

##６．予測
操作：
ビューを作成した後に、アナリティクスペインの予測をビューにドラッグ

過去のデータを基に未来の予測を作れます。（上下幅も。）作れるけどあんま使わないかな。


#その他
##７．プライマリグループ
操作：
①同一ID、異なるカテゴリのデータを持ったデータソースを2つ準備する。
②片方をプライマリデータソース、もう片方をセカンダリデータソースとして接続する。
③IDでリレーションシップを作成。
④IDとセカンダリデータソースのディメンジョンをビューに表示
⑤セカンダリデータソースのディメンジョンを右クリック⇒「プライマリグループの作成」

![プライマリグループ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589595/8fbf192c-e331-0e50-3677-28400b4e24da.png)
上記の図はスーパーストアに「カテゴリ」がなく、別のデータソースからカテゴリのグループを設定しようというケース。

感想：
めっちゃ便利！ID毎に別データからいろんなカテゴリデータを持ってきてディメンジョンを作成できるので、データが散らばっている場合は効果的に活用できる。
プライマリグループ作成後はセカンダリデータソースを閉じても問題ないので、必要なければ閉じるようにしたほうが間違えが起きなくていいかと。


##８．パラメーター
操作：
データペインのディメンションの右側の「▼」をクリック⇒パラメーターの作成

使いこなせたら非常に便利。パラメーターだけでは意味をなさないので、一緒に計算フィールドを設定する必要があるので注意。
よくある使い方は、とあるディメンジョンを選択するパラメーターを作成。その後、パラメーターとディメンジョンが等しいかどうかの判定を行う計算フィールド(*)を作って、フィルターへ入れるという流れ。

(*)よく使う計算フィールドの中身　⇒　TRUE or FALSEを判定する
[パラメーター] = [対象のディメンジョン]

##９．ヒストグラム（ビンの作成）
操作：
（ビンの作成）ヒストグラムを作りたいメジャーを右クリック⇒作成⇒ビン⇒ビンのサイズを任意の値に設定
（ヒストグラムの作成）作成したビンのディメンジョンを列に、メジャーをカウントで集計して行に入れれば完成。
感想：
ヒストグラムとは、あらかじめ決めた範囲毎に何件のレコードが存在するかを並べたもの。
いろんな分布をみるのによくでてくるやつですね。
ビンのサイズはパラメーターで可変にできるので、基本パラメーターで作っちゃったほうが後で操作できていいかも。


##１０．メジャーの非集計
操作：
メジャーを右クリックして行or列にドラッグ。
出てくるポップアップの一番上を選択。

1レコード毎のメジャーの値をビューにプロットできるので、散布図が作れないときに使える。（でもあんま使わないかな・・・。）

##１１．集計/非集計
そもそも集計と非集計ってなにって方は下記サイトがわかり易いかな・・・。
http://tableaujpn.blogspot.com/2015/09/understanding-aggregate-and-non.html
フィルタ等をかける時に、集計であれば集計後の数字でフィルタ、非集計であれば1レコード毎の数字でフィルタと結果が変わってくるので、試してみるとわかり易いかも。
未だに計算フィールド作るときにつまづくポイント。

#さいごに
LOD計算の事も書きたいけど、うまく言語化できない。
Ruby のクラスメソッドを委譲したい時は SingleForwardable を使おう

[Ruby 2.7.0 リファレンスマニュアル > ライブラリ一覧 > forwardableライブラリ > SingleForwardableモジュール](https://docs.ruby-lang.org/ja/latest/class/SingleForwardable.html) より。

## 結論

クラスメソッドの委譲には `SingleForwardable` が使える（というのが調べてもパッと出てこなかったのでメモ :memo:）。

```ruby:例
require 'forwardable'

class Implementation
  def self.service
    puts "serviced!"
  end
end

module Facade
  extend SingleForwardable
  def_delegator :Implementation, :service
end

Facade.service # => serviced!
```

## 具体例


例えば、`Bugsnag` gem を使いたいが、そのまま直で使うと後で Sentry に乗り換えづらいので、`BugReport` モジュールを用意してきちんとラップしておこうと思った場合などに、クラスメソッドの委譲が行きます。

```ruby:Bugsnagの例
module BugReport
  extend SingleForwardable
  def_delegator :Bugsnag, :notify
end

BugReport.notify # Bugsnag.notify が実行される
```


Rails 使ってる場合は `ActiveSupport` の `delegate` 使っても良いと思います。

```ruby:delegateの例
module BugReport
  class << self
    delegate :notify, to: :Bugsnag
  end
end

BugReport.notify # Bugsnag.notify が実行される
```

委譲、便利ですね :thumbsup:
【初心者向け】Railsで投稿される日時を日本時間に変更する（タイムゾーンの修正）

#タイムゾーンを日本に変更するにはconfig/application.rbを修正する

#参考

伊藤さんいつも参考にしています、ありがとうございます。
https://qiita.com/jnchito/items/831654253fb8a958ec25


#どのように記述するのか

```ruby

module hogehoge
  class Application < Rails::Application

   config.time_zone = 'Tokyo'
   config.active_record.default_timezone = :local

  end
end
```

上記2文を追加するだけ。


#追加した記述の2文を解説

```ruby

config.time_zone = 'Tokyo'
```
↑実際の表示を修正する記述


```ruby

config.active_record.default_timezone = :local
```
↑DBに保存する際にどの時間帯で保存するかの記述


#伊藤さんが推奨されているlメソッドが便利でした！！しかも設定簡単


```ruby

module hogehoge
  class Application < Rails::Application

   config.time_zone = 'Tokyo'
   config.active_record.default_timezone = :local

  end
end
```
この設定を下記のように修正します。


```ruby

module hogehoge
  class Application < Rails::Application

    config.i18n.default_locale = :ja
    config.active_record.default_timezone = :local

  end
end
```

config.time_zone = 'Tokyo'を書き換えただけですね。

#config/localesにja.ymlファイルを作成

```ruby

ja:
  time:
    formats:
      default: "%Y/%m/%d %H:%M:%S"
```

と記述しました。

#このあと、必ずサーバーを再起動（再起動しないと反映されないっぽい）

あとは、時間を表示させたいviewに

```ruby

<%= l post.created_at %>
```

っといった形式にするだけ。


ここは違う、こうした方が良い等々ございましたらご指摘いただけますと幸いです。
最後までみていただき、ありがとうございます。
勉強会について

# 勉強会について


---
目次

1. 勉強会ってどんなのがあるの？
1. 勉強会ってだれがやってるの？
1. 勉強会ってお金かかるんじゃないの？
1. 勉強会に参加するメリットって何？
1. 勉強会についてまとめ
1. おまけ　md形式って何？

---

## 勉強会ってどんなのがあるの？

大きくは以下の４つ

（以降、個人所感による勉強会感のため、実情と異なる場合は実情を優先の上ご指摘ください）

1. セミナー形式
    - 輪講形式（ゼミ形式）を含む
1. LT形式
    - 同一テーマでのLTの場合はゼミ形式／セミナー形式に含むこともある
1. ハンズオン形式
    - ワークショップ形式ともいう
1. フリースタイル形式
    - もくもく会

（細かく他もあるが割愛）

---

## 勉強会って誰がやってるの？
- 企業
    - 人材派遣会社が多い印象
        - そもそもこの業界はSESが多いのだが
    - 自社開発製品を持つ企業の発表もある
- 有志団体／コミュニティ
- 個人

主催は単独でというわけではないこともある

- 例えば有志団体の開催に際し、企業が協賛として会場や飲食物の提供をすることがある
    - 大体そういう場合はアピールタイム…CM的な発表が入る

---

## 勉強会ってお金かかるんじゃないの？

一概にそうとも言い切れません。

- 企業主催の場合は、研修形式ではない場合はたいてい無料
    - 入門レベルのハンズオンの場合でも無料だったりする
- 有志団体やコミュニティ／個人が主催の場合、会場使用料相当というケースが多い
    - 「コワーキングスペース」が会場のケースが多いため
        - だいたい500円～1000円くらい
    - 貸会議室を人数割りする前提で借りるケースもある
    - （先に書いた通り）企業協賛として会場提供されている場合無料のことが多い
- マンツーマンに近いハンズオンや、大規模セミナーあたりはお高いものもある
    - 勉強会と言えなくはないが、同じ「勉強会」呼びだが毛色が違うものもある

- 言うまでもないけど自社の内部勉強会は（ふつうは）無料
    - 業務後にやるやつは勤務時間外扱いのことも
        - その場合フォローとしてか会社のお金で飲み食いできたりすることも多い
    - 会社にもよるけど発表者に寸志を出してくれる会社もある

---

## 勉強会に行くメリットって何？

- 知見が広がる
    - 業務外の知識を学べる機会って大事
- 同様の問題意識／成長意識を持った人と知り合えたりする
    - 人脈って大事
- タダ飯が食える、タダ酒が飲める
    - 本当に無料かどうかはさておき、コミュニケーション大事

---

## 勉強会を開催するメリットって何？

（honamiの私見を含む一例です）

- 企業：自社の宣伝（製品や開発文化等）、リクルーティグ
- 有志団体：技術の普及を通したコミュニティの振興
- 個人：スキルアップ、キャリアアップのためのフック作り
- 社内勉強会：社内コミュニケーションの促進、スキルアップ

単に懇親会という名目でお酒を飲みたい、というケースも結構ある

---

## おまけ　md形式って何？

md→MarkDown

- プレーンテキスト（ただのtxt）を別文書に変換する為の記法
- テキストエディタでも読めるが、対応したビューワで開くと箇条書きや段落／ページ区切りが反映される
- git系を中心に、コードに沿える文書として使用されているケースが増えてきている
    - gitbucket（社内gitでも使用している）向けのドキュメント(特にreadme) はmd
- wiki記法に似ている（互換性があるwikiもある）
    - StackOverflowやQiitaといった技術系サイトはmdを改変した記法
    - JIRA（atlassian）等はリッチエディタがほぼmdと同じ
LightGBMでランキング学習

# LightGBMでランキング学習

LightGBMにはランキング学習するためのアルゴリズムが実装されているのでその使い方を簡単に紹介します



公式のドキュメントやすばらしい日本語記事もあるのですが、***Python APIを用いた例が紹介されているものは少なかったのでここにまとめます***。実際、データをファイルから読み取って使用するより、Pythonでデータ整形してからそのデータをnp.arrayやpd.DataFrameとして渡すほうが使用頻度として多いと思います。
そもそもランキング学習がよくわかってない場合やLightGBMの基本的な使い方がわかってない場合は別の記事を参照してください。

- LightGBM公式ドキュメント : https://github.com/microsoft/LightGBM/tree/master/examples/lambdarank
- 世界一わかりやすいLGBMでのランキング学習の解説記事 : http://szdr.hatenablog.com/entry/2018/12/05/001732
- 世界一わかりやすいランキング学習解説ブログ : http://szdr.hatenablog.com/
- LightGBMの基本的な使い方 : https://blog.amedama.jp/entry/2018/05/01/081842

※ LightGBMのランキング学習アルゴリズムはlambdarankとrank_xendcgが実装されていますが、基本的な使い方は同じなので今回はlambdarankを用います



### パラメータ
パラメータのobjectiveをlambdarankにすることでランキング学習のアルゴリズムに設定されます。評価指標(metric)はndcg, mapなどがあります。ndcg_eval_atに設定した値によってvalidデータのndcgやmapが算出されます。例えば、今回のような`[3, 5]`を渡した設定だと、ndcg@3とndcg@5が算出されます。

```python
params = {
    'objective': 'lambdarank',
    'metric': 'ndcg',
    'ndcg_eval_at': [3, 5],
    'boosting_type': 'gbdt',
}
```

### データセット
最も重要なのはデータセットにクエリデータを渡さなければいけないことです。先程参照した解説記事ではクエリファイルを渡すか、クエリコラムを渡すかといった方法が紹介されていますが、データをファイルから読み込まない今回の設定ではうまくいきません。`group_column`というパラメータはデータをファイルから読み込むときにしか使えないので注意が必要です。そのため今回のようにデータをnp.arrayやpd.DataFrameのようなデータで渡す場合は、下のように**Datasetクラスの引数として、`group`にクエリデータを渡します**。

```python
dtrain = lgb.Dataset(train, group=train_query)
dval = lgb.Dataset(test, reference=dtrain, group=test_query)
moodel = lgb.train(params, dtrain, valid_sets=dval)
```

このクエリデータとは何行が同じクエリかということを表しており、例えば下のような配列になります。最初の3行が同じクエリに属する、次の13行が同じクエリに属する、...といったことを表しています。ここで、また注意しなければならないのはDatasetクラスにわたすデータはクエリごとに連続して配置されていなければなりません。

```
[3, 13, 5, 8, 19,....]
```

学習は通常どおり行えば問題ないです。

### 予測
学習させたあとは予測です。この際に`model.predict()`関数にクエリデータをわたす引数がないぞと思う方がいるかも知れませんが、予測の際にはクエリデータは必要ありません。lambdarankはランキングからスコア算出モデルを学習させる方法であって、ランキングをそのまま予測するモデルではない$^{※1}$ので予測にクエリデータ必要ありません$^{※2※3}$。

```python
pred = model.predict(test, num_iteration=model.best_iteration)
```



※1 : もちろん予測スコアでソートすればそれがそのままランキングになります
※2 : validデータのクエリを渡しているのは、予測のためではなくvalidデータのndcgやmapを算出するのにクエリデータが必要だからです
※3 : LightGBMも公式examplesでは予測の際にもrank.test.queryというクエリを渡していますが、いらないんじゃないかと思います



### 参照
- 公式ドキュメント : https://github.com/microsoft/LightGBM/tree/master/examples/lambdarank
- 世界一わかりやすいLGBMでのランキング学習の解説記事 : http://szdr.hatenablog.com/entry/2018/12/05/001732
- ランキング学習： RankNetからLambdaRank、そしてLambdaMARTへ : https://qiita.com/kiita_da_yo/items/8ba552fce5b99cbf85fd
- Lambdarank, Lambdamartの論文 : http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.180.634&rep=rep1&type=pdf
AWS ECS サービス作成時に生成されたService discovery nameを消す

# はじめに
ECSで色々と作成しているとサービスが乱立してしまいがちで、それによってエラーが発生したりもします。
本記事はそれらを削除する方法をメモしておくものです。




# 要らないサービス名称を消す
**AWS Cloud Map**からサービス名称を一覧表示することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570763/8c828b14-5924-9018-4203-805b66cf1525.png)


ここで不要なもののラジオボタンを押し、削除ボタンを押してあげれば削除完了となります。

なお、サービスインスタンスが存在する場合は、そちらを先に解除しないと削除できません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570763/77dab78b-6f1a-3a78-e831-fd4237f252f6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570763/05f509a9-4f26-867b-a18a-9af0555598c1.png)
※Route53の```.local```ホストゾーンの当該レコードも一緒に削除されます。

# まとめ
筆者はECS設定中に以下のエラーに遭遇しました。
```creation failed: Service already exists. (Service: AWSServiceDiscovery; Status Code: 400; Error Code: ServiceAlreadyExists; Request ID: xxx)```

Serviceが既に存在している為に作成できないとか。

[こちらの記事][1]によれば、以下で対処可能とのことです。
>対処1：別のサービス名で作成する。
>対処2：「サービスの検出サービスの設定」を「既存のサービスの検出サービスの選択」で進める。

が、そもそもサービスが乱立していて整理されていないのが根本原因だと思い、
不要なものを削除する方法を調べるに至りました。

# 参考
[Amazon ECS サービス作成に失敗する][1]

[Amazon ECS 開発者ガイド][2] 
※CLIで削除したい場合


[1]:https://qiita.com/leomaro7/items/2d8da03bb686a03934b1
[2]:https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/delete-service.html
PythonによるDiffusion MRIのbvec fileの極性変更

# はじめに
diffusion MRIで重要なMPGのGradient Tableであるbvecの極性がMRI装置と解析ソフトウェアで互換性がない。
被験者は200人以上いるため、一人ひとり手直しするのは困難である。
そこで、Pythonでbvec fileの中の極性を任意に変更できるスクリプトを作成した。
FSLやMRtrixではbvecの極性を修正するコマンドはないんじゃないかな？

詳しい解説・コードは[PythonによるDiffusion MRIのbvec fileの極性変更](https://www.aiprogrammers.net/entry/2020/04/19/004724)をご覧ください。
Binwalkで-eオプション(抽出)ができないとき

# 環境
- Windows 10
- Binwalk v2.1.2-4521cf6
- git bash for windows

# 問題
git bash上で

```
$ binwalk -e data
```

のように`-e`オプションを付けても，含まれているデータが抽出できなかった．

# 解決
ヘルプにファイルのシグネチャ，拡張子及び実行コマンドを指定できる`-D`オプション或いは`--dd`オプションを使用する．

```
$ binwalk --dd=".*" data
```

これにより，データが抽出できた．

`-D`，`--dd`オプションは以下の通り．

```
$ binwalk --help
...
    -D, --dd=<type:ext:cmd>      Extract <type> signatures, give the files an extension of <ext>, and execute <cmd>
...
```
Rails Whereで取得した値にdestoryが使えない理由

##詰まったこと

Whereを使い取得した値をdestroyを使って削除しようとしたが、以下のエラーが出てできなかった。

```
ArgumentError (wrong number of arguments (given 0, expected 1)):
```

##解決方法

whereで取得した値は配列になっているため、destroyを使えない。
find_byを使うと削除できるようになる。

以下の記事を参考
[Railsのwhereメソッドと仲良くなろう](https://qiita.com/yu-croco/items/c175583cd65585e1058c)


```rb
product = Product.where(product_id: 3)
product.destroy

⬇︎

product = Product.find_by(product_id: 3)
product.destroy
```
Slackのカスタム絵文字の数を数える(ElixirとRubyを使って)

# はじめに
- [はてな社内のSlackには、カスタム絵文字が2028個！ 連携アプリ46個で、飲み会ダッシュボタンも爆誕！](https://internet.watch.impress.co.jp/docs/column/slack_info/1235656.html)
- あなたが参加しているワークスペースには何個のカスタム絵文字がありますでしょうか?

# カスタム絵文字数

- 1,667個ありました

# カウント方法
- SlackのAPI [emoji.list](https://api.slack.com/methods/emoji.list)を使います
- tokenが必要になります
    - トークンの取得方法は、[Slack API 推奨Tokenについて](https://qiita.com/ykhirao/items/3b19ee6a1458cfb4ba21) の記事が詳しいです
    - ありがとうございます :bow:
    - 必要なスコープは、`emoji:read`が必要になります
- 以下、[Ruby](https://www.ruby-lang.org/ja/)と[Elixir](https://elixir-lang.org/)を使って書いてみます

# Ruby
```Ruby:slack_emoji_list_count.rb
require 'open-uri'
require 'json'

TOKEN = "xoxp-...secret..."

body = URI.open("https://slack.com/api/emoji.list?token=#{TOKEN}", &:read)
puts JSON.parse(body)["emoji"].reject { |k, v| v.start_with?('alias:') }.size()
```

## 実行結果
```
% ruby -v
ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-darwin19]
% ruby slack_emoji_list_count.rb
1667
```

# Elixir
```elixir:lib/sandbox/slack_emoji_list.ex
defmodule Sandbox.SlackEmojiList do
  @token "xoxp-...secret..."

  def run do
    url()
    |> HTTPoison.get!()
    |> Map.get(:body)
    |> Jason.decode!()
    |> Map.get("emoji")
    |> Enum.reject(fn {_key, value} -> String.starts_with?(value, "alias:") end)
    |> Enum.count()
    |> IO.puts()
  end

  defp url do
    "https://slack.com/api/emoji.list?token=#{@token}"
  end
end
```

以下、Elixirの環境が整っていない方向けに説明をします。

## 1. インストール
- [Installing Elixir](https://elixir-lang.org/install.html)
- macOSの方は、[asdf-vm](https://asdf-vm.com/#/)がオススメです
    - とりあえず試したい場合には[Homebrew](https://brew.sh/index_ja)を使って、`brew install elixir`でのインストールでもよいとおもいます

## 2. プロジェクト作成
```
% mix new sandbox
% cd sandbox
```

## 3. 依存ライブラリを追加
- HTTPクライアントの[HTTPoison](https://hex.pm/packages/httpoison)
- _A blazing fast JSON parser and generator in pure Elixir_の[Jason](https://hex.pm/packages/jason)をmix.exsに追加します
    - (意訳) 純なElixirで書かれた爆速で[Hot! Hot!](https://www.nicovideo.jp/watch/sm15878681)なJSON パーサー、ジェネレーター

```elixir:mix.exs
  defp deps do
    [
      {:httpoison, "~> 1.6"},
      {:jason, "~> 1.1"}
    ]
  end
```

- 依存ライブラリのダウンロード
```
% mix deps.get
```

## 4. ソースコードを追加
- lib/sandbox/slack_emoji_list.ex (前述)を作る

## 5. 実行

```
% iex -S mix
Erlang/OTP 22 [erts-10.5.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Interactive Elixir (1.10.0) - press Ctrl+C to exit (type h() ENTER for help)
iex> Sandbox.SlackEmojiList.run
1667
:ok
```

ありがとうございます:rocket:

# おまけ
- 同僚に、https://${workspace}.slack.com/customize/emoji にアクセスしたときに表示される画面に数がてているとおしえてもらいました
![2c471a8a-02a9-431a-8c44-eb05f56bfa92.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/2c13809c-f17a-0c92-24d8-da0bbb8f226f.png)

- ただ上の結果と1個ずれています
- 少し調査したところ、画像URLの先頭からの文字列が２種類あることがわかりました

```Elixir
%{"https://a.slack-edge.com/" => 1, "https://emoji.slack-edge.com/" => 1666}
```
- "https://a.slack-edge.com/" で始まるほうが無効なカスタム絵文字になっているのかなとおもいましたが、ふつうに使えていました
- これが使えなければ、ああ、これがだめなやつでカウントされていないのだなと納得したわけですが、そうではありませんでしたので謎だけが残りました
js,esファイルをtsに置き換えるのにやったこと

## 置き換える前の状況

- js, es, tsファイルが混在
- テストが書かれてないコードが存在
- JSDocは書かれている（間違ってる箇所あり）

tsからesファイルを読み込むことは出来ないので、呼び出し先のファイルがesだと、呼び出し元ファイルもesで作らないといけない。
どこかのタイミングでesをjsに変更していればよかったのですが、ずるずるとesが増えている状況。

## 目的

- 今より型安全にする
- esファイルを駆逐する

## やったこと

### 型定義ファイルを作成

呼び出し頻度の高いファイルにデコレーターが使われており、それに型を付けることができませんでした。
https://github.com/microsoft/TypeScript/issues/4881

仕方なく以下のように型定義ファイルを作成し、対応しました。

``` Xxx.d.ts
declare module "xxx/xxx/Xxx" {
    import { Test } from "test";

    export default class Xxx {
        static count() => number;
    }
}
```

``` test.ts
// 呼び出しクラスに型なくても
import Xxx from "xxx/xxx/Xxx";
// 型定義ファイルを作ったおかげて型が効く
Xxx.count();
```
### `(* as any)`で対応する。

今回の目的は完全な型づけではなく、tsファイル化することだったので、
依存度が小さい（型付けで得られる効果が小さい）ファイル、かつ、型付けコストが高いものは`(* as any)`で対応しました。 

### `@ts-ignore`する

`(* as any)`で対応できない場合や、型の解決に時間がかかる場合は`@ts-ignore`で対処しました。

## 型がない弊害

型がないので関数のインターフェースが決めれず、以下のようなモンスターが生まれていました。

``` xxx.js
async function something(somethinId: number): Promise<any[] | null | object> {
  if (isHappened) {
    return [];
  }
  if (isSomething) {
    return null;
  }
  return {};
}
```

JSDocは書かれているものの、渡す引数の型を間違えている。（動いているの？:scream_cat:）

``` xxx.js
export default class Test {
    /**
     * コンストラクタ
     * @param {string} name
     * @param {number} id
     */
    constructor(name, id) {
        this.name = name;
        this.id = id;
    }
}

const test = new Test(name, null);
```

その他にも、存在しない関数を呼び出してる等もありました。（実行されないだろう箇所に書いてあったので、問題はなかったです。）

型 >>>>>> コメント

以上です。
Maya で skinned mesh を smooth(subdivision) して skin weight copy する

## 背景

* Maya で(特に)キャラクターモデルがある. UV 付き. skinning あり. render 時は subdivision されるようになっている. 
* subdivide された状態の形状で, skin weight 付きで, データをエクスポートしたい.
* Maya で, メッシュに smooth(subdivision) をかけてからデータを export(glTF など)すると, subdivide された頂点にはスキンウェイトがついていない
  * Skin weight を visualize しても, subdiv された頂点には weight がついていない.  Maya 上では, skinning したあとに subdiv しているので, 動いているように見える(subdiv してから skinning すると, うまくいかない)
* Smooth proxy だと, subdivide されたメッシュ頂点と, skin weight が取得できるが, どうも subdivide される形状が render 時 subdivision と合わないっぽい

skinned mesh に対して, mesh smooth(subdivision) をかけて, skin weight visualize すると, こんな感じになってしまいます.

![skin-maya.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/5b93fd97-f7e3-3347-58eb-8076ddfe80ad.png)


## Maya の機能で行う方法

処理としては, skin weight の値を, subdivide mesh にうまく補間できればよいことになります.

* shape をコピー(必要に応じて, copy special)
* Mesh smooth(subdivide)
* (optional) subdivide されたメッシュの freeze. 基本不要のはずですが, うまくいかなければ freeze お試しください.
* src shape の skeleton(joints) を選択し, subdivide された mesh に skinCluster で bind
* Skin weight copy(UV 空間で行う)
  * 通常, このようなことをやりたい状況では, UV 座標がついているはずだとは思います. ついてなければまずは UV 座標をアサインするとよいでしょう.

joints 選択は,
  
Skinning: Select Joints Assigned to a SkinCluster
https://kleinhei.nz/2019/03/skinning-select-joints-assigned-to-a-skincluster/

でいけます. ありがとうございます.

```
$sel = `ls -sl`; 
select -r `skinCluster -q -inf (findRelatedSkinCluster($sel[size($sel)-1]))`;
```

Skin weight copy の設定はこんな感じです.

![skin-copy.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/e68a59cd-8124-c638-22cb-d6c1d0eed6fb.png)

Influence Association は Name にしましたが, ほかでもいいかもしれません.

これでうまくいくはずです!

![subd-skin-copy.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/5113866f-ac26-e12e-df42-7b39bea45ebb.png)

(手前が subdivided mesh)

### あとから分割(?)

Copy skin weight は, ヒストリには対応していないようです. subdivision level をあとで変更するとおかしな結果になります.

### subdivision before skinning

今回の skin weight コピー以外にも, subdivide(polySmooth) してから skinning というノード構成にしたいときがあります.
Maya の Hypershade や Node editor で入れ替えはやりやすいかな? `.ma` を吐いて, テキストエディタでつなぎ順を変えたほうが手っ取り早いかもしれません.

### 元メッシュに反映させたい

元メッシュに blendshape が設定されているなどで, duplicate したメッシュでシーンを差し替えるのが難しいときもあります.
その場合は, 元メッシュも subdivide し, 一旦 skin bind を外してから, 複製して subdivide されたメッシュから skin weight copy すればうまくいくかもしれません. ただ, この場合は元メッシュが subdivide されて重くなりますので, シーンエクスポート用のみとして利用しましょう.

## 推奨される方法

skin weight 自体は, 頂点のスカラーデータなので, エクスポータや, Maya python や, 自前形状処理ツールで opensubdiv など使ってでうまく weight を補間するのが理想です.

Maya skinning 情報の import/export メモ
https://qiita.com/syoyo/items/32a65647dea165e47b9f

リアルタイムレンダリングの場合は, tessellation shader で分割(skinning 処理したあとにメッシュ分割)ですが, Catmark 分割シェーダを移植するなどの必要があります.

ただ, どちらも開発の手間がかかるので(Maya python の場合は API 調べるのがめんどい), Maya の標準機能だけで完結するのであればそのほうがいいでしょう.

## TODO, 問題点

* [ ] Skin weight copy, どうもいろいろ input connection がついていると Maya(最新 2020 でも) だと不安定っぽい?
* [ ] Skin map(テクスチャ)を読むという手もあるが, これも Maya だと不安定っぽくよく落ちる
* [ ] bindPose を考慮する
Laravel で HTTPエラー時のメッセージを日本語化する

#前提
Laravel 6.6で確認しています。

#やりたいこと
 - べつに独自のエラーページは作らなくてもいいけど、日本語にしたい。
 - エラーページにちょこっと手を加えたい。
 - FormRequestの`authorize`やGateでの403エラーを日本語にしたい。

#手順
##1.翻訳ファイルの作成

`/resources/lang/`の直下に(`en`や`ja`に入れない)
`ja.json`という名前でjsonファイルを作成します。

##2.日本語化

あとは下記のように、日本語のメッセージを書いていきます。

```json:/resources/lang/ja.json
{
    "Unauthorized": "未認証",
    "Forbidden": "許可されていません。",
    "Not Found": "ページが見つかりません。",
    "Page Expired": "有効期限が切れています。",
    "Too Many Requests": "リクエストが頻繁です。",
    "Server Error": "エラーが発生しました。",
    "Service Unavailable": "現在サービスはご利用頂けません。",
}

```

ただしこれでは、`Formrequest`の`authorize`メソッドが`false`の時や、`Gate`などで認可状態でないときに

>403 | This action is unauthorized

と出てしまいます。

これは、`vendor\laravel\framework\src\Illuminate\Auth\Access\AuthorizationException.php`内でエラーが出たときに、メッセージがなかったらこのメッセージにするとべた書きで決まっているためです。

```php:vendor\laravel\framework\src\Illuminate\Auth\Access\AuthorizationException.php
    /**
     * Create a new authorization exception instance.
     *
     * @param  string|null  $message
     * @param  mixed  $code
     * @param  \Exception|null  $previous
     * @return void
     */
    public function __construct($message = null, $code = null, Exception $previous = null)
    {
        parent::__construct($message ?? 'This action is unauthorized.', 0, $previous);

        $this->code = $code ?: 0;
    }
```

なので、`Handler`クラスを修正し、下記のようにエラーが出たら
インスタンスを判別し、403と独自のメッセージを返すようにします。


```php:app\Exceptions\Handler.php
    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $exception
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $exception)
    {
        if ($exception instanceof \Illuminate\Auth\Access\AuthorizationException) {
            return abort(403, __('Unauthorized Action'));
        }
        return parent::render($request, $exception);
    }

```

そして、`ja.json`に追記します。

```json:/resources/lang/ja.json
{
~省略~
    "Unauthorized Action": "許可されていない操作です。"
}

```

これで日本語化できたと思います。
もし、漏れていても同様にすれば日本語化できるはずです。

##エラーページにちょこっと手を加えたい

```
php artisan vendor:publish --tag=laravel-errors
```

上記コマンドで、`views`配下に`errors`が作成され、そこにデフォルトのエラーページも入っているので、よしなに編集します。


ちなみに、https://github.com/caouecs/Laravel-lang で様々な国の翻訳ファイルが公開されています。
今回日本語化したもの以外にも、デフォルトの`view`で使用されているものも翻訳されています。

バリデーションエラーや、独自ページ作る系の記事が多いのでそんなに需要ない感じなんですかね。
Python備忘録

この記事は, python初心者の学習の記録です.
自分のわからなかったところを主に書いてます.
なので順序はごちゃごちゃです. 参考までにどうぞ,,,

#NumPy
##[np.array](https://algorithm.joho.info/programming/python-numpy-shape-size/)

```
# -*- coding: utf-8 -*-
import numpy as np

# 2次元配列の宣言・初期化
A = np.array([[1, 2],
              [3, 4],
              [5, 6]])

# 行列の大きさ
print("行列Aの大きさ:", A.shape)
print("行列Aの行数:", A.shape[0])
print("行列Aの列数:", A.shape[1])

"""
行列Aの大きさ:(3, 2)
行列Aの行数:3
行列Aの列数:2
"""
```
##[np.reshape](https://deepage.net/features/numpy-axis.html)
shape[0]は**行数**表示, shape[1]は**列数**表示.

```
import numpy as np

a = np.arange(24)

print(a)
# [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]

print(a.shape)
# (24,)

print(a.ndim)
# 1

a_4_6 = a.reshape([4, 6])

print(a_4_6)
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

print(a_4_6.shape)
# (4, 6)

print(a_4_6.ndim)
# 2

```

np.ndimでは, 簡単に書くと, 要素の数がわかる. [reshape](https://note.nkmk.me/python-numpy-reshape-usage/)は上記のコードの通り.

##[[:, 0]](https://teratail.com/questions/13705)
全ての0列目. 2x2の配列なら省略せずに書くと, a[0:2, 0]となる.
A[a:b, c:d]はa~bまでの行でc~dまで(b, d含まない)の列を抜き出す意味.

##[np.where](https://note.nkmk.me/python-numpy-where/)
```
import numpy as np

a = np.arange(9).reshape((3, 3))
print(a)
# [[0 1 2]
#  [3 4 5]
#  [6 7 8]]

print(np.where(a < 4, -1, 100))
# [[ -1  -1  -1]
#  [ -1 100 100]
#  [100 100 100]]

print(np.where(a < 4, True, False))
# [[ True  True  True]
#  [ True False False]
#  [False False False]]

print(a < 4)
# [[ True  True  True]
#  [ True False False]
#  [False False False]]
```

where以下が条件だけの場合は, true or falseが出てくる.

##[np.hstack](https://www.sejuku.net/blog/72890)

列数が同じ配列の統合. 行数の場合はnp.vstack.

##[np.unique()](https://note.nkmk.me/python-numpy-unique/)

()内の配列の中で, かぶりなく抜き出していく.

```
import numpy as np

a = np.array([0, 0, 30, 10, 10, 20])
print(a)
# [ 0  0 30 10 10 20]

print(np.unique(a))
# [ 0 10 20 30]

print(type(np.unique(a)))
# <class 'numpy.ndarray'>
```