OmniAICreator/Qiita-1.07M huggingface dataset:
Firebase初心者向け！Firebaseでパスワードを使わずにメールリンク認証を行う方法

今日はほぼ自分用のメモとして、Firebaseのメールリンク認証を行う備忘録を書いていきます。

なぜこの記事を書くかと言うと、Firebaseのアカウントでパスワードリセットを行うときにユーザーをログインさせないと新しくパスワードを設定することができないんです。

じゃあパスワード変更できないじゃんと思ったのですが、さすがグーグルさん！

Firebaseにはパスワードなしでリンクを使うことで、ログインすることができます。

特に詳しい説明は致しませんのでご了承ください。

それでは見ていきましょう！

#アクションコードの設定#

メールリンクの送信はパスワードはいらないものの、メールアドレスは必要なのでユーザーに入力してもらいましょう。

Firebaseのこちらのドキュメント[メールのアクション リンクを生成する](https://firebase.google.com/docs/auth/admin/email-action-links)にアクションコードの設定が書かれているのでわからなかったら見て下さい。

以下のようにアクションコードを設定します。

```index.js
 // メールリンクにアクションコードを設定
 const actionCodeSettings = {
    url: window.location.origin + '飛ばしたいパス（例：/user）',
    handleCodeInApp: true
 }
```

``url``：この後にメールを送るのですが、その送ったメールのリンクに**続行URL**というもの。要するにメールにクリックし、処理を終えたときにどのページに飛ぶかを記録。

``handleCodeInApp``：これについてはあまり僕も詳しくないので、先ほど貼ったドキュメントを見て下さい。どうやらWebだったらブラウザに、iosだったらiosアプリ、AndroidならAndroidアプリに飛ぶらしい。（正しいかは分からない）

#メールの送信、およびEmail情報の保存#

次に、ユーザーにメールを送信します。

同時にローカルストレージにメールアドレスを保存します。

```index.js
      // メールリンクにアクションコードを設定
      const actionCodeSettings = {
        url: window.location.origin + '/actionresetpassword',
        handleCodeInApp: true
      }

      // ここから追加

      // メールリンクの送信
      firebase
        .auth()
        .sendSignInLinkToEmail('example@gmail.com', actionCodeSettings)
        .then(() => {
          // ローカルストレージにemail情報を保存
          window.localStorage.setItem('email', 'example@gmail.com')
        })
        .catch((error) => {
          alert(error)
          return
        })
```

#メールリンクが本当に正しいかの確認#

最後に、クリックしたリンクが本当に正しいのかを確認します。

クリックしたページで、``isSignInWithEmailLink``という関数を使って判断します。

```action.js
      if (firebase.auth().isSignInWithEmailLink(window.location.href)) {
        // リンクが正しいとき

        const email = window.localStorage.getItem('email')
        if (!email) {
          // ローカルストレージにemailキーが存在しない場合、もう１度入力
          alert('申し訳ございませんが、ご入力いただいたメールアドレスを確認できなかったため再度ご入力お願いします。')
        }

        // サインイン（これを行わないとパスワードリセットができない）
        firebase
          .auth()
          .signInWithEmailLink(email, window.location.href)
          .then(() => {
            // email情報を消去
            window.localStorage.removeItem('email')
            window.location.replace(this.$router.currentRoute.query.continueUrl)
          })
      } else {
        // リンクが正しくないとき
        alert('申し訳ございませんが、リンクの有効期限が切れているため再度ご入力お願いします。')
        window.location.replace('/')
      }
```

``isSignInWithEmailLink``の引数には現在のURL（window.location.href）を渡します。

そして、先ほど``actionCodeSettings``で設定した``url``は、メールリンクの``continueUrl``というクエリ情報として渡されます。これを``this.$router.currentRoute.query.continueUrl``などのように取得します。

このようにして**続行URL**を使用します。

また、ローカルストレージに保存したEmail情報をもとに``signInWithEmailLink(email, window.location.href)``でログインすることができます。

初めてだったので、割と時間かかりました。。。

Firebaseのドキュメントはとても分かりやすくていいなと思いました。

皆さんも誰かが書いた記事を読むだけでなく、公式ドキュメントを読むことでより理解が深まると思うのでぜひ見て下さい！

以上、「Firebase初心者向け！Firebaseでパスワードを使わずにメールリンク認証を行う方法」でした！

良ければ、LGTM、コメントお願いします。

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも毎日初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい！！

Thank you for reading
初心者がkerasを使った画像分類でメモリエラーに直面したときの対処法(サーベイ中心)

# なぜこんな問題に直面したのか？
現在、会社の自己啓発プロジェクトの一環として、機械学習初心者数人で、kaggleの[cassava classification](https://www.kaggle.com/c/cassava-leaf-disease-classification)のプロジェクトにトライしております。
pythonはここ一年でようやく慣れてきましたが、画像データを取り扱うのは初めてでなかなか不慣れなことが多いです。
同プロジェクトでCNNについての輪講を実施したので、使ってみようと思っていたのですが、

```
MemoryError
```

('Д')
大量の画像データなんて扱ったことないし、所詮数値データなんだからnumpyに直してしまえば全部読み込めるだろうと思っていたのですが、２万枚というレベルになるとなかなか厳しそうですよね。ということで、自分なりに考えたり調べたりした結果を共有しようと思います。

# 実際にはどのくらいのサイズになるのか？

ざっくり全部展開するとどのくらいになるのか計算してみます。

| 項目|値 |
|:-:|:-:|
|  画像サイズ | 800x600  |
| 枚数 |  21,397枚 |
|  チャンネル数 | 3 |
|  各要素の値の範囲 | 0-255(8bit) |

$$
600\times 800\times 21397\times 3\times 1[byte] \approx  30[GB]
$$

え？さすがに重たすぎる？？ダウンロードしても2GB程度なのに？？
と思ったのですが、jpg画像ファイルは圧縮がかかっていたりサイズ調整がなされていることで実際のサイズよりは小さくなっているようです。それにしてもちょっと重すぎる感じがしますが、本題とは関係ないのでいったん保留。

ということで、すべての画像を数値としてメモリに保持するのは困難であるようです。


# kerasの公式ドキュメントに従う
- modelクラスのメソッドを使用する(train_on_batchとtest_on_batch)
- modelクラスのメソッドを使用する(fit_generator)

https://keras.io/ja/getting-started/faq/#_8

# ImageDataGeneratorクラスの存在に頼る
kaggleのnotebookランキングを見ているとどうもImageDataGeneratorなるものがあるようです。詳しくは[こちら](https://qiita.com/gal1996/items/00ed3589e13448496b4c)に。簡単に言えば、一つ一つ画像を加工して取り出してくれるものです。こんな感じで使います。引数は[ここ](https://keras.io/ja/preprocessing/image/)に

```
from keras.preprocessing.image import ImageDataGenerator
datagen = ImageDataGenerator(
            featurewise_center = False,
            samplewise_center = False,
            featurewise_std_normalization = False,
            samplewise_std_normalization = False,
            zca_whitening = False,
            rotation_range = 45,
            width_shift_range = 0.2,
            height_shift_range = 0.2,
            horizontal_flip = False,
            vertical_flip = False,
            validation_split = 0.2
        )
```

# 画像を切り取る
意外とこれをやってるnotebookがたくさんありました。切り取るサイズはまちまちでしたが、256や512など2の累乗が割と多かった気がします。しかも縦横同サイズが多いです。しかし正方形でなければいけないという決まりもないので自由にってかんじですね。(https://teratail.com/questions/200002)


# 精度向上のメモ
画像認識は結局、転移学習が強いらしいです。
あらかじめパラメータも設定してもらってるので、かなり楽できそうですね。
ただし、パラメータ数が莫大なので注意(68万とかあるらしい)。
今回はefficientnetというやつを使いました。
https://qiita.com/omiita/items/83643f78baabfa210ab1

使い方は簡単。kaggleにもともとインポートされてないのでnotebook上で以下の記述をする。
```
!pip install git+https://github.com/qubvel/efficientnet
```

notebook上の記述は単純でよい。またmodelはB0~B7まである。

```
from efficientnet.keras import EfficientNetB0

model = EfficientNetB0(include_top = False, weights = None,input_shape = (TARGET_SIZE, TARGET_SIZE, 3))
model = model.output

```
この後プーリング層や全結合層をくっつけてあげるといい精度を出せるみたい。


# 参考
https://aotamasaki.hatenablog.com/entry/2018/08/27/124349
https://developers.wonderpla.net/entry/2017/10/24/110000
https://www.haya-programming.com/entry/2017/02/09/190512
https://nonbiri-tereka.hatenablog.com/entry/2016/01/03/230429
途中からのレコードデータを抽出するSQL

#途中からのレコードデータを抽出するSQL
ORACLE SQLで、XXX行からYYY行までのレコードを抽出したかったので、そのためのSQLを備忘を含め以下に記載しました。

```
SELECT *
FROM
  (
    SELECT
      ROWNUM AS NUM     --疑似列
      ,B.*
    FROM
      (
        SELECT *
        FROM TABLE A
        ORDER BY
          AGE           --年齢
          ,GENDER       --性別
      ) B
  ) C
WHERE
  NUM BETWEEN 11 AND 20 --11行~20行のレコードを抽出
```
別のSQLならLIMIT OFFSET を使用すれば簡単に途中からのレコードを抽出できるのですが、ORACLEだと私の知る限りではこの方法しかないと思います、少々煩わしいですけど。
UbuntuにVisual Studio Codeをインストールするとディレクトリを開くアプリとして登録されてしまうのを解除

# 背景

UbuntuにVSCodeをインストールすると、ディレクトリを開くデフォルトアプリケーションとして登録され、スマホをUSBでMTP接続したときにアプリケーションランチャーに出てくるアイコンをクリックするとVSCodeが起動してしまう。
その他のアプリケーションでもフォルダを開くボタンをクリックしたときにVSCodeが起動してしまって開けない、ということも発生した。

Nautilusでは普通のファイルは右クリックから「開き方」でデフォルトアプリケーションを選択できるのだが、ディレクトリについてはこの「開き方」タブがないため、Nautilusでは設定ができなかったので、別の解決方法を試した。

## 解決方法

アプリケーションがどのMIMEタイプに対応しているのかは、.desktopファイルで管理されている。

VSCodeの.desktopファイルを好きなエディタで開く。

~~~bash
cd /usr/share/applications
sudo nano code.desktop
~~~

`MimeType=`となっている部分に`inode/directory`という記述があるので、これを削除して保存する。

~~~txt:/usr/share/applications/code.desktop
#MimeType=text/plain;inode/directory;application/x-code-workspace;
MimeType=text/plain;application/x-code-workspace;
~~~

最後に.desktopファイルの変更をデータベースに反映すればOK。

~~~bash
sudo update-desktop-database
~~~
Laravelのモデルとマイグレーション 

#概要
`Laravel`の学習に伴って最低限の知識を整理した個人的な備忘録です。

#Eloquentについて
データベースと連携しデータの取得や登録、削除など、一連のデータ操作を簡単に行う為の機能。`Rails `でいう`ActiveRecord`的なやつ。

#モデルファイルの作成方法

```
php artisan make:model Test
```
上記のコマンドで`Test`モデルのファイルを作成できるが、`app`フォルダ直下に作成されてしまう。

```
php artisan make:model Models/Test
```
`app`フォルダの下に`Models`ファイルを作成し、その中にモデルファイルを作成。
以下実行結果。

```php:app/Models/Test.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Test extends Model
{
    //
}
```
`-mc`をつけることでマイグレーションファイルとコントローラーファイルもまとめて作成可能。

```
php artisan make:model Models/Test -mc
```

#マイグレーション
マイグレーションファイルの作成コマンド

```
php artisan make:migration create_tests_table
```
マイグレーションファイルを作成した後にデータベースにテーブルを作る際のコマンド

```
php artisan migrate
```

#感想
上級者は知らない言語のフレームワークでも大体理解できると聞いたことがあります。Railsしか触ってなかった時はそんなの絶対嘘だろと思ってましたが、Laravelにも触るようになってからその気持ちが分かるようになりました。
初心者が初心者と情報を共有する~OSのインストール~

機械学習コンペKaggleやSignateに興味があり、機械学習をやるためにPCを用意したい！！でも「ディープラーニング PC」なんかで検索した日には個人レベルでは石油王じゃないと買えなさそうなPCばかり出てくる！！そういうのじゃなくて、もっと機械学習初心者が気軽にGPUを使って計算できるようなPCを手始めに買って、適性を見極めたい！！あんまり安いとやる気なくなりそうだから15万円以内ぐらいで。
という思いが私にあり、「機械学習初心者向けの自作PCをやるか…」となったわけです。
ただ正直、全く(でもないけど)知識はないし、そもそも初心者過ぎて「不良品と組み上げミスの違いが判らない」という残念な懸念事項がある。
というわけで、最初はOS無しのPCにOSをインストールするところから、自作PCを始めてみたいと思ったわけです。それを「自作PC」と呼んでいいのかはさておき。
ゆくゆくはマザーボード、メモリ、GPU、電源、CPUなどを選定していければ、と思う。というわけで、やったことのメモです。初心者が初心者相手に「ほら、難しくなかったよ」と伝えるための啓発のような記事です。

#PCのスペック
簡単に言ってしまえば、ドスパラのMagnate MTをカスタム注文したものです。
OS無し
CPU intel core i5-10400 (6コア12スレッド)
メモリ 16GB
GPU RTX 1660super
SSD 250 GB(ケチった)
追加HDD 1TB
マウス無し
キーボード無し

です。OSに関しては「機械学習をもっと本腰を入れてやる」とかそういう状態になったら「ubuntuがいいらしい」というコメントを参考に、それをインストールしたいなと。
今回はWindows10 proを入れます。理由は単純、リモートデスクトップをやりたいから。

お値段送料込みで95000円弱！！安い！！(上記の検索結果を見て感覚がおかしくなっています)。

ちなみにOSはWin 10proを普通に電気屋で購入したので25000円！！高いね！！！合計120,000円弱でした。

#組み上げ
といっても、家に届いてそれを開封して組み上げるだけ。
本体はもう組みあがっているし、電源ケーブルをつないで、ディスプレイにつなぐ。
初めて知ったんですが、GPU側のディスプレイ出力端子につなぐ必要があるらしい。
HDMIケーブルを接続。

そして大事なのが、OSのデータが入ったUSBメモリとマウス・キーボードを接続すること。マウス・キーボードは無線でも大丈夫でした。bluetoothはどうなんだろう？ダメそう。
OSデータについて
[Microsoftの公式ページ](https://www.microsoft.com/ja-jp/software-download/windows10)からデータはダウンロードできる。8 GBぐらいの容量が必要なので、1,000円ぐらいで8 GBのUSBメモリを購入し、ダウンロードしました。この際、このUSBメモリはOSの」インストールにしか使えなくなるみたいなので、ほかのデータを保存するために無駄に容量の大きなUSBメモリを買う必要はなさそう。
これをPCに接続。これで準備万端。

![DSC_0774_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070392/0e8e6fa6-0f2d-549d-c0c1-c4cd55a88174.jpeg)
こんな風に、特に刺し方などは考えず、接続。

#電源ONとその後
結論から言うと、とても簡単に物事が進みました。
データ保存領域がSSDとHDDの二つあり、どのようにこの二つを分けてOSをインストールすればいいのだろう、と心配でしたがそれも杞憂に。

1.まずは
![DSC_0775_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070392/afe4dbab-ce18-9f19-afd9-425f07b1a2fe.jpeg)
言語とキーボードの設定ですね(直撮りですみません)。まぁデフォルトで大丈夫でしょう。

2.次に
![DSC_0776_LI_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070392/3ca0653c-d529-a07f-e86e-3d6d0c62c6d1.jpeg)
ライセンス認証です。購入したOSについていたものを入力しました。今更ですが、この画像中のマウスポインタの下にあるアイコンを押したらキーボードなくてもできたんですかね？

3.次いで
![DSC_0777_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070392/9c58eeae-27dc-bdd0-12ca-70100b4c4442.jpeg)
インストールの種類を選択するのですが、最初のインストールなので、画面の指示に従い、下のカスタム Windowsのみをインストールする、を選択。

4.最後に
![DSC_0778_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070392/67dc4803-398a-9e9e-786d-a91892fedef8.jpeg)
ここで記憶領域の選択。どっちがHDDでどっちがSSDか書いていないのですが…。容量的には下ですね。ということで下を選択。

そうすると
![DSC_0780_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070392/320b8efe-2950-50f7-0116-d8c1c2e05812.jpeg)
インストールが始まり、

![DSC_0782_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070392/259d1853-c06e-2d67-e537-9bc0aebfbf50.jpeg)
見慣れた（ほんと？）Windowsの初期設定画面が出てきました。これであとはWindowsPCの初期設定と同じやり方で設定できます。

#最後に
意外と簡単でした。OSのインストールをしただけですが。
そしてPCのスペックに関してですが、これだけあればそれなりに機械学習でいろいろできる(≒Kaggleとかに参加してもそこまで支障はない)って最近出版されたどこかの本に書いてありました。これでバリバリ機械学習を進めていきます。
Crostiniの初期設定

ChromebookのLinuxコンテナ（Crostini）は非常に便利です。
開発や検証に使用して不要になったらすぐに削除できますし、作成も数分で完了します。
そこでCrostiniを使い始める前にやっておくべきと思う最低限の設定です。

# 環境
- Asus Chromebook C425TA
- Google Chrome OS
 - バージョン: 87.0.4280.142（Official Build）（64 ビット）
- Debian GNU/Linux 10 (buster)

# sources.listに国内CDNミラーを追加する
debianの[サイト](https://www.debian.or.jp/using/mirror.html)を参考にして`/etc/apt/sources.list` に国内のCDNミラーサーバを追加する。

```
$ sudo vim /etc/apt/sources.list
```

以下の2行を追加して元の2行はコメントアウトしてしまう。

```
deb http://ftp.jp.debian.org/debian/ buster main contrib non-free
deb http://ftp.jp.debian.org/debian buster-updates main contrib
```

# パッケージの更新
```
$ sudo apt-get update && sudo apt-get -y upgrade
```

# vimrcをsudo vimでも使えるようにしておく
```
$ sudo ln -s ~/.vimrc /root/.vimrc
```

# ターミナルの設定

この設定はChromebook側の設定なのでLinuxコンテナを再作成しても失われることはない

1. croshを開く（Chromeで`Ctrl+Alt+T`）
2. croshで`Ctrl-Shift-P`を入力すると【ターミナル設定】画面が開く
3. 【キーボード バインディング/ショートカット】に以下の値を設定する

```
{
  "Ctrl-Shift-Space": "PASS",
  "Ctrl-Space": "PASS"
}
```

この設定をしておかないとターミナル上で日本語入力のオン/オフができません。

# 最後に
他にも日本語入力の設定などやるべきことは多々ありますが、最低限やっておいたほうが良い設定でした。
内容に誤りがあれば教えて頂けたら幸いです。
ここまで読んでいただき、ありがとうございました。
dieselでAssociations

## 概要

タイトルのことをやりたかったので以下を参考にやってみました
https://docs.diesel.rs/diesel/associations/index.html

一つのRoomに複数のCommentが存在しているケースでやってみます。

## モデル

dieselでは現状has_manyの概念がなく、belongs_toを使って関連付けをするようです。

### Room

親となるRoomの定義です。
Identifiableのアトリビュートが必要なようです。

```rust
#[derive(Identifiable, Queryable, PartialEq, Debug)]
#[table_name="rooms"]
pub struct Room {
    pub id: i32,
    pub name: String,
}
```

### Comment

次に子となるCommentの定義です。親と同じくIdentifiableが必要です。

また、子にはAssociationsのアトリビュートも付ける必要があります。
さらにbelongs_toで親のモデルを指定しましょう。

```rust
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
#[belongs_to(Room)]
#[table_name="comments"]
pub struct Comment {
    pub id: i32,
    pub message: String,
    pub room_id: i32,
}
```
### 呼び出し部分

この例ではRoomのidが1のデータを取得し、それに紐づくCommentを全て取得しています。

```rust
let room = rooms.find(1).first::<Room>(&connection)?;
let comments = Comment::belonging_to(&room)
    .load::<Comment>(&connection)
    .expect("error on load comments");
```

## 補足

### foreign_keyを指定する

デフォルトはbelongs_toで指定したモデルを元に"{モデル名(snake case)}\_id"でforeign_keyを判別するようです。

例えばモデル名をRoomModelとCommentModelに変更すると、room\_model\_idをforeign_keyとして使おうとして、プロパティが存在しないためエラーとなります。

```rust
#[derive(Identifiable, Eq, PartialEq, Debug, Queryable, Associations)]
#[belongs_to(RoomModel)]
#[table_name="comments"]
pub struct CommentModel {
    pub id:i32,
    pub room_id: i32,
    pub message: String,
}
```

このような場合はbelongs_toにforeign_keyを指定することにより、エラーが解消されます。

```rust
#[derive(Identifiable, Eq, PartialEq, Debug, Queryable, Associations)]
#[belongs_to(RoomModel, foreign_key = "room_id")] // foreign_keyを指定
#[table_name="comments"]
pub struct CommentModel {
    pub id:i32,
    pub room_id: i32,
    pub message: String,
}
```

## さいごに


ZEROBILLBANKでは一緒に働く仲間を募集中です。
[ZEROBILLBANK JAPAN Inc.](https://zerobillbank.com/%e3%81%8a%e5%95%8f%e3%81%84%e5%90%88%e3%82%8f%e3%81%9b/)
DataTables Editor エンターキーで即時Submitされる件

 DataTables Editorを利用したフロント環境を構築しています。

デフォルトのままだと、新規追加や修正等のポップアップを表示後、文字入力後にエンターキーを押下すると他の項目が空であっても即時Submitされてしまいます。

DataTables Editor自体が英語圏で開発されたものである事も影響しているのでしょう。

日本の様に、

>1. ひらがな入力後にスペースを押して漢字変換
>2. エンターで確定
>3. 次のフォーム

という操作を行う文化は他の国には無いのではないでしょうか？

しかしそんな日本の為？という訳でも無いのでしょうが、エンターでの即時Submitを回避する方法があります。

実際、色々調べてみて実現できなくて、最終的には無理やり他のJSで無効化しようかと思っていたのですが、オフィシャルにEnterでのSubmitを無効化するオプションが有りました。

（英語マニュアルのみなので難しいですね）

# エンターキーで即時Submitを無効化する

オプションは【onReturn】になります。

デフォルトだとSubmitになっていますので、falseに明示的に指定する事で回避できます。

無効化したいフォームを作成する際のmain要素の中に記述する事で反映されます。

```javascript:test.js
// 即時submitOFF
formOptions: {
    main: {
        onReturn: 'false'
```

# 感想

Datatables Editorはとても便利なのですが、あまり情報が無いので調べるのに苦労します。

しかし使いこなせば短期間で色々な事が実現できる便利なライブラリです。

DeepL等で何とか翻訳しながら活用したいと思います。

同じような沼に陥っている方の参考になれば幸いです。
【初心者必見】たった2行！親要素を無視して画面幅いっぱいまで要素をはみ出させる方法

#どうも7noteです。いままでのルールを覆すようなとっておきの必殺技を紹介します。

position指定等をしないと、基本的には子要素が親要素をはみ出すことはありません。
なのでこんなデザインは難しい。。。とおもいますが1行で解決できます。

**親要素をはみ出して幅いっぱいになるデザイン**

![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/fb4bfcda-8fa9-e418-2559-d53e69afa73c.png)

## 解決方法

```index.html
<div class="oya">
  <div>コンテンツ1</div>
  <div class="wide">コンテンツ2</div>
  <div>コンテンツ3</div>
  <div>コンテンツ4</div>
</div>
```

```style.css
.oya {
  max-width: 1000px; /* 基本は可変。最大横幅を1000pxに指定 */
  margin: 0 auto;    /* 左右中央に配置 */
  background: #DDD;  /* 背景色をグレーに指定 */
}

.oya > div:nth-child(2n){
  background: #fAA;  /* 偶数番目だけ背景色をピンクにする */
}

.oya .wide {
  margin: 0 calc(50% - 50vw);  /* 画面幅いっぱいにはみ出させるためのネガティブマージン */
  width: 100vw;                /* 幅を画面幅いっぱいに指定 */
}
```

## 解説

親要素には幅を指定しておきます。
そして、ネガティブマージンを取ります。計算式は`calc(50% - 50vw)`。
ここの50%は親要素の半分という意味で、50vwが画面幅の半分。計算すると画面の端から親要素の端までの長さになります。
これで**「子要素の幅 + ネガティブマージン = 画面幅いっぱい」**ということになります。

## まとめ

初めてこの方法を知った時はそれは衝撃でした。これまでわざわざ親要素でない要素にたいして左右の余白をauto`matrgin: 0 auto；`と横幅のサイズ指定をしていましたから。
ですがこの方法であれば、基準の幅を指定しつつ、はみ出す要素にだけ追加でCSSを書けばいとも簡単に「親要素からはみ出すようなコンテンツ」を作ることができます。

毎日開発をやっていると突然これまでの考え方や作り方が一新されるような作り方に出会う瞬間があります。
その経験の数が、スキルの差やスピードに直結するんだなと思います。
日々精進あるのみですね。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
git-flow入門

# git-flow 入門

git-flowの入門記事です。


gitに関する説明はありません。

## git-flowとは？

![git-flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388190/9d62ac18-33f3-ea1f-c8d8-2c8f2671212c.png)

git-flowはGitを用いた開発を助けてくれるツールです。

git-flowを使うことで複雑になったブランチ管理を容易に管理することができるようになります。

git-flowはGitに標準搭載されておらず利用する場合はインストールをする必要があります。

インストール方法はこちらから
https://github.com/petervanderdoes/gitflow-avh/wiki/Installation

git-flowはVincent Driessenさんにより提唱された"A successful Git branching model"というブランチモデルをベースとしています。

## git-flowのメリット

ー　コマンド1つで複数の作業を行ってくれる。
ー　1からブランチのワークフローを設計する必要がなく、Git Flowのブランチワークフローに沿った開発を行うことができる。
ー　あらかじめブランチの名前に意味がある。

これがgit-flowの良い点です。より詳しく説明します。

## git-flowのコマンドについて

git-flowにはオリジナルのコマンドがあります。Gitコマンドでできることですが、Git コマンドの場合だと複数行う必要がありますがGit Flowでは1回でまとめて行うことができます。

### git-flowの基本コマンドの流れ

### git-flowの初期化

**まず初期化を行います**

```
git flow init
```

ここから各種設定を行います。

```
Branch name for production releases: [master] main
```

まずルートとなるブランチの名前を入力します今回はGitHubを利用することを前提とするのでブランチの名前は**main**とします。

```
Branch name for "next release" development: [develop]
```

つぎに開発用ブランチの名前を設定します。開発用ブランチはgit-flowにおいて一番利用されるブランチとなるためわかりやすい名前にしましょう。

今回はデフォルトの**develop**とします。

```
How to name your supporting branch prefixes?
Feature branches? [feature/] 
```

作業を行うブランチの名前を決定します。新規の機能や修正を行う場合に利用するブランチです。

> 例）　ログイン機能を作成するときは**feature/login**となります。

```
Release branches? [release/] 
```

リリースを行うブランチの名前を決定します。開発が進みリリースをする際に利用するブランチです。

```
Hotfix branches? [hotfix/] 
```

リリースをした後に障害や不具合を修正するブランチの名前を決定します。

```
Support branches? [support/]
```

サポートを行うためのブランチの名前を決定します。

```
Version tag prefix? []
```

バージョンを指定します。

以上でgit-flowの初期設定は完了しました！これでgit-flowを使うことができます。

### git-flowを使った実践開発

git-flowの開発用ブランチは**develop** branchから開発を始めます。

**開発開始コマンド**

```
git flow feature start { 開発する内容について記述する }
```

これにより開発を行うブランチが作成されます。

**開発終了コマンド**

```
git flow feature finish { 開発する内容について記述する }
```

上記コマンドを実行することで、開発で使っていたブランチを終了させることができます。

### releaseとhotfixについて
申し訳ありません。**release**と**hotfix**に関しては使用したことがありません。

もしreleaseとhotfixを利用した人は下記の記事を参考にしてください。

- [git-flow cheatsheet](https://danielkummer.github.io/git-flow-cheatsheet/index.ja_JP.html)

こちらの記事はgit-flowのコマンドについてまとめたもので手軽によむことができて、内容もとても充実しています。

## git-flowのデメリットについて

[こちらの記事](https://itnews.org/news_contents/please-stop-recommending-git-flow)がとてもわかりやすいです。

git-flowのようにブランチのワークモデルがあらかじめ定義されているのはとても便利のように思えますが、git-flowは冒頭に登場した画像からわかるように複雑なブランチワークフローです。

## 最後に

私としてはgit-flowをとても気に入ってます。導入も容易なのでまずは気軽に使ってみてください！
リーダブルコード 5章 コメントすべきことを知る

本書の第１部「表面上の改善」にある5章のサマリーをまとめる。
（編集途中）

**コメントの目的は、書き手の意図を読み手に知らせることである**

# 5.1 コメントするべきでは「ない」こと

コメントを読むとその分だけコードを読む時間がなくなる。
コメントは画面を占領してしまう。
つまり、**コメントにはそれだけの価値を持たせるべき。**

**コードからすぐにわかることをコメントに書かない**

## コメントのためのコメントをしない

コメントを付けたければ、大切なことを説明した方がいい。

## ひどい名前はコメントをつけずに名前を変える

優れたコメントより名前の方が大切。関数名を「自己文書化」する。

**優れたコード > ひどいコード + 優れたコメント**

# 5.2 自分の考えを記録する

優れたコメントは「考えを記録する」ためのもの。

## 「監督のコメンタリー」を入れる

コメントにはコードに対する大切な考えを記録しなければいけない。
コードが汚い理由をコメントに書いてもいい。

## コードの欠陥にコメントをつける

コードは絶えず進化するので、その過程で欠陥を生む運命にあり、それを文書化することを恥ずかしがってはいけない。
プログラマがよく使う記法がいくつかある。

|記法  |典型的な意味  |
|---|---|---|
|TODO: |あとで手をつける  |
|FIXME: |既知の不具合があるコード  |
|HACK: |あまりキレイじゃない解決策 |
|XXX: |危険！大きな問題がある  |

大切なのは、これからコードをどうしたいのかを自由にコメントに書くこと。
そういうコメントを書くことで、コードの品質や状態を知らせたり、さらには改善の方向を示したりできる。

## 定数にコメントをつける

定数を定義するときには、その定数が何をするのか、なぜその値を持っているのかという「背景」が存在する場合が多い。
定数の値を決めたときに頭の中で考えていたことを記録することが大切。

# 5.3 読み手の立場になって考える

どこにコメントをつければいいか判断するのに、「他の人」（プロジェクトのことを君のように熟知していない人）にコードがどのように見えるか想像する必要がある。

## 質問されそうなことを想像する

他人が疑問を持つようなところにコメントをつければいい。

## ハマりそうな罠を告知する

関数やクラスを文書化するときには、「このコードを見てびっくりすることは何だろう？　どんなふうに間違えて使う可能性があるだろう？」と自問するといい。
ユーザが使った「あと」に気づくよりも、使う「前」に告知する方がいい。

## 「全体像」のコメント

新しくチームに参加した人に、ソースコードを読んだだけでは得られない情報を高レベルのコメントとして書くべき。
短い適切な文章で構わない。ないよりまし。

## 要約コメント

関数の内部でも「全体像」についてコメントする。低レベルのコードをうまく要約したコメントがよい。

# 5.4 ライターズブロックを乗り越える

ライターズブロック（行き詰まってしまって、文章が書けないこと）を乗り越えるには、とにかく書き始めるしかない。自分の考えていることをとりあえず書き出す。

コメントを書く手順は
1. 頭の中にあるコメントをとにかく書き出す
2. コメントを読んで（どちらかと言えば）改善が必要なものを見つける
3. 改善する

早めにしょっちゅうコメントを書いていけば、最後にまとめて大量のコメントを書くような事態に陥ることはない。

# 5.5 まとめ

コメントすべきではないこと：
* コードからすぐ抽出できること
* ひどいコードを補う補助的なコメント。コメントを書くのでなくコードを修正する

記録すべき自分の考え：
* なぜコードが他のやり方ではなくこうなっているのか
* コードの欠陥を示す
* 定数の値にまつわる背景

読み手の立場になって考える：
* コードを読んだ人が「えっ？」と思うところを予想してコメントをつける
* 平均的な読み手が驚くような動作は文書化しておく
* ファイルやクラスには「全体像」のコメントを書く
* 読み手が細部に捕われないように、コードブロックにコメントをつけて概要をまとめる
beforeブロックを使った共通化

#目次
<b>①beforeとは</b>
<b>②beforeブロックの書き方</b>
<b>③まとめ</b>

##①beforeとは
describeやcontextの内部でテストが実行される前に共通のインスタンス変数をセットアップすることができる。

##②beforeブロックの書き方
```php:spec/model/client_spec.rb
1 require 'rails_helper' 
2 RSpec.describe Client ,type: model do
3  before do
4   @client = FactoryBot.build(:client)
5  end
6
7
8 
9   describe 'クライエントの新規の登録' do 
10     it "nameが無ければクライントの登録はできない" do 
11        @client.name = ""  
12        @client.valid?                 
13        expect(@client.errors.full_messages).to include("Name can't be blank") 
14       end
15     end
16   end
```

##<b>③まとめ</b>
beforeを使うことによって、テストに使用するFactoryBotをわざわざ生成しなくても、テストの実行の前にbeforeの中身が実行される。何回もFactoryBotの記述をしなくてよくなる。
virtualenv でプロジェクトごとに異なる Python バージョンを使う


# はじめに

venv/virtualenv などのような表記を見かけますが、
venv は virtualenv の省略表記ではありません。
それぞれの概要は以下です。

- venv
    - パッケージ切り替えに使用できる
    - Python標準(組み込みモジュール)
    - virtualenv のサブセット
    - https://docs.python.org/ja/3/library/venv.html
- virtualenv
    - パッケージ切り替え + Python version の切り替え に使用できる
    - venv は標準だが、virtualenv は 3rd party (PyPA)
    - https://virtualenv.pypa.io/en/latest/index.html
    - pepに高度な分離を行ってくれる旨が書かれています
        - https://www.python.org/dev/peps/pep-0405

# 前提

mac で挙動確認を行いました。
https://www.python.org/downloads/ のインストーラーを用いて、
3.8 と 3.9 を install してあります。
python3 は 3.8 のバージョンを向いています。

```
$ ls /Library/Frameworks/Python.framework/Versions   
3.8/     3.9/     Current@
$ which python3
/Library/Frameworks/Python.framework/Versions/3.8/bin/python3
```

# virtualenv で 3.8 と 3.9 の環境を作成する

virtualenv を install します。
virtualenv は 3.8 のディレクトリに install されました。

```
$ pip3 install --user virtualenv

$ which virtualenv
/Users/<user_name>/Library/Python/3.8/bin/virtualenv
```

まずは python3.9 の仮想環境を作ります。
(python3.9 の環境ができたことが分かります。)

```
$ virtualenv -p python3.9 venv39
$ tree -L 3 venv39
venv39
├── bin
│   ├── activate
│   ├── activate.csh
│   ├── activate.fish
│   ├── activate.ps1
│   ├── activate.xsh
│   ├── activate_this.py
│   ├── pip
│   ├── pip-3.9
│   ├── pip3
│   ├── pip3.9
│   ├── py.test
│   ├── pytest
│   ├── python -> /usr/local/bin/python3.9
│   ├── python3 -> python
│   ├── python3.9 -> python
│   ├── wheel
│   ├── wheel-3.9
│   ├── wheel3
│   └── wheel3.9
├── lib
│   └── python3.9
│       └── site-packages
└── pyvenv.cfg

$ . venv39/bin/activate
$ python3 --version    
Python 3.9.1
```

続いて python3.8 の仮想環境を作ります。
(python3.8 の環境ができたことが分かります。)

```
$ virtualenv -p python3.8 venv38

$ tree -L 3 venv38
venv38
├── bin
│   ├── activate
│   ├── activate.csh
│   ├── activate.fish
│   ├── activate.ps1
│   ├── activate.xsh
│   ├── activate_this.py
│   ├── pip
│   ├── pip-3.8
│   ├── pip3
│   ├── pip3.8
│   ├── python -> /Library/Frameworks/Python.framework/Versions/3.8/bin/python3.8
│   ├── python3 -> python
│   ├── python3.8 -> python
│   ├── wheel
│   ├── wheel-3.8
│   ├── wheel3
│   └── wheel3.8
├── lib
│   └── python3.8
│       └── site-packages
└── pyvenv.cfg

$ . venv38/bin/activate
$ python3 --version
Python 3.8.6rc1
```

以上で異なる Python バージョンの環境を作成することができました。
お疲れさまでした。

# 参照したドキュメント
- [CLI interface — virtualenv documentation](https://virtualenv.pypa.io/en/latest/cli_interface.html#section-discovery)
- [Virtualenv ドキュメント](https://virtualenv.pypa.io/en/latest/index.html)
- https://www.python.org/dev/peps/pep-0405
読みやすいコードのためには lodash の isEmpty や size を使わない方がよいかも。というかよい。

# lodash はとてもいい

とてもいいです。lodash。
ただ、いくつかの点で使い方を誤ると、いまいちなコードになります。

特に、isEmpty と size については前から気になっていたので書いておきます。

最近、こちらの記事をよみました

lodashの真偽値判定まとめ - Qiita
https://qiita.com/ko-flavor/items/83e06afde5508541edaa

isEmptyの挙動についてしっかり書かれています。

lodashの size関数でも似たようなものになります。

```js
_.size(value) === 0
```

となるものを、isEmpty(value) = true としているようです。

isEmptyもsizeも引数として、配列やオブジェクトや文字列、なんでも受け付けるはずです。

細かくは知りません。調べていません。使ってはだめなのがわかるので使わないものなので、詳しく知らべる気しないです。

# なぜだめなのか

読みづらいコードになってしまうからです。

コード上で、こういうコードをみかけたとします。

```js
// [A]
  if (_.isEmpty(value)) {
    funcA(value);
  }
```

これと、下記は似たようなものに見えるかもしれません。

```js
// [B]
  if (value.length === 0) {
    funcA(value);
  }
```

ですが、優れているのは[B]のコードです。

なぜか。

[A]のコードは、valueに何がはいっているか、さっぱりわかりません。
[B]のコードは、valueに、stringかarrayかが入っていることが即時に読み取れます。

stringかarray以外なら、基本、動かないので[B]の処理が書かれていればvalueの中身を類推できます。
[A]のコードでは、無理。


自分は、lodashのいくつかの点で満足がいかないので
Parts.js というライブラリを作っています。lodashみたいな関数群をそろえているのですが、互換性はないです。
https://github.com/standard-software

ですので、lodashのisEmptyを作りたく気持ちも分からなくはないですし、作ったら作ったでちょっと使えるかも、と思わなくもないところですが、やはり isEmpty は作るべきではないです。

Parts.js では、parts.propertyCount というオブジェクトのプロパティ個数をカウントする関数を作っています。
オブジェクトが渡されなければエラーを吐いて落ちる関数です。

```js
// [C]
  if (parts.propertyCount(value) === 0) {
    funcA(value);
  }
```

これも、value内部がオブジェクトの場合では、[A]のコードと同じように動きます。
ですが、[A]のコードより[C]のコードは確実に優れています。

なぜか。
先程と同じ理由です。

[A]のコードは、valueに何がはいっているか、さっぱりわかりません。読み取れない。
[C]のコードは、valueに、objectが入っていることが即時に読み取れます。

これがコードリードに大きく影響します。

# 混乱したスパゲティコードを素早く解きほぐすために

自分は多くのプロジェクトに参加してきました。
ぐちゃぐちゃなコードをよく見てきました。
そして、それを素早く読み取り、リファクタリングしていきます。

そういうときに[A]系のコードがガシガシ書かれている何百行、何千行のコードを見ると、
ここから読み取れることが少なすぎて、実際に動かしてみて、console.log 仕込まないと、どういう動きになるのかよくわからなくなるのです。

ほとんどのプロジェクトが大抵、混乱したコードに悩まされると思います。
[A]のコードが大量にかかれていて、
valueに、0か、空文字か、空配列か、空オブジェクトか、
なにが入ってくるかわからないようなぐちゃぐちゃなコードの中で
それを読み解こうとして必死になって時間を食います。

たった1行のことですが、
[B]や[C]のようなコードで書いてくれる癖をつけておいてくれたら
こんなにスパゲティにもならないだろうと思うわけです。
そうするとコードリードが実にやりやすいのです。

# もっと上手に

たとえば、[B]だと配列か文字列かとわかりますが、もっとよく書くことができます。

```js
// [D]
  if (value === '') {
    funcA(value);
  }
```
これなら、valueが文字列確定だから、とてもよいです。[B]より優れています。

また、次のような数行関数を作ればいいでしょう。

```js
// [E]
const arrayCount = (value) => {
  if (!Array.isArray(value)) {
    throw new Error('arrayCount');
  }
  return value.length;
}
:

  if (arrayCount(value) === 0) {
    funcA(value)
  }
```

これなら、valueは配列に確定するので、これも[B]より優れています。

繰り返しになりますが、
プロジェクト全体を通して[A]のコードで書かれていると、プログラム全体は何がなにやらわからなくなりがちです。

プロジェクト全体が[C][D][E]のコードで書かれていれば、丁寧で読みやすいコードになります。

[A]よりも[B]、さらには、[C][D][E]がよい、と判断できる人が書いたプログラムはとても読みやすくなります。

動かしてconsole.logの動作確認などしなくても、コードを読めば、そこに書かれている動きがすぐにわかるのです。

というわけで、

lodashの _.isEmptyや _.size は書かれているコードを読んでも何を判断しているのかが即座にはわからなく、読みにくいコードになってしまい、また代替手段も多くあるために、使うべきではない関数になってしまっています。

ご参考にしていただけると幸いです。
playwright-androidでAndroidの自動操作ができる？

Playwrightで、ADBを介してAndroid端末を自動操作をするための仕組みが作られているらしい。
https://github.com/microsoft/playwright/issues/1122#issuecomment-742170088

## 準備

```
npm init --yes
npm install playwright-android
```

## Android上のChromeを動かす

```js
const playwright = require('playwright-android');

playwright.android.devices().then(async ([device]) => {
  console.log(`Model: ${device.model()}`);
  console.log(`Serial: ${device.serial()}`);
  try {
    const context = await device.launchBrowser();
    try {
      const [page] = context.pages();
      await page.goto('https://github.com/YusukeIwaki');
      await page.click('header button');
      await page.click('input[name="q"]');
      await page.keyboard.type('puppeteer');
      await Promise.all([
        page.waitForNavigation(),
        page.keyboard.press('Enter'),
      ]);
      await page.screenshot({path: './YusukeIwaki.android.png'})
    } finally {
      await context.close();
    }
  } finally {
    await device.close();
  }
});
```

まだまだ開発中っぽいが、 `page.screenshot` なども意外とちゃんと動く。

![playwright-android.play.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74571/5448f6af-bdb2-4ed6-9672-6240260743c4.gif)

## Androidネイティブアプリを動かす

こっちはまだ試していない。
Agora入門 ビデオ通話を試してみる

最近業務でAgoraを使ったので、その共有で記事を書いていきます！

今回は、Agora入門として、ビデオ通話を試してみます！

# 今回の目的
Agoraのサービスを使って、ビデオ通話を試してみる

# 必要な物を準備

##　agora.ioにユーザー登録

次の[サイト](https://sso.agora.io/en/login/)からユーザー登録を行います。
※ 登録には電話番号が必要です。

登録が完了したこんな画面が表示されたらOKです！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606623/16bd1edd-65ee-085f-df59-1dee43b666c8.png)

## プロジェクト作成

[プロジェクト管理](https://console.agora.io/projects)ページからプロジェクト作成を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606623/13864507-8463-4628-2727-32e319aea4e1.png)

プロジェクト名を適当に入力してプロジェクト作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606623/9b8c5a10-7c87-949f-4c6c-7a70dec08bb8.png)
※ 登録時にアプリ証明書を有効にしてください

##  接続情報に必要な一時トークンを作成
1. 先ほど作成したプロジェクトの編集画面に入り、　一時トークンを作成するボタンを押下する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606623/d7b5e894-f051-246a-6d62-129a6dc771e1.png)
※ ボタンが存在しない場合は、アプリの証明書が有効になっていないかもです。


2.トークン生成ページに遷移するので適当にチャンネルネームを入力して、トークン生成ボタンを押下します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606623/9ef6e9cb-a065-0992-d886-3ac8ddb613ed.png)

トークンが無事生成されたら準備完了です！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606623/bf7b66c4-9a43-7175-a48a-906fb0c754cb.png)

# ビデオ通話接続
1. 先ほど作成したトークン情報を使ってビデオ通話接続を行います！
接続の[ページ](https://react-agora-sample-app.web.app/)は、自分が事前に用意したページを使ってみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606623/92720112-62da-92af-0bc0-d39408c52479.png)

2. 先ほど作成したトークンのページに表示されている情報をページに入力していきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606623/a2344050-2f39-621d-f576-d0f8ec764be7.png)
※ トークンとチャンネル名の入力の順番に注意してください

3. 接続
入力後、マイクとカメラの使用を求めらるので許可するとビデオ通話が開始されます。
開始するとこんな感じでビデオ通話が開始されたら成功です！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606623/282c2399-1f2c-2a2a-8078-4f6d1c794456.png)

# おわりに
今回は、Agoraのサービスを使ってビデオ通話を試してみました。
コードを書かなくて退屈だった人が多いと思うので、
次回はReactでAgoraの実装をやってきます！

最後まで読んでくれたらLGTMしてくれると嬉しいです！！！
Ansible-base 2.10 (オフラインインストール) 

#0. はじめに
Ansible2.10から従来のAnsible2.9とは異なり、モジュールの大半がansible-galaxyに集約され最低限のモジュールが利用できるansible-baseの提供が開始される。
ただし、Ansible2.10のインストール形式には以下の２種類がある。
①Ansible-base
Ansible-baseのみの提供。最低限のモジュールとpluginのみ包含されるため、必要なモジュールはansible-galaxyから取得する。
②Ansible
従来の配布形態と同様、Ansible-baseにモジュールやpluginがバインドされた形式。

今回の記事では、②Ansibleのオフラインインストールを実施。
※②Ansible 2.10については別の記事をご参照

#1. ansible-baseインストール用ファイルのダウンロード
pipコマンドでansibl-baseインストール用ファイルをダウンロード。
実行結果は以下の通り。

```
# pip3.9 download -d ansible ansible-base
# ls -ltr
合計 9288
-rw-r--r--. 1 root root 5836841 12月 5 16:23 ansible-base-2.10.3.tar.gz
-rw-r--r--. 1 root root  125774 12月 5 16:23 Jinja2-2.11.2-py2.py3-none-any.whl
-rw-r--r--. 1 root root  269377 12月 5 16:23 PyYAML-5.3.1.tar.gz
-rw-r--r--. 1 root root 2606314 12月 5 16:23 cryptography-3.2.1-cp35-abi3-manylinux2010_x86_64.whl
-rw-r--r--. 1 root root   35858 12月 5 16:23 packaging-20.7-py2.py3-none-any.whl
-rw-r--r--. 1 root root   19151 12月 5 16:23 MarkupSafe-1.1.1.tar.gz
-rw-r--r--. 1 root root  405977 12月 5 16:23 cffi-1.14.4-cp39-cp39-manylinux1_x86_64.whl
-rw-r--r--. 1 root root   10963 12月 5 16:23 six-1.15.0-py2.py3-none-any.whl
-rw-r--r--. 1 root root   67842 12月 5 16:23 pyparsing-2.4.7-py2.py3-none-any.whl
-rw-r--r--. 1 root root  112041 12月 5 16:23 pycparser-2.20-py2.py3-none-any.whl
```

#2. インストール
1.の手順でダウンロードした資源をオフラインの環境に配置。
以下コマンドを実行し、ansible-baseをインストール。

```
# pip3.9 install <パッケージ名>
```
インストールされたことを確認する。

```
# ansible --version
ansible 2.10.3
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/python390/lib/python3.9/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.9.0 (default, Dec 5 2020, 16:14:32) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]
```

**※以下、必要に応じで実施**
"ansible"で実行できるようシンボリックリンクを作成

```
# ln -s /usr/local/python390/bin/ansible /usr/bin/ansible
```

#3. テスト用playbook実行
以下テスト用のplaybookを作成し、稼働確認

```
---
  - hosts: localhost

    tasks:
      - file:
          path: /tmp
          state: directory

```

実行結果は以下の通り。ansible-baseが正常に動いていることが確認できた。

```
# ansible-playbook test.yml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that
the implicit localhost does not match 'all'

PLAY [localhost] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [file] ********************************************************************
ok: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```
curlコマンドでJSONデータをPOSTリクエストしてみた


コマンドの例文

```
curl -H "Content-Type: application/json" -X POST -d "{ \"key\" : \"value\"}" url
```

ポイント①
`-H "Content-Type: application/json"`
を付ける

ポイント②
`-X POST `
を付ける

ポイント③
`-d "{ \"key\" : \"value\"}"`
JSON（連想配列）のkeyとvalueは`\"`で囲む
↓ダメな例①
``-d `{ "name" : "nodejsTaro" }` ``
↓ダメな例②
`-d "{ name : nodejsTaro }"`


#テストしてみる
サーバーはこんな感じのnode.jsサーバーだったと仮定する。

```js:server.js
"use strict";

const express = require("express");
const app = express();

// middleware
app.use(express.json());
app.use(express.urlencoded());

// 好きな設定にする
app.use((req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*");
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept, Authorization"
  );
  res.header(
    "Access-Control-Allow-Methods",
    "GET, POST, PATCH, DELETE, OPTIONS"
  );
  next();
});

// /helloWorldへのPOSTリクエストに対する処理
app.post("/helloWorld", function (req, res) {
  const name = req.body.name;
  console.log(`hello ${name}`);
  res.status(200).send(`Nice to meet you, ${name}`);
});

// Listen to the App Engine-specified port, or 8080 otherwise
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
  console.log(`Server listening on port ${PORT}...`);
});

module.exports = app;

```
#実行

```
C:\Users\user1\mydir> curl -H "Content-Type: application/json" -X POST -d "{ \"name\" : \"nodejsTaro\" }" http://localhost:8080/helloWorld
Nice to meet you, nodejsTaro
```
ABC189のC問題をDP(かもしれない方法)で解いてみた

だいたい自分用メモ. プログラミングからPythonから競プロからDPまで何もかも初心者なので、何もかも間違っている可能性有り.

#問題概要#
[C - Mandarin Orange](https://atcoder.jp/contests/abc189/tasks/abc189_c)

$l$から$r$までの範囲の皿に乗っているみかんを、1皿につき$x$個ずつ(但し、皿に載っているみかんの数を超過してはならない)ガバーッと食べたときの最大個数を求める.
要するに、$A_i$のヒストグラムの中に書くことのできる長方形のうち、最も面積が大きいものはどれかを求めればいいということ.

《イメージ図(N=6, A=[2,4,4,9,4,9]が与えられた場合)》
![スクリーンショット 2021-02-01 21.13.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916473/65339911-95a4-31a4-105f-0469293f92e5.png)
板タブで描くの難しいですね.

#考えたこと#
つい先日一次元配列を用いたDP(カエルのやつ)をなんとか理解したところだったので、その練習ついでに、二次元配列を使ったDP(メモ型回帰?)で解いてみようと考えた(でもDPのことまだ何も分かってないので、この解き方がDPなのかどうか分からないです).

例えばA=[2,4,4,9,4,9]が与えられたとして、Aの1番目から3番目までを切り出して作る長方形の高さは、

+ 1番目のみで作れる長方形の高さは2(これをH[0]とする)
+ 1から2番目の中で作れる長方形の高さはH[0]とA[1]の小さい方(=H[1])
+ 同様に、1から3番目の中で長方形の高さはH[1]とA[2]の小さい方

という流れで求められるので、それらを二次元配列に記録したいということ.
(日本語が下手)

#やってみたこと1#

```python.py
N = int(input())
A = [int(i) for i in input().split()]
dp = [[0]*(N) for j in range(N)] # 配列を作る

for i in range(N):
    dp[i][i]=A[i] 
    # 1皿のみの場合、長方形の高さは林檎の個数と等しい

for left in range(N):
    for right in range(left+1,N):
        dp[left][right]=min(dp[left][right-1],A[right])
        # [right-1]皿前まで選んだ場合の高さと[right]皿目の林檎の個数を比較して、小さい方で更新

for left in range(N):
    for right in range(left,N):
        x = dp[left][right]
        ans = max((right+1-left)*x,ans)
        #dpで求めた長方形の高さと横の長さを掛け、面積の最大値を求める
print(ans)
```
A=[2,4,4,9,4,9]として、
dpを出力するとこんな感じになります.

```python:dp
[[2, 2, 2, 2, 2, 2],
 [0, 4, 4, 4, 4, 4],
 [0, 0, 4, 4, 4, 4],
 [0, 0, 0, 9, 4, 4],
 [0, 0, 0, 0, 4, 4],
 [0, 0, 0, 0, 0, 9]]
```

i行は「i番目の皿から始めたときの長方形の高さ」で、
j列は「j番目の皿までを選んだときの長方形の高さ」を意味しています.
つまり、左上から4行目4列目の9は「4番目の皿から4番目の皿までで作れる長方形の高さ」であり、その右の4は「4番目の皿から5番目の皿までで作れる長方形の高さ」を表していることになります.
肝心の```dp[left][right]=min(dp[left][right-1],A[right])```の部分なのですが、ベルトコンベアに流されてどんどん高さ制限のゲートに削られていくイメージです.

![スクリーンショット 2021-02-01 22.09.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916473/ad92f64c-dc05-7e35-14e3-4cd203001030.png)
 
(ゴミみたいな図を書いてしまい申し訳ございません)

#やってみたこと2#
良く考えたらこんなにfor並べる必要なくない？と思ってまとめたコード.

```python.py
N = int(input())
A = [int(i) for i in input().split()]
 
dp = [[0]*(N) for j in range(N)]
 
ans = 0
for left in range(N):
    dp[left][left]=A[left]
    for right in range(left,N):
        if right!=left:
            dp[left][right]=min(dp[left][right-1],A[right])
        x = dp[left][right]
        ans = max((right+1-left)*x,ans)
        
print(ans)
```
スッキリはしたけど、dp[left][left]=A[left]は何をやっているのかめちゃめちゃわかりづらい気もする.
#まとめ#
DPは難しい...
FactoryBotについて

#目次
①FactoryBotとは
②FactoryBot導入について
③FactoryBotのメリット

##①FactoryBotとは
ダミーのインスタンスを簡単に作成することができるテストツール。

##②FactoryBot導入について
factory_bot_railsというgemを使用する。
Gemfileのdevelopmentのtest環境にfactory_bot_railsを記述し、bundle installをする

```php:Gemfile
 group :development, :test do
  gem 'rspec-rails'
  gem 'factory_bot_rails'
end
```

```php:ターミナル
 bundle install
```

```php:ターミナル
 rails g factory_bot:model client
 #factoryディレクトリにclient.rbを作成する
```
```php:spec/factories/client.rb
FactoryBot.define do
 factory :client do
   name                  {"careet_boy"}
   email                 {"niconico@gmail"}
   password              {"niconico"}
   password_confirmation {"niconico"}
  end
end

```


##③FactoryBotのメリット
結論としては、記述が楽になる。

```php:spec/model/client_spec.rb
1 require 'rails_helper' 
2 describe Client do
3   describe 'クライエントの新規の登録' do 
4     it "nameが無ければクライントの登録はできない" do 
5       client = Client.new(name: "",email:"aaa@gmail",password:"11111",password_confirmation:"11111") 
6       client.valid? 
7       expect(client.errors.full_messages).to include("Name can't be blank") 
8     end
9   end
10 end
```

上記のコードがFactoryBotを使うことによって以下のように記述ができる

```php:spec/model/client_spec.rb
1 require 'rails_helper' 
2 describe Client do
3   describe 'クライエントの新規の登録' do 
4     it "nameが無ければクライントの登録はできない" do 
5       client = FactoryBot.build(:client) #Clientのインスタンスを生成し
6       client.name = ""                   #nameを空にする
7       client.valid? 
8       expect(client.errors.full_messages).to include("Name can't be blank") 
9     end
10   end
11 end
```

補足:
FactoryBotのbuildとcrateの違い
・buildはデータが保存されない
・createはデータが保存される
データベースの値を利用するテストが必要な場合はcreateを使用する。
データベースにアクセスする必要がない場合は,buildを使用する。テストの実行速度を上げるため。
[Rails] Can't resolve image into URL: to_model delegated to attachment, but attachment is nil


[![Image from Gyazo](https://i.gyazo.com/131cf19a8491d4ea84c7433ab1d789bc.png)](https://gyazo.com/131cf19a8491d4ea84c7433ab1d789bc)
[![Image from Gyazo](https://i.gyazo.com/c8d9018f404f8f2dcaf00e0382c49712.png)](https://gyazo.com/c8d9018f404f8f2dcaf00e0382c49712)

投稿してDBに保存してある記事を一覧表示しようとしたら、エラーが発生しました。
画像の表示が引っかかっているようです。
画像のアップロードにはActive Storageを使用しています。


タイトルのエラー文を翻訳すると↓です。
「画像を URL に解決できません: to_model は添付ファイルに委任されていますが、添付ファイルは nil です。」

おそらく「to_model は添付ファイルに委任されています」とは、アソシエーションのhas_one_attachedが効いてるというメッセージだと思われます。
にも関わらず、添付ファイルはnilですと返ってくる、
[![Image from Gyazo](https://i.gyazo.com/014d8ead9623eddd6787e5e51fe6b0ad.png)](https://gyazo.com/014d8ead9623eddd6787e5e51fe6b0ad)
ArgumentErrorなので引数を確認すると↑のようになっている、
１、２個の実引数を期待しているんだが０個だよと言われています。

アセットパイプライン、画像のサイズ辺りが怪しいと思い20分くらい調べていくと、
結論：DBに画像が添付されておらず、文字情報だけの記事が入っており、それを表示させようと
　　　していたことが原因でした。（笑）

画像必須のバリデーションを設定していなかったことが今回のエラー発生要因として大きいと理解しました。
KerasでModelCheckpointの重み保存をメモリ上に行う方法

Kerasで学習途中の最適な重みを保存しておくには、ModelCheckpointコールバックを使うのが定石です。

[Tensorflow チュートリアル - 訓練中にチェックポイントを保存する](https://www.tensorflow.org/tutorials/keras/save_and_load?hl=ja#%E8%A8%93%E7%B7%B4%E4%B8%AD%E3%81%AB%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E3%82%92%E4%BF%9D%E5%AD%98%E3%81%99%E3%82%8B)

しかし、保存先がファイルしか選択できません。ファイルをやたり読み書きするのは気が引けますし、なによりも遅いです。これを**メモリに保存しておいて取り出す方法がありそうで無い**です。いろいろ探したところ、英文の質問応答サイトに方法が書かれていたので、実際に試してブラッシュアップした内容を共有します。

[オリジナルの記述である質問応答サイトはこちら](https://stackoverflow.com/questions/60567679/save-keras-model-weights-directly-to-bytes-memory)

以下が作成した**メモリに重みを書き出す**コードです。ModelCheckpointは使っていませんが、同等の処理を記述できメモリ保存できるコールバックを新たに作成しています。ディスクに書き出すのと比較して、体感で5倍程度の学習速度になりました（もちろんエポックの計算量に依存します）。

```Python
# メモリに重みを保存するコールバック
class SaveBestWeightsInMemory(tf.keras.callbacks.Callback):
    def __init__(self):
        super().__init__()
        self.best = np.Inf
        self.best_epoch = 0

    def on_epoch_end(self, epoch, logs=None):
        if np.less(val_loss := logs.get('val_loss'), self.best):
            print(f'{epoch=}: val_loss improved from {self.best:.4f} to {val_loss:.4f}'
                  ', saving model to memory.')
            self.best = val_loss
            self.best_epoch = epoch
            self.best_weights = self.model.get_weights()

# 学習コード本体（モデル作成、コンパイル済）
epochs = 3000
callback = [
    sb_cb := SaveBestWeightsInMemory(),   # 今回作成のコールバックの呼び出し
    LambdaCallback(on_epoch_end=lambda epoch, logs: (
        print(f'{epoch=}: ' + ', '.join([f'{k}:{v:.4f}' for k, v in logs.items()]))
        if epoch % 10 == 0 else None)),   # 10エポックに1度経過表示をするコールバック
    EarlyStopping(monitor='val_loss', patience=500),   # 通常はアーリーストッピングと組み合わせ
]
result = model.fit(x_train, y_train, epochs=epochs, verbose=0,
                   callbacks=callback, validation_data=(x_val, y_val))
model.set_weights(sb_cb.best_weights)   # メモリ保存した最適な重みを読み出す
```

なお、上記コードには、Python3.8以上でないと動かない文法が入っています。
【Python】PermissionErrorの原因と対策

pythonを使用してExcelファイルの操作を勉強しています。
本日の気づき(復習)は、「PermissionError」というエラーに関してです。
プログラムを実行した際、下記のようなエラーが出ました。

```ruby:ターミナル
PermissionError: [Errno 13] Permission denied: ファイル名
```

# 原因と対処法
原因は二つあるようです。

1. 参照するブックが開かれている。
2. 参照するブックが読み取り専用だった。

対処法も二つ。

1. 参照するブックを閉じる。
2. 参照するブックの読み取り専用設定を解除する。

私は、今回「２」の方でした。
仕事で使おうとしていたのが裏目に出ました・・・。

# 余談：読み取り設定の登録・解除方法
読み取り設定のON/OFFは結構簡単です。
設定したいブックが閉まっていることを確認したら

1. ブックを右クリック
2. プロパティをクリック
3. 属性にある、読み取り専用のチェックボックスをクリックし、ＯＫ。
4. 解除の場合はチェックボックスを外し、ＯＫ
5. 解除の場合は確認が入りますので再度ＯＫ

本来は読み取り設定すると同時にパスワードをかける方が望ましいとは思いますが
Pythonの備忘録なので、この辺で・・・。

# 参考にさせて頂いたサイト様
https://daizyu.com/posts/2020-05-19-005/

ありがとうございます！
【Swift】オリジナルスプラッシュ画面の実装方法

#はじめに

個人アプリ作成時にスプラッシュ画面が表示できず1時間くらい無駄にしたので、
備忘録がてら対応策を共有をさせていただきます。

スプラッシュ画面とは、アプリが起動し一番最初に表示される画面のことです。
Twitterでいうと、Twitterのロゴマークである鳥が表示されると思います。

そちらがスプラッシュ画面に該当します。

あのような動きのあるスプラッシュ画面を作成しようと思ったのですが、
**「そもそもスプラッシュ画面を表示することができない」**という現象に陥りました。

その問題を解消するために行ったことを共有していきます。

###環境
・Swift version 5.3
・XCode version 12.3

#対応策

**①. XCodeの再起動
②. アプリのアンインストール**

上記の二つはおそらく対応されている方がほとんどではないかなと思います。
どの記事でも似たようなことを行っているのでとりあえず再起動してみてください！

**③. Storyboardの再作成**

スプラッシュ画面にするためのStoryboardを再作成します。

LaunchScreen.stroryboardならそちらを再作成し、
オリジナルのStoryboardならそちらを再作成してください。

**④. Launch Screen Fileの設定**

projext > General > App icons and Launch images > Launch Screen File の内容を
表示したいStoryboardのファイル名にします。
![スクリーンショット 2021-02-01 22.18.31.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/9dab2eb9-89cc-56c0-06e1-f7abaa1345b6.jpeg)

**⑤. Initial View Controllerの指定**

オリジナルのStoryboardを使用する際に、オリジナルのViewControllerを作成すると思います。

その際に、ViewControllerをクリックし、
右メニューの、**□ is Initial View Controller**にチェックを入れます。

すると下画像のように矢印がつくはずです。
![スクリーンショット 2021-02-01 22.07.42.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/9a7d4643-237c-851c-24b8-821675be8045.jpeg)


#さいごに

以上、私が行って解決した対応策でした。

ちなみに私は⑤でした。

ブレークポイントやprint( )でそもそも読み込まれていないことはわかっていましたが、
初歩的な内容過ぎて見落としていました・・・。

皆さんのお力になれたら幸いです。

最後までご覧いただきありがとうございました。
テストについて

#目次
<b>①テストとは</b>
<b>②テストコードのパターン</b>
<b>③テストコードの種類</b>
<b>④RSpecの使い方</b>
<b>⑤単体テストについて</b>
<b>⑥テストコードの実行の仕方</b>

##①テストとは
専用のプログラムによってwebアプリケーションの動作を確認することをテストという。
テストをする際に、テストコードを記述する必要がある。
※テスコトードとは、アプリケーションが正しく動くか確認するためのコード。
ruby on railsでは、RSpecというgemを利用して、テストコードが実装可能である。


##②テストコードのパターン
<b>正常系</b>と<b>異常系</b>がある。

<b>正常系</b>とは、
想定されたインプットがあった時に、想定されたアウトプットを得ることができること。例えば、ログインしたときのみ、投稿ができる
という時に、投稿ができるといったことが正常系である。

<b>異常系</b>とは、
想定されていないインプットがあった時に、エラーが出力されたアウトプットが得ることができること。例えば、ログインない場合は、投稿ができないときに、登録できないなどのメッセージが想定どおり出力されることを異常系という。

##③テストコードの種類
<b>単体テストコード</b>と<b>統合テストコード</b>の二つがある。

<b>単体テストコード</b>とは、
モデルやコントローラなどの機能ごとにしっかり動くか確認するコードのこと

<b>統合テストコード</b>とは、
ユーザーがブラウザを操作することをコードで再現し、問題がないかを確認するコードのこと

##<b>④RSpecの使い方</b>
1,gemfileに記述する

```php:Gemfile
group:development,:test do
 gem 'rspec-rails','~>4.0.0'
end
```

2,bundle　installの実行

```php:ターミナル
bundle install
```
3,RSpecのインストール

```php:ターミナル
rails g rspec:install
```

4,ドキュメント形式に変更する

```php:.spec
--require spec_helper
--format documentation ←こちらを記述する
```

理由としては、
この記述を書くことによって、テストコードのの実行中にどのスペックがパスし、どのスペックが失敗したのかがわかりやすくなる。

##⑤単体テストの記述の仕方

2つのパターンを紹介する。
1つ目は、モデルの単体テスト。

1,モデルのテストファイルを作成する

```php:ターミナル
  rails g rspec:model client
#ここではクライエントモデルを作成する
```

2,テストコードの記述の仕方

```php:spec/model/client_spec.rb
1 require 'rails_helper' 
2 describe Client do
3   describe 'クライエントの新規の登録' do 
4     it "nameが無ければクライントの登録はできない" do 
5       client = Client.new(name: "",email:"aaa@gmail",password:"11111",password_confirmation:"11111") 
6       client.valid? 
7       expect(client.errors.full_messages).to include("Name can't be blank") 
8     end
9   end
10 end

```

上記のコードの説明
2行目のdescribeとは、
グループ分けをするメソッド。例えば、今回の場合は、Clientモデルに対してテストを行うといったように、どの機能に対してテストをするぞという宣言のようなものと理解すれば良い。3行目もdescribeがあるが、入れ子構造を取ることもできる。

4行目のitについて、
何かの処理をするのではなくて、プログラムの仕様を記述したものである。

7行目expectについて、
こちらはテスト対象を検証するためのメソッド。書き方としては、
expect(実行結果).to eq 想定の結果
toの次にくるものをmatcher(マッチャー)と呼ばれる。

matcherの種類としては、

|matcher|使い方|意味|
|:---:|:---:|:---:|
|eq(値)|expect(1+1).to eq 2|1+1は2と等しい|
|include|expect([1,2,3]).to include 3 |[]の配列に3が含まれる|
|be_valid|expect(client).to be_valid|railsのclientモデルのvalidationに成功すること|

##⑥テストコードの実行の仕方

```php:ターミナル
 bundle exec rspec spec/ディレクトリ名/ファイル名_spec.rb
```
上記のターミナルに実行する。
elmを使って統計ライブラリを作って実際にそれを利用するまで。-第一話　平均-

# ここに至る経緯

ふと思い立って自作ライブラリを作ってみることにしました、その題材に統計を選んだ理由は単純に勉強したほうが良いと思った分野だからです。
正直まだ統計学とelmのことをわかっていないところがありますのでツッコミがあればお願いします。
数式は書き方わからないので略します。
ちなみに参考にした書籍は統計の場合は[完全独習　統計学入門](https://www.amazon.co.jp/%E5%AE%8C%E5%85%A8%E7%8B%AC%E7%BF%92-%E7%B5%B1%E8%A8%88%E5%AD%A6%E5%85%A5%E9%96%80-%E5%B0%8F%E5%B3%B6-%E5%AF%9B%E4%B9%8B/dp/4478820090?SubscriptionId=AKIAIXNEYMK6UFDZYSVQ&tag=tachbookrank-22&linkCode=xm2&camp=2025&creative=165953&creativeASIN=4478820090)と[はじめての統計学](https://www.amazon.co.jp/%E3%81%AF%E3%81%98%E3%82%81%E3%81%A6%E3%81%AE%E7%B5%B1%E8%A8%88%E5%AD%A6-%E9%B3%A5%E5%B1%85-%E6%B3%B0%E5%BD%A6/dp/4532130743/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=%E3%81%AF%E3%81%98%E3%82%81%E3%81%A6%E3%81%AE%E7%B5%B1%E8%A8%88%E5%AD%A6&qid=1612185224&s=books&sr=1-1)です。
最近は上で得た知識だけでは少し早いかもしれませんが[統計学入門](https://www.amazon.co.jp/%E7%B5%B1%E8%A8%88%E5%AD%A6%E5%85%A5%E9%96%80-%E5%9F%BA%E7%A4%8E%E7%B5%B1%E8%A8%88%E5%AD%A6%E2%85%A0-%E6%9D%B1%E4%BA%AC%E5%A4%A7%E5%AD%A6%E6%95%99%E9%A4%8A%E5%AD%A6%E9%83%A8%E7%B5%B1%E8%A8%88%E5%AD%A6%E6%95%99%E5%AE%A4/dp/4130420658/ref=sr_1_4?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=JJAFDN1O3GJW&dchild=1&keywords=%E7%B5%B1%E8%A8%88%E5%AD%A6%E5%85%A5%E9%96%80&qid=1612185336&s=books&sprefix=%E7%B5%B1%E8%A8%88%E5%AD%A6%2Cstripbooks%2C256&sr=1-4)を読んでいます。

追記：勢いで書いてしまったのでソースコードを貼るのを忘れていました。[https://github.com/saburooo/simple-stat](https://github.com/saburooo/simple-stat)
また、作った成果もリリースしています。[https://mysimple-stat.web.app/](https://mysimple-stat.web.app/)


## まずは平均から。

elmで平均を求めるやり方として真っ先に思い立つのはこんなコードです。

```elm
average:List Float -> Float
average sample = (List.sum sample) / (List.length sample)
```

これは正確には算術平均というそうで最もシンプルな平均の求め方です。求めやすいけどこの計算だけではデータの内部がどうなっているのかわからないのが欠点です。

## 偏差
この関数を使って偏差を求めてみたいと思います、これは要するに求められた平均からどんだけずれているかを表現した数字です、リストで返すことにします。

```elm
deviation : List Float -> List Float
deviation list =
    map (\e -> e - average list) list
```

## 標準偏差
更に応用して標準偏差を求めて見たいと思います。よくS.D.と略されるこの数値ですがこれは平均からどんだけずれているか、そして***そのズレが常軌を逸脱しているか否かを示す***数値になります。
計算の仕方は先程の偏差から算出したリストを2乗して合計し、それにリストの長さを割ってルート計算をする順番になります。

```elm
standardDeviation : List Float -> Float
standardDeviation list =
    sqrt (sum (map (\e -> e ^ 2) (deviation list)) / Basics.toFloat (length list - 1))
```

正直ほぼ直訳で関数作りましたが多分これで通じると勝手に思ってます。いい書き方があったら教えてください。

## 変動係数
その次は変動係数を求めてみたいと思います。
標準偏差と算術平均で割ることで求められます。

```elm
coefficientOfVariation : List Float -> Float
coefficientOfVariation sampleData =
    standardDeviation sampleData / average sampleData
```

これが求めることで平均値を2つ求められたとしてその2つを正確にばらつき具合を比較できます。例えば「昔と今では月収が変わってるけどばらつき具合がどうなのかがわからない」時に使います。

## 標準化
まずは標準化まで書いていこうと思います。
やり方は先程の計算式をもとに

```elm
standartdization: List Float -> List Float
standartdization list =
    List.map (\l -> (l - (average list)) / (standardDeviation list)) list
```
こうして求めたリストのそれぞれの値に10を掛けて50を足した値が偏差値になります。今回はここまでにします。
シリーズ化していく予定です。