OmniAICreator/Qiita-1.07M huggingface dataset:
C# DataGridView BindingListで自動的に表示される列を制御する

#背景
BindingList<T>に自分で作ったクラスを登録し、DataGridViewのdatasourceにセットするとDataGridViewにデータが反映され便利である。ただ、自分で作ったクラスのデータのうち、一部しかデータグリッドに乗せたくない場面もある。その時にわざわざデータグリッド表示用のクラスと、それ以外のデータも管理するクラスを別々に作成するのは管理上手間がかかる。このため、1つのクラスだけでデータグリッドに表示させる/させないを制御する方法を調べたのでメモっておく。

#方法
クラスのpublicなプロパティとして用意したデータのみがDataGirdViewに表示されるという性質を利用し、以下のように欺けばよい。

```C#
 /// データグリッド表示用のプロセスデータクラス
    public class ProcessData
    {
        // データグリッドで自動で見せる列
        public int processId { get; set; }
        public string Arguments { get; set; }
        public DateTime startTime { get; set; }
        public DateTime endTime { get; set; }
        public String exitCode { get; set; }
        public String status { get; set; }


        // データグリッドで自動で見せない列
        private Process process;
        private String inputString;
        private StringBuilder outputStringBuilder;
        private string workingDirectory;
        private PythonCommandExecutorForm detailForm;
        
        private string fileName;

        public ProcessData()
        {
            this.outputStringBuilder = new StringBuilder();
        }

        public void setProcess(Process process)
        {
            this.process = process;
        }
        public Process getProcess()
        {
            return this.process;
        }
        public void setOutputStringBuilder(StringBuilder outputStringBuilder)
        {
            this.outputStringBuilder = outputStringBuilder;
        }
        public StringBuilder getOutputStringBuilder()
        {
            return this.outputStringBuilder;
        }
        public void setWorkingDirectory(String workingDirectory)
        {
            this.workingDirectory = workingDirectory;
        }
        public String getWorkingDirectory()
        {
            return this.workingDirectory;
        }
        public void setFileName(String fileName)
        {
            this.fileName = fileName;
        }
        public String getFileName()
        {
            return this.fileName;
        }
        public String getInputString()
        {
            return this.inputString;
        }
        public void setInputString(String inputString)
        {
            this.inputString = inputString;
        }
        public void setDetailForm(PythonCommandExecutorForm detailForm)
        {
            this.detailForm = detailForm;
        }
        public PythonCommandExecutorForm getDetailForm()
        {
            return this.detailForm;
        }

    } 
```
Linux Mint にCUDAをインストールした

#はじめに
Linux Mint にCUDAをインストールしました。あれこれと試行錯誤していたらなんとかなったのですが、あとで再インストールするときのために記録を残します。

#Linux　Mint
Linux Mint 18.1 “Sarah” MATE　
ハード　GALLERIA　DT（ドスパラ）

#インストール手順
Nvidia社の下記のページよりインストール
https://developer.nvidia.com/cuda-downloads

Linux -> x86_64 -> Ubunut -> 16.04 -> dev[network]

この後に表示されたインストールの指示にしたがい端末にコピーペーストして作業しました。所要時間はおよそ40分

```
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-ubuntu1604.pin
sudo mv cuda-ubuntu1604.pin /etc/apt/preferences.d/cuda-repository-pin-600
sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub
sudo add-apt-repository "deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/ /"
sudo apt-get update
sudo apt-get -y install cuda

```

#トラブル
順調に進んでいたものの最後の最後になって画面が切り替わりメッセージが出力され<ok>と表示になるのですがマウスもエンターキーも効きません。端末を強制終了させました。

ググってみるとcudaのためのドライバーに問題があるようです。メニュから　driver で検索して　driver-manager  を起動しました。そうするとパスワードの入力を求められインストールが始まりました。それが終わってみるとcudaのドライバはすでに設定されていました。Nvidiaー440というバージョンのものでした。

さて、これでいいのかと思い端末でnvccを入力するも、ダメです。おかしいなぁ。メッセージのヒントに従ってあれこれやりましたがうまくいきません。でもすでにcudaはインストールされているというメッセージが表示されます。

#解決
リブートしました。解決しました。推測ですがドライヴァーが正しく動作するためにはリブートが必要だったように思います。

#パスの設定
さらに次のように端末より入力する必要がありました。
Nvidia　公式ページより
https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#post-installation-actions

```
 export PATH=/usr/local/cuda-10.2/bin:/usr/local/cuda-10.2/NsightCompute-2019.1${PATH:+:${PATH}}

```

これをいちいち入力していたのでは面倒なので恒久的にPATHを設定します。通常、~/.bash_profile なはずなのですが、うまくいきません。~./profileに書き込むとPATHが通るようになります。

端末より　nvcc -V でバージョンが表示されました。やれやれホット一安心。

なにかの参考になりましたら。
Cloud Functions

いろいろメモ

#テスト

## トリガーとなるイベント

### ダメなテストデータの書き方
####前提：firebaseを使って実行するFunctions

```typescript:index.ts
export const setUser = functions.https.onCall((data) => {
    const collection = firebase.firestore(app).collection('Users');
    const docRef = collection.doc(data.userCode);
    docRef.set({firstName:data.firstName});
    return {Message : 'Users Set Success!'}
});
```
####ダメだったテストデータ
```:TestData
{"userCode":"20","firstName":"asada"}
```
####ＯＫだったテストデータ
```:TestData
{"data":{"userCode":"20","firstName":"asada"}}
```
####最後に
jsonの最上部は「data」でした。
videojsでendedイベントが発火しない場合の対処法

#発生していた問題
+ videojsを利用して動画再生をしている
+ 動画再生が最後に達したら次のリストの動画を自動再生
+ ほとんどの動画で問題なく最後に達して次の動画が自動で再生ができるが、一部の動画だけが最後に達しても次の動画に遷移しない。
+ 使っていたvideojsのバージョンは7.6.0

#問題が発生していたJSコード一部
```js
var player = videojs("#videojs_element");
player.on("ended", function() {
   // ここで再生が終了したら次の動画へ遷移する処理を行っている
});
```

#問題の分析

##endedが発火しているのか確認
以下のコードでendedが発火するか確認したら、問題が発生する動画では、consoleにended startというログが出ない。

```js
var player = videojs("#videojs_element");
player.on("ended", function() {
   console.log('ended start');
   // ここで再生が終了したら次の動画へ遷移する処理を行う。
});
```

##timeupdateを入れて再生位置と終了位置をリアルタイムで監視

問題が発生する動画ではendedが発火しないので、videojsのtimeupdateというイベントを使って現在の再生位置と終了位置をリアルタイムで監視してみた。

```js
var player = videojs("#videojs_element");
// ended部分はコメントアウト
//player.on("ended", function() {
//   // ここで再生が終了したら次の動画へ遷移する処理を行う。
//});
// 以下を追加
player.on("timeupdate", function(){
    var self = this;
    console.log(self.currentTime()+'='+self.duration());
});
```
問題が発生する動画ではコンソールログの結果を見るとcurrentTime()がduration()の値まで達していない。。。

```
251.9711=254.034
252.220862=254.034
252.470623=254.034
252.721052=254.034
252.970452=254.034
253.220424=254.034
253.470793=254.034
253.722037=254.034
253.941767=254.034
```

問題が発生しない動画のコンソールログの結果を見ると、currentTime()がduration()の値まで達している。

```
142.565163=144.203763
142.813788=144.203763
143.063869=144.203763
143.313899=144.203763
143.564323=144.203763
143.814652=144.203763
144.06434=144.203763
144.203763=144.203763
```

問題が発生する動画は、duration()の値の小数点以下の桁数が３桁までになっています。ちなみに、問題が発生する他の動画も小数点以下の桁数が３桁まででした。


#対象方法

根本的な解決ではないかもしれませんが、endedイベントで終了処理を行うのではなく、timeupdate内で終了処理を呼び出すことにしました。
小数点以下の値が怪しいので、小数点以下は削って比較するようにしました。

```js
var player = videojs("#videojs_element");
// ended部分はコメントアウト
//player.on("ended", function() {
//   // ここで再生が終了したら次の動画へ遷移する処理を行う。
//});
// 以下を追加
player.on("timeupdate", function(){
    var self = this;
    if (Math.round(self.currentTime())==Math.round(self.duration())) {
        // ここで再生が終了したら次の動画へ遷移する処理を行う。
    }
});

```
【localStorage】オブジェクトを読み書きしたいときの基本構文

## はじめに
**localStorage**で**オブジェクト**を読み書きしたいときの基本構文を備忘録としてまとめました。

## 環境
```yaml
OS: macOS Catalina 10.15.1
Chrome: 78.0.3904.108（Official Build） （64 ビット）
Firefox: 71.0(64ビット)
```

## 1.公式での使用例
まずは[公式](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)で紹介されている使用例です。
**１つのキーに対し、１つのスカラー値**を読み書きする例となっています。

```javascript:sample.js
// 書き込み
localStorage.setItem('myCat', 'Tom');

//　読み込み
let cat = localStorage.getItem("myCat");

// 削除
localStorage.removeItem("myCat");
```

ただ、これは以下のように、**オブジェクト**では使えません。

```javascript:sample.js
let object = {
    key1: "name1",
    key2: "name2"
};

localStorage.setItem("myObject", object);
```
一見大丈夫そうでも...
↓

```shell
"[object Object]"
```
出力はこうなってしまいます。

**localStorage**に**オブジェクト**を突っ込みたい方も多いのではないでしょうか？

次は**オブジェクト**で使うための基本構文です。

## 2.オブジェクトを読み書きするときの基本構文
問題は、**JavaScriptオブジェクト⇔JSON文字列の変換**が行われていなかったことです。

```javascript:sample.js
let object = {
    key1: "name1",
    key2: "name2"
};

// 書き込み ※JavaScriptオブジェクト -> JSON文字列に変換
localStorage.setItem("myObject", JSON.stringify(object));

// 読み込み ※JSON文字列 -> JavaScriptオブジェクトに変換
JSON.parse(localStorage.setItem("myObject"));

// 削除 ※変わらず
localStorage.removeItem("myObject");
```
これで無事、**localStorage**を使って**オブジェクト**を読み書き出来るようになりました！

## おわりに
最後まで読んで頂きありがとうございました:bow_tone1:

どなたかの参考になれば幸いです:relaxed:

## 参考にさせて頂いたサイト（いつもありがとうございます）
- [Window.localStorage - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)
- [Web Storage API を使用する - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API)
- [localStorageを使いこなすための覚え書き | misclog（ミスクログ）](https://misc-log.com/localstorage/)
Apache Solr インストール〜起動まで（MAC）

![solr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322577/52ab8d2e-01d3-a5f3-2cbb-8eecb1f39fb6.png)

#Solrとは
#####Apacheが提供しているオープンソースの全文検索エンジン

クックパッドなど大規模なサービスに利用されていて、とにかく速いことが特徴

###目次
1.Javaのインストール
2.Solrの起動
3.データの投入
4.検索
5.リセット
6.Javaのインストール

Solrの起動にはJavaが必要。入っていない場合はHomebrewを使ってインストールしましょう。

インストールの前にHomebrewを更新

```
$ brew update
```
##javaのインストール

```
$ brew cask install java
```
バージョンを確認してインストール場所のパスを確認

```
$ /usr/libexec/java_home -V
```
インストール場所を.bash_profileにコピペして追記し、パスを通す
※パスは$ /usr/libexec/java_home -Vで確認したものに書き換えを

```:.bash_profile
export PATH=$PATH:/Library/Java/JavaVirtualMachines/openjdk-12.0.2.jdk/Contents/Home`
`export JAVA_HOME=/Library/Java/JavaVirtualMachines/openjdk-12.0.2.jdk/Contents/Home
```

※.bash_profileがなければルートディレクトリに作成

追記した内容が反映されるようbash_profileを更新

```
$ source ~/.bash_profile
```
下記コマンドで記述したパスが表示されればOK

```
$ echo $PATH`
$ echo $JAVA_HOME`
```
ミラーサイトからsolr-7.7.2.zip をダウンロード

http://ftp.tsukuba.wide.ad.jp/software/apache/lucene/solr/7.7.2/

解凍したsolr-7.7.2ディレクトリに$ cdで移動
場所はどこでも大丈夫

##Solrの起動
起動コマンドを入力

```
$ ./bin/solr start -e cloud
```

###起動オプションを入力

####起動するノード数

*`This interactive session will help you launch a SolrCloud cluster on your local workstation.`*

*`To begin, how many Solr nodes would you like to run in your local cluster? (specify 1-4 nodes) [2]: `*

デフォルトの2つでOKなので`Enter`
####１つ目のノードのポート番号

*`Ok, let's start up 2 Solr nodes for your example SolrCloud cluster.`*

*`Please enter the port for node1 [8983]:`*

こちらもデフォルトでOKなので`Enter`
####２つ目のノードのポート番号

*`Please enter the port for node2 [7574]:`*

こちらも`Enter`
####コレクション名

*`Please provide a name for your new collection: [gettingstarted]`*

コレクション名は下記で

```
echproducts
```
####インデックスの分割数

*`How many shards would you like to split techproducts into? [2]`*

デフォルトでOKなので`Enter`
####レプリカの数

*`How many replicas per shard would you like to create? [2]` *

こちらも`Enter`
####configset

*`Please choose a configuration for the techproducts collection, available options are:`*

*`_default or sample_techproducts_configs [_default]`*

促されているように下記でセット

```
sample_techproducts_configs
```

すると
…

*`Created collection 'techproducts' with 2 shard(s), 2 replica(s) with config-set 'techproducts'
Enabling auto soft-commits with maxTime 3 secs using the Config API
POSTing request to Config API: http://localhost:8983/solr/techproducts/config
{"set-property":{"updateHandler.autoSoftCommit.maxTime":"3000"}}
Successfully set-property updateHandler.autoSoftCommit.maxTime to 3000
SolrCloud example running, please visit: http://localhost:8983/solr `*

…

↑で言われたとおりhttp://localhost:8983/solr  にアクセスします
 

Apache Solrの画面が表示されていれば起動できています

##データの投入
解凍したsolr-7.7.2の中のexampleディレクトリの中にあらかじめsolrが用意したサンプルファイルがあるので、今回はとりあえずそれを投入

```
$ bin/post -c techproducts example/exampledocs/*
```
 
##検索
```
$ curl "http://localhost:8983/solr/techproducts/select?q=book&wt=xml&indent=true"
```
↑
q=検索したいワード
wt=出力するファイル形式
indent=インデントをつけるかどうか
をそれぞれ入れると・・

···

検索結果がxml形式で出力される！

···

##停止
```
$ bin/solr stop -all
```
 
##リセット
ノードを削除し最初の状態に戻します

```
$ bin/solr stop -all ; rm -Rf example/cloud/
```
【MySQL】はじめてのクエリチューニング vol.2 EXPLAINの確認方法

クエリチューニングに欠かせないEXPLAINについて
![mysql.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322577/794720ed-da97-ea52-2b86-ca866954ae1a.jpeg)

## 目次

1.EXPLAINとは

2.各項目の意味

3.チェックすべきところ

# EXPLAINとは
インデックスがどう働いているか確認出来る
クエリチューニングを行うときまず最初に行うのがEXPLAIN

# EXPLAINの使い方
クエリの頭にEXPLAINをつけて流すと「実行計画」と呼ばれるものが出力される
最後に¥Gをつけると縦に出力されて読みやすくなります

:zap:実行計画はデータ量によって全く違うものになるので、本番と近い環境で行いましょう

#各項目の意味するところ
**id**・・テーブル読み込みの順番

**select_type**・・クエリの種類

**table**・・該当テーブル

**type**・・テーブルにどのようにアクセスしているか

**possible_keys**・・使用可能なインデックス

**key**・・possible_keysの中からオプティマイザによって選ばれ有効になっているインデックス

**key_len**・・インデックスが有効になっている対象カラムの長さ（バイト）

**ref**・・keyで比較されているカラム名（定数が指定されているときはconstと表示される）

**rows**・・フェッチされる行数の見積もり（正確なものではない）

**Extra**・・インデックスの効き具合やソートの仕方etc

# チェックすべきところ
### type

*ALL*や*INDEX*になっている場合はチューニング必須

ALLはインデックスが効いていない状態でテーブルを全スキャンしているので大変遅い

INDEXはインデックス全体をスキャンしている状態でこちらも遅い

インデックスの最適化が必要

### Extra

Using temporary, Using filesortでrowsが多い場合はチューニング必須

order byを使ったクエリで、全てのテーブルが結合されたのち並び替えが行われている状態で遅い

結合前にインデックスによってソートをかけることで解消できる

とりあえず以上
:zap:別途補足します
windowsで、https経由でgithubにpushするuserは資格情報にキャッシュされている

# やろうとしたこと
gitbash on Windowsでgithubへpushなどを行っていたが
ふとgithubの別アカウントでpushしたいリポジトリがあったのでuserを切り替えようとした

# 起きた問題
どう足掻いても、githubへpushするときのuserが切り替わらない。。。

gitbashで

```
git config --global user.name "chigau_user"
git config --global user.email chigau_user@hogehoge.com"
```

とかやったり、
C:\\Users\\Watashi\\.netrc を削除したり、

リポジトリをcloneし直すついでに 

```
git clone https://chigau_user@github.com/chigau_user/...
```

とかやったり。。。
Windows再起動したり。。。
散々やってもダメ。。。

# 解決方法
やっとの思いで↓こちらにたどり着いたのですが、
https://qiita.com/mzkii/items/d47c37964c435a981114
こちとらWindows。。。
キーチェーンなんてないし。。。


...あっ

お ま え か っ ！！！
![ss1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/ddac893c-89e2-4ba1-9081-3e144165c151.png)

ゆるさへんで！
ほんま！！

時間返して。。。
【MySQL】はじめてのクエリチューニング vol.3 複合インデックスとSQLの評価順序 

複合インデックスを作成する際に注意しなければいけないSQLの評価順序との関係について説明します
![mysql.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322577/ab271ce3-bb51-867e-e366-6a0cdfdc60dc.jpeg)

## 目次

1.インデックス作成

2.インデックス削除

3.複合インデックス作成

4.評価順序

# インデックス作成
インデックス作成のメリット・デメリットについては別記事で
https://qiita.com/okasir4444/items/2cd98b430481c433d6f5

任意のインデックス名をつけて下記のクエリで作成できます

```sql:
ALTER TABLE テーブル名 ADD INDEX インデックス名(カラム名);
```
# インデックス削除

ちなみに削除はこのように記述します

```sql:
ALTER TABLE テーブル名 DROP INDEX インデックス名;
```
複数のカラムを指定することもでき、これを複合インデックスと言います

# 複合インデックス作成

```sql:
ALTER TABLE テーブル名 ADD INDEX インデックス名(カラム名1, カラム名2);
```
この指定するカラムの組み合わせによって、処理速度が大きく変わります

# SQLの評価順序

そして作成するとき、カラム名の順番が非常に大事です

SQLの評価順序にのっとって記述しないとインデックスが有効になりません

評価順序 = SQLが実行される順番です

上から順に実行されていきます

FROM

ON

JOIN

WHERE

GROUP BY

HAVING

SELECT

DISTINCT

ORDER BY

LIMIT

例えばこのようにインデックスを作成したとき 　

```sql:
ALTER TABLE users ADD INDEX XXX(col1, col2);
```
下記のクエリだと評価順序を守っているのでインデックスは有効です

```sql:
SELECT * FROM users WHERE col1 = Z ORDER BY col2;
```
ではこちらはどうでしょうか

```sql:
SELECT * FROM users WHERE col2 = Z ORDER BY col1;
```
3.WHERE句にcol2、8.ORDER BYにcol1が記述されていて、インデックスの記述順とSQLの評価順序が逆転しています

この場合インデックスは無効になってしまいます

インデックス作成でカラムを指定するときは、評価順序を意識しましょう
Raspberry Pi 4（Raspbian Buster with desktop）に、openmdiavaultを導入

Rasberry pi 4にopenmediavaultを導入して、NASを構築したときの手順メモ。
詳細は省略。リンク先の記述を、大変参考にさせて頂きました、多謝！

#1. Rasberry pi4の初期設定

###・microSDカードに、Raspbian Buster with desktopを導入。
macOSでの作業手順になります。ddでイメージを書き込むときは、「rdisk」（シーケンシャルアクセス）で指定すると、高速に書き込みが完了します。


```
$ diskutil unMountDisk /dev/disk5
$ sudo dd if=/Users/[User Name]/Downloads/2019-09-26-raspbian-buster.img of=/dev/rdisk5 bs=1m
```



【参照】https://qiita.com/shippokun/items/9070fc58f69d8c063e44

###・起動後の各種アップデート

```
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get dist-upgrade
$ sudo rpi-update
$ sudo reboot
```

【参照】https://qiita.com/tanuwo/items/04df160281153c0e24bc

###・SSHの有効化、VNCの有効化、固定IPアドレスの設定
VNCを有効化すると、認証方式が「UNIX password」となりますが、私が利用しているMobaXtermでは接続できませんでした。認証方式を「VNC password」とすることで解決。

（後日追記予定）

#2. openmediavaultの導入

PC Watch 西川さんのコラム「openmediavaultでNAS化に挑戦! そしてDockerで遊ぶ」を拝見して、openmediavaultを初めて知りました。WebGUIで設定のできる、本格NASが構築できるだということでチャレンジ。

```
$ cd /opt
$ wget -O - https://github.com/OpenMediaVault-Plugin-Developers/installScript/raw/master/install | sudo bash
$ sudo reboot
```

【参照】https://pc.watch.impress.co.jp/docs/column/nishikawa/1230154.html

#3. 導入後のトラブル対処
openmediavault導入後に、色々とトラブったので。こちらの手順を備忘録として残しておきたく。
###・固定IPの設定が消えた。
・Raspbianの、Network設定画面（GUI）も表示されません。
・openmediavaultの、Network設定画面で設定しても、エラーになります。

【原因】openmediavaultを導入すると、「dhcpcd5」関連のパッケージが削除されてしまうため。再インストール。

```
$ sudo apt-get install dhcpcd5
$ sudo systemctl start dhcpcd5
```

###・「pi」ユーザーで、SSHログインができない。
・正しいパスワードを入力しても、「Access deined」と拒否されます。

【原因】openmediavaultを導入すると、「pi」ユーザーが「ssh」グループに所属していないため。
EmacsとDockerで簡単LaTeX環境構築

# TL;DR

```emacs-lisp
(use-package yatex                                                                                   
  :mode ("\\.tex\\'" . yatex-mode)                                                                   
  :config                                                                                            
  (let (                                                                                             
        (prefix "docker run --rm -v $PWD:/workdir paperist/alpine-texlive-ja ")                      
        (cmds '(                                                                                     
                bibtex-command                                                                       
                dvi2-command                                                                         
                makeindex-command                                                                    
                tex-command                                                                          
                YaTeX-dvipdf-command                                                                 
                )))                                                                                  
    (cl-loop for cmd in cmds collect (set cmd (concat prefix (eval cmd)))))) 
```

# はじめに
LaTeXの環境構築のためにローカル環境を汚すことに抵抗ある人は多いだろう．
そんな人のために親切な方がDockerイメージを公開してくれている．
各コマンドをエイリアスに登録しても良いのだが，YaTeXを使っている人はLaTeXのコマンドを直接実行することは基本的にないので，init.elに書いてしまおう，というおはなし．

（気が向き次第追加執筆予定）
Rubyではメソッドにreturnの記述要らない？

Railsで開発している際に既存コードにreturnが書かれていなかったり、returnを書いてrubocopに指摘されたりしたので調べました。
rubyでは不要であればreturnは書かない方針のようです。

## RubyではReturnの記述は不要
Rubyのメソッドでは、**最後に評価された値が返る**という仕様になっています。
例えば以下のような文字列を返すメソッドがあります。

```ruby
def hoge(is_hoge)
  if is_hoge
    "hoge"
  else
    "fuga"
  end
end
```

最後に評価された値が返るので、それぞれ以下を返します。

```ruby
hoge(true)  # "hoge"

hoge(false) # "fuga"
```

## 後置ifでは注意が必要
例

```ruby
def hoge(is_hoge)
  "fuga"
  "hoge" if is_hoge
end
```
``` ruby
hoge(true) # "hoge"

hoge(false) # nil
```
なんとなく`hoge(false)`でfugaが帰って来そうですが、最後で評価された値が返るのでnilが帰ってきます。

後置ifでは、ifの右側の値が評価されたあと、trueならば左側が評価されます。
falseであればnilを返します。

例の場合、`hoge(false)`で`if is_hoge`は成立しないので、左側のfugaは評価されず、
`"hoge" if is_hoge`が最後に評価された値となり、nilを返します。
pythonの標準入力受け取りinput()とsys.stdinはどっちがいいの？

なんとなく`input()`を避けて`sys.stdin`を使ってきたけど実際どっちがいいのか？を速度とコード量的に比較してみました。追加でfileinputも比較します。
###結論　sys.stdinを使え
動作速度は
**input() <<< fileinput < sys.stdin**

　
###比較方法
- オンライン実行環境の[paiza.io](https://paiza.io/ja) を使用（特に意味は無し）。
- `1 2 3 4`の様な数字+空白のフォーマットを**1万行**、標準入力として渡す。
- `time`を使って、標準入力をintに変換しlistに格納するまでの時間を計測。

#input()の動作速度
```input()のコード例.py
data_all = [input().split() for i in range(10000)]#データ一括取得
data_list = [[int(s) for s in line]for line in data_all] #データのint化
#for line in data_all:
#    data_list.append([int(s) for s in line])
```
動作時間: 約21.1[msec]

#sys.stdinの動作速度
```sysのコード例.py
data_list = [ [int(s) for s in line.split()] for line in sys.stdin ]
#data_list = []
#for line in sys.stdin:
#    data_list.append([int(s) for s in line.split()])
```
動作時間: 約10.5[msec]

#fileinputの動作速度
```py
import fileinput
data_list = [ [int(s) for s in line.split()] for line in fileinput.input() ]
```
動作時間: 約12.5[msec]

## sysの方がコードもスッキリ
内包表記に変えました。input()使うとどうしても2行になっちゃうかな...
動作速度はinput()の方が倍近く遅いですね。他の方の記事を見ていると、10倍以上差が出たりする様です。`sys`を使った方が色々と良さそうですね。
追加で試したfileinputですが、sys.stdinほど速くもないかなぐらいでした。

###int変換なしの場合
input()の場合、約12.9[msec]
sys.stdinの場合、約5.5[msec]
fileinputの場合、約7.5[msec]
int変換って意外と時間かかりますね。動作速度はやっぱりsys.stdinが速そうです。
Java勉強始めたてによる二次元配列

自分用メモ
##参考にはなりませんよぉ～
####Javaに触れつつ持ち合わせてる知識だけで二次元配列を考えてみる
今回は5行5列の二次元配列に１～５のランダムな数字をぶち込んで表示させた

<b>やったこと</b>
二次元配列の宣言
　　　　↓
１～５のランダムな要素を代入　　
　　　　↓
改行しつつ表示させるのを5回繰り返す
みたいな

```java

package sample;

public class sample {

	public static void main(String[] args) {

		String sep = System.lineSeparator();

		int x = 6;
		int y = 6;

		int[][] array = new int [x][y];

		for(int i = 1; i < x; i++){
			for(int j = 1; j < y; j++){
				array[i][j] = new java.util.Random().nextInt(5)+1;
				System.out.print(array[i][j]);
			}
			System.out.print(sep);
		}

	}

}


```

出力はこんな感じ

```
53232
31333
24344
34225
12133
```
###感想
なんだこの稚拙なコードは！！って感じですわね。調べてみた感じだとリストやランダムなど便利なコレクションがあるみたいですね～～。classの外側にimport java.util.~;とか書いてあってこれマジで何ってなったりしてるので追々勉強していこうと思いましたまる。（Qiitaの書き方も勉強…）
次回は探索アルゴリズムなども考慮しつつ隣どうし重複しないランダムな要素を含んだ二次元配列書く＾
【Oracle】おしゃれな(動的)SPOOLを

# はじめに
毎回SPOOLのファイル名を手修正している人が多いので、
少しでも効率化して欲しいという想いを込めて記事にしました。

動的なspoolを目指そう。

#目次
- 誰に向けたものか
- SPOOLについて
- おしゃれなSPOOLとは？
- 例題と解説
    - 【chapter1】DB名をログに出力したい
    - 【chapter2】時間をログに出力したい
    - 【chapter3】スキーマ名をログに出力したい
    - 【chapter4】その場で思いついたものをログに出力したい
- SYS_CONTEXTについて
- おわりに
 
#誰に向けたものか
・Oracle使う人
・Sqlplusを使う人 
・Database 運用者

#SPOOLとは
SPOOL はSELECT結果やターミナルをログに出力するためのコマンド

```sql

--SPOOL開始
SPOOL <ファイル名>

--SPOOL終了
SPOOL OFF
```

#おしゃれなSPOOLとは？
手修正を加えることなく動的にログファイルが出力されること
(勝手に定義しました)

#例題と解説

###【chapter1】DB名をログに出力したい
複数のDBがある環境でそれぞれのDB名をログに出力したい場合

```sql
--DB名をログに出力したい

--1.DB_NAME 列を varDB_NAME という変数として宣言する。
COLUMN DB_NAME NEW_VALUE varDB_NAME

/******************************************************
 * 構文：COLUMN <列の別名> NEW_VALUE <変数名>
 * <列の別名>と<変数名>はなんでもいい。
 ******************************************************/

--2.DB名の情報をとってきて DB_NAME 列として扱う。
SELECT SYS_CONTEXT('USERENV','DB_UNIQUE_NAME') AS DB_NAME FROM DUAL;

/******************************************************
 * SYS_CONTEXT('USERENV','DB_UNIQUE_NAME')でDB名を取得し、DB_NAME 列として扱う。
 * ↓
 * このとき1.で 変数としても宣言しているので varDB_NAMEとしても扱うことができる。
 * 
 * SYS_CONTEXT：一言でいうとセッション情報が取得できる。使い方は後述。
 ******************************************************/

--3.SPOOLする
SPOOL object_check_&&varDB_NAME\.log

/******************************************************
 * &&：変数(置換変数)を使用するときに使うもの。
 * \ ：変数の区切り位置を意味する(これがないとどこまでが変数か分からないため)。
 ******************************************************/
```

コードを実行すると
object_check_<DB名>.logというログファイルが出力される。

```sql

--実際の実行例
SQL> COLUMN DB_NAME NEW_VALUE varDB_NAME
SQL> SELECT SYS_CONTEXT('USERENV','DB_UNIQUE_NAME') AS DB_NAME FROM DUAL;

DB_NAME
--------------------------------------------------------------------------------
PROD1

SQL> SPOOL object_check_&&varDB_NAME\.log
SQL> 
SQL> SPOOL
現在object_check_PROD1.logでスプールしています。
SQL> SPOOL OFF
SQL> 
SQL> !ls -ltr *.log
-rw-r--r-- 1 oracle oinstall  94  1月 25 00:37 object_check_PROD1.log
```

###【chapter2】時間をログに出力したい

時間をログに出力したい場合

```sql

COLUMN NOW NEW_VALUE varNOW
SELECT TO_CHAR(SYSDATE,'YYYYMMDDHH24MISS') NOW FROM DUAL;
SPOOL object_check_&&varNOW\.log

--出力例：object_check_20200125004643.log

/******************************************************
 * YYYYMMDDHH24MISS
 * YYYY：年 MM:月 DD:日 HH24：時間 MI：分 SS:秒
 ******************************************************/
```
###【chapter3】スキーマ名をログに出力したい
スキーマ名毎に実施する作業でスキーマ名をログに出力したい場合

```sql

COLUMN USER_NAME NEW_VALUE varUSER_NAME
SELECT SYS_CONTEXT('USERENV','SESSION_USER') AS USER_NAME FROM DUAL;
SPOOL object_check_&&varUSER_NAME\.log

--出力例：object_check_SYS.log

```

###【chapter4】その場で思いついたものをログに出力したい
これはワンライナーで
(COLUMN <○○> NEW_VALUE <○○> は不要)

```sql

SPOOL object_check_&&1\.log

--実行例
SQL> SPOOL object_check_&&1\.log
1に値を入力してください: ああああ
SQL> 
SQL> SPOOL
現在object_check_ああああ.logでスプールしています。
SQL> 
SQL> !ls -ltr *.log
-rw-r--r-- 1 oracle oinstall   0  1月 25 01:27 object_check_ああああ.log


```

#SYS_CONTEXTについて

セッションの情報を取得できます。
他にもたくさん種類がありますので以下の資料をご参考ください。

Oracle® Database SQL言語リファレンス 11gリリース2 (11.2)
https://docs.oracle.com/cd/E16338_01/server.112/b56299/functions184.htm

#おわりに
SPOOL 1つ取ってみても奥が深いですね。
これを意識するだけで効率化を図ることができるので是非ご利用ください。
Rails4系で統合テストをDocker環境内で行う

# はじめに
今回Railsのバージョンアップに向けて不足していた箇所のテストを書いていました。
その一環で統合テストを書こうとして軽く詰まったので似たような境遇方のためになればと思い(こんなレアケースに遭遇する人は少ないと思いますが)記事にしました。

# なぜ統合テストなのか
プロダクトで使用している外部サービスのAPIがjsにしか対応しておらず、プロダクト内で重要な機能の一部に組み込まれていたため。

# 環境
Rails 4系
Ruby 2.5.7
Rspec 3.9.1
capybara 3.30.0

# 対象
- すでにRspecのテスト環境が整っている。
- dockerを用いて開発を行なっている。
    - dockerを用いていない場合はローカルにインストールされているブラウザを使用すれば簡単に実装できると思います。

# Railsアプリケーションが入っているコンテナにchromeなどを導入する
ブラウザ用にコンテナを分けるか迷いましたが、circleciにブラウザが導入されているRubyのイメージがあったため開発環境下でもRailsアプリケーションが入っているコンテナに導入することにしました。

Dockerfileに以下のchromeやseleniumなどをインストールするためのコマンドを書き足します。

```:Dockerfile
FROM ruby:2.5.7
# 下記の内容については現在の設定内容に合わせて変更してください。

# googleが用意している公開鍵をaptに追加
RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add -

# aptに安定版chromeがインストールできるレポジトリgoogle-chrome.listを追加します。
RUN echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' | tee /etc/apt/sources.list.d/google-chrome.list

# aptで必要なパッケージをインストールします。
# seleniumをpipでインストールするため一緒にインストールします。
RUN apt-get update -qq && apt-get install -y [nodejsやRDBMSのクライアントなど] google-chrome-stable python3-pip

# seleniumでchromeを動かすためのchromedriverをダウンロードします。
# installしているchromeのバージョンに対応したchromedriverをインストールする必要があるため
# http://chromedriver.storage.googleapis.com/LATEST_RELEASE
# でchromeの安定バージョンを取得することができるため、その値を用いてchromedriverのバージョンを指定しています
RUN LATEST_RELEASE=$(curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE) &&\
    wget http://chromedriver.storage.googleapis.com/$LATEST_RELEASE/chromedriver_linux64.zip

# ダウンロードしたchromedriverを解凍します。　このときPATHが通っている階層に配置しましょう。
RUN unzip chromedriver_linux64.zip -d /bin/

# pipでseleniumをインストールします。
RUN pip3 install selenium

# これより下はRailsのインストールなど既存のコードになるかと思います。
```

# Rails側で統合テストを動かす設定
Gemfileに以下を追加

```:Gemfile
gem 'selenium-webdriver'
```

rails_helper.rbに以下を追加

```ruby:rails_helper.rb
require 'selenium-webdriver'
```

以下の内容を設定ファイルを作成して記述する。（rails_helper.rbなどに書いても可）

```ruby:spec/support/capybara.rb
Capybara.register_driver :selenium do |app|
  option = Selenium::WebDriver::Chrome::Options.new(
    args: %w[--headless --disable-gpu --no-sandbox]
  )
  Capybara::Selenium::Driver.new(
    app,
    browser: :chrome,
    options: option,
    timeout: 600, # この設定がないとテスト内容によってはcircleciで Net::ReadTimeout となってしまう
    desired_capabilities: { accept_insecure_certs: true }
  )
end
Capybara.javascript_driver = :selenium
```

以上の設定で統合テストが実行できる環境が出来上がったと思います。

# さいごに
Rails4系で統合テストのやり方を調べるとcapybara-webkitを使用した記事しか出てこなかったり、良さげなやり方を見つけてもsystem testに対応していなかったりとなにから導入していいのか調べるところからで少し詰まってしまいました。。。
また、せっかくdockerを使用しているので初めはブラウザ用のコンテナを用意しましたがコンテナ間の接続に証明書が必要でした。
証明書の発行まで書こうかと思いましたがcircleciでブラウザーが含まれたimage(今回だとcircleci/ruby:2.5.7-node-browsers)があったため分けずに構築してみました。
初めての内容ばかりだったのでおそらく改善できる点がたくさんあると思います。
改善点や気になったことがあればコメントで教えていただけると嬉しいです！

# 参考記事
https://qiita.com/zo30005/items/a5dcede868a3d1cca4a8
https://www.google.com/linuxrepositories/
https://www.linuxbabe.com/ubuntu/install-google-chrome-ubuntu-18-04-lts
https://circleci.com/docs/2.0/circleci-images/#language-image-variants
joinsで結合したモデルのscopeを使ってデータを取得する方法

inner joinかつ別モデルのscopeを利用してそのモデルの状態を条件にデータを取得したい。
例えば、「紐づくuserのstatusがtrueであるtweet」を取得したいときは以下のように書ける。

```rb
Tweet.joins(:user).merge(User.available)
```

user.rb

```rb
class User < ApplicationRecord
  has_many :tweets
  scope :available, -> {
    where(status: true)
  }
end
```
tweet.rb

```rb
class Tweet < ApplicationRecord
  belongs_to :user
end
```
paizaとか競技プログラミングで使う標準入力をintで一括取得する(python)

paizaとか競技プログラミングやっている時用の標準入力受け取り&int化。
入力値は`1 2 3`の様に間にスペースが入ってたりすることを想定してます。
input使うのがなんか嫌なので`sys`使ってます。実行速度もsys使った方が速いのでいいのかなぁと。
実行時間の比較は別記事にしてます。[pythonの標準入力受け取りinput()とsys.stdinはどっちがいいの？](https://qiita.com/Sak1361/items/d84a6e6dac7157b12de8)

```1行の場合.py
data = [int(s) for s in sys.stdin.readline().split()]
```

```複数行の場合.py
data = list()
for l in sys.stdin:
    data.append([int(i) for i in l.split()])
#1行で書くと↓
data = [ [int(s) for s in line.split()] for line in sys.stdin ]
```
目的別VScodeプラグイン【備忘録】


# 概要

目的ごとにここにまとめる。


# Javscript開発

基本的にVue.jsベースの開発環境です。

- Vetur
- Vue 2 snippets
- ESLint
- Debugger for Chrome
- live Server


# Golang開発

- Go

# Markdown編集

- Markdown All in One
- Markdown PDF
- markdownlint
- Markdown Preview Enhanced
初学者がAtomに入れたパッケージ

# はじめに
自分の使っているPCにAtomをインストールしたので、その際に入れたパッケージの備忘録です。

# *Japanese Menu*
Atomのメニューバーとコンテキストメニュー、設定画面を日本語に翻訳してくれるパッケージ

# *Show Ideographic Space*
全角スペースを見えるようにしてくれるパッケージ
調べものをしながらコーディングをすると、やってしまうことがあるため入れました

# *File Icons*
開いているファイルの種類をアイコンで表示してくれるパッケージ

# *autocomplete+paths suggestions*
ディレクトリのパスを自動補完してくれるパッケージ

# *atom-beautify*
自動的にコードのインデントなどを整形してくれるパッケージ

# Vue.js用のパッケージ
## language-vue-component
vue用のシンタックスハイライトが追加されるパッケージ

## *vue-autocomplete*
vue component用の入力の自動補完をしてくれるパッケージ

## *vue-hyperclick*
vue componentから定義元へジャンプできるパッケージ
※hyperclick,js-hyperclick,language-vue-componentを入れてないといけません

# 最後に
今回、AtomをインストールしたのはこれからVue.jsの勉強をしようと思ったからです。
今まではサーバーサイドよりのことを勉強してきたので、これからフロントを多めに勉強していきたいと思います。
セキュリティマネジメントの勉強-暗号化技術と認証

#暗号化技術
##暗号化
平文を暗号文にする
暗号化 <---> 復号

暗号化鍵、復号鍵が存在する

##共通鍵暗号＝秘密鍵暗号方式
暗号化鍵＝復号鍵
鍵が１種なので、秘密にしておく必要あり。

利点は単純で高速。
ただし、経路の数だけ鍵が必要になる。
zipのパスワード的なやつかな。

###DES
Data Encryption Standard
56bit、米国の旧国家暗号規格
今では安全性低い

###RC4
ストリームで徐々に暗号化していく
WEPでつかわれている
高速だが安全性はお察し

###Triple DES
DESを３回やる
でも推奨されない

###AES
Advanced Encryption Standard
DES後継
XORを繰り返し行う。128bit,192bit,256bit色々あり。
XORを行う回数を段数という

###Camelia
NTTと三菱が作った
AESと同等の安全性を保ちつつ、消費電力低めらしい

###Kcipher-2
九州大学とKDDIが作った
ストリーム型128bit
AESより7〜10倍早い

##公開鍵暗号方式
暗号化鍵≠復号鍵
公開鍵と秘密鍵のキーペアを作成。
公開鍵だけ他人に渡す。

相手の公開鍵で暗号化するから、相手は自身の秘密鍵でのみ解錠できる。
これによって守秘が実現できる。

ここで鍵とSeed値を同じように暗号化して送る事で、鍵共有が実現できる。

これとは逆に、自分の秘密鍵で暗号化して相手に送りつける事で
本人証明ができる。

###RSA
Rivest Shamir Adleman
大きい数での素因数分解が厳しいという前提のもとに作られている。
2048bit以上の安全性証明ついたやつのみ推奨。
https://qiita.com/izutetsuya/items/ff0347d26d1699ae3a94
なるほど厳しそうである。

###DH鍵交換
Diffie-Hellman key exchange
鍵共有の方式。
離散対数問題が安全性の根拠。
http://yougo.ascii.jp/caltar/%E9%9B%A2%E6%95%A3%E5%AF%BE%E6%95%B0%E5%95%8F%E9%A1%8C

###DSA
Digital Signature Algorithm
有限体上での離散対数問題が根拠。
https://www.cryptrec.go.jp/exreport/cryptrec-ex-0602-2006.pdf

###楕円曲線暗号
Elliptic Curve Cryptography:ECC
楕円曲線上の離散対数問題を根拠としている
RSAの後継で、署名アルゴリズムとしてECDSAがあるらしい

##ハッシュ
改ざんを検出するが、防止はできない
同じハッシュとなるメッセージを発見するのがむずいので、衝突発見困難性という
これが強度となるらしい
すなわち、盗聴されても元の値がわからないので強みとなる

###MD5
128bit。理論的に弱点がある
https://qiita.com/mogulla3/items/720c9c9731de0e906af2

###SHA-1
Secure Hash Algorithm 1
NIST(アメリカ国立標準技術研究所)が規格つくった160bitハッシュ
脆弱性が既にバレているが、互換性維持の目的でのみ容認されている

###SHA-2
Secure Hash Algorithm 2
NIST(アメリカ国立標準技術研究所)が規格つくった224bit以上のハッシュ
256以上が推奨されている

##ソルト
パスワード変換時にいらんのくっつけて、特定しづらくするために添加するもの
レインボー攻撃(ハッシュから原文を逆算)に対して有効。

##HMAC
Hash-based Message Authentication Code
メッセージに秘密鍵くっつけてハッシュにする
すなわち暗号化してハッシュする方式
強い

##危殆化
策定当初は強い暗号化強度だったけど時代とともに弱くなること
CRYPTEREC(暗号監視機関)の情報を要チェックや
https://www.cryptrec.go.jp/


#認証技術
##認証
本人認証、メッセージ認証、時刻認証など

###Authentication（二者間認証）
認証情報をアクセス先のサーバに求める方式

いわゆるbasic認証

###Certification（三者間認証）
認証局とかの第三者に認証させる
PKI(Public Key Infrastructure)はこれを利用している

oauthもこれだよ、な？？

##デジタル署名
本人の秘密鍵を持ってる事が自分自身であることの証明になる
受信者は相手の公開鍵で解答することで真正性がわかる

これにハッシュを組み合わせて、改ざんを検出することもできる

主にRSA、DSA、ECDSAが使われる

##XML署名
W3Cが勧告してる
文書全体だけじゃなくて、一部だけとか複数の文書への署名、複数人の署名に対応している
タグに使うアルゴリズムを指定するらしい

##リスクベース認証
通常と違う環境からログインしたら、通常認証と追加認証を行う
Googleアカウントのあれ

##メッセージ認証
送信前のハッシュと受信後のハッシュを比較することで改ざん検知する
伺かのアレ

###MAC
HMACの一段階前
メッセージ認証に共有の秘密鍵を突っ込む

###送金内容認証＝トランザクション認証
金融機関で送金内容にメッセージ認証を行う
利用者ごとに秘密鍵を用意して、金融機関との間で共有しておく
実際に送るときはHMACとかつかって改ざん検知する


##時刻認証（タイムスタンプ）
PKIとかのデジタル署名では他人の改ざんは検知できるが
本人による改ざんは検知できない
そこでタイムスタンプをくっつけて正当性を確かめる
TSA（時刻認証局）の時刻認証サービスを使って
書類のハッシュに時刻情報をくっつけ、TSAの署名を行ってタイムスタンプを作る

###時刻認証によってわかること
存在性（その時刻には存在したこと）、完全性（その時刻以降改ざんされていないこと）

###チャレンジレスポンス方式
認証サーバがランダムに異なる情報を送りつけて認証する（チャレンジ）
チャレンジにパスワード加えて演算した結果を返す（レスポンス）
ハッシュ使ったり、公開鍵、共通鍵暗号の３種がある
一般的なのはハッシュ
MkDocs+Read the Docsで面倒なWordのドキュメント管理から抜け出す

#はじめに
今までWordでパッケージソフトのドキュメントを作成し管理していたのですが、管理が割と面倒でした。

そんな面倒なWordのドキュメント管理から抜け出す方法を模索したので、その方法を残しておきます。
あまり日本語の情報が見当たらず意外と苦労したので参考になると幸いです。
#MkDocs
Markdownで書けてhtmlを自動生成してくれてオンラインでみれるURLを発行してくれるものがないかさがしていたらMkDocsに出会いました。静的サイトジェネレータです。他にもHugoとかもありますよね。
[MkDocs](https://www.mkdocs.org/)
![スクリーンショット 2020-01-24 23.36.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337592/b289baf9-ea53-0057-9053-ecaa9d28f959.png)
**テーマが色々と選べますが、Read the Docsを使用する場合、テーマはreadthedocsとmkdocsの２つのみしか使用できなかったので注意です。個人的にはmaterialがカッコイイ**
#MkDocs使い方
以下の記事を参考にすればすぐに作成できます。

[MkDocsによるドキュメント作成](https://qiita.com/mebiusbox2/items/a61d42878266af969e3c)<br>
[MkDocs 使ってみた。](https://www.kimoton.com/entry/2017/07/08/121050)<br>
[MkDocs：インストールから github pages へのデプロイまで](https://www.kakistamp.com/entry/2019/08/31/154536)
#Read the Docs
古いバージョンを使っている人が古いマニュアル見る需要は普通にあるとおもいます。
しかし残念ながら、MkDocsだけではバージョン管理が出来ませんでした。
そしてバージョン管理できるものを探していたらRead the Docsに出会いました。
[Read the Docs](https://readthedocs.org/)
![スクリーンショット 2020-01-24 23.40.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337592/ef7631b6-a111-2fc4-c562-cc1e866db9cf.png)
# Read the Docsでバージョン管理の方法
まずは[こちら](https://docs.readthedocs.io/en/stable/intro/import-guide.html)を参考に作成したmkdocsのリポジトリをインポートしてビルドします。
バージョン管理方法は、gitでタグ付けしてバージョン管理を行います。
gitでタグ付けしたコミットをpushすれば、自動的にRead the Docsでバージョンが別れた状態でデプロイされます。
各バージョンのドキュメントにURLが発行されて、参照することが可能になります。
**gitのタグでバージョン管理するのは初めてやったので、ここが少し不安。。**
#ハマった点
- **Read the Docsでサポートされるmkdocsのテーマはreadthedocsとmkdocsの２つのみ。**最初はmaterialで作っていたので、泣く泣くreadthedocsに変更しました。materialかっこよかった。。
- **無料のRead the Docsでビルド出来るリポジトリはパブリックのみ。**プライベートの場合は、[Read the Docs for business](https://readthedocs.com/)を使う必要があります。Basicプランで$50 per monthかかるみたいですね。
- 最初にRead the Docsでリポジトリをインポートしてビルドする際に次のエラーが発生し、ビルドが失敗。**`Read-the-docs build fails with “cannot import name 'PackageFinder' from 'pip._internal.index`**この[stackoverflow](https://stackoverflow.com/questions/59846065/read-the-docs-build-fails-with-cannot-import-name-packagefinder-from-pip-in)の通りにプロジェクトをwipeした後に、再ビルドしたら解決。gitのissuesにもあがってます。[Latest pip release fails #6554](https://github.com/readthedocs/readthedocs.org/issues/6554)

#終わりに
静的サイトジェネレータって色々あって面白いですね。
どれがどんな用途に適しているのか、色々と模索していきたいです。
とりあえず、hugoのacademicはカッコイイから使ってみたい。
JAWS-UGコンテナ支部 #16に参加しました【備忘】

# はじめに
[1/23のJAWS-UGコンテナ支部#16](https://jawsug-container.connpass.com/event/160835/)に行ってきたので、その時に知らなかったり知っていたけど曖昧だったことをまとめようと思います。

ただ自分がコンテナ知らな過ぎるせいで、ほとんど用語集兼資料リンク集になっています。

どうでも良いですが、「kubectl」は人によって読み方が違うようです。
今回のイベントでは「きゅーぶしーてぃーえる」と読む人が多かったですが、今日（1/24）に参加したOpenshiftのハンズオンでは「きゅーびーこんとろーる」と言っていました。わけがわからないよ（QB違い）

# kubetnetesの設計思想
[当日の発表資料](https://speakerdeck.com/inductor/understanding-eks-and-its-ecosystem-from-oss-perspective?slide=10)より抜粋

- 宣言的に構成管理
- コントローラを中心とした高い拡張性
- コンテナを基とした軽量、柔軟、高速なスケーリング

# 用語集

## KubernetesのIngressについて
[Ingress(kubernetesのドキュメント)](https://kubernetes.io/ja/docs/concepts/services-networking/ingress/)

平たく言うと、外部（インターネットなど）からのアクセスをクラスター内のServiceにルーティングしてくれるコンポーネント。
Serviceというのは複数のPodをひとまとめにした論理的な単位のこと。

[Service(kubernetesのドキュメント)](https://kubernetes.io/ja/docs/concepts/services-networking/service/)

※参考
[Amazon EKS の ALB Ingress Controller](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/alb-ingress.html)

## コンテナネットワークインターフェース(CNI)

KubernetesがAWSのネットワーク（VPC）と繋ぐためのプラグインらしいです。

[ポッドネットワーキング (CNI)](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/pod-networking.html)

[CNI カスタムネットワーク](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/cni-custom-network.html)

## コンテナストレージインターフェース(CSI)

平たく言うとCNIのストレージ版。

[Kubernetes Container Storage Interface（CSI）とは？](https://medium.com/makotows-blog/https-medium-com-makotow-kubernetes-contaienr-storage-interface-a0c4a0d04bad)

[Introducing Container Storage Interface (CSI) Alpha for Kubernetes](https://kubernetes.io/blog/2018/01/introducing-container-storage-interface/)


# 学習用記事
[イベントレポート](https://hi1280.hatenablog.com/entry/2020/01/24/214554)
発表資料のリンクをまとめて下さっていました。

[Amazon EKS Advent Calendar 2019](https://qiita.com/advent-calendar/2019/amazon-eks)

# その他雑感
もちろん他にも色々な話がありましたが、自分が理解していなさ過ぎて本当にただのWebページ貼り付けマンになりそうだったのである程度絞りました（それでもほぼリンク集ですが）

とりあえずeksctlは超便利らしいので今度使ってみようと思います。
基本情報技術者　テクノロジ系　第7章 セキュリティ④

続いてこちらも

# メッセージ認証とディジタル認証

メッセージ認証は文書が改竄されてないか検証する

ディジタル認証はメッセージダイジェスト関数(ハッシュ関数)と暗号技術を利用

## メッセージダイジェスト認証
ハッシュ関数の一種
文書改竄の確認をする

いくつかの特徴がありますが
出力値が同じであれば入力は同じとして扱います。

## ディジタル署名

公開鍵暗号方式で

メッセージ(元の文書)
ディジタル署名(メッセージをダイジェスト化してさらに秘密鍵で暗号化した物)

この二つを送って、送った先で公開鍵で復号して内容を確認する方式

## 公開鍵証明書と認証局(CA)

公開鍵が確かであると認証するのが
公開鍵証明書

発行する組織が
認証局(CA)

### PKI(公開鍵基盤)
CAによってセキュリティレベルを高めた環境のことを言います。
カスタムUserモデルを作成した後にUserが上手く追加されない件


## 起きたこと

なにが起きたかというと、

1. AbstractUserモデルを継承してカスタムUserモデルを作成。
2. adminにadmin.register.site(CustomUser)のように**普通に登録**
3. admin管理画面から新しくUserを登録！
4. 何故かパスワードが生で表示される。
5. ログインできない！！！

という問題が発生しました。。
結論から申しますと2の操作が原因です。


ちなみにUserのカスタマイズについては以下の記事に詳しくあります。
[okoppe8さんの記事](https://qiita.com/okoppe8/items/10ae61808dc3056f9c8e)

## 解決方法
UserAdminをadmin.site.register()の第２引数に登録してあげる。

```python:admin.py
from django.contrib import admin

from . models import CustomUser
from django.contrib.auth.admin import UserAdmin
)


admin.site.register(CustomUser, UserAdmin)

```

## 元のコード
管理画面をカスタマイズするためにUserAdminを自作してしまい、CustomUserモデルのadminとして登録してしまっていました。
これだと、パスワードが上手くハッシュされずに登録され、認証時にエラーとなってしまいます。

```python:admin.py
from django.contrib import admin

from . models import CustomUser


class UserAdmin(admin.ModelAdmin):
    list_display = ('username', 'id', )


admin.site.register(CustomUser, UserAdmin)


```

## 参考
Stuck Overflow
[Created User from django custom admin page can't login](https://stackoverflow.com/questions/30507666/created-user-from-django-custom-admin-page-cant-login)
基本情報技術者　テクノロジ系　第7章 セキュリティ③

私情で遅れがちですが
続きを書きます。

# エンティティ認証技術

パスワード認証やバイオメトリクス認証など
ユーザやホストが本物であるか確認する技術

## パスワード認証
正しいパスワードを知っているかで判断する一般的な方法

基本パスワードはパスワードファイルに格納しています。
それだけだと安全性に難があるのでハッシュ値に変換して格納し
必要な時に計算します。

##　チャレンジレスポンス認証

毎回サーバ側からパスワードを変更する方法

1,サーバから乱数を送ってくる
2,クライアントが鍵で暗号化する
3,サーバに送って復号する。

要は暗号化する鍵(ソフトウェア)を持ってるか確認する方法

## バイオメトリクス認証

指紋、声紋、虹彩、静脈で判断する方法

基本FRRとFARは相反します。

### FRR(本人拒否率)
本人でも認証に失敗する確率

喉を痛めているなど

### FAR(他人受入率)
他人であっても認証に成功する確率

## シングルサイオン(SSO)
一度、認証サーバで認証を受ければ
各サーバでの認証を省略できるシステム

ローカルに置いて、メールやファイルサーバなど
いちいち個別で認証するのが手間なので、このような方法が生まれました。

代表的なのが

kerberos認証や
XML形式のSAMLなど
パスワードの定期更新の弊害のわかりやすい説明を考えてみた

## 概要
いまだにパスワードの定期更新がベストプラクティスとして、開発プロセスに組み込まれていたりする。そんな残念な職場で伝えやすそうな説明の仕方を考えてみた。

* パスワードを複雑にする → 覚えられないのでメモする → 保管場所(漏洩箇所)が増える
* 定期更新を短くする → 更新前後で新しいパスワードを覚えなおすのが面倒 → 辞書攻撃に弱いパスワード量産

## 定期更新でありがちなループ

|    |   |   |
|----|---|---|
|1.  | セキュリティー管理者 | パスワードの定期更新を短くする
|2.  | 担当者 | 「定期更新前後でせっかく覚えたパスワードを覚えなおすの面倒だぞ」<br> → **辞書攻撃に弱いパスワード** を量産
|3.  |       | **辞書攻撃でパスワードが漏洩する**
|4.  | セキュリティー管理者 |「漏洩したパスワードがほかにあるかもしれず、手軽に根本対策したいぞ。」<br>→ **1.に戻る**

**まとめ**
辞書攻撃する人たちからすると、脆弱なパスワードを量産してくれるのですから、格好の餌場です。
最近はネットワーク回線も高速だし、攻撃者は次回のパスワード更新までに自分の仕事をすべて終えているでしょう。

なお、パスワードスプレー攻撃というのもあるので、連続するパスワードの試行が同一IPから来るとは限りません。

**以降は、余談です。**

## 整理
* 辞書攻撃でいえば、アルファベットを記号に読み替えるノウハウも攻撃ツールに組み込むのは簡単
* 短い間隔の定期更新を促すより、文字種や長さなど強度が高いパスワードを維持するほうが結果的に攻撃には強い
  * 定期更新しない前提だと、人間がパスワードを考えるよりは、生体認証だとかの方が強度の底上げにはなる

## IDとパスワード認証の関係

* ID ... 本人であることを識別するもの  
  例、ユーザーID、デバイスID、生体情報
* パスワード認証 ... IDのなりすましがないかを検証するもの

### 生体情報の扱い
生体情報は、認証というより、どちらかというとID寄りの考え方です。
生体情報は、いつも持ち歩いているので、パスワードとしてみるとパスワード持ち歩きです。
標的型攻撃の対象になった人が、友人や家族によって眠らされたりして、その間に生体情報を使って、なりすますことができるかもしれない。
こういうのは、テレワークなどが行われるとリスクが高まると考えられる。

パスワードは、本人の記憶の中にだけあるので、泥酔、睡眠時などのなりすましには強い。

## 今風の考え方
情報を活用した、より効果的な施策が色々でてきている。

* 認証システムへの攻撃に関するノウハウが高まってきて、攻撃のアクティビティがある程度、分かるようになってきている  
  → アクティビティの監視、および辞書攻撃など攻撃を完遂する前に防護
* 攻撃者の行動から、辞書攻撃に使われるリストなどパスワードの強度もある程度わかるようになってきている  
  → 強度の低い人にピンポイントで対策を促す通知を送ることもできる

パスワードの定期更新は情報を活用できない残念な企業で生き残っているのではなかろうか。
情報活用というと、IT企業を連想する。ITというと Information Technology 情報技術だ。
IT企業が残念な企業なら、その企業はもう表舞台に立つことはないだろう。
セキュリティ動向含めて、外部の動き・課題の把握する文化のない企業に何ができようか。

## 参考
* [NIST Special Publication 800-63B](https://pages.nist.gov/800-63-3/sp800-63b.html)
* [パスワードスプレー攻撃とは？仕組みと被害の特徴、対策方法について徹底解説 | CyberSecurity.com](https://cybersecurity-jp.com/cyber-terrorism/30629)
Go言語とginをWindows上で動かしてみる

#はじめに

始めてqiitaで記事を書くので緊張しています...
『[良い記事を書くには](https://help.qiita.com/ja/articles/qiita-article-guideline)』を参考にしていますが、至らぬ点などございましたら申し訳ありません。

# 環境

* OS: windows 10 Home
* Go: 1.13.6
* Git: 2.25.0
* Text Editor: Atom

# インストール

Go言語、Gitのインストールは、Windows用インストーラから行います。
ginのインストールはコマンドプロンプトより行います。

1. Go言語をダウンロード&インストール -> https://golang.org/dl/

2. Gitをダウンロード&インストール -> https://git-scm.com/download/win
　ginをgithubよりダウンロードするのですが、その際にGitが必要になります(当たり前か...)
　僕はこれに気が付かず、時間を浪費しました。

3. ginをダウンロード&インストール -> https://gin-gonic.com/ja/docs/quickstart/
　上記ページを参考にginのダウンロード&インストールを行います。
　
　`go get -u github.com/gin-gonic/gin`

# 動作確認

『[クイックスタート | Gin Web Framework](https://gin-gonic.com/ja/docs/quickstart/)』を参考にさせていただきました。
以下のプログラムを、コマンドプロンプトより`go run test.go`で実行します。

```Go:test.go
package main

import "github.com/gin-gonic/gin"

func main() {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run() // 0.0.0.0:8080 でサーバーを立てます。
}
```

参考ページには『ブラウザで `0.0.0.0:8080/ping` にアクセスする』と書いてありますが、なぜかつながりませんでした。
かわりに、`localhost:8080/ping`から接続したところ無事アクセスすることができました。

# Hello, world from Gin ! をしてみる

『[Go / Gin で超簡単なWebアプリを作る](https://qiita.com/hyo_07/items/59c093dda143325b1859)』を参考に、先ほどの```test.go```を少し書き換えます。

```Go:test2.go
package main

import "github.com/gin-gonic/gin"

func main() {
    r := gin.Default()
    r.LoadHTMLGlob("*.html")
    r.GET("/", func(c *gin.Context) {
        c.HTML(200, "index.html", gin.H{})
    })
    r.Run() // 0.0.0.0:8080 でサーバーを立てます。
}
```

`index.html`を用意します。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title>test index</title>
    </head>
    <body>
        <h1>Hello, world from Gin !</h1>
    </body>
</html>
```
コマンドプロンプトより`go run test2.go`で実行し、ブラウザより`localhost:8080`へ接続します。
以下が表示されて、無事動作していることがわかりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488997/f3b6d4e4-fb4d-42d3-5174-2c5fb07ace04.png)

# さいごに

Goとginを使ったWebアプリの開発がWindows上で行えることがわかり一安心です。

また、最近はWebアプリもどきをHeroku上で動かしたりしています。
データのやり取りなんかはJavaScript+GASなんかで行っていたのですが、限界が見えてしまったためサーバ側でも処理をさせようと思ったのが、今回 Goとginを触ったきっかけです。

今回書いたプログラムをベースに使えるアプリを作っていきたいと思う所存です。
チーム開発における負のスパイラル。成果がいつまでも出ない理由。

※チームメンバーの能力の差に開きがある場合を想定しています。

多くのチームではPull Requestを使った開発をしており、自分が書いたコードが他の人の協力（レビュー）なしにリリースされることはない。

チームメンバーそれぞれに別タスクを割り振る場合、優先順位が高いタスクを能力が高いメンバーに割り振り、低いものは能力が低いメンバーに割り振ることで、チームの成果を大きくすることを目指す。

合理的な判断だと思う。

しかし、優先順位の低いタスクに関する相談やPull Requestのレビューは後回しにされがちで、成果を出しづらい。

成果が出ないと優先順位が高いタスクが割り当てられず、成果が出しづらい環境が続いてしまう。

成果が出ないメンバーがいる場合はこのスパイラルに陥っていないか気にしてみるとよいかもしれない。
プログラミング学習１年目下半期に読んだ本まとめ

プログラミングを学習し始め約1年経ったので、ここ半年に読んだIT関連の本をまとめます（順不同）。
上半期に読んだ本については
[プログラミング学習半年の間に読んだ本まとめ](https://qiita.com/kota_sho/items/225fab8a515d17b96e52)
昨夏に就職し、業務に必要なとなる知識、将来的に役立ちそうな事など様々な本を読みました。
感想メインなので、内容の詳細はタイトルからリンクにアクセスして見てください。


[１、コンピューターシステムの理論と実装]
(https://www.oreilly.co.jp/books/9784873117126/)
コンピューターが動く根本的なところを理解したいと思い買った一冊。実際に仮想環境で１からコンピューターを作れるカリキュラム形式となっている。ただ、自分にとっては難しすぎて一通り目を通して結局実践はまだ出来ておらず、改めて挑戦したい。

Qiita記事：
[【読書】コンピューターシステムの理論と実装を読んで](https://qiita.com/kota_sho/items/f057af29151bda0d101b)


[２、SEの基本]
(https://www.amazon.co.jp/SE%E3%81%AE%E5%9F%BA%E6%9C%AC-%E5%B1%B1%E7%94%B0-%E9%9A%86%E5%A4%AA/dp/4534045123)
エンジニアとしてIT企業で働くにあたっての最低限の基礎知識が書かれている。開発手法やマネジメントなど一通り広く浅く、ざっと目を通しただけだけどとりあえず読んでおいてよかった。


[３、ずっと受けたかったソフトウェアエンジニアリングの新人研修](https://www.shoeisha.co.jp/book/detail/9784798157566)
前述の本と似たような内容だったが、こちらの方が要件定義〜設計〜開発〜テスト〜導入の各プロセスについて詳細に書かれていて初心者の自分にとって役に立った。


[４、イラスト図解でよくわかるITインフラの基礎知識]
(http://gihyo.jp/book/2018/978-4-7741-9600-8)
インフラについて勉強したいなと思い最初に手に取った本。とりあえず易しそうだったから。正直読み返すことはないかなという感じ。インフラを分野毎順番に勉強するなら目次見て、[IT用語辞典e-words](http://e-words.jp/)とか見た方が分かりやすいかもしれない。


[５、レガシーコードからの脱却 
ソフトウェア寿命を延ばし価値を高めるための９つのプラクティス]
(https://www.oreilly.co.jp/books/9784873118864/)
今まで読んだIT関連の本ではNo１かもしれない傑作。元々ネットでの評判が高かったので買ってみた。
コーディング技術も書いてあるが、どちらかというと開発プロジェクトをどう進めていくのかという「考え方」が中心。もちろん、その中でより詳細に開発手法（ペアプログラミングを推奨したり）含め、「９つのプラクティス」として詳しく書いてある。小難しい本かなと思ったが、実際文章も読みやすく分かりやすい。特にプロジェクトマネージャー向けにオススメされてる本みたいだが、開発者が読んでも間違いなく役立つ。10年後もきっと読み返してるはず。


[６、ITエンジニアのための【業務知識】がわかる本]
(https://www.shoeisha.co.jp/book/detail/9784798157382)
要件定義では顧客のビジネスモデル、業務について理解しなければならないため一通り読んだ。財務・会計、受発注処理、在庫管理など。辞書として持っておきたい。


[７、だまし絵を描かないための-要件定義のセオリー-]
(https://www.amazon.co.jp/%E3%81%A0%E3%81%BE%E3%81%97%E7%B5%B5%E3%82%92%E6%8F%8F%E3%81%8B%E3%81%AA%E3%81%84%E3%81%9F%E3%82%81%E3%81%AE-%E8%A6%81%E4%BB%B6%E5%AE%9A%E7%BE%A9%E3%81%AE%E3%82%BB%E3%82%AA%E3%83%AA%E3%83%BC-%E8%B5%A4-%E4%BF%8A%E5%93%89/dp/4865940685)
さらっと読み流しただけ。題名どおりセオリーなので実用書というよりか読み物に近い一冊か。


[８、ゼロからわかるVisual Basic超入門]
(https://www.amazon.co.jp/%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E3%82%8F%E3%81%8B%E3%82%8B-Visual-Basic%E8%B6%85%E5%85%A5%E9%96%80-%E6%94%B9%E8%A8%822%E7%89%88-%E3%81%8B%E3%82%93%E3%81%9F%E3%82%93IT%E5%9F%BA%E7%A4%8E%E8%AC%9B%E5%BA%A7/dp/4774191175)
VBのことを全然知らなかったので、まずはこれに目を通した。２日で読み終わった。というか全部隅から隅まで読んではいない。「変数とは何か」などの説明から始まり、これからプログラミング始めますという人向けなのだろうか。VBとは何かという概要を掴むのにはいいのかもしれない。

[９、令和02年　イメージ＆クレバー方式でよくわかる　栢木先生の基本情報技術者教室](https://www.amazon.co.jp/%E4%BB%A4%E5%92%8C02%E5%B9%B4-%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8-%E3%82%AF%E3%83%AC%E3%83%90%E3%83%BC%E6%96%B9%E5%BC%8F%E3%81%A7%E3%82%88%E3%81%8F%E3%82%8F%E3%81%8B%E3%82%8B-%E6%A0%A2%E6%9C%A8%E5%85%88%E7%94%9F%E3%81%AE%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85%E6%95%99%E5%AE%A4-%E6%A0%A2%E6%9C%A8/dp/4297110113)
SNSやネットで調べたら一番人気だったのでこの本を選んだ。現在勉強中。
[Elixir] Enum.find_index/2 の複数の index を返す関数を書いてみる

@QUANON さんの[[Ruby] Array#find_index の複数の index を返すバージョンがほしい](https://qiita.com/QUANON/items/ca06f3068c87b3a21e18) を[Elixir](https://elixir-lang.org/)で書いてみました

# バージョン情報
```
% elixir -v
Erlang/OTP 22 [erts-10.5.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Elixir 1.9.4 (compiled with Erlang/OTP 22)
```

# やりたいこと
[Enum.find_index/2](https://hexdocs.pm/elixir/Enum.html#find_index/2) は引数に一致する最初の要素のインデックスを返す。

```Elixir
iex> ~w(🦜 🐟 🐁 🦄 🐁) |> Enum.find_index(&(&1 == "🐁"))
2
```

でも一致するすべてのインデックスを返してほしいな。

```Elixir
iex> ~w(🦜 🐟 🐁 🦄 🐁) |> Awesome.indexes(&(&1 == "🐁"))
[2, 4]
```

# 方法
```Elixir:lib/awesome.ex
defmodule Awesome do
  @moduledoc false

  @doc """
  indexes

  ## Examples

      iex> ~w(🦜 🐟 🐁 🦄 🐁) |> Awesome.indexes(&(&1 == "🐁"))
      [2, 4]

      iex> ~w(🦜 🐟 🐁 🦄 🐁) |> Awesome.indexes(&(&1 == "🐟"))
      [1]

      iex> ~w(🦜 🐟 🐁 🦄 🐁) |> Awesome.indexes(&(&1 == "🐝"))
      []

      iex> ~w(🦜 🐟 🦄) |> Awesome.indexes(&(&1 == "🐁"))
      []

      iex> ~w(🐁 🐁 🐁 🐁 🐁) |> Awesome.indexes(&(&1 == "🐁"))
      [0, 1, 2, 3, 4]

      iex> [] |> Awesome.indexes(&(&1 == "🐁"))
      []

  """
  def indexes(list, fun) do
    list
    |> Enum.with_index()
    |> Enum.filter(fn {v, _} -> fun.(v) end)
    |> Enum.map(fn {_, idx} -> idx end)
  end
end
```

# 最初に書いたバージョン
```Elixir:lib/awesome2.ex
defmodule Awesome2 do
  @moduledoc false

  @doc """
  indexes

  ## Examples

      iex> ~w(🦜 🐟 🐁 🦄 🐁) |> Awesome2.indexes(&(&1 == "🐁"))
      [2, 4]

      iex> ~w(🦜 🐟 🐁 🦄 🐁) |> Awesome2.indexes(&(&1 == "🐟"))
      [1]

      iex> ~w(🦜 🐟 🐁 🦄 🐁) |> Awesome2.indexes(&(&1 == "🐝"))
      []

      iex> ~w(🦜 🐟 🦄) |> Awesome2.indexes(&(&1 == "🐁"))
      []

      iex> ~w(🐁 🐁 🐁 🐁 🐁) |> Awesome2.indexes(&(&1 == "🐁"))
      [0, 1, 2, 3, 4]

      iex> [] |> Awesome2.indexes(&(&1 == "🐁"))
      []

  """
  def indexes(list, fun) when is_list(list), do: _indexes(list, fun, 0, [])

  defp _indexes([], _, _, result_list), do: result_list

  defp _indexes([head | tail], fun, idx, result_list) do
    if fun.(head) do
      _indexes(tail, fun, idx + 1, result_list ++ [idx])
    else
      i = Enum.find_index(tail, &fun.(&1))

      if i,
        do:
          _indexes(Enum.slice(tail, (i + 1)..-1), fun, idx + 2 + i, result_list ++ [idx + 1 + i]),
        else: result_list
    end
  end
end
```
- 長い。。。
- [if/2](https://hexdocs.pm/elixir/Kernel.html#if/2) 入れ子で使っている。。。
- こんなに複雑なことをする必要はないと思い直して、発想を変えてみました
- もとの記事の `map.with_index { |element, i| i if element == val }.compact` これをよく見ればよかった。。。
- まあ、とにかく書けたことはよかった
メモリ領域とガベージコレクション

## 0. はじめに
プログラムのメモリ領域とガベージコレクションについてまとめました。

## 1. メモリ領域の種類
プログラム実行時のメモリ領域は「静的領域」「ヒープ領域」「スタック領域」に分類される。

### 1-1. 静的領域
#### 格納する情報
- グローバル変数やプログラムの命令、クラス情報など

#### 格納するタイミング
- C++では、アプリケーション開始時に全てのクラス情報を一括格納する。
  - メリット・・・プログラムの動作によって変化しないため、実行性能が良い。
  - デメリット・・・メモリ使用量が大きくなる。
- Javaや.NETでは、クラスが必要となった時点で逐次格納する。そのため、静的領域ではなく**メソッドエリア**と呼ばれることが多い。
  - メリット・・・新しいクラスを読み込む度にオーバーヘッドが発生するため、実行性能が悪くなる。
  - デメリット・・・メモリ使用量を減らすことができる。

### 1-2. ヒープ領域
#### 格納する情報
- 生成したインスタンスなど。

#### 格納するタイミング
- プログラムの実行時。

### 1-3. スタック領域
#### 格納する情報
- メソッドの引数、ローカル変数、戻り値など。

#### 格納するタイミング
- メソッド呼び出し時。

## 2. ガベージコレクション
- ヒープ領域のインスタンスが不要になったら自動で解放する仕組み。
- ガーベッジコレクタがというプログラムが制御を行う。
- プログラミング言語(Javaの場合、Java VM)が提供する。
- 自動で解放するとはいえ、一時的に数万～といった大量のインスタンスを作った場合は、当然メモリを大きく消費するので注意。
- 削除対象となるのは、静的領域、ヒープ領域から辿れない、孤立したインスタンス。



## 3. 参考文献

- [**オブジェクト指向でなぜつくるのか**](https://www.amazon.co.jp/dp/4822284654/)