OmniAICreator/Qiita-1.07M huggingface dataset:
SQLで月次チャーンレート(解約率・退会率)・継続率を出す

# 概要
チャーンレート(解約率・退会率)とは、全てのユーザーのうち解約したユーザーの割合を示す指標のことです。継続率は、 `1 - チャーンレート` で出ます。

今回は前月からのチャーンレートを見ます。2019-06の時は、2019-05時点のユーザ数のチャーンレートを、2019-05の時は、2019-04時点のユーザ数のチャーンレートを、というように変動的にやるSQLです。

※値は適当です。最初のデータは前月がないので0になります。
![チャーンレート](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105093/9095c92a-9e20-81c4-e504-43547fd63ced.png)

# SQL

```sql

SELECT
  this.month
  ,count(distinct last.user_id) / count(distinct this.user_id) churn_rate
  ,1 - count(distinct last.user_id) / count(distinct this.user_id) keizoku_rate
FROM (
  -- 当月のユーザー数
  SELECT
    date_trunc(date(u.created), month) month
    ,u.id user_id
  FROM
    users u
  GROUP BY month
) this LEFT JOIN (
  -- 前月のユーザー数
  SELECT
    date_trunc(date(u.created), month) month
    ,u.id user_id
  FROM
    users u
  GROUP BY month
) last ON this.user_id = last.user_id
and this.month = date_add(last.month, interval 1 month) -- 前月処理
GROUP BY month
ORDER BY month DESC
```

ポイントは、当月を前月+1ヶ月と、LEFT JOINすることです。
`and this.month = date_add(last.month, interval 1 month)`

日別、週別、四半期別、年別に `date_trunc(date(u.created), XXXX`)` を使って、分析してみるのも楽しいですね。

また課金しているなどアクティブなユーザーのチャーンレートを見るのも面白いと思います。その場合は、 `GROUP BY month, X.user_id` と、ユーザーIDをユニークにすることを忘れずに。
docker環境でのbyebugのやり方

#普通にbyebug仕込んでもparams効かない！！

![失敗ver.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303093/7a3d8958-5538-9667-a38c-ca1213b2edca.gif)

パラメータとか見たいのに見せてくれない...
そしてブラウザは一生読み込み中に...

###Docker環境ならではの原因が！！

コンテナをアタッチしないといけないみたいです。。コンテナが起動している状態で以下のコマンドを打ちます。

```console

docker attach <コンテナ名　または　コンテナID>

```

アタッチ後のbyebug
![成功ver.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303093/dfd7228d-b1bb-99c0-1cd1-e17ce0d6e566.gif)

OK!

終了したい（デタッチ）時は`q`と打ってEnterで終了できますが、このやり方だとコンテナ止まっちゃうんだよな。。。
他にいいやり方ありましたら教えてください。

1ヶ月くらいデバッグなしでポートフォリオ作ってたからだいぶラクになるww
コントローラのテストをRequest specで書く際に、session値を設定する

## はじめに
テスト対象外のロジック（sessionの取得）が原因でテストが進まなかったため、
session値を設定する必要がありました

##動作環境
RSpec 3.7


##テストの対象ソース
```ruby:Orders_Controller.rb

class OrdersController < ApplicationController
  include SessionHelper
  before_action :authorized_user, only: [:index, :show, :edit, :update]

  def index
    @user = current_user
    @orders = @user.orders
  end
end
```

```ruby:session_helper.rb

class SessionHelper
  def current_user
    token = session[:token]
    if token.present?
      @user ||= User.find_by(id:session[:user_id])
    end
  end
end

```







##エラーが出た書き方
```ruby:orders_controller_spec.rb
require 'rails_helper'

RSpec.describe OrdersController, type: :request do

  describe "GET #index" do

    let(:user)  { create(:user) }
    let(:order) { create(:order, user_id, user.id) }

    it 'リクエストは200 OKとなること' do
      get orders_url , params: { session: { token: user.token, user_id: user.id } }
      expect(response.status).to eq 200
    end
  end
end
```
##エラー内容
```console:コンソール
  1) OrdersController GET #index リクエストは200 OKとなること
     Failure/Error: @orders = @user.orders
     NoMethodError:
       undefined method `orders' for nil:NilClass
```

##サクセスした書き方
```ruby:orders_controller_spec.rb
require 'rails_helper'

RSpec.describe OrdersController, type: :request do

  describe "GET #index" do

    let(:user)  { create(:user) }
    let(:order) { create(:order, user_id, user.id) }

    before do
      allow_any_instance_of(ActionDispatch::Request).to receive(:session).and_return({ remember_token: user.remember_token, remember_user_id: user.id })
    end

    it 'リクエストは200 OKとなること' do
      get orders_url
      expect(response.status).to eq 200
    end
  end
end
```
このようにスタブ化することで、sessionを設定できました

[こちらの記事を参考にさせていただきました](https://qiita.com/blueberrystream/items/884d0d23caf50b6553a0)
Chrome の CSS transition がページロード時に動いてしまう問題の機序と対処

## TL;DR

外部 CSS を読み込んだら、何かしらスクリプトを走らせよう。

## 前置き

外部スタイルシートに CSS transition を記述した際、仕様上は初期状態への遷移は発生しないはずなのだけれど、Chrome だと、デフォルトのスタイルから初期状態への遷移が発生してしまう、という問題。

かなり以前から知られていた問題らしいのだけれど、未だに直っておらず、それぞれに対処法は考えられているものの、なぜそれで動くのかよくわからなかったので、少し追っかけてみた。

結果、全容を把握するに至らなかったのだけれど、おおよその機序と回避方法が分かったので、メモがてらに残しておく。

## 問題の発生する例

例えば、こんなスタイルシートがあって、

~~~css:hoge.css
.anim {
    background-color: red;
    transition: background-color 5s ease-out 0s;
}
.anim:hover {
    background-color: blue;
}
~~~

こんな html を書く。

~~~html:hoge.html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <link rel="stylesheet" href="hoge.css">
    </head>
    <body>
        <p class="anim">hoge</p>
    </body>
</html>
~~~

最初は赤背景で、マウスオーバーしたら青に……というのを期待するのだけれど、
Chrome で実行すると、ページ読み込み時にデフォルト(透過)から赤への遷移アニメーションが挟まってしまう。

## 機序

どうやら Chrome さんは、外部スタイルシートを遅延解決しようとしているようで、
上記のような記述だとスタイルの適用が後回しにされる。
それが初期 DOM 構築後になると、新規にクラスが設定されたとして、遷移アニメーションが発火してしまう。

## 対処

初期 DOM 構築完了前に、外部スタイルシートを解決させる。
具体的には何かしらスクリプトを動かすだけで良い。
スクリプト実行前に、外部スタイルシートの解決を行ってくれる。

例えば以下のように。

~~~html:hoge.html(改1)
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <link rel="stylesheet" href="hoge.css">
    </head>
    <body>
        <p class="anim">hoge</p>
        <script>console.log("ちゃんとスタイル適用してね。");</script>
    </body>
</html>
~~~

もちろん、`link` の直後でも良い。

~~~html:hoge.html(改2)
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <link rel="stylesheet" href="hoge.css">
        <script>console.log("ちゃんとスタイル適用してね。");</script>
    </head>
    <body>
        <p class="anim">hoge</p>
    </body>
</html>
~~~

外部スタイルシートが複数あることを考えると、前者の `body` の最後に入れてしまう方法が汎用的でよい気がする。

なお、`script` 要素の中身は何でもいいが、空にするのはダメ(単にスキップされる)。
空白のみ、はアリだけれど、module bundler や minifier に消されてしまう可能性があるので注意。

**追記:** `script` 要素は外部スクリプトの読み込みでも大丈夫なようです。(コメント欄参照)

## 補遺

`link` は `script` の前に置け、という対処方法が紹介されることもあった(し、誤りではない)けれど、`link` の前に `script` があること自体が問題を起こしているわけではない。

`link` の後に何かしら中身のある `script` を置く、ということが回避策になるようだ。

## 先人たち

https://qiita.com/yaegaki/items/46209320e7163cb638a9
https://intp.jp/?p=796
https://css-tricks.com/transitions-only-after-page-load/
【初心者】positionは、relativeで範囲を決めてabsoluteで動かそう！

## はじめに
入社前にHTMLとCSSをかじったとはいえ、知らないタグや使い方が大量に出てきた研修課題。その中でもpositionの使い方をどんなに調べても意味不明だったので、自分が理解した（と思っている）内容をまとめました。

## positionとは
positionはcssプロパティの1つで、配置方法を設定します。ここで注意しないといけないのは、配置方法を設定するだけでその位置を指定しているわけではないということ。実際に「ここに表示！」とする場合は、top・bottom・right・leftなどで位置を指定する必要があります。

話は戻って、どういう時にpositionプロパティを使うことになるのかというと、よく画像の右上や左上あたりに「NEW」というアイコンがあったり、画像の上に何かを重ねて表示したいときに使用するらしいです。（ふむふむ・・・）ググッて調べてみると「ボックスの配置方法（基準位置）が、相対位置（relative）か絶対位置（absolute）かを指定する際に使用します。」とか書かれています。が！この相対位置とか絶対位置と言われた途端に分からない・・。

## 相対位置と絶対位置
言葉の意味を確認すればちょっとわかる気がしてくるかと思い調べてみました。

・相対：他との関係の上に存在あるいは成立していること
・絶対：他に比較するものや対立するものがないこと

つまり、相対位置の配置方法にすると基準にする位置がその時々で異なり、絶対位置の配置方法にすると指定した位置になにがなんでも表示される融通が利かないやつなのかと。
ここでさらに疑問なのが、何を基準に配置されるかということ。相対位置の説明では「ずれている図」が、絶対位置の説明では「重なっている図」が描かれていることが多いのですが、それは基準を軸に動きの違いを説明しているからです。いろいろな表現方法はあると思うのですが、わたしは下記のように理解しています。

・相対位置の基準：本来その要素が表示される位置を基準にする
・絶対位置の基準：親要素を基準にする

## absoluteを使うときはrelativeとセットで使おう！
relativeとabusoluteがそれぞれどういう動きをするかはいろいろ調べていただくとして・・。わたしがググって調べてもなかなか目につかなかったのがこのセット使い。全然分かっていない初心者からすると、absoluteとrelativeは使い分けるものだと思い込んでいたので「なんでこれを教えてくれなかったんだっ！！」と声を大にして言いたいところですが、書いてあるサイトにはきちんと書いてありました（汗）
親要素を基準に位置を決めるabsoluteを使用する場合は、必ず親要素にrelativeを設定しておく必要があります。指定しない場合どうなるかというと、relativeを探してさまよい、自分が思っているところに出したいものが表示されません。そのため、今回のタイトルにもある通り、relativeで動かせる範囲を決めてabsoluteで位置を指定するというセット使いと覚えておいた方がいいでしょう。

## 牧場の羊に例えて考えよう
はい、久しぶりのたとえ話です。笑
今回はrelativeを牧場に、absoluteを羊にして考えてみました。
羊は柵のある牧場内でしか動き回ることが出来ないのでabsoluteになります。そのため、羊の親要素に該当する牧場はrelativeを指定しておく必要がありますね。

もし牧場ごと移動したい場合（いや、本来はありえないですが・・）は、牧場の配置位置を指定してあげると、羊の位置を変えずに牧場の位置を変更することが出来ます。これがセット使いの良いところだなと個人的には思っています。

~~~html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <link rel="stylesheet" href="css/index.css">
  </head>
  <body>
    <div class="area">
      <img src="img/area.png" width="450px">
      <div class="sheep">
        <img src="img/sheep.png" width="100px">
      </div>
    </div>
  </body>
</html>
~~~
~~~css
.area {
        position: relative;
        width: 450px;
        /*牧場ごと移動したい場合は位置を指定します*/
        left: 30px;
        /* 以下の設定は分かりやすいようにするためで必須ではありません。 */
        border: 1px solid black;
}

.sheep {
         position: absolute;
         /* 以下の値をいろいろ変更し羊の位置を変えます（全部指定する必要なし） 
         top: ;
         bottom: ;
         left: ;
         right: ;
         */
         top: 50%;
         left: 20%;
        /* 以下の設定は分かりやすいようにするためで必須ではありません。 */
        border: 1px solid red;
}
~~~

上記ソースをそのままコピペしてファイルを作成し、実行すると下記の結果イメージのように表示されます。cssで指定している位置のパーセンテージの値を変更することで、羊の位置が牧場内（正確には枠線内）で動かせることが分かると思います。あえて位置を指定せずに実行してみるのも面白いと思います。
<img width="418" alt="image.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390061/0f75ddd5-e6df-23cd-fe94-a720ab3c90aa.png">

##正しく設定出来ているか確認したいとき
正しく設定出来ていれば、absoluteで設定している位置をtop:0もしくはbottom:0のどちらかだけ設定して実行すると、動いている上下の範囲（＝relativeの範囲）が分かります。うまく親要素にrelativeが設定出来てない場合は画面から消えたり、画面の一番上にかろうじて表示されていたりします。わたしはいい感じに表示されるようになっても、このチェックはなるべくするようにしています。

## まとめ
調べても調べても全然理解できなかったposition。結局最後は先輩に解説してもらってようやくここまで理解したのですが、どんなに考えても分からない場合は人に解説してもらうのが一番分かるものですね。結局、相対位置と絶対位置はなんだったんだろう・・とちょっと思ってしまったのですが、今のところはセット使いだけ覚えておくことにしました。
自分で勉強して理解することも大事ですが、間違って覚えてしまうリスクもあるので、先輩たちに直接聞いて確認することも忘れないようにしたいなと改めて思いました。
PerlでHTTPS通信がうまくいかないときの対処方 on Ubuntu

Perlでhttpsへの通信をやろうとして失敗したときの対処メモ。

# 環境

- Ubuntu 18.04.2 LTS
- perl 5.28.2

今回はAnyEvent::HTTPを使って非同期通信をしようとした。
初期状態で通信を実施すると、httpステータスコード596で、「TLS support not available on this system」となる。

Perlでhttpsをサポートするには下記のモジュールを入れるが、Net::SSLeyがインストールできずに失敗した。

```:console
cpanm Net::SSLeay
cpanm Crypt::SSLeay
cpanm IO::Socket::SSL
```

ログを確認すると、「/usr/bin/ld: -lz が存在しません。」とある。なので、下記をインストールすることで上記モジュールもインストールでき、https通信を行うことができた。

```:console
sudo apt-get install zlib1g
sudo apt-get install zlib1g-dev 
```

zlib は gzip と PKZIP で使われている deflate 圧縮法を実装したライブラリ、らしい。
自分の環境では、zlib1g-devのほうがOSにインストールされてなかったので、追加でインストールした形になる。
BigDecimal.valueOf(double)の話

# BigDecimalでの小数
javaで小数計算する場合はBigDecimalがデファクトスタンダードです。
double型やfloat型で計算しようものならあっと言う間に誤差が出てひどいことになります。

しかも、このBigDecimalは性質の悪いことに新人が一番使ってしまいそうな
以下のようなコードを書くと結局誤差が出てしまいます。
double型で宣言した時点で誤差が出ているので、
それを基にBigDecimalを作っても誤差がそのまま保持されてしまうからです。
新人の頃、先輩から下のように書けと散々叩き込まれたものです。

```java

BigDecimal bad = new BigDecimal(1.3);
//内部的に1.3000000000000000444089209850062616169452667236328125

BigDecimal good = new BigDecimal("1.3");

```

## BigDecimal.valueOf(double)
というわけで、BigDecimalで小数を扱う時は引数は文字列だと完全に体に染み込んでいるのですが、
最近ちょっと検索してみると、BigDecimal.valueOf(double)でdouble型は問題なく扱えるという風に書いてある解説ページが結構ありました。

しかし、``new BigDecimal(double)`` がdouble型の時点で正確な10進数の小数を保持できないために誤差が出てしまうということを考えると、
``BigDecimal.valueOf(double)``も誤差が出てしまうはずです。

しかし、意外なことに確かに大抵のケースで``BigDecimal.valueOf(double)`` は正しく動きます。

```java
BigDecimal fromValueOf = BigDecimal.valueOf(1.3);
//これはnew BigDecimal("1.3") と同じ値になる
```
これはどういうことでしょうか。

### BigDecimal.valueOfの実装
``BigDecimal.valueOf(double)`` の実装を見てみると、以下の通りでした。
(OpenJdk より引用)

``` java
    public static BigDecimal valueOf(double val) {
        //コメント部分は省略
        return new BigDecimal(Double.toString(val));
    }
```
意外と実装はシンプルで、``Double.toString(double)``でdouble型を文字列化した値を使って文字列からBigDecimalを生成しています。
よって、Double.toString(double)がそのdouble値の元となったリテラルの値(またはそれに対応する数値表現)をきちんと返してくれる限り、意図した通りのBigDecimalを返してくれそうです。

#### Double.toString()はきちんと値を復元してくれるのか？
ほとんどの場合大丈夫ですが、非常に小数点以下の桁数の多い数の場合完璧には戻らないようです。

``` java
BigDecimal.valueOf(1.0000000003000003)
//1.0000000003000002
```
とはいっても、狙って出さないと基本的にずれませんし、
これだけ細かい桁数を使うことはほぼないと思われます。

## まとめ
* BigDecimal.valueOf(double)は一度文字列変換しているので信頼性が高い
* 滅多にない誤差まで気になるのなら文字列で宣言できるところは文字列で宣言を

## 余談
ちなみに、これはリテラルで宣言したdoubleをそのまま使った場合の話です。
double型で演算した後の値を使うとうまく行きません。

```java
BigDecimal.valueOf(1.3 + 1.5 + 1.4)
///4.199999999999999
```
演算はBigDecimalにしてからですね。
GitHub Pagesの始め方

＊＊＊　備忘録です。間違い等があればご指摘ください。　＊＊＊

GitHub Pagesでは以下の２種類のURLのウェブページを作成できる。
&nbsp; https://ユーザー名.github.io
&nbsp; https://ユーザー名.github.io/リポジトリ名
以下、それぞれについて作成方法を説明する。
***

### 前提
- GitHubの[Sign up（ユーザー登録）](https://github.com)は終了している。
- [SSH公開鍵の作成とGitHubへの登録](https://qiita.com/tomot3/items/6557a6560c80996e5dfe)は終了している。

### https://ユーザー名.github.io の場合

1. [https://github.com/](https://github.com/)にSign inする。
2. 右上の「+」から「New repository」を選択する。
3. 「Repository name」に「ユーザー名.github.io」を入力する。
4. ~~リポジトリを公開する場合は「Public」、公開しない場合は「Private」をチェックする。どちらを選んでもウェブページは公開される。~~　有償版のGitHubを使用している場合は「Public」（リポジトリを公開する）あるいは「Private」（リポジトリを公開しない）をチェックする。無償版を使用している場合は「Public」を選択する。※[@xylitol45@github](https://qiita.com/xylitol45@github)さんにご指摘いただきました。ありがとうございます。
5. 「Initialize this repository with a README」をチェックする。
6. 「Create repository」をクリックする。
7. ローカルホストでindex.htmlファイルを作成し、リモートリポジトリを更新する。

    ```
$ cd ~/GitHub  <-- 各自のGitHubのリポジトリを保存しておくディレクトリ
$ git clone https://github.com/ユーザー名/ユーザー名.github.io.git
$ cd ユーザー名.github.io
$ echo "Welcome to ユーザー名.github.io" > index.html
$ git add index.html
$ git commit -m "Create index.html"
$ git push
$ open https://ユーザー名.github.io  <-- 作成したウェブページを確認（更新に若干時間がかかる）
```

8. ローカルホストでファイルの修正や追加を行ったら、リモートリポジトリを更新する。

    ```
$ git add ファイル名
$ git commit -m "コメント"
$ git push
$ open https://ユーザー名.github.io  <-- 修正したウェブページを確認（更新に若干時間がかかる）
```

### https://ユーザー名.github.io/リポジトリ名 の場合

1. [https://github.com/](https://github.com/)にSign inする。
2. 右上の「+」から「New repository」を選択する。
3. 「Repository name」にリポジトリ名を入力する。
4. ~~リポジトリを公開する場合は「Public」、公開しない場合は「Private」をチェックする。どちらを選んでもウェブページは公開される。~~　有償版のGitHubを使用している場合は「Public」（リポジトリを公開する）あるいは「Private」（リポジトリを公開しない）をチェックする。無償版を使用している場合は「Public」を選択する。※[@xylitol45@github](https://qiita.com/xylitol45@github)さんにご指摘いただきました。ありがとうございます。
5. 「Initialize this repository with a README」をチェックする。
6. 「Create repository」をクリックする。
7. 「Create new file」をクリックする。
8. 「Name your file...」に「docs/index.html」と入力し、「Commit new file」ボタンをクリックする。
9. 「Settings」をクリックする。
0. 画面をスクロールさせて、下の方にある「GitHub Pages」の「Source」から「master branch /docs folder」を選択する。
1. ローカルホストでindex.htmlファイルを作成し、リモートリポジトリを更新する。

    ```
$ cd ~/GitHub  <-- 各自のGitHubのリポジトリを保存しておくディレクトリ
$ git clone https://github.com/ユーザー名/リポジトリ名.git
$ cd リポジトリ名/docs
$ echo "Welcome to リポジトリ名" > index.html
$ git add index.html
$ git commit -m "Revise index.html"
$ git push
$ open https://ユーザー名.github.io/リポジトリ名  <-- 作成したウェブページを確認（更新に若干時間がかかる）
```

8. ローカルホストでファイルの修正や追加を行ったら、リモートリポジトリを更新する。

    ```
$ git add ファイル名
$ git commit -m "コメント"
$ git push
$ open https://ユーザー名.github.io/リポジトリ名  <-- 修正したウェブページを確認（更新に若干時間がかかる）
```
Codeigniterのorder_byで、NULLのレコードをあとに取得する方法

### MySQL
- MySQLの `ORDER BY column_name ASC` で、column_nameがNULLのレコードは先に取得されるが、以下のように記述することで、column_nameがNULLのレコードをあとに取得できる。

```
SELECT * FROM table_name ORDER BY column_name IS NULL ASC, column_name ASC;
```
- 参考記事
  - https://qiita.com/hanamako/items/dda36ef1beff1533a77f

### Codeigniter 
上記をPHPのCodeigniterで実現する場合の書き方は以下

```
$this->db->order_by('column_name IS NULL', 'ASC', FALSE);
$this->db->order_by('column_name', 'ASC');
```
- 第1引数に `IS NULL` を入れるため、第3引数にFALSEを指定して、明示的にエスケープを外している
- 参考記事
  - https://teratail.com/questions/27440
SSH公開鍵の作成とGitHubへの登録

＊＊＊　備忘録です。間違い等があればご指摘ください。　＊＊＊

### 1. 前提
GitHubの[Sign up（ユーザー登録）](https://github.com)は終了している。

### 2. SSH公開鍵の作成

```
$ ssh-keygen
```
~/.sshディレクトリに、id_rsa（秘密鍵ファイル）とid_rsa.pub（公開鍵ファイル）が作成される。

```
$ pbcopy < ~/.ssh/id_rsa.pub
```

id_rsa.pubの内容がクリップボードへコピーされる。

### 3. GitHubへの登録
1. [https://github.com/](https://github.com/)にSign inする。
2. 右上のアイコンから「Settings」を選択する。
3. 左のメニューから「SSH and GPG keys」を選択する。
4. 「New SSH key」を選択する。
4. 「Title」にコンピュータ名等（自分で区別できればなんでも良い）を入力し、「Key」にid_rsa.pubの内容をペーストする。
5. 「Add SSH key」をクリックする。

```
$ ssh -T git@github.com
```

正しく登録されていれば、以下のように表示される。

```
Hi ユーザー名! You've successfully authenticated, but GitHub does not provide shell access.
```
ヒープソート

# ヒープソート
- いかなるデータに対しても$O(n\log n)$の計算量
- 平均の計算量ではクイックソートの方が優れている
- 基本的な考え方は「選択ソート」つまり，「ある範囲内での最(大|小)値を見つけて，その位置を確定させる」ことを繰り返すことで整列させる
- 選択ソートでは「ある範囲での最(大|小)値」だけに注目しているので，最(大|小)値を除く他の値同士の大小関係の情報を捨てているが，ヒープソートではその情報をデータ構造の中に残しておくことで計算量を減らす
- ここで求められているのは**「複数の値の集合から最大値を効率的に取り出すことができる」**ようなデータ構造
- このようなデータ構造は**「優先順位つき待ち行列」**という
- 優先順位つき待ち行列をどうやって実現するかには複数の選択肢がある
- 例えば優先順位つき待ち行列を平衡木を用いて実現しようとしても全然構わない．その場合，平衡木の右端のノードが最大値になっているのでそこを取り出せばいい．
- が，常に平衡木の右端を取り除くことになるので，最大値を得るたびに木のバランスが崩れ，リバランスの処理が必要になる
- 確かに平衡木を用いて優先度つき待ち行列を実現してもいいが，平衡木ほどリッチなデータ構造でなくても優先度つき待ち行列は実現できる
- それが**「部分順序つき木」**
- 部分順序つき木では**「親はその直の子供より大きい」**ような木構造
- 二分探索木の大小関係を縦にした感じ
- 部分順序つき木では木全体の根が常に最大値になっている
- が，しかし，優先度つき待ち行列を部分順序つき木で実現するのはまだリッチで，通常は部分順序つき木を配列を使って表現したものを使う

![](https://image.slidesharecdn.com/11-170415110802/95/11-8-638.jpg?cb=1492254513)

- 部分順序つき木をよく観察してみると，**配列の$i$番目に対して$2i$番目に「$i$の左の子供」$2i+1$番目に「$i$の右の子供」と配置するとルール決めすると，**部分順序つき木を配列上に表現できそうだと気がつく

![](https://slidesplayer.net/slide/16807321/97/images/6/%E9%85%8D%E5%88%97%E3%81%AB%E6%9C%A8%E3%82%92%E8%A1%A8%E7%8F%BE%E3%81%97%E3%81%9F%E3%81%93%E3%81%A8%E3%81%AB%E3%81%99%E3%82%8B%EF%BC%88%EF%BC%91%EF%BC%98%EF%BC%98%E3%83%9A%E3%83%BC%E3%82%B8%EF%BC%89+%E6%A0%B9+%EF%BC%92%E6%AE%B5%E7%9B%AE+%EF%BC%93%E6%AE%B5%E7%9B%AE+%EF%BC%94%E6%AE%B5%E7%9B%AE.jpg)

- 配列上に表現した部分順序つき木のことをさして**ヒープ**ということがある
- 配列を使って任意のルールを満たす二分木が表現できるかと言われるとそうではない
- 部分順序つき木が配列上に表現できるのは「**左右の子供の順番が自由だから**」
- 部分順序つき木を配列上で表現すると「全体から数えて$i$番目のノードが親ならば，$2i$番目と$2i+1$番目のノードがその子供になっている」ので，「配列の長さが$n$ならば，全体から数えて$n$番目の子供が存在しているということだから，$n/2$番目のノードが**「子供を持っている」ノードの中で最も若い（インデックスが最大）ノード**ということになる
- ここでやりたいのは，**「ランダムな順番になっている配列をヒープに変換して，最大値を取り出す」**こと
- ヒープに変換するとはどういうことかといえば，**「全ての親について，親子間で部分順序つき木のルール（親≧子）を守らせる」**ようにすること
- つまり，$n/2$番目のノード（これが最もインデックスの大きい親）から遡って行きながら，「親≧子」のルールを守っていなければ親子をひっくり返していく == `downheap`

```go
func HeapSort(target *[]int) []int {
	*target = append([]int{-1}, *target...)
	downheap := func(parent, lastIdx int) {
		parentValue := (*target)[parent]
		for {
			child := 2*parent
			if child > lastIdx { break }
			if child != lastIdx { // `parent` has 2 children
				if  (*target)[child+1] >  (*target)[child] {
					child += 1
				}
			}
			if  (*target)[child] <= parentValue {
				break
			}
			(*target)[parent] =  (*target)[child]
			parent = child
		}
		(*target)[parent] = parentValue
	}
	n := len(*target)-1
	for i := n/2; 1 <= i; i-- {
		downheap(i, n)
	}
	for i := n; 2 <= i; i-- {
		(*target)[1],  (*target)[i] =  (*target)[i],  (*target)[1]
		downheap(1, i-1)
	}
	return (*target)[1:]
}
```
agora.io Video SDK for React Native クイックスタートガイド

#概要
agora.ioではReactNativeを利用した開発が可能です。
コミュニティで公開されているサンプルを元にビルドしてみたのでメモとして公開します。
(Reactがなかなか素直に動いてくれず苦労しました。。。)

[サンプル](https://github.com/fu-jimoto/AgoraIO-ReactNative)

#ビルド方法
1.上記サンプルプロジェクトをダウンロード
2.ファイルの展開
3.プロジェクトのルートフォルダへ移動
4.パッケージの追加

```shell
$ npm i
$ react-native link
```
5.local.propertiesを作成
6.utils.jsにAPP IDを追記

```javascript:utils.js

export const APPID = '***';
…
```

7.実機ビルド

```shell
$ react-native run-android --deviceId ***
```

#アプリの画面
###入室前
![Screenshot_20190613-193056.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/a13fcbba-a8c9-db11-8d28-e35e39aecc6c.png)
###入室後
![Screenshot_20190613-193114.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/daac0492-a63e-e671-2ba5-1169197ace6f.png)




##最後に
[**agora.ioに関するお問い合わせはこちらから**](https://jp.vcube.com/lp/agora?utm_campaign=Agora&utm_source=Qiita&arc_id=5d413ccf49089b350ba0)
[<img width="912" alt="スクリーンショット 0001-08-15 13.41.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/5d815376-9b89-08fa-9434-6fa7e8e67bcf.png">](https://jp.vcube.com/lp/agora?utm_campaign=Agora&utm_source=Qiita&arc_id=5d413ccf49089b350ba0)
npmについてのまとめ

Javascriptのパッケージ管理に使うnpmについてまとめます。

## 前提条件
* npm version 6.9.0
* macOS

## npm概要
### npm（Node Package Manager）とは?
* Node.jsのモジュール管理ツールです。
* フロントエンドで使用するJavascriptのパッケージ（例えば、vueやjQueryといった有名なフレームワーク、gulpなどのビルドシステム等）のインストールとバージョン管理に使います。
* [公式サイト](https://www.npmjs.com/)
* [公式ドキュメント](https://docs.npmjs.com/)

### npm自体のインストール方法
* Node.jsをインストールするとnpmもインストールされます。
https://nodejs.org/en/download/

### パッケージ管理の基本となるファイル：package.json
* アプリケーションのマニフェストファイルです。
* そのアプリケーションに必要なパッケージ名・バージョンがリストされます。
* package.jsonにリストされたパッケージ情報を元に、アプリケーションに必要なパッケージを一括インストールすることができます。

### scopeについて
* scopeとは、パッケージ名の前につける、@から/までの名前空間のことです。
* @以降は、npmユーザーアカウントまたは組織名が入ります。
* [参考](https://docs.npmjs.com/about-scopes)

```
@npm/package-name   （例：@vue/cli）
```

## npmを使ったパッケージのインストール方法
### インストールの種類
インストールには2種類あります。

#### ローカルインストール
* 個別のプロジェクトのnode_modulesディレクトリ配下にパッケージがインストールされます。
* この場合、パッケージは個別のプロジェクトでのみ使用できます。

```
npm install {パッケージ名}  （例：npm install gulp）
```
#### グローバルインストール
* npmのルートディレクトリ配下にパッケージがインストールされます。
* この場合、全てのプロジェクトでパッケージを使用できます。
    
```
npm install -g {パッケージ名} （例：npm install -g gulp）
```
※ --saveオプションはnpm v5.0.0からデフォルトになっています（つけなくてもpackage.jsonにパッケージがリストされます。）。https://blog.npmjs.org/post/161081169345/v500

#### グローバルインストールをしたパッケージの確認方法
* グローバルインストールしたパッケージは、npmのルートディレクトリ配下に格納されます。

```
//ルートディレクトリを確認
$ npm root -g    // /usr/local/lib/node_modules

$ cd /usr/local/lib/node_modules

$ ls //インストール済みパッケージが表示されます。
```

## パッケージのバージョン表記
![スクリーンショット 2019-06-14 15.02.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260824/72d27842-48ad-60b9-9da4-4b95fbebd2cb.png)

###  パッケージのバージョンの見方
* Major Release：仕様そのものの変更。upgradeする場合はアプリケーションの改修が必要になる可能性あり。
* Minor Release：仕様を維持した状態での機能追加。upgradeしてもアプリケーションは壊れない。
* Patch Release：バグ修正。upgradeしてもアプリケーションは壊れない。

#### 参考
* [セマンティックバージョニング](https://semver.org/lang/ja/)

### チルダ（~）、キャレット(^)の意味
* 何もない場合
    *  例： `"lodash": 4.17.4`
    * 4.17.4にバージョンを固定する。
* キャレット(^)がついている場合
    * 例： `"lodash": ^4.17.4`
    * 最新のマイナーバージョンをインストールする。（メジャーバージョンにより新しいものがあっても、そこは更新しない） 
* チルダ(~) がついている場合
    *  例： `"lodash": ~4.17.4`
    * 最新のパッチバージョンをインストールする。（メジャー・マイナーバージョンにより新しいものがあっても、そこは更新しない）

#### 参考
* [npmのバージョニング](https://docs.npmjs.com/about-semantic-versioning)
* [バージョニングの計算サイト](https://semver.npmjs.com/)

## 主なコマンド一覧

#### 初期化（package.jsonの生成）
* 単にinitした場合はpackage名、descriptionなどを聞かれるので、自分で設定します。デフォルト設定で良い場合は-yオプションをつけます。

```
$ npm init    
$ npm init -y
```

#### パッケージインストール（一括）
* package.jsonにリストされたパッケージを一括インストールします。

```
$ npm install
```
#### パッケージインストール（個別）
```
$ npm install {パッケージ名}        //ローカルインストール
$ npm install -g {パッケージ名}     //グローバルインストール
$ npm install lodash@4.17.3       //バージョンを指定したインストール
```
#### パッケージアンインストール（個別）
```
$ npm uninstall {パッケージ名}       //ローカルインストールしたパッケージをアンインストール
$ npm uninstall -g {パッケージ名}    //グローバルインストールしたパッケージをアンインストール
```
#### パッケージの更新
```
$ npm update {パッケージ名}
```

#### パッケージを一覧表示
```
$ npm list
$ npm list --depth 0    //依存関係をのぞいて表示（ツリー表示の深さを0にする）
```

参考：CLIのドキュメント:https://docs.npmjs.com/cli-documentation/

## 参考
* [npm公式ドキュメント](https://docs.npmjs.com/)
* [npm入門](https://qiita.com/maitake9116/items/7825d90c09f3e2f87dea)
Laravelで「~ must return a relationship instance」というエラーに一瞬悩んだ件

LaravelのModelで以下のようなエラーが出て、解決までいっとき悩んだので、メモです。

```
~ must return a relationship instance
```

私の場合、単純に、Modelの関数内で**「returnをさせていなかった」**のが原因でした。。笑

当たり前すぎでお恥ずかしいのですが、
一瞬悩んでググり、海外に同じ症状で悩んだ人の記事をいくつか見かけたので、
晒しておきます。
Laravel5.8で導入したvuejs-paginateのデザインが反映されない問題

# 環境と経緯
- Laravel 5.8
- Vue.js 2.6
- [vuejs-paginate 2.1](https://www.npmjs.com/package/vuejs-paginate)

Laravel + Vueのアプリケーションでページネーション機能が欲しかったので、vuejs-paginateを導入したが、公式通りに導入してもなぜかデザインが反映されない
。
# 症状と原因

本来なってほしいデザイン

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="js,result" data-user="wim_web" data-slug-hash="orjQaO" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="vuejs-paginate with bs3">
  <span>See the Pen <a href="https://codepen.io/wim_web/pen/orjQaO/">
  vuejs-paginate with bs3</a> by うぃむ@謳って⤴謳って⤴雲の上ぇぇええ☁🥰 (<a href="https://codepen.io/wim_web">@wim_web</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

おかしいデザイン

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="js,result" data-user="wim_web" data-slug-hash="QXjJqG" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="vuejs-paginate with bs4">
  <span>See the Pen <a href="https://codepen.io/wim_web/pen/QXjJqG/">
  vuejs-paginate with bs4</a> by うぃむ@謳って⤴謳って⤴雲の上ぇぇええ☁🥰 (<a href="https://codepen.io/wim_web">@wim_web</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

コードをみてもらえれば分かるのですが、どちらのコードも全く同じです。
ではなにが違うのかというとBootstrapのバージョンです。
デザインがきちんと反映されているほうが3系で、反映されていないほうが4系です。
ReadMeでBootstrapについて特に言及されていなかったので原因がわかるまで時間がかかりました。。。

# 改善コード
paginateコンポーネントにCSSのクラスの情報を追加してあげる。

```
<paginate 
  :pageCount="10"
  :containerClass="'pagination'"
  :page-class="'page-item'"
  :page-link-class="'page-link'"
  :prev-class="'page-item'"
  :prev-link-class="'page-link'"
  :next-class="'page-item'"
  :next-link-class="'page-link'"
  :clickHandler="clickCallback">
 </paginate>
```
codepenで試してみてね！
Search: list で複数チャンネルを一発で検索する

#結論
**検索クエリ q に"チャンネル名"*****(NOT チャンネルID)*****を' OR 'でつないだやつをぶち込む。**

ここでわかった人、知ってた人は帰って良し！

私にとってはブレイクスルーだったので記事にすることにしました。

以下、具体例。
#今までやってたこと

```python:search.py
#チャンネルIDのリスト
channel_id = ['UCxxx', 'UCxxx', 'UCxxx']

#おまじない
youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, developerKey=DEVELOPER_KEY)

#検索部分
def youtube_search(CHANNEL_ID):
	search_response = youtube.search().list(
		part = 'id, snippet',
		type = 'video',
		eventType = 'live',
		maxResults = 1,
		channelId = CHANNEL_ID
	).execute()

#実行
for ID in channel_id:
	youtube_search(ID)
```

※基本的な定義部分とfieldsは省いてます

上のようにチャンネルIDのリストを作り、ループさせていました。
これだと検索したいチャンネルの数だけquotaが食われるのでやばいです。私は18チャンネル分繰り返していて一日五回までの必殺技みたいになってました。

#解決策
~~まず、`channelId = CHANNEL_ID` を `q = ' OR '.join(CHANNEL_ID)`と変更し`maxResult`を目的のコンテンツが引っかかるように指定します。~~

まず、チャンネルIDではなく、[Channels: list](https://developers.google.com/youtube/v3/docs/channels/list?hl=ja)の`snippet.title`などでわかる正確なチャンネル名をダブルクォーテーションで囲ったやつ`"チャンネル名"`のリストを作成します。
これを`' OR '.join(CHANNEL_NAMES)`のように OR (前後にスペース)でつなげたやつを検索クエリに投げます。そうすると目的のものを含んだデータが返ってくると思います。
このデータを、目的のコンテンツを`if`などでチャンネルIDでフィルタリングして利用します。

これで1回の検索でたくさん検索できます。
※チャンネル名をOR接続したやつの合計文字数が多くなりすぎると、後半が検索漏れすることがあるのでそういうときは分けましょう。私の推しでは、6チャンネルはいけました。

~~あたかも、上を書き換えれば動くように書いてますが`eventType`や`order`と共存できませんでしたなんでぇ……~~

~~この方法、ほとんど上手く行くのですがチャンネルIDに二連続のダッシュ`—-`が入っていると検索結果がバグります。これの解決方法があったらよろしくお願いします。~~　そもそもIDを使わなくなりました。
###実装例
```python:search.py
#チャンネルIDのリスト
channel_names = ['xxxChannel', 'xxxチャンネル', 'xxxちゃん寝る']

#おまじない
youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, developerKey=DEVELOPER_KEY)

#検索部分
def youtube_search(CHANNEL_NAMES):
	search_response = youtube.search().list(
		part = 'id, snippet',
		type = 'video',
		eventType = 'live',
		maxResults = 50,
		q = ' OR '.join(CHANNEL_NAMES)
	).execute()

#実行

youtube_search(channel_names)
```

##雑記
以上、初投稿でした。お見苦しい点等ありましたら言ってください。
この解決法を見つけたきっかけは単なる思い付きで、「ブラウザ検索欄にチャンネルID貼り付けたらどうなる？いけるじゃん……じゃあORで繋いだら……じゃあAPIでも……」って感じでした。結局、チャンネル名でしたが......
閃きって大切だなあって思いました(小並感)

チャンネルIDで検索する方法も場合によっては有効だと思いますが、私は`eventType = 'live'`が欲しかったのでこちらを採用しました。
検索対象の人が必ずオリジナルのタグとかつけていればそれを検索してもいけるのかな？とか思ったり。

大幅な修正申し訳ございません。私の確認不足でした......

##リンク
[Search: list](https://developers.google.com/youtube/v3/docs/search/list?hl=ja)
Webブラウザでhtml文字列を開く

(この記事を書いた時の環境:macOS Mojave 10.14.4 & Python 3.7.3)

Pythonには**webbrowser**という標準ライブラリがある。

以下のようにurlを渡してやることでそのurlをウェブブラウザで開いてくれる。

~~~Python
>>> import webbrowser
>>> url = "https://www.google.co.jp"
>>> webbrowser.open_new_tab(url)   #新しいタブで開く
~~~

"file:///"を付けて渡してあげればローカルファイルも開ける。

~~~Python
>>> import webbrowser
>>> url = "file:///Users/hoge/Documents/hello.html"
>>> webbrowser.open_new_tab(url)   #新しいタブで開く
~~~

## ファイルパスやurlじゃなくてhtml文字列から開きたい

でもwebbrowser自体はurl(やファイルパス)をWebブラウザで開く機能しかない。

しゃーなし一時ファイルを作ってそのパスをwebbrowserに渡そう。

~~~Python:web_opener.py
import webbrowser
import tempfile
import time
html = "<!doctype html>\n<html>\n<head>\n<title>Hello world!</title>\n</head>\n<body>\nHello world!\n</body>\n</html>"
with tempfile.NamedTemporaryFile("w+", suffix=".html") as fp: #名前付きの一時ファイル作成
    fp.write(html) #書き込み
    fp.seek(0) #先頭に戻す
    webbrowser.open_new_tab("file://"+fp.name)  #新しいタブで開く
    time.sleep(1) #一秒待つ
~~~

webbrowserはブラウザを開く命令を投げるだけで、Webブラウザのロード完了を待ってくれない。
そのため少し待たないとWebブラウザでロードが完了する前に一時ファイルが消える。
そのため、html文字列のサイズや環境によっては、もっと削除までのsleepが必要かもしれません。

htmlをpython上でいじってそのままWebブラウザで表示を確認したいときに便利。　
(だけどもっといい方法があるような気がしなくもない。今後思い付いたら記事にする予定。)

以上。
Seleniumでinstagramのフォロワーを取得したい

instagramをスクレイピングしたいけど、フォロワー取得するにはログインが必要
フォロワーはポップアップウィンドウをスクロールしないと見れない
→なのでSeleniumを使う


Seleniumについてはこちらの[ドキュメント](https://kurozumi.github.io/selenium-python/index.html)を参照

環境
- Python3(3.7系)
- Selenium
- Chromedriver
- beatutifulsoup4(4.7.1以上推奨)

スクリプト(2019年6月確認)

```python3:sample.py
# coding:utf-8

# コマンドライン引数で指定したinstagramerのフォロワーをSeleniumで取得する
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import bs4
import pandas as pd

import time
import random
import sys

def main():
    username = sys.argv[1]
    print("start crawling follower of " + username)

    # chromedriverのファイル場所はよしなに書き換えてください
    driver = webdriver.Chrome('./chromedriver')
    driver.get('https://www.instagram.com/accounts/login/?source=auth_switcher')
    time.sleep(2)

    # login
    id = driver.find_element_by_name("username")
    id.send_keys("YOUR USERNAME")
    password = driver.find_element_by_name("password")
    password.send_keys("YOUR PASSWORD")
    password.send_keys(Keys.RETURN)
    time.sleep(3)

    driver.get('https://www.instagram.com/' + username + '/')
    time.sleep(3)
    follower_button = driver.find_elements_by_css_selector("li.Y8-fY")[1]
    follower_button.click()
    time.sleep(3)

    dialog = driver.find_element_by_css_selector("div.isgrP")

    # scroll popup window
    # 2300人ほどのユーザーが取れる
    for i in range(200):
        driver.execute_script("arguments[0].scrollTop = arguments[0].scrollHeight", dialog)
        time.sleep(random.randint(500,1000)/1000)

    page_url = driver.page_source
    soup = bs4.BeautifulSoup(page_url,"lxml")
    elm = soup.find_all("a", {"class": "FPmhX notranslate _0imsa"})
    followers = []
    for e in elm:
        followers.append(e.text)

    df = pd.Series(followers)
    df.to_csv("insta_followers_of_" + username + ".csv")
    print("csv file is created.")
    driver.close()

if __name__ == '__main__':
    main()
```


sleepを挟んでJSの読み込みを待ってあげないとNo such element exceptionが発生するので、こまめに挟んであげています。
ただしSeleniumの場合はsleepではなくWebDriverWaitの使用が普通のようなので、そちらを使ってもいいと思います。[参考](https://kurozumi.github.io/selenium-python/waits.html)


実行例

```
python sample.py masami_nagasawa
```



ポップアップウィンドウのスクロールは以下のコードで実行しています。
range()の引数でスクロールする回数を設定しています。
200回スクロールして2300人ぐらい取れました.
取得したい人数に応じて数字を調整してください。

```python3
for i in range(200):
        driver.execute_script("arguments[0].scrollTop = arguments[0].scrollHeight", dialog)
        time.sleep(random.randint(500,1000)/1000)
```
【検証忘備録】Retina  3倍Retina

##始めに
ニートから見習いエンジニアに転職して約１ヶ月。
HTML、CSSと格闘する毎日。
そんな中、スマホ用のサイトを構築する事になった時のお話。

##3倍Retina！？

今回スマホ用のサイトを構築するに当たって、要件の一つにRetina対応があった。
Retinaについて調べてみると、3倍Retinaなる物の存在を知り、
どのように違うのか気になったので検証してみた。

###そもそもRetinaとは
>Retinaディスプレイ（英語：Retina Display）は、アップル製品のうち、100〜160ppi程度であった従来のディスプレイ解像度の、およそ倍の解像度、高画素密度のディスプレイを指す名称である。「Retina」（レティナ）は英語で「網膜」という意味で、画素が細かく人間の目で識別できる限界を超えている[1]、ということから命名された。
>
”Retinaディスプレイ”『ウィキペディア (Wikipedia): フリー百科事典』
更新日時：2019年6月6日 (木) 07:11 　URL: http://ja.wikipedia.org

ざっくりと説明すると、画像を描画する点の集まりが今までの倍！
より鮮明に綺麗に表示されるという事。

###ここで疑問が…
通常のRetinaですら人の目で識別できる限界を超えるほど画素が細かいのに、
さらに画素の細かい3倍Retinaは必要なのか…？
他のエンジニア方もあまり気にしていなかったみたい…

###実際にやってみた
今回は先輩のiPhoneXをお借りして検証。
等倍の画像、Retina対応の画像、3倍Retina対応の画像を並べて比較してみた。

<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="html,result" data-user="ShunyaTsukamoto" data-slug-hash="agOqoB" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="agOqoB">
  <span>See the Pen <a href="https://codepen.io/ShunyaTsukamoto/pen/agOqoB/">
  agOqoB</a> by ShunyaTsukamoto (<a href="https://codepen.io/ShunyaTsukamoto">@ShunyaTsukamoto</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

###結果
等倍とRetinaの違いははっきりと確認できるが、
Retinaと3倍Retinaの違いはぱっと見では分からなかった。

強いて言うならば、Retinaと3倍Retinaを拡大、比較した際に、
光の加減が少し違うかもしれないという違いだけだった。

###感想
個人的には今の所3倍Retinaは必要無いように感じた。
ただ、今後要件の上がる事があるかもしれないので
頭の片隅に置いておく事にする。
[Node.js]aws-sdkを利用してDynamoDBを操作する

Node.js環境下のJavaScriptでDynamoDBと接続する方法について、実装の際に少し詰まったのでまとめます。
※2019年6月時点の内容となります。

#環境
Mac、ローカル環境からの接続を想定しています。
プログラムが、AWS上ですでに動いている場合は、IAMロール等での設定が好ましいかと思いますが、今回はその説明は割愛します。
IAMロールを使用した際でも、aws-sdkが優先順位をつけて、良しなに接続を切り替えてくれるのでソースコードの修正は発生しないと思います。

#モジュールのインストール
aws-sdkを用いて接続する為、aws-sdkモジュールをインストールします。

```
npm install --save aws-sdk
```

#DynamoDBへの接続情報を設定
aws-sdkがルート配下の.awsフォルダのcredentialsを参照して、dynamoDBへの接続情報を取得してくれます。
以下の通り、接続情報を設定します。

```
~$ mkdir .aws
~$ cd .aws
.aws $ vi credentials
```

```:credentials
[default]
aws_access_key_id = dynamodbのaccess_key_id
aws_secret_access_key = dynamodbのsecret_access_key
```

dynamodbのアクセスキーとシークレットアクセスキーの取得方法は割愛します。

#実装
実装する際のソースコードサンプルです。
##Serviceの実装
まずはaws-sdkのrequireと各種設定部分を記載します。

```javascript:dynamodb.js
const AWS = require('aws-sdk');
AWS.config.update({region: 'ap-northeast-1'});
const docClient = new AWS.DynamoDB.DocumentClient({apiVersion: '2012-08-10'});

class ServiceDynamoDB {
    ...
}
```

この辺りの記述方法は複数ありますが、一番推奨されていそうなDocumentClientを利用しています。
apiVersionはDynamoDBのバージョンを固定できます。環境に合わせて修正してください。

###DynamoDBの特定のテーブルへのデータの挿入
サービス側の実装ですので、テーブル名やキー項目、データ項目は引数で受け取るようにしています。

```javascript:dynamodb.js
class ServiceDynamoDb {
    static async put_item (table, items) {
        let params = {
            TableName: table, // 格納したいテーブル名
            Item: {
                'id': items.keys.id,
                'sortKey': items.keys.sort_key,
                'data': items.data
            }
        }

        await docClient.put(params, function(err, data) {
            // エラー処理
            if (err) {
                throw new Error(`Failed to save data to DynamoDB. ${err.message}`);
            }
        });
    }
    ...
}
```

###DynamoDBの特定のテーブルへのデータの更新
更新も同様に実装。削除や他の操作は今回やらなかったので割愛します。

```javascript:dynamodb.js
class ServiceDynamoDb {
    ...
    static async update_item (table, items) {
        let params = {
            TableName: table,
            Key: {
              'id' : items.keys.id,,
              'sortKey' : items.keys.sort_key
            },
            UpdateExpression: 'set data = :s',
            ExpressionAttributeValues: {
              ':s' : items.data,
            }
          };

          await docClient.update(params, function(err, data) {
            if (err) {
                throw new Error(`Failed to save data to DynamoDB. ${err.message}`);
            }
        });
    }
}
```

##呼び出し元の実装
作ったサービスを呼び出し、使用してみます。

```javascript:index.js

const DynamoDB = require("ServiceDynamoDb"); // パスはServiceを置いた場所

//データの作成
let items = {
    keys: {
        id: "xxxxxx", 
        sort_key: "xxxxxxx" // id、sort_keyで一意 
    },
    data: "おはようございます"
};
// データの挿入
await DynamoDB.put_item("テーブル名", items);

// データの修正
items.data: "こんにちは"
// データの更新
await DynamoDB.update_item("テーブル名", items);

```

#まとめ
DynamoDBへの接続方法のまとめでした。
色々と接続方法はあると思いますので、接続方法の一例と考えていただければと思います。
draw.io を使ってみた

毎年会社で行なっている恒例行事の3泊4日のプログラミングキャンプで、
まさかの**リーダー**に任命されました。 

彼女にはリーダー向きじゃないのにねって言われました。（確かに...）

プログラミングキャンプで要件を整理する上で`draw.io`を使ってみました。
チームで共有がしやすく、導入が簡単でしたので、投稿してみました。

https://about.draw.io/
<img width="960" alt="スクリーンショット 2019-06-14 15.53.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272551/951a12d1-4269-55d3-b8b1-126c39a1ca32.png">

# 導入方法
[こちら](https://www.draw.io/)にアクセスして、アカウントを設定するだけ。
**無料**なので、導入コストが低いです。

ちなみにデスクトップ用アプリもあります。

# 使用方法

基本的には他のデザインツールと同じように、
左のメニューにある図形を選択して、図などを作成していきます。

<img width="1392" alt="スクリーンショット 2019-06-14 23.16.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272551/a177f40e-2e40-4c9f-202f-b1fe34cd228f.png">

<img width="1391" alt="スクリーンショット 2019-06-14 23.17.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272551/e970293b-a03c-7c86-d436-1f934ce48a80.png">

<img width="1391" alt="スクリーンショット 2019-06-14 23.17.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272551/5f2409cf-4244-b9b0-906e-6617800e8d21.png">

<img width="1391" alt="スクリーンショット 2019-06-14 23.18.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272551/ae8ab19e-747c-d608-e223-5b72b7e2cdb0.png">

左のメニューにある図形は用途に合わせてカスタマイズができます。
何を使うか悩むぐらい種類が豊富です。

![スクリーンショット 2019-06-14 16.33.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272551/8e355f9f-cd63-94b6-9e2e-37bf05229949.png)

テンプレートも豊富です。
まだ駆け出しなので、書き方がわかるテンプレートを参考にできるのは助かりました。

![スクリーンショット 2019-06-14 16.37.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272551/11289722-04ae-0385-bf52-e99d93ed4e46.png)

# 保存方法

保存先も色々選べます。

![スクリーンショット 2019-06-14 16.52.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272551/3fb26ec8-068c-c79d-b303-71b9211cfca9.png)

今回は作成した図をチームに共有したいので、`Googleドライブ`を選択しました。
あとはスプレッドシートなどと同じで、共有できるURLを取得して、URLをチームの人に教えたら共有完了。

もしよかったら、皆さんも触ってみてください。
Vue.jsでdataを初期値に戻す

## 概要
Vueでデータを初期値にリセットする方法です．dataの項目が増えた際に一括で初期値に戻す方法を探した結果，この方法になりました．

## 方法
次のresetメソッドを追加し，呼び出すことでdataの項目がすべて初期値に戻されます．

```js
const app = new Vue({
        el: '#app',

        data: () => ({
            value : 1,
            name : 'hoge',
        }),

        methods: {
            reset : () => {
                Object.assign(app.$data, app.$options.data());
            },
        },
    });
```

## 参考
公式ドキュメント
https://jp.vuejs.org/v2/api/
【Slack】Qiitaでの投稿を自動でSlackに流すようにした時にやったこと

# 概要
社内の知識共有のために，エンジニアが書いたQiitaの記事を自動でSlackに流すようにした話．

### できるようになること
任意のユーザーのQiitaの投稿をSlackに自動で流せる．

# 使うもの
<img width="1072" alt="スクリーンショット 2019-06-14 16.40.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390000/5712aa6f-bedf-cfe8-6f59-0bc09a44b96d.png">
[RSS App](https://slack.com/apps/A0F81R7U7-rss)

# 手順
1. SlackにRSS Appをインストール 
2. 自動で投稿したいQiitaのユーザーを登録
3. 寝て待つ

## 1. SlackにRSS Appをインストール 
Slackに[RSS App](https://slack.com/apps/A0F81R7U7-rss)をインストール
RSSフィードを購読できるようになります．

一般のニュースサイトも購読できるので情報収集に便利．

## 2. 自動で投稿したいQiitaのユーザーを登録
```:slack
/feed subscribe https://qiita.com/USER_NAME/feed
```
`USER_NAME`に任意のユーザー名を入れて，Slackの任意のチャンネルに上のメッセージを送信する．

## 3. 寝て待つ
新規投稿があれば2，3分後くらいに自動でSlackに投稿されます．

Done.

# Happy Hacking :sunglasses: !
Rubyでバイオリンプロットを作る【Plotly】

こんにちは。

IRuby + JupyterLab ユーザー限定ですが、Ruby + Plotly でバイオリンプロットを描くのはとても簡単です。

環境の準備が少し大変ですがどうぞ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/c2383211-1e38-b3e0-c16d-3432de18ecd7.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/f570e444-6239-baed-d3f0-d39b263058a5.png)

## 準備
大前提としてJupyter Lab + IRuby環境が導入されているものとします。IRubyの導入はところどころトラップがありますが、各種Webの情報を参照して、Github master から最新版のインストールすることをおすすめします。
https://github.com/SciRuby/iruby

1. plotly-extensionを導入します。
https://github.com/jupyterlab/jupyter-renderers/tree/master/packages/plotly-extension

2. iruby-plotly をインストールします。
https://github.com/zach-capalbo/iruby-plotly

```bash
gem specific_install https://github.com/zach-capalbo/iruby-plotly
```

## Irisデータセットを使ってバイオリンプロットを試す
Jupyter Labを起動します。
ここでは、拙作の `rdatasets` Gemを使ってIrisデータセットを呼び出しています。

```ruby
require 'rdatasets'
require 'iruby/plotly'
```

```ruby
iris = RDatasets.datasets.iris
iris.head(5)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/f67ea06f-d95a-db5c-4e07-feaa65fbd223.png)

```ruby
species = iris.Species.to_a.uniq
```
["setosa", "versicolor", "virginica"]

```ruby
data = species.map do |sp|
  sepal_length = iris.where(iris["Species"].eq sp)["Sepal.Length"].to_a
  {y: sepal_length, type:"violin", name: sp}
end
```

ここで作られるdataは次のようなオブジェクトです。バイオリンプロットだけ試したい人は、こちらからどうぞ。

```ruby
data = [{:y=>[5.1, 4.9, 4.7, 4.6, 5, 5.4, 4.6, 5, 4.4, 4.9, 5.4, 4.8, 4.8, 4.3, 5.8, 5.7, 5.4, 5.1, 5.7, 5.1, 5.4, 5.1, 4.6, 5.1, 4.8, 5, 5, 5.2, 5.2, 4.7, 4.8, 5.4, 5.2, 5.5, 4.9, 5, 5.5, 4.9, 4.4, 5.1, 5, 4.5, 4.4, 5, 5.1, 4.8, 5.1, 4.6, 5.3, 5],
:type=>"violin",
:name=>"setosa"},

{:y=>[7, 6.4, 6.9, 5.5, 6.5, 5.7, 6.3, 4.9, 6.6, 5.2, 5, 5.9, 6, 6.1, 5.6, 6.7, 5.6, 5.8, 6.2, 5.6, 5.9, 6.1, 6.3, 6.1, 6.4, 6.6, 6.8, 6.7, 6, 5.7, 5.5, 5.5, 5.8, 6, 5.4, 6, 6.7, 6.3, 5.6, 5.5, 5.5, 6.1, 5.8, 5, 5.6, 5.7, 5.7, 6.2, 5.1, 5.7],
:type=>"violin",
:name=>"versicolor"},

{:y=>[6.3, 5.8, 7.1, 6.3, 6.5, 7.6, 4.9, 7.3, 6.7, 7.2, 6.5, 6.4, 6.8, 5.7, 5.8, 6.4, 6.5, 7.7, 7.7, 6, 6.9, 5.6, 7.7, 6.3, 6.7, 7.2, 6.2, 6.1, 6.4, 7.2, 7.4, 7.9, 6.4, 6.3, 6.1, 7.7, 6.3, 6.4, 6, 6.9, 6.7, 6.9, 5.8, 6.8, 6.7, 6.7, 6.3, 6.5, 6.2, 5.9],
:type=>"violin",
:name=>"virginica"}]
```

```ruby
IRuby.plot(
  data,
  title: "Rubyのバイオリンプロット",
  width: 600, height: 600
  )
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/91cf5a4d-d01f-bc6c-7649-f50203f82e88.png)

## おまけ ヒストグラム

```ruby
data = species.map do |sp|
  sepal_length = iris.where(iris["Species"].eq sp)["Sepal.Length"].to_a
  {x: sepal_length, opacity: 0.6, type:"histogram", name: sp}
end

IRuby.plot(
  data,
  title: "Rubyのヒストグラム",
  width: 600, height: 600, barmode: "overlay"
  )
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/a515b86c-3529-c70d-719b-2bb0504c85cf.png)

こんな感じで簡単にグラフを描くことができます。

この記事は以上です。
Amazon Lightsail(Ubuntu)の個人的初期設定（随時加筆）

# 初期ユーザ

- パッケージ類アップデート
- タイムゾーン変更
- 作業用ユーザー作成

```sh
sudo apt-get update
sudo apt-get upgrade
sudo timedatectl set-timezone Asia/Tokyo
sudo adduser kure
sudo usermod -G sudo kure
su - kure
```

# 作業用ユーザー

- SSH用鍵作成
- zshのインストール
- zshの設定
- GitHubへのSSH鍵の登録
- vimの設定

```sh
mkdir .ssh
sudo chmod 700 .ssh/
vim .ssh/authorized_keys
chmod 600 .ssh/authorized_keys
vim .ssh/authorized_keys
sudo apt-get install zsh
chsh -s /usr/bin/zsh
# https://gist.github.com/kuredev/13f0d03dce5619aaf1f86b6412a61fb2
vim ~/.zshrc
ssh-keygen -t rsa
# 表示される公開鍵を登録
cat .ssh/id_rsa.pub
ssh -T git@github.com
# https://gist.github.com/kuredev/7caa60a6ae42974da9c1e2739a109dc9
vi ~/.vimrc
```

# その他リンクメモ

ターミナルでコマンド履歴の入力補完 - Qiita https://qiita.com/hinatades/items/d38be4830191f251935d#zsh

ターミナルのカスタマイズ
Powerlineとlsd
https://qiita.com/kure/items/13da77c6c1dceedff5c5
UnicodeEncodeDecodeError: BOMありUTF-8ファイルの読み込み

# 問題
Pythonでテキストファイルを読み込むために以下のコードを実行した．

```python:readtext.py
f = open('test.txt','r',encoding='utf-8')
line = f.readline()
print(line)
```

そしたら，UnicodeEncodeDecodeErrorが出ました．

```python:UnicodeEncodeDecodeError
"'cp932' codec can't encode character '\ufeff' ..."
```

解決したのでメモしておきます．

# 諸条件
OS: Windows10 Pro
IDE: PyCharm Community 2019.1
Env: Anaconda3
その他：テキストファイルはWindowsのエディタで作成

# 原因
\ufeffはUTF-8テキストの開始を表す文字列だそうで，cp932（Windowsの標準入出力文字コード）にはないので，エンコーダーが困ってしまっちゃったようです．よしよし．
ちなみにこのエンコーダーは，unicode文字列をwindowsに書き出したりするときに自動でcp932に変換してくれるらしいです．親切が裏目にでちゃったんだね．よしよし．

# 解決策
ファイルを開く時に，\ufeff付きのUTF-8テキストであることを教えてあげるとうまくいきました．ちなみに\ufeff付きのファイルをBOMありUTF-8っていうらしいです．

```readtext2.py
f = open('text.txt','r',encoding='utf-u-sig') # BOMありUTF-8
line = f.readline()
print(line)
```

めでたしめでたし．

# その他
以下の情報のおかげで無事に問題を解決することができました．どうもありがとうございます．

1. [(Windows) Python3でのUnicodeEncodeErrorの原因と回避方法](https://qiita.com/butada/items/33db39ced989c2ebf644)
2. [\ufeffって？？？](https://qiita.com/msk02/items/c3a1c4a1e1ef94c37228)
JavaScript voidってなんぞや？

qiita初投稿ですよろしくお願いします。

# 発端

なんとなくtypescriptのコンパイル結果を見ていた時のこと、<br>
デフォルト引数を指定した関数で見慣れない表記が

ソース

```ts
const fn = (arg : string, opt : string = "initial") => 
    console.log(`arg: ${arg}, option: ${opt}`)
```

コンパイル後

```Javascript
var fn = function (arg, option) {
    if (option === void 0) { option = ""; }
    return console.log("arg: " + arg + ", option: " + option);
};
```

んんん。。。？

>void 0

おまえだれや。。。？

# 調べてみる

まずコンパイル後のjsファイルなのでtypescriptのvoid型とは関係なさそう？

ということでmozillaのjsリファレンスを見てみる。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/void

なるほど、どうやらこいつの正体は演算子。

受け取った式を実行後undefinedを返してくれるみたいですね。

## option === undefined でいいんじゃね？
これ

>option === undefined

やればいいだけなのに遠回りなのでは？と思ってた僕はまだ甘かったです。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/undefined


>undefined は、グローバルオブジェクトのプロパティであり、すなわちグローバルスコープ内の変数です。>undefined の初期値はプリミティブ値である undefined です。

>モダンブラウザ (JavaScript 1.8.5 / Firefox 4 以降) での undefined は、ECMAScript 5 仕様により、設定不可、書込不可のプロパティとなります。そうでない場合でも、上書きは避けてください。


つまり環境によってはプロパティundefinedはプリミティブ値のundefinedではない可能性があるので
それをケアしてるんですね。

とはいえこれのうまい使いどころあんまり思いつかないですね。。。

リファレンス内サンプルだと

``` HTML
<a href="javascript:void(0);">
  Click here to do nothing
</a>
```

のようにページ遷移しないよう,hrefを上書きしてたりでした。

# おわり
コンパイル後の吐き出されたjs追っかけてみるといろいろ気づきがあって面白かったです。

これ以外にも見慣れない記述があったので後に記事にできたらなぁ、と思います。

最後までお読みいただきありがとうございました！
メモ: Axiosでトークン認証を絡めたリトライがやりたい

# is何
Axiosでトークン認証つきのリクエストを送って、認証エラーで弾かれたらトークンを新規取得 or 生成した上でリトライしたい
という処理をどのように実装したかのメモ。

# どうするの
### リトライ処理
リトライ処理自体はそんなに難しくない。
というのも、エラーレスポンスの中にリクエスト設定`config`が丸々入っているので、それを使って再リクエストしてやればいい。

```js
axios
  .get("https://hogehoge/member_contents/", {
    headers: {
      Authorization: "Bearer: xxxxxxxxxx"
    }
  })
  .catch(async err => await retryHandler(err));

const retryHandler = async err => {
  // 再リクエストを発火
  return await axios(err.config);
};
```

### トークン再取得の処理を挟む
そこで、`catch`内でaxiosを実行してやる前に、トークンを取得する処理を行う。

```js
axios
  .get("https://hogehoge/member_contents/", {
    headers: {
      Authorization: "Bearer: xxxxxxxxxx"
    }
  })
  .catch(async err => await retryHandler(err));

const retryHandler = async err => {
  // トークンを再取得する
  const res = await axios.get("https://hogehoge/get_token");
  // config内のトークンを書き換える
  err.config.headers.Authorization = `Bearer: ${res.data.token}`;
  // 再リクエストを発火
  return await axios(err.config);
};
```

## おまけ：複数同時リクエストに対応する
トークンを必要とするリクエストが走るのは最大で同時に1つだけ、というのなら上の実装でいいが、
例えばこのようにトークン認証を使ったリクエストが複数走るとなるとちょっとまたコードを変更する必要がある。

```js
let token = "xxxxxxxxxxxx";

axios.get("http://hogehoge/member_contents/1", {
  headers: {
    Authorization: `Bearer: ${token}`
  }
}).catch(async err => await retryHandler(err));

axios.get("http://hogehoge/member_contents/2", {
  headers: {
    Authorization: `Bearer: ${token}`
  }
}).catch(async err => await retryHandler(err));
```

というのも、この処理だと同時に2つのリクエストに対して再認証を要求するため、
retryHandlerが2回走る ＝ トークンを2回発行するというよくない感じの処理になっている。
というわけで、

- 2回目のretryHandlerでは1回目の処理が終了するまで待つ
- トークンは常に最新のものを使う

といった処理が必要になる。それを踏まえて書き直した処理がこちら。

```js
let token = "xxxxxxxxxxxx";
let isFetchingToken = false;

// 遅延処理用のウェイト処理
const wait = (ms) => new Promise(resolve => setTimeout(ms, resolve));

axios.get("http://hogehoge/member_contents/1", {
  headers: {
    Authorization: `Bearer: ${token}`
  }
}).catch(async err => await retryHandler(err));

axios.get("http://hogehoge/member_contents/2", {
  headers: {
    Authorization: `Bearer: ${token}`
  }
}).catch(async err => await retryHandler(err));

const retryHandler = async err => {
  // トークン取得中なら遅延して再び同じ処理を繰り返す
  if (isFetchingToken) {
    await wait(500);
    return await retryHandler(err);
  }

  // 失敗したリクエストのトークンと最新トークンが同一なら再取得
  if (err.config.headers.Authorization === token) {
    isFetchingToken = true;
    // トークンを再取得して最新トークンを更新
    const res = await axios.get("https://hogehoge/get_token");
    token = res.data.token;
    isFetchingToken = false;
  }
  // config内のトークンを最新トークンに書き換える
  err.config.headers.Authorization = `Bearer: ${token}`;
  // 再リクエストを発火
  return await axios(err.config);
};
```

- 失敗したリクエストに用いたトークンと、最後に取得したトークンが同一なら再取得し、違うならトークンは並列実行中の他のリトライ処理で更新したとみなしてそれを使う。
- すでにトークン取得中のフラグが立っていれば遅延ループさせてトークン取得終了を待つ。

といったちょっとした~~ややこしい~~処理を挟むことで余計なトークン再発行を防ぐことができる。
CakePHP Model の拡張方法

`bake model all` で生成したファイルを直接編集することもできますが、この方法だと `Model/Entity` や `Model/Table` に加えた変更内容を毎回戻す必要があります。

次の方法は、継承クラスを用意することで、bake の影響を受けません。
なお、ディレクトリの階層は、同じ階層が良いです。

## 例：Users

source/htdocs/app/src/Model/Entity/ExtendedUser.php

```php
namespace App\Model\Entity;

use Authentication\PasswordHasher\DefaultPasswordHasher;

class ExtendedUser extends User
{
    /**
     * @param $password
     *
     * @return bool|null|string
     */
    protected function _setPassword($password)
    {
        if ($password === null || $password === '') {
            return null;
        }

        return (new DefaultPasswordHasher())->hash($this->password);
    }
}
```

source/htdocs/app/src/Model/Table/ExtendedUsersTable.php

```php
namespace App\Model\Table;

class ExtendUsersTable extends UsersTable
{
    public function __construct(array $config = [])
    {
        $config['entityClass'] = \App\Model\Entity\ExtendedUser::class;
        parent::__construct($config);
    }
}
```

source/htdocs/app/src/Controller/AppController.php
`initialize()`

```php
        $tableLocator = TableRegistry::getTableLocator();
        $tableLocator->setConfig('Users', ['className' => \App\Model\Table\ExtendUsersTable::class]);
```