OmniAICreator/Qiita-1.07M huggingface dataset:
【Devise】アカウント登録、ログイン/ ログアウト、アカウント編集後のリダイレクト先の変更

#はじめに

Deviseのインストール時、アカウント登録後などのリダイレクト先は自動的に指定されます。

このデフォルトのリダイレクト先を変更するためには、コントローラをカスタマイズする必要があります。

①コントローラを作成し、ルーティングを変更する
②作成したコントローラで、メソッドを定義する
という流れで実装します。
※②で紹介するメソッドをapp/controllers/applictaion_controller.rbで定義するだけでもリダイレクト先を変えることはできます。しかし、今後似たようなメソッドを定義していくとapplictaion_controllerが肥大化してしまいます。それを防ぐためにも今回は、
『メソッドはなるべく個々のコントローラで定義し、複数のコントローラで使い回すメソッドのみapplication_controllerで定義する』
という方針にします。

#実行環境
この記事は以下の環境で動作確認しています。
ruby (2.3.7)
rails (5.2.3)
devise (4.6.2)

#①.コントローラ作成、ルーティング設定

ターミナルなどで以下のコマンドを実行

```sh
$ rails g devise:controllers users
```

これで、registration_controller, sessions_controller,.....などのコントローラがapp/controllers/usersの下に作成されます。 
ここで作成されたコントローラを編集することでリダイレクト先を変更します。

ちなみに、先程作成したコントローラは、deviseで設定されているコントローラクラスを継承しています。したがって、deviseでもともと設定されているメソッドもすべて利用できます。

```app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
```

と記述されていることからも、継承されていることがわかります。

rails routes コマンドを実行すると

```sh
Prefix Verb     URI Pattern         Controller#Action
new_user_session GET      /users/sign_in(.:format)             devise/sessions#new
user_session POST   　　  /users/sign_in(.:format)    　       devise/sessions#create
・・・
new_user_registration GET      /users/sign_up(.:format)        devise/registrations#new
```

のように表示されると思います。
このように、Controller#Actionが devise/registrations,devise/sessionsになっていると、これから定義するメソッドが反映されません。



```config/routes.rb
devise_for :users, controllers: {   registrations: 'users/registrations',
                                    sessions: 'users/sessions' }
```

と設定すれば、

```sh
Prefix Verb     URI Pattern         Controller#Action
new_user_session GET      /users/sign_in(.:format)              users/sessions#new
user_session POST         /users/sign_in(.:format)              users/sessions#create
・・・
new_user_registration GET      /users/sign_up(.:format)         users/registrations#new
```

となり、コントローラのカスタマイズが反映されるようになります。

#②. メソッド定義
・アカウント登録後
・アカウント編集後
のリダイレクト先を指定する場合、

```app/controllers/users/registrations_controller.rb
#アカウント登録後のリダイレクト先
def after_sign_up_path_for(resource)
  リダイレクト先のパス(root_pathとかusers_pathとか)
end

#アカウント編集後のリダイレクト先
def after_update_path_for(resource)
  リダイレクト先のパス
end
```

上記を追加します。

※リダイレクト先のパスを users_path(resource) とすると、登録後にユーザーの個人ページにリダイレクトされるようになります。

※ユーザー登録にメール認証を導入してくれる confirmableモジュール を有効にしている場合は、
after_sign_up_path_for ではなく after_inactive_sign_up_path_for と書いてください。登録直後はアカウントがまだ有効になっていないからです。

・ログイン後
・ログアウト後
のリダイレクト先を指定する場合、

```app/controllers/users/sessions_controller.rb
#ログイン後のリダイレクト先
def after_sign_in_path_for(resource)
  リダイレクト先のパス
end 
#ログアウト後のリダイレクト先
def after_sign_out_path_for(resource)
  リダイレクト先のパス
end 
```

上記を追加します。
Vim/NeovimにALEをインストールすると追加されるALEコマンド(抜粋)

ALE(Asynchronous Lint Engine)はvim/neovim上でプログラムのコードチェックをいい感じにやってくれるプラグインです。

みなさん便利なキーマップなどゴリゴリ設定していると思いますが、私のような手抜きvimmerはなるべくデフォルトの機能でどうにかしたいです。OSのクリップボードへコードをコピーするため、ALEを停止する方法を調べたところ行き当たったのでメモとしてピックアップしました。

インストールや設定方法は次のページなどをご参照ください。
「NeovimでモダンなPython環境を構築する」
https://qiita.com/lighttiger2505/items/e0ada17634516c081ee7

※※「おい何言ってるんだ、普通はこうするんだ！」など、ご指摘ありましたらコメントください※※

## ALEをインストールすると追加されるALE標準コマンド(抜粋)
|コマンド |機能 |
|---|---|
|:ALEEnable |ALEをオンにする |
|:ALEDisable |ALEをオフにする |
|:ALEToggle |ALEのオフ/オフを切り替える |
|:ALEFirst |先頭のハイライトへ移動する |
|:ALELast |一番後ろのハイライトへ移動する |
|:ALENext |次のハイライトへ移動する |
|:ALENextWrap |次のハイライトへ移動する<br />(最後まで行くと最初からループ) |
|:ALEPrevious |前のハイライトへ移動する |
|:ALEPreviousWrap |前のハイライトへ移動する<br />(最後まで行くと最初からループ) |
|:ALEDetail |(カーソル位置の) エラーの詳細を別バッファに表示する |
|:ALEFix |(カーソル位置の) 自動修正を実行する |

## ハイライト移動系コマンドのオプション

ALEFirstやALELast、ALENextやALEPreviousなどはオプションをとることでジャンプするエラーの種類や挙動を指定できます（各オプションは複数指定も可能です）。

|オプション |機能 |
|---|---|
|-wrap |最後まで行くと最初からループ |
|-error |errorのハイライトを対象にして移動 |
|-warning |warningのハイライトを対象にして移動 |
|-style |style error/warningのハイライトを対象にして移動 |

## もっと知りたい人は

他にもたくさんのALEコマンドが公式のdocに紹介されています。
https://github.com/dense-analysis/ale/blob/master/doc/ale.txt
【React/TypeScript】onClickなどのイベント処理で要素ごとに引数を渡したい場合

Reactでリストなどを実装する際などに、クリックされた要素に応じて処理を変えたいなどのケースに遭遇します。
以下の例においてhandleClickにおいて、クリックされた要素に関数情報が欲しい、といった状況です。

```react:App.tsx
const App: React.FC = () => {
  const handleOnClick = () => {
    // クリックされた要素に応じた処理を行う。
  };
  return (
    <div className="App">
      <ul>
        {["dog", "cat", "rabbit"].map(v => (
          <li onClick={handleOnClick} key={v}>
            {v}
          </li>
        ))}
      </ul>
    </div>
  );
};
```

以下の記事において、イベント処理に引数を渡す際、主に３つのアプローチが取れるということがまとめられています。投稿者の方に感謝申し上げます。

https://qiita.com/tsuuuuu_san/items/73747c8b6e6e28f6bd23

今回はこちらの記事を参考に、要素ごとに異なる引数を渡したいというケースに絞り、自分が調べた内容を追加しつつ、React/TypeScriptで実装するサンプルを載せていきます。



```:検証環境のバージョン
"react": "^16.9.0",
"typescript": "3.5.3"
```


## コールバックにアロー関数を渡す
もっともポピュラーな解決策として、onClickにアロー関数を渡すという実装方法があります。

```react:App.tsx
const App: React.FC = () => {
  const handleOnClick = (v: string) => {
    console.log(v);
  };
  return (
    <div className="App">
      <ul>
        {["dog", "cat", "rabbit"].map(v => (
          <li onClick={() => handleOnClick(v)} key={v}>
            {v}
          </li>
        ))}
      </ul>
    </div>
  );
};
```
直感的かつ実装が用意なので、もっとも見かけることの多い実装方法でした。
ただ[公式のイベント処理に関するドキュメント](https://ja.reactjs.org/docs/handling-events.html)でも語られていますが、レンダリングのたびに関数が生成されることから、パフォーマンスを気にするような状況においては注意が必要となりそうです。

## ~~bindを使う~~
TypeScriptを使わない場合であれば、以下のようにbindを使って引数を増やすという手段もあります。

```react:App.jsx
const App = () => {
  const handleOnClick = (v, e) => {
    console.log(v);
  };
  return (
    <div className="App">
      <ul>
        {["dog", "cat", "rabbit"].map(v => (
          <li onClick={handleOnClick.bind(this, v)} key={v}>
            {v}
          </li>
        ))}
      </ul>
    </div>
  );
};
```

ただ自分ではTypeScriptのレールに乗りつつ、適切な実装方法を見つけることができませんでした。
TypeScriptでbindを使うこと自体が個人的には怖いので、bindを使う方法については__採用しない__方針としました。

## HTMLElementの属性から値を取得する
イベントを受け取った側で、イベント内のHTML要素から値を取得するという手段もあります。

```react:App.tsx
const App: React.FC = () => {
  const handleOnClick = (e: React.MouseEvent<HTMLElement>) => {
    console.log(e.currentTarget.dataset.item);
  };
  return (
    <div className="App">
      <ul>
        {["dog", "cat", "rabbit"].map(v => (
          <li onClick={handleOnClick} key={v} data-item={v}>
            {v}
          </li>
        ))}
      </ul>
    </div>
  );
};
```

datasetだけではなく、getAttributeを使って任意の要素の値を取得することも可能です。

```react:App.tsx
const App: React.FC = () => {
  const handleOnClick = (e: React.MouseEvent<HTMLElement>) => {
    console.log(e.currentTarget.getAttribute("data-item"));
  };
  return (
    <div className="App">
      <ul>
        {["dog", "cat", "rabbit"].map(v => (
          <li onClick={handleOnClick} key={v} data-item={v}>
            {v}
          </li>
        ))}
      </ul>
    </div>
  );
};
```

datasetを使った場合は戻り値がstring | undefined
getAttributeを使った場合は戻り値がstring | null

という差異がありました。
パフォーマンスの面におけるコールバック渡しとの優劣は現状つけられていませんが、比較的腑に落ちやすい実装方法に感じました。

## まとめ
具体的なベストな手法を確定できていませんが、同様の課題に取り組んでいる方の参考に少しでもなれば幸いです。
閲覧ありがとうございました。
二項係数についての等式

```math
\def\bi(#1,#2){{}_{#1}\!\mathrm{C}_{#2}}
\def\fraction(#1/#2){\frac{#1}{#2}}
```
#二項係数
二項係数は，次のように定義しておく。

```math
\bi(a,b) := \fraction(a!/{(a-b)!b!})
\qquad 
(a \geq b) 
```

##二項係数の和

```math
\bi(n,0) + \bi(n,1) + \bi(n,2) + \bi(n,3) + \cdots + \bi(n,n)
=
2^n
```


```math
\bi(n,0) - \bi(n,1) + \bi(n,2) - \bi(n,3) + \cdots (-1)^n \bi(n,n)
=
0
```

つまり

```math
\sum_{k=0}^n \bi(n,k) =2^n
\\
\sum_{k=0}^n (-1)^k \bi(n,k) =0 
```

証明

```math
\begin{eqnarray}
(1+x)^n = \sum_{k=0}^n \bi(n,k) x^k
\end{eqnarray}
```

両辺のxに1を代入して，証明終了。



```math
\begin{eqnarray}
(1-x)^n = \sum_{k=0}^n \bi(n,k) (-1)^k x^k
\end{eqnarray}
```

両辺のxに1を代入して，証明終了。

帰納法による証明
「ただいま編集中」


## 係数つき二項係数

$$
\sum _{k=1}^n k \bi(n,k) = 2^{n-1} n
$$

$$
\sum_{k=1}^{n-1} (-1)^k k \bi(n,k) = (-1)^n (-n)
$$

直接的な証明

```math
\begin{eqnarray}
k \bi(n,k)
&=&
k \fraction(n!/{(n-k)! k!})\\
&=& \fraction(n!/{(n-k)! (k-1)!}) \\
&=& n\fraction({(n-1)!}/{(n-1-[k-1])! (k-1)!}) \\
&=& n \bi(n-1,k-1) \\
\end{eqnarray}
```

```math
\begin{eqnarray}
\sum _{k=1}^n k \bi(n,k) 
&=& \sum _{k=1}^n \bi(n-1,k-1) n \\
&=& 2^{n-1} n
\end{eqnarray}
```

```math
\begin{eqnarray}
\sum _{k=1}^n (-1)^k k \bi(n,k) 
&=& \sum _{k=1}^n (-1)^k \bi(n-1,k-1) n \\
&=& 0
\end{eqnarray}
```

```math
\sum _{k=1}^{n-1} (-1)^k k \bi(n,k) = - (-1)^{n} n \bi(n,n)
```

より示せた。



######多項式を微分する証明

```math
\begin{eqnarray}
(1-x)^n = \sum_{k=0}^n \bi(n,k) (-1)^k x^k
\end{eqnarray}
```

両辺をxで微分して

```math
\begin{eqnarray}
-n (1-x)^{n-1} = \sum_{k=1}^n k \cdot \bi(n,k) (-1)^k x^{k-1}
\end{eqnarray}
```

1 を代入する

```math
\begin{eqnarray}
0 &=& \sum_{k=1}^n k \bi(n,k) (-1)^k
\\
\sum_{k=1}^{n-1} k \bi(n,k) (-1)^k &=& - n \bi(n,n)(-1)^n
\end{eqnarray}
```

和をとる範囲に注意して頂きたい。

##二項係数の積の和
次のような和を考える。右辺は計算結果。

```math
-\bi(2,1)
=
-2
```


```math
-\bi(3,1) + \bi(3,2)\bi(2,1)
=
3
```

```math
-\bi(4,1) + \bi(4,2)\bi(2,1) + \bi(4,3)\bi(3,1) - \bi(4,3)\bi(3,2)\bi(2,1)
=
-4
```

```math
\begin{eqnarray}
&&-\bi(5,1)
\\
&&+ \bi(5,2)\bi(2,1) + \bi(5,3)\bi(3,1) + \bi(5,4)\bi(4,1)
\\
&&- \bi(5,3)\bi(3,2)\bi(2,1) - \bi(5,4)\bi(4,3)\bi(3,1) - \bi(5,4)\bi(4,2)\bi(2,1)
\\
&&+ \bi(5,4)\bi(4,3)\bi(3,2)\bi(2,1)
\\
&&=5
\end{eqnarray}
```

うまく表記することが難しいが，$k\geq 2$に対して一般に次のような等式が成立する

```math
\begin{eqnarray}
&&-\bi(k,1)\\
&&+ \bi(k,2)\bi(2,1) + \bi(k,3)\bi(3,1) +\cdots  +\bi(k,k-1)\bi(k-1,1)\\
&&\vdots \\
&& + (-1)^j \sum_{a_1-a_j = k-1, a1 > a_2 > \cdots > a_j} \prod _{i=1}^j \bi(a_i,a_{i-1})
\\
&& \vdots\\ 
&&+ (-1)^{k-1} \bi(k,k-1)\bi(k-1,k-2) \cdots \bi(2,1)\\
&&=(-1)^k (-k)
\end{eqnarray}
```

証明は帰納法で行う。表記が煩雑になるので，記号を導入する。

```math
\begin{eqnarray}
S_k
&:=&-\bi(k,1)\\
&&+ \bi(k,2)\bi(2,1) + \bi(k,3)\bi(3,1) +\cdots  +\bi(k,k-1)\bi(k-1,1)\\
&&\vdots \\
&& + (-1)^j \sum_{a_1-a_j = k-1, a1 > a_2 > \cdots > a_j} \prod _{i=1}^j \bi(a_i,a_{i-1})
\\
&& \vdots\\ 
&&+ (-1)^{k-1} \bi(k,k-1)\bi(k-1,k-2) \cdots \bi(2,1)\\
&&=(-1)^k (-k)
\end{eqnarray}
```

S_1, S_2,... ,S_kで成立していると仮定。

```math
\begin{eqnarray}
S_{k+1}
&=&-\bi(k+1,1)\\
&&- \bi(k+1,k) S_k\\
&&- \bi(k+1,k-1) S_{k-1}\\
&&\vdots \\
&& - \bi(k+1,1) S_2\\

&&= \sum_{j=1}^k \bi(k+1,j) (-1)^j (-j)
\\
&&= (-1)^{k+1}(k+1) 
\end{eqnarray}
```
cuDNN で  CUDNN_STATUS_INTERNAL_ERROR が出たときの問題解決

## 問題

TensorFlow とか, 自前コードで cuDNN で `CUDNN_STATUS_INTERNAL_ERROR` が出る.

## 原因

だいたいにおいては, CUDA とのバージョンのミスマッチや, 古かったり異なる cuDNN のバージョンの .so にリンクしているのが起因している.


## 対処方法

まずは `ldd` で古い `libcudnn.so` とリンクしていないか確認します.

`cuDNN-sample` をコンパイルして動かして正常に動くか確認しましょう.

https://github.com/Hardware-Alchemy/cuDNN-sample

### それでもダメなときは...

今の所 CUDA/cuDNN のバージョン間違い以外で遭遇したことはないため... ハードウェアの故障の可能性があるかも?
(dmesg で XID エラーが出ていないか確認しましょう https://docs.nvidia.com/deploy/xid-errors/index.html )
ARKitでラファエルになる


メモとして残しておく。
できるだけコピペで動くようにしておく

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">やった！！<br>自分もラファエルになれた！！！ <a href="https://t.co/bp3EIajxPm">pic.twitter.com/bp3EIajxPm</a></p>&mdash; shogo.yamada@Flutterマン (@yshogo87) <a href="https://twitter.com/yshogo87/status/1165513089187336192?ref_src=twsrc%5Etfw">August 25, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

```swift

import UIKit
import SceneKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate {
    
    @IBOutlet var sceneView: ARSCNView!
    private var faceGeometory: ARSCNFaceGeometry!
    private var faceNode: SCNNode!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        sceneView.delegate = self
        sceneView.showsStatistics = true
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        guard ARFaceTrackingConfiguration.isSupported else { return }
        guard let device = sceneView.device else { return }
        
        faceGeometory = ARSCNFaceGeometry(device: device)
        
        if let material = faceGeometory.firstMaterial {
            material.diffuse.contents = UIColor.white
            material.lightingModel = .physicallyBased
        }
        faceNode = SCNNode(geometry: faceGeometory)
        let configuration = ARFaceTrackingConfiguration()
        configuration.isLightEstimationEnabled = true
        sceneView.session.run(configuration)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        sceneView.session.pause()
    }
    
    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        guard let faceAnchor = anchor as? ARFaceAnchor else { return  }
        faceGeometory.update(from: faceAnchor.geometry)
        node.addChildNode(faceNode)
    }
    
    func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
        guard let faceAnchor = anchor as? ARFaceAnchor else { return  }
        faceGeometory.update(from: faceAnchor.geometry)
    }
    
}

```
Puppeteerが原理主義すぎるのでラッパーモジュールを育てている話

## Puppeteerの不思議な（不親切な？）挙動

Puppeteerで要素が可視状態になるまで待ちたいとき、次のように記述できます。

```js
page.waitForSelector('#myId', {visible: true})
```

しかし、このノリで何でも取り出せると思うとハマることがあるので注意が必要です。具体的には次のようなHTMLに対して

```html
<div style="visibility:hidden">foo</div>
<div>bar</div>
<div>baz</div>
```

Puppeteerで次のように記述したとしましょう。

```js
page.waitForSelector('div', {visible: true})
```

これで`<div>bar</div>`が帰ってくるかと思いきや、これは期待通りに動きません。

実際には`<div style="visibility:hidden">foo</div>`がvisibleになるのを待ってしまってタイムアウトします。

## どういうことか？

上記はPuppeteerの仕様です。これをバグとしてPRを投げた偉い人がいるんですが、Puppeteerの作者に却下されています。

- [fix: waitForSelector with visible:true causes timeout by razorman8669 · Pull Request \#4373 · GoogleChrome/puppeteer](https://github.com/GoogleChrome/puppeteer/pull/4373)

作者によれば、「CSSセレクタとオプションの組み合わせで要素を指定するのはよくない、排他的に要素を限定するようなCSSセレクタを書くべきだ、PuppeteerのAPIはそういうポリシーで作っている」とのことです。

## 自分でラッパーモジュールを作ろう

作者のポリシーはわかるけど僕はルーズに書きたいんですよね…。

Puppeteer本体のAPIでは今後も便利関数は却下されそうなので、ルーズに書きたい人は自分専用のラッパーモジュールを育てていくのがいいと思います。

ちなみにPuppeteerではAPIの機能追加がしやすいように全APIが1ファイルからアクセス可能になっており、次のように簡単に機能追加できます。

```js
const {ElementHandle} = require('puppeteer/lib/api');

ElementHandle.prototype.isVisible = async function () {
  return (await this.boundingBox() !== null);
}
```

こうすれば`ElementHandle`に`.isVisible()`が増やせます。

最初の例であれば、私なら次のように書きます（意味は変わってしまいますが目的は達成できるのではないでしょうか）。

```javascript
  await page.waitForSelector('div');
  visibleDivs = await page.$$('div').then(
    els => asyncFilter(els, el => el.isVisible())
  );
  // visibleDivsが0個ならビジーループ、1個以上なら処理継続
```

上記コード中の`asyncFilter()`は「[JavaScriptで配列のfilterにasync関数を使いたい \- Qiita](https://qiita.com/hnw/items/f104a1079906fc5c2a96)」で紹介したものです。

# 参考URL

ちなみに私が作っているラッパーはnpmで公開しています。上のメソッド以外にも私が便利だと思った関数を追加しています。参考にして頂ければ幸いです。

 - [@hnw/puppeteer\-customized \- npm](https://www.npmjs.com/package/@hnw/puppeteer-customized)
ARKitで使うためのsncファイルを読み込み

メモとして残しておく


```swift
    private let sampeTest: SCNReferenceNode? = {
        let path = Bundle.main.path(forResource: "overlayModel", ofType: "scn")!
        let url = URL(fileURLWithPath: path)
        return SCNReferenceNode(url: url)
    }()
```
C++11 variant-lite(std::variant の backport) を使う

## 背景

* 計算グラフの評価や, AST(abstract syntax tree)の処理を C++ でやりたい. コンパイラの作成とか機械学習とか, ノードベースのシステムとか(シェーダとかアニメーションとか)
* Python とかだと簡単にかけるけど, C++ は型があるので面倒ね
* クラスを継承というのが C++ では王道かもだけど, golang とかにみられるようなインターフェイスベースの仕組みが昨今は流行りのようだしコードもスッキリするような?(多重継承のあるクラスだとソースコードを追うのがめんどい)
  * 継承ベースだと, 性能が気になります(vtable のコストはどれくらいかしら?)

C++17 から, std::variant が導入されました.

https://en.cppreference.com/w/cpp/utility/variant
型セーフな Union を表現できます.
テンプレートベースな実装(のはず)ので, 性能の点からは問題なさそうです!

AST などの処理したいひとむけに Visitor パターンを実現できる std::visit も用意されています.
ありがとうございます.

標準に入ったということは, それなりに需要があったということでしょう.

## variant-lite

C++17 コンパイラはまだまだ広く普及してはいませんので, ここでは
C++11 コンパイラでも使える martinmoene 先生の variant-lite を使います.

https://github.com/martinmoene/variant-lite

variant-lite の主な制約は以下になります.

* 型は 7 個まで(このあたり必要であれば generator script を改変して増やすことができる)
* nonstd::visit では const 修飾された変数しか扱えない(visit して中身を更新はできない)
  * visit して内部ステートをアップデートしたいときは, 自前で visit 相当を書く必要があります(か, C++17 を使う).

## 利用サンプル

以下のようにテンプレート引数に扱いたい型を列挙します.

```c++
#include "nonstd/variant.hpp"

#include <string>
#include <iostream>

class Muda
{
 public:
  Muda() {}
  ~Muda() {}

  std::string speak() { return "muda muda muda"; }
};

class Bora
{
 public:
  Bora() {}
  ~Bora() {}

  std::string speak() { return "bora bora bora"; }
};

int main(int argc, char **argv)
{

  using op_t = nonstd::variant<Muda, Dora>;

  op_t op = Muda();

  struct SpeakVisitor {
    std::string operator()(const Muda &v) const { return v.speak(); }
    std::string operator()(const Bora &v) const { return v.speak(); }
  };

  std::cout << std::visit(SpeakVisitor(), op) << "\n";
```

## 変数がどの型か調べる.

`std::is_same` で行けそうですが, どうもややこしいテンプレートを書かないとダメそうかも...?

`index_of` で型に対して番号を取得できるので, とりあえずは `index_of` メソッドで判定するのがコードもわかりやすくなってよさそうです.
  
variant-lite のソースコードより

```c++
CASE("index_of<>(): method should be static" "[.issue-30]")
{
#if variant_CPP11_OR_GREATER && ! variant_USES_STD_VARIANT
    typedef variant<int, double, std::string> Value;
    Value value("Some string");

    switch ( value.index() )
    {
    case Value::index_of<int>():
        // do something
        break;
    case Value::index_of<double>():
        // do something
        break;
    case Value::index_of<std::string>():
        // do something
        break;
    }

    EXPECT( !!"prevent warnings" );
#else
    EXPECT( !!"index_of<>(): test is not available (no C++11, or std::variant)" );
#endif
}
```

## Mapbox variant

Mapbox variant では, 再帰を扱うことができますので, mapbox variant もご検討ください.

https://github.com/mapbox/variant
testコマンドでワイルドカードを含むpathを評価したい

# 検証環境
- Windows10 Pro 1903
- WSL(Ubuntu)
- bash 4.4.20

```bash
root@mycomputer:~# bash --version
GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
root@mycomputer:~#
```

# 検証
ワイルドカードをtestに渡すと、（そのpathで表せるファイルなどが存在する場合は）エラーになる

```bash
root@mycomputer:~# ll /tmp/{hoge,fuga}/*
-rw-rw-rw- 1 root root 0 Aug 24 23:13 /tmp/fuga/1.log
-rw-rw-rw- 1 root root 0 Aug 24 23:13 /tmp/fuga/2.log
-rw-rw-rw- 1 root root 0 Aug 24 23:13 /tmp/hoge/1.log
-rw-rw-rw- 1 root root 0 Aug 24 23:13 /tmp/hoge/2.log
-rw-rw-rw- 1 root root 0 Aug 24 23:13 /tmp/hoge/3.log
root@mycomputer:~#
root@mycomputer:~# [ -f /tmp/fuga/*.log ] ; echo $? # binary operator expectedエラー
-bash: [: /tmp/fuga/1.log: binary operator expected
2
root@mycomputer:~#

# 余談だが、全く存在しないpathであればtestできる
root@mycomputer:~# [ -f /tmp/fuga/*.txt ] ; echo $? 
1
root@mycomputer:~#
```

ワイルドカードを含むpathをtestしたい時はfor文を使う。forの変数（以下例の場合target）にはワイルドカードが展開された後の値が格納されるので、testの評価対象がワイルドカードを含まなくなり、エラーが出ない。

```bash
root@mycomputer:~# ll /tmp/{hoge,fuga}/*
-rw-rw-rw- 1 root root 0 Aug 24 23:13 /tmp/fuga/1.log
-rw-rw-rw- 1 root root 0 Aug 24 23:13 /tmp/fuga/2.log
-rw-rw-rw- 1 root root 0 Aug 24 23:13 /tmp/hoge/1.log
-rw-rw-rw- 1 root root 0 Aug 24 23:13 /tmp/hoge/2.log
-rw-rw-rw- 1 root root 0 Aug 24 23:13 /tmp/hoge/3.log
root@mycomputer:~#
root@mycomputer:~# target_arr=(
>   "/tmp/hoge/?.log"
>   "/tmp/fuga/*.log"
>   "/tmp/fuga/*.txt"
> )
root@mycomputer:~# for target in ${target_arr[@]} ; do
>   echo ${target}
>   [ -f ${target} ] ; echo $?
> done
/tmp/hoge/1.log # /tmp/hoge/?.log の1つ目
0
/tmp/hoge/2.log # /tmp/hoge/?.log の2つ目
0
/tmp/hoge/3.log # /tmp/hoge/?.log の3つ目
0
/tmp/fuga/1.log # /tmp/fuga/*.log の1つ目
0
/tmp/fuga/2.log # /tmp/fuga/*.log の2つ目
0
/tmp/fuga/*.txt # /tmp/fuga/*.txt。存在しないので1
1
root@mycomputer:~#
```

なおbrace展開 (`{}` を用いたpath指定) は上記の限りではない。forの変数に展開済みのpathを格納したくてもbraceだと展開されないようだ。

```bash
root@mycomputer:~# target_arr=(
>   "/tmp/{hoge,fuga}/1.log"
> )
root@mycomputer:~# for target in ${target_arr[@]} ; do
>   echo ${target}
> done
/tmp/{hoge,fuga}/1.log # 展開されていない
root@mycomputer:~#
```
サーバ型を前提にした時のRPAの最小導入費用

RPAの目的は組織全体としてROIを出すことである。つまり、現場作業、人的工数、IT投資を全体で見たときに組織全体で総合的に費用削減となり、余剰人材の再配置等につなげ、組織全体の働き方を次の段階に引き上げることである。

RPAの導入が日本で始まってから4年近く経つが、現場からアメーバ的に組織内導入が広がったケースでは、結果的にソフトウェア費用、管理工数、外注費用がコントロールできなくなりROIが出せてないケースが多いようである。

RPAを本格導入するには、**COE (Center of Excellence)**と呼ばれる、組織内のRPA導入を取り仕切る中心組織を作り、IT管理の専門家やプロジェクトマネージャーを配置して、業務をRPAの対象とするかしないか、どのレベルまでRPAで対応するか等のガイドラインの作成と展開を行う、といった統制が必要となる。

そうすると必要になってくるのがサーバによる統制/管理機能である。よってROIを出すためのRPAの本格導入にはサーバ型が必須となる。

デスクトップ側のロボットは、無料のツールから有償のものまで様々あるが、できることはWindowsが提供されるライブラリにほぼ依存するため、各ツールでロボット単体ができることはほぼ変わらないと言っていい。一方、サーバによる管理機能については、無料ツールはないものが多く、有償のベンダーも提供する機能にはかなりばらつきがある。

ここでは、ひとまず費用の面で、PoCを始めるにあたってどれくらいの費用で開始できるのかについて比べてみることにした。

# 主要RPAツールベンダーの最小導入費用
以下の表では、RPAツール5強の比較をしてみることにする。サーバ1台、デスクトップ2～3台程度のライセンスがあれば最小限のPoCはまわせるので、各社ともライセンス費用の最小構成でそれを満たすことができる。

||WinActor|BizRobo!|UIPath|Automation Anywhere|BluePrism|
|:--|:--|:--|:--|:--|:--|
|提供企業|NTTアドバンステクノロジ社|RPAテクノロジ社|UIPath社|Automation Anywhere社|BluePrism社|
|RPA種別|デスクトップ型|デスクトップ型|デスクトップ型|サーバ型|サーバ型|
|最小導入費用<br/>(デスクトップ型)|90.8万円～|90万円～<br/>(BizRobo! mini)|52.5万円～<br/>(リセラーに依存)|-|-|
|最小導入費用<br/>(サーバ型)|318.8万円～<br/>(WinDirector)|720万円～<br/>(BizRobo! Basic)|386万円前後～<br/>(UIPath Orchestrator)|120万円前後～|120万円前後～|
|サーバ型最小構成時の<br/>同時接続数|100台|10台|1,000台(unattended)、<br/>10,000台(attended)|～数千台(1,000台までを推奨)|不明|

(注) 金額はいずれも年額のサブスクリプション。実際の販売価格は取扱代理店によって異なる可能性があるので、それぞれの販売代理店に確認願う。

特筆すべきは、**デスクトップ型ではお安めに使えるツールは、サーバが入った途端に金額が跳ね上がるケースが多い**ので、デスクトップ型で安価に始められるからと言って安易に手を出してしまうのは後々のことを考えると考えモノである。

このほかに、実際にPoCをまわすにはサーバ・デスクトップPCの費用や、専門コンサルタント・技術者の外注費用が必要になる。サーバPCは20万円、デスクトップPCは10万円とする。コンサルタントや技術者は、少なくとも最初の導入段階ではRPAプロジェクトを正しくまわすためには短期間でもつけておいたほうがいいだろう。コンサルタントや技術者は外注すると一人100万円/月はくだらないので、初月から200万円くらいはかかることになる。


# 導入規模が上がる・期間が長くなると一番響いてくるのは外注費用
サーバ型RPAプロジェクトのPoCで3カ月で一区切りの結果を出そうとした場合のプロジェクト費用は、どのツールを選択するかにもよるが、外注費用を300万円くらいと見積もると**450万円～1,100万円くらいの費用**がかかることになる。PoCの規模を上げていき、導入期間が長くなってくると、**一番響いてくるのは人月費用**、つまり外注費用となる。これは内製でどれだけの技術者をそろえられるか、また、選択したRPAツールがどういうレベルのユーザーを対象としているのか(**Excelマクロがわかる程度のノンプログラマーなのか、Visual Studio等の開発ツールが理解できるプログラマーなのか等**)にも依存してくる。

少なくとも、COEを構築して継続してRPAプロジェクトを進めていく場合に、外注費用を小さく抑えてもプロジェクトがまわるような体制をどれだけ早く作れるかどうかに、RPAプロジェクト全体の費用感は大きく影響するといえる。

これらのことを踏まえ、COEを構築する際の社内人材の確保、RPAの開発ツール・実行ツールを扱わせる従業員のレベルと範囲の定義と、サーバ機能による統制・管理・野良ボットを使わせない仕組みづくりが、RPAプロジェクト全体としてROIを出せるかどうかにかかっている。RPAツールもこれらを踏まえた選定が必要となってくるだろう。
M5StickC + Speaker Hat で音を出す

#動機など
先日 M5StickC を購入した際、合わせて買っていた「Speaker Hat」を使ってみようとサンプルコードを開いてみたものの、公式のスケッチサンプルが仰々しく（？）、私の手には余るものだったので、とりあえず音を出すにはどうしたらいいかを調べることにしました。

#音を出す方法

##参考にしたサイト
最終的にこちらの説明やソースがわかりやすかったです。

[M5Stack の内蔵スピーカーから Beep 音（電子音）を出す実験（mgo-tec電子工作）](https://www.mgo-tec.com/blog-entry-beep-sound-speaker-m5stack.html)

##ポイントだと思ったところ

- SPEAKER HAT で音を出すのに使うのは26番ピン
- 音を出すのには dacWrite() 関数が使える。
- 調べたところ、これ以外にも方法はありそう。参考→[ESP-WROOM-32に関するTIPS](https://trac.switch-science.com/wiki/esp32_tips)の中にある「DAC(アナログ出力)」「PWM等」の部分
- 音量を調整しようとしたら、ひとまずdacWrite()を使うことになるのかも。

##ソースコード

これで「プー」と１回鳴ります。

~~~C
#define GPIO_PIN 26 //SPEAKER HATの出力は26番ピン

// スピーカーの音量調整。
uint8_t beepVolume = 50;

// とりあえず１回だけ鳴らすために、setup()の中に書いた

void setup() {
  for (int i = 0; i <= 1000; i++) {
    dacWrite(GPIO_PIN, 0);
    delayMicroseconds(500);
    dacWrite(GPIO_PIN, beepVolume);
    delayMicroseconds(500);
  }
}
~~~

#感想など
とりあえずこれで、M5StickC+SPEAKER HATで「音を出す仕組みの基本」みたいなところはわかりました。
それにしても、ノイズがかなり出ます。使い方によっては気になると思いますが、今回はひとまず音が出たのでよしとします。
iOSのショートカットアプリでSlackリマインダーのGUIを作る

## はじめに
Slackにはメッセージをやり取りする他にファイルや画像を送り合ったり、アプリを追加して外部サービスと連携することができます。
その中の1つに[リマインダー機能](https://get.slack.help/hc/ja/articles/208423427-%E3%83%AA%E3%83%9E%E3%82%A4%E3%83%B3%E3%83%80%E3%83%BC%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B)があります。
リマインダーは自分以外にも特定のメンバー、チャンネルにも設定でき、通知時間も柔軟に決めることができます。
しかし、このリマインダーは`/remind`から始まるスラッシュコマンドからしか設定できません。
書式としては公式のリマインダー設定にあるように下記のように記入します。

```text:リマインダー設定
/remind [@メンバー/#チャンネル] [何を(日本語化)] [いつ(英語)]
```
これだけの書式を記憶に頼るといつも間違ってしまうため、iPhoneのショートカットアプリを使用して簡易なGUIを作成しました。

## 環境
iOS:12.3.1

## ショートカットアプリとは
[‎「ショートカット」をApp Storeで](https://apps.apple.com/jp/app/%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88/id915249334)
アプリの解説から引用
> Siriショートカットを使えば、1回タップするかSiriに一言伝えるだけで、Appでの作業をすばやく実行できます。“ショートカット” Appでは、よく使うAppの複数の操作をまとめた独自のショートカットを作成できます。ギャラリーに用意されたサンプルを使ってみることも、ドラッグ＆ドロップでショートカットを独自に作ることもできます。

この説明には無いですがこのアプリでは**変数**が使用でき、**APIが叩ける**という特徴があります。
つまりこのアプリだけで**API経由でSlackの操作がノンコーディングで出来る**ということです。

## 事前準備
### Slack tokenの取得
Qiitaポストを参考にSlackのトークンを取得
[【画像で説明】SLACKの推奨アクセストークン（レガシートークンじゃない方）を取得する方法 - GUIで取得編 - - Qiita](https://qiita.com/komiya_____/items/0e988239ed3f5145a22c)
Permission Scopesで「reminders:write」を選択

## ショートカット作成
今回は自分にリマインダーを通知するショートカットを作成します。
任意の人へのリマインダーを設定する場合には選択リスト等の追加入力が必要になります。

### リマインド日時を入力
日付フォーマットでは標準で用意されているものでは上手く設定できなかったのでカスタムを選択
文字列フォーマットは`yyyy-MM-dd HH:mm`を入力
入力を「date」に設定
<img width="375" alt="IMG_4850.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218344/0d5d82d3-7f19-3938-35b1-57723dddde44.png">

### メッセージを入力
注意することは特になし
入力を「text」に設定
<img width="375" alt="IMG_4851.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218344/eef861f3-3dbf-043f-56d6-417e674f3710.png">


### URLの設定
SlackAPIのDocumentにあるMethod URLを入力
[reminders.add method \| Slack](https://api.slack.com/methods/reminders.add)

### URLの内容を取得
詳細を開き方法は「POST」を選択
ヘッダに表のパラメータを設定

| キー          | テキスト                                |
| ------------- | --------------------------------------- |
| Authorization | Bearer [xoxpから始まる取得したトークン] |
| Content-type  | application/json                        |
| Charset       | utf-8                                   |

本文(パラメータ)にjsonを選択し、表のパラメータを設定

| キー | パラメータ       |
| ---- | ---------------- |
| text | text(変数)       |
| time | date(変数)       | 
| user | [自分のユーザID] |
<img width="375" alt="IMG_4852.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218344/4ed17181-5b56-000b-6828-0492f631ce2f.jpeg">

### 結果を表示
任意のテキストを入力をし、結果を表示する
<img width="375" alt="IMG_4853.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218344/2a94d183-896d-ed75-7e8d-66e7c63fccd9.png">


## まとめ
Slackのリマインダーに簡易的なGUIを追加できました。
Slackのトークンには権限のスコープが設定できるので少し難しいですが、
DocumentのWorks with欄に書かれているRequired scope(s)の権限をトークンに設定すれば大丈夫だと思います。
他のSlackAPIの簡易GUIが作れるので是非挑戦してみてください！
! [rejected]        master -> master (non-fast-forward) error: failed to push some refs to 'https://github.com/hoge/hoge.git

~~なぜgitが動いてくれないのか。その理由を知る為我々はアマゾンの奥地へ向かった。~~
####向かいません。

僕の場合、以下のコマンドで治りました。

```bash
git pull --rebase origin master
```

...よくわからないけど動いてるのでヨシ！
[Vim] インデントという概念がある

# 書いたこと

* インデントとは何なのか
* インデントの挿入方法
* コーディングを行うためのインデント設定ベストプラクティス

# インデントとは何なのか

プログラミングの世界では、**行の先頭からの空白** をインデントと呼びます。

ですが、コンピューターの世界では、直接的にインデントを表す制御文字は存在しません。

かろうじて「水平タブ (\0x09 in ascii)」が存在しますが、これは直接インデントを表すものではなく、世の中にはインデントを「スペース(\0x20 in ascii)」で表す人もいます。


つまり「**インデント**」とは **概念** なのです。


## Vimにおけるインデント

そんな中、Vimはファイルの解析を行い、先頭からの空白をインデントとして認識し、**見た目の空白数** を挿入します。

その際には、以下のオプションが使われます。

|オプション|説明|
|:---|:---|
|**shiftwidth**|インデントの見た目の空白数の設定値|

# インデントの挿入と削除

インデントの挿入・削除には、手動と自動がある。

## 手動挿入

### ノーマルモード

`>>` or `<<` を行うことで選択行にインデントが挿入される。

### インサートモード

|キー操作| 説明 |
|:---|:--|
|**\<C-t\>** | インデントの挿入 |
|**\<C-d\>** | インデントの削除 |

## 自動挿入

インサートモードにて、以下のオプションによって自動的に挿入される。

|オプション| 説明 |
|:---|:--|
|**autoindent (ai)** | 改行時に、前の行と同じ数だけ自動でインデントを挿入される | 
|**smartindent (si)** | 改行時に、ブロックに応じて自動でインデント数を調整して挿入される|
|**smarttab (st)** | 行の先頭で\<Tab\>キーを入力するとインデントを挿入する |

## インデント 見た目の空白数の正体

手動や自動でインデントを埋め込む時、Vimは行の先頭に「**タブ制御文字 (\0x09)**」もしくは「**スペース (\0x20)**」を書き込みます。

### 埋め込まれる文字はオプションの値によって決まる

例: `set shiftwidth=6　softtabstop=4 noexpandtab` としたとき、インデントによって埋め込まれる制御文字

```
[\0x09][\0x20][\0x20]
```

上記、

> * `noexpand` `noet` \<TAB\>キーの入力をスペースに置き換えない
> * `softtabstop` `sts` \<TAB\>キーの入力による見た目の空白数

であるから、

* インデントの見た目の空白数は 6
* \<TAB\>キーの入力による見た目の空白数は 4
* \<TAB\>キーの入力をスペース (\0x20) に置き換えない

そのため見た目の空白数の足りない分(2つ分)がスペースで補われています。

# プログラマーのためのインデント設定　ベストプラクティス

プロジェクトやOSSによってインデントにスペースを使うかタブを使うかまたスペースを使う場合、スペースの数を２にするか４にするか８にするかマチマチです。

そこでインデントにタブかスペースを使うかは `expand` で切り替えられるようにし、スペースが使われる場合は、文字数を `tabstop` のみで変えらえるようにします。

例: タブをインデントとする場合

```:.vimrc
set noet ts=4 sts=-1 sw=0
```

* `softtabstop` `sts` → 負数にすると `shiftwidth (sw)` に従う
* `shiftwidth` `sw` → ０にすることで、 `tabstop` に従う

こうすることによって、

* タブからスペースの切り替えは、 `expandtab` で OK 
* 挿入する見た目の空白数は `tabstop` の値を変更するだけで OK

となります。

ぜひ、お試しください。

# Appendix

## `tabstop` と `softtabstop` の違い

|オプション| 説明 |
|:---|:--|
|**tabstop** | タブ制御文字(\0x09 in ascii)に対する**見た目上の空白数**を設定する|
|**softtabstop**| インサートモード時に、\<Tab\>キー、\<BS\>キーの入力に対する**見た目上の空白数**を設定する|

# 参照

* [[あるマのメモ書き] タブもしくはスペースとインデント](https://yossan.hatenablog.com/entry/2019/08/25/161102)
* [[vim-jp] Hack #143: 見た目を変えずにタブ文字とスペースを相互に変換する](https://vim-jp.org/vim-users-jp/2010/04/30/Hack-143.html)
RedisのSorted Setを利用した同点順位のランキング作成

## はじめに
とあるサービスでランキング計算をする実装を組んでいた。ふと、アプリケーション側ではなく、Redisに任せることもできることを思い出したので、調査がてらサンプルコードを書いたので記事にまとめる。

## 実現したいこと
* スコア情報を持つデータがある。Redisを使用して同点順位によるランキングを作成したい

## 開発環境
* Redis 4.0.11
* Ruby 2.6.1p33
* gem
    * redis 4.1.2

## 実装方法
今回は動作検証のためRubyと redis gemを使用して実装をした。後ほどサンプルコード全文を共有する。

### 準備
まずは redis gemを利用してRedisに接続をする。Redisに接続したら、以降は `REDIS` オブジェクトを通じてRedisを操作する。

```ruby
require 'redis'

# Redisに接続
REDIS = Redis.new(host: 'localhost', port: 6379)

# 初期化
REDIS.del("ranking")
```

### RedisのSorted Setで実装
日本語ではソート済みセット型と呼ばれ、Redisにスコアを登録するとRedis側で並び替えをしてくれる。

新しいデータを登録するには [zadd](https://www.rubydoc.info/github/redis/redis-rb/Redis#zadd-instance_method) を使用する。データは以下のようにして追加する。これを追加するだけでRedis側が自動的に並び替えをしてくれる。

```ruby
REDIS.zadd("ranking", 200, "A")
```

ソート済みのデータを取得するには [zrevrange](https://www.rubydoc.info/github/redis/redis-rb/Redis#zrevrange-instance_method)を使用する。降順のランキング情報を1件目から10件スコア情報も合わせて取得できる。 `:with_scores => true` を指定することでスコア情報も合わせて返すこともできる。

```ruby
rankings = REDIS.zrevrange("ranking", 0, 10, :with_scores => true)
```

順位計算は [zcount](https://www.rubydoc.info/github/redis/redis-rb/Redis#zcount-instance_method)を使用する。このメソッドは指定の範囲でスコアが何件あるかを計算する。下記の例だと指定のスコア以上の値が何件あるかを算出している。これにより同点順位が計算できる。

```ruby
rankings.each do |r|
  # 同点順位計算処理: 同じスコア以上のものが何件あるか算出する
  rank = REDIS.zcount("ranking", r[1], "+inf")
  p r
  p rank
end
```

### サンプルコード
今回のサンプルコードはこちら。

```ruby
require 'redis'

# Redisに接続
REDIS = Redis.new(host: 'localhost', port: 6379)

# 初期化
REDIS.del("ranking")

# 検証データを登録
REDIS.zadd("ranking", 200, "A")
REDIS.zadd("ranking", 150, "B")
REDIS.zadd("ranking", 30, "C")
REDIS.zadd("ranking", 200, "D")
REDIS.zadd("ranking", 180, "E")
REDIS.zadd("ranking", 190, "F")
REDIS.zadd("ranking", 250, "G")
REDIS.zadd("ranking", 210, "H")
REDIS.zadd("ranking", 10, "I")
REDIS.zadd("ranking", 30, "J")

# 降順のランキング情報を1件目から10件スコア情報も合わせて取得す
rankings = REDIS.zrevrange("ranking", 0, 10, :with_scores => true)
rankings.each do |r|
  # 同点順位計算処理: 同じスコア以上のものが何件あるか算出する
  rank = REDIS.zcount("ranking", r[1], "+inf")
  p r
  p rank
end
```

### 実行結果
実行結果を見る。ポイントは４位。200点で同点が２つあるため、4位が２つとなっており、190点が5位から始まっている。これで実現したいことは達成できた。

```sh
$ bundle exec ruby ranking.rb
["G", 250.0]
1
["H", 210.0]
2
["D", 200.0]
4
["A", 200.0]
4
["F", 190.0]
5
["E", 180.0]
6
["B", 150.0]
7
["J", 30.0]
9
["C", 30.0]
9
["I", 10.0]
10
```

## 終わりに
あるあるな実装例ではあるが、Redisの Sorted Setを利用したことが無かったので、学習までにサンプルコードを書いて記事にまとめた。アプリケーション側で順位計算ができているなら、Redisにさせる必要もない。ただゲームなどでリアルタイム性が必要な要件がある場合は、Redisに任せるのが良さそうである。

## 参考
* [Class: Redis — Documentation for redis/redis\-rb \(master\)](https://www.rubydoc.info/github/redis/redis-rb/Redis)
* [Command reference – Redis](https://redis.io/commands#sorted_set)
* [phpredisを使用してランキング集計を行う - ダメプログラマの技術メモ](http://damepg.hatenablog.com/entry/2014/08/07/231828)
DonkeyCar 3.1.0 処理時間を確認する

#目的
Vehicle.pyから呼び出される一連の処理は，DRIVE_LOOP_HZ が既定の 20 なら 50ms 以内に完了する．

モデルファイルによっては推論に時間が掛かることがあるのでこれをチェックする．

注：Tensorflow のバージョンが上がるにつれて推論の時間が長くなる傾向がある．
#準備
manage.py を編集

V.start を呼び出す引数に「verbose=True」を追加する．

    V.start(rate_hz=cfg.DRIVE_LOOP_HZ, 
            max_loop_count=cfg.MAX_LOOPS, verbose=True)

myconfig.pyでTrue/False設定可能にすると良い

#確認方法
DonkeyCar動作中のターミナル画面に10秒ごとに

Part Profile Summary: (times in ms)
+------------------------------+--------+-------+-------+--------+
|             part             |  max   |  min  |  avg  | median |
+------------------------------+--------+-------+-------+--------+
|          TubWriter           | 17.31  |  2.86 |  4.16 |  3.81  |
| DualShock4JoystickController |  2.79  |  0.05 |  0.09 |  0.08  |
|        ThrottleFilter        |  1.62  |  0.03 |  0.03 |  0.03  |
|        PilotCondition        |  0.82  |  0.02 |  0.03 |  0.03  |
|         FileWatcher          |  6.34  |  0.08 |  0.15 |  0.12  |
|          DriveMode           |  9.17  |  0.04 |  0.20 |  0.17  |
|      TriggeredCallback       |  2.52  |  0.02 |  0.02 |  0.02  |
|        DelayedTrigger        |  0.63  |  0.02 |  0.03 |  0.03  |
|         FileWatcher          |  2.22  |  0.04 |  0.06 |  0.04  |
|           PiCamera           |  2.19  |  0.03 |  0.06 |  0.05  |
|        ImgPreProcess         | 11.34  |  1.15 |  1.60 |  1.46  |
|         PWMSteering          | 13.76  |  1.56 |  2.10 |  1.80  |
|         PWMThrottle          | 11.73  |  1.46 |  1.85 |  1.63  |
|         KerasLinear          | 74.78  | 35.61 | 49.87 | 49.08  |
|     AiRecordingCondition     |  7.80  |  0.02 |  0.03 |  0.03  |
|        AiRunCondition        |  5.98  |  0.02 |  0.03 |  0.03  |
+------------------------------+--------+-------+-------+--------+
のようなサマリーが表示される．
「Kerasxxx」の行が推論処理の時間．
また，

WARN::Vehicle: jitter violation in vehicle loop with value:

が表示されたら，処理時間をオーバーしている．

注：サマリーを算出する間はCPUが占有されループ処理が止まるので注意．
Git　消したリモートブランチが残っている時にした事　［メモ］

# リモートブランチが無くならない

Gitでプルリク（PullRequest）の練習として、適当なブランチを作成した。
ブランチ名はfront.（ネーミングセンスが残念なことは認めます笑）

プルリクの流れを確認した後は、いらなかったのでGitHub上から、こちらのfrontブランチを削除したのだが、ターミナルで確認した所、なぜかfrontブランチが無くなっていない。

### gitコマンドで確認

```terminal
git branch -r                                                                                                                                               
origin/front
origin/master
```

ほら無くなってない笑

オプションｒ　（-ｒ）は、remoteって意味なので、リモートブランチの確認時に使用。
-a なら　リモートもローカルも全部表示できるよ。


まぁ消えてないなら消してしまえと思い、gitコマンドでブランチ削除を入力。

```
git push --delete origin front                                                                                                                                               
error: unable to delete 'front': remote ref does not exist
error: failed to push some refs to 'git@github.com:〜〜〜'
```

なんかremoteのref がないから　’front’を削除することができないらしい


### pruneを使え

エラーをググるとすぐに答えがありました。
pruneを使えとのことだったので、早速使ってみると

```terminal
git remote prune origin                                                                                                                                                      
Pruning origin
URL: git@github.com:github~~.git
 * [pruned] origin/front
```

ブランチ確認

```
git branch -r
origin/master
```

frontブランチが消えている！！！

pruneコマンドを使うと、リモートの状態を再度取ってくれるそうです。

ちなみにpruneの意味は刈り込む, 透かす, 刈る, 切り落とす, 切り払う等なので、
ブランチを切り落とすって意味で解釈しています。
Rails6でBootstrap4とFont-Awesomeの導入

# rails6にする
```
rbenv exec gem install rails
rails -v
~~[log]
Rails 6.0.0
~~
```
新しくプロジェクト作成時に自動でwebpackerがインストールされる

```
rails new . -d postgresql
〜〜[log]
rails  webpacker:install
Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/
〜〜
```

yarnをインストールして手動でwebpackerをインストール

```
brew install yarn
rails  webpacker:install
~~[log]
✨  Done in 5.31s.
Webpacker successfully installed 🎉 🍰
~~[log]
```

## ディレクトリ構成

```
app/javascript:
├── packs
│   └── application.js
└── src
    └── application.scss
```

## Bootstrapの導入

```
yarn add bootstrap@4.3.1 jquery popper.js
mkdir app/javascript/src
touch app/javascript/src/application.scss
echo 'import "bootstrap"' >> app/javascript/packs/application.js
echo 'import "../src/application.scss"' >> app/javascript/packs/application.js
echo '@import "~bootstrap/scss/bootstrap";' >> app/javascript/src/application.scss
touch config/initializers/generators.rb
echo 'Rails.application.config.generators.assets false' >> config/initializers/generators.rb
```

## Font-Awesomeの導入

```
yarn add @fortawesome/fontawesome-free
echo 'import "@fortawesome/fontawesome-free/js/all"' >> app/javascript/packs/application.js
echo '@import "~@fortawesome/fontawesome-free/scss/fontawesome";' >> app/javascript/src/application.scss
```
rails6でcarrierwave実装(aws-s3)

rails6でcarrierwaveを実装使用としたら
動機: gem 'fog'で実装しようとしたらエラー出たので
出ないようにした。

# プロジェクトを作成

[ターミナル]

```
mkdir [プロジェクト名]
cd [プロジェクト名]
rails new . -d postgresql
rails db:create
```

## Slimの導入

```
echo 'gem "slim-rails"' >> Gemfile
echo 'gem "html2slim"' >> Gemfile
bundle
bundle exec erb2slim app/views/layouts/ --delete
```

# rails6 & carrierwave
photoモデルをつくって、imageカラムに画像をアップロード出来るように設定します。



## インストール

```
echo "gem 'carrierwave'" >> Gemfile
echo "gem 'fog-aws'" >> Gemfile
echo "gem 'rmagick'" >> Gemfile
bundle
```

## 実装例

```
rails g scaffold photo image
rails db:migrate
rails generate uploader Image
```

## carrierwaveの設定

```ruby:/app/uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base

  # リサイズしたり画像形式を変更するのに必要
    include CarrierWave::RMagick

  # 画像の上限を640x480にする
    process :resize_to_limit => [640, 480]



  if Rails.env.development?
      storage :fog
  elsif Rails.env.test?
      storage :file
  else
      storage :fog
  end

  def store_dir
      "uploads/#{model.class.to_s.underscore}"
  end

  def extension_whitelist
      %w(png jpg)
  end
  # filenameをuuid
  def filename
      "#{secure_token}.#{file.extension}" if original_filename.present?
  end

  protected
    def secure_token
        var = :"@#{mounted_as}_secure_token"
	model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
    end
end
```




## AWS S３の認証情報をcredentialsに追加

```
rails credentials:edit
```

```
aws:
  access_key_id: いつもの
  secret_access_key: いつもの

s3_fog_directory: S3のバケット名
```

前半で設定した内容を元に設定する
* aws_access_key_id　S3用に用意したIAMユーザーのアクセスキー
* aws_secret_access_key　S3用に用意したIAMユーザーのシークレットアクセスキー
* region　S3のリージョン
* config.fog_directory　S3のバケット名


```ruby:config/initializers/carrierwave.rb
CarrierWave.configure do |config|
  config.fog_credentials = {
    provider: 'AWS',
    aws_access_key_id: Rails.application.credentials.dig(:aws, :access_key_id),
    aws_secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key),
    region: 'ap-northeast-1'
  }

  config.fog_directory  = Rails.application.credentials.dig(:s3_fog_directory)
  config.cache_storage = :fog
end
```


```ruby:app/models/photo.rb
class Photo < ActiveRecord::Base
  mount_uploader :image, ImageUploader
end
```




```ruby:app/views/photos/_form.html.slim
= f.file_field :image
```


```ruby:app/views/photos/show.html.slim
= image_tag photo.image.to_s
```


# 参考文献

https://github.com/carrierwaveuploader/carrierwave
【備忘録】PyCharmで仮想環境作成後、インポートエラーになる解決法

PyCharmを起動後、プロジェクトフォルダ直下で`python -m venv venv`コマンドを打って仮想環境作成後、コード書き始めると何故かインポートエラーになった。

# 原因
プロジェクトインタプリターの設定。

# 解決策
仮想環境内のpython.exeをプロジェクトインタプリターに設定する。

#### 手順
①File>Setting>Project>Project Interpreterを開く
②Project Interpreterの右横にある歯車マーク>Addをクリック
③ポップアップ画面でVirtual Environmentを選択し、New Environmentエリアの「Base Interpreter」の右横にある「...」をクリック
④当該プロジェクトフォルダ>Scripts>python.exeを選択
AWSのアカウント登録にセキュリティコード(CVV2)関連で失敗する件

#はじめに
AWS超初心者(利用開始前)の方向けの記事です。
AWSへアカウントを登録しようとした際、本人確認画面でエラーになり、先に進めない状況が続いていました。
AWSからのメールには「AWSがクレジットカードのCVV2(セキュリティコード)に対応していない」ことが原因という内容が書かれていたので、同じ状況に陥った方向けに自分がとった解決法を書きます。

#まとめ
- AWSがクレジットカードのセキュリティコードに対応しておらず、カード会社側のセキュリティ認証で弾かれていた
- カード会社に連絡し、セキュリティコードの一時解除をしてもらった

# 何が起こったか
###AWSの個人利用アカウント登録の際、本人確認画面でエラーになる
(※エラーそのものはキャプチャし損ねました…)<br>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487269/9638d5b9-f656-8b40-ea98-0a5ad0c85224.png)

###EC2インスタンスを立てることができない
アカウント認証ができていない状態でもマネジメントコンソール自体は使用できます。
試しにEC2インスタンスを作成できるか試してみたのですが、これもだめでした。
EC2ダッシュボード自体を開くことができない状態です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487269/b50f0baf-f882-74a2-373d-5acf35163c8c.png)



###AWSからAccount Alertメールが届く

以下一部抜粋

> - Amazonは、クレジットカードに関連付けられたCVV2セキュリティコードを受け入れるように設定されていません。銀行がこの要件を一時的に解除できる場合があります。
> - 承認は低額（$ 1.00）であり、銀行が拒否する場合があります。

どうやら、クレジットカードが本当に使用できるかの承認に用いられる$1.00の決済(日本でいう1円オーソリ)時に、クレジットカード会社側で弾かれているそうです。
理由はAWSがクレジットカードのセキュリティコードに対応していないからみたいです…。
このあたり、法人向けカードを使用している方は問題が起きないのでしょうか…？

# やったこと
###電話依頼
メールの通り、カードの発行会社(イシュア)に対してセキュリティコードの制限解除を電話で申請しました。
対応自体は非常にスムーズで、連絡がついてから実際に制限が解除されるまで5分もかかりませんでした。

自分の場合は三井住友カード(ちなみにAmazonマスターカード)を使用していたので、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487269/9b11496f-da81-e13f-ee0b-0d6258dd9a82.png)
ここにある「各種変更手続き・サービスに関するお問い合わせ」へ問合わせし、自動案内で「店舗でカードを使用できなかった」のような番号を選択しました。
待つこと10分弱、つながったオペレータさんへ「セキュリティコードの制限を一時的に解除してほしい」という旨を伝え、解除してもらいました。
念の為期間を聞いてみると、だいたい1週間ほど解除してくれるそうです。

この時、実際に上記の$1.00決済に失敗していると「〇〇日✕✕時の決済の件でしょうか？」という具合でオペレータさんも話が理解しやすいと思います。

###クレジットカード情報の更新
電話後しばらく待つと本人確認に成功しましたが、EC2ダッシュボードは開くことができないままでした。
`マイアカウント>設定>お支払い情報`にあるクレジットカードの`編集`から、カードの情報を(変更部分がなくとも)更新することで、ダッシュボードを開くことができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487269/26666370-2402-7f50-cad8-a19aa699620a.png)



# 所感
「個人で利用するクレジットカードのセキュリティコード認証一時解除」というよく考えると非常に恐ろしい手続きをすることで、無事アカウント登録をすることができました。
ネットで検索してもほとんど同じ症例が出てこないあたり、わりと珍しい現象なのでしょうか…？

また、今後AWSの無料利用枠の範囲を超え支払いが発生した場合、都度電話で制限解除を依頼する必要があるそうなのですが、これもどうなのかと思いました。。

# 参考
- [AWS利用料(37円)が払えない！なんで？](https://note.mu/agw/n/n01fcd5621c4e)
- [クレジットカードのセキュリティコードとは何か　VISA、マスター、JCBなど主要ブランド解説](https://zuuonline.com/archives/183392)
- [利用者から見るクレジットカードの「オーソリ」とは：１円オーソリの意図も](https://www.etc-navi.net/authorization)
【JavaScript】配列から条件を満たす要素を全て削除する

- 8/29 コメント欄でご指摘をいただいた通り、変数へ再代入を行っていた部分を修正しました。

## やりたいこと

配列の要素を見て行って、条件に合致するものを削除したい。

```javascript
let array = [1,2,3,4,5,6,7,8,9,10]; //5以下の数を削除したい
```

## (NGな方法)forEachとspliceを組み合わせる

下記のようなコードは正しく動作しない。

```javascript
let array = [1,2,3,4,5,6,7,8,9,10]; //5以下の数を削除したい
array.forEach((element, index) => {
    if (element <= 5) {
        array.splice(index, 1);
    }
})
document.writeln(array); // Output: 2,4,6,7,8,9,10
```
理由としては単純で、forEachで前から捜査していき、条件を満たす要素にたどり着いたとき、
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316990/39e5f137-5854-4d4c-3902-d3628d8805a6.png)
その要素は削除されて、配列の要素が1つ詰められる。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316990/3397caef-7bc6-bde7-f66c-af33cb57e154.png)
forEachは、**上図の状態において**次の要素を参照するので、この場合2番目に処理されるのは"2"ではなく"3"になる。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316990/7fc1732b-d837-d6b8-ee36-f173f02fec90.png)
つまり、**要素の削除が起こるとその次の要素に対する処理がスキップされる**ため、結果としてこんな配列になる。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316990/17571af8-713f-6ea5-41db-2aded0966bf1.png)

## (正しい方法)filterを用いる
filterを使うことで正しい動作をさせることができる。ただし条件を反転する必要はある。

```javascript
const array = [1,2,3,4,5,6,7,8,9,10]; //5以下の数を削除したい
const newArray = array.filter(element => !(element <= 5));
document.writeln(newArray); // Output: 6,7,8,9,10
```
## まとめ
モダンな書き方に慣れ親しみたい

## 参考

- [Javascriptで指定した配列の要素を削除する](https://qiita.com/Sekky0905/items/598b47fea2106b8c140e)
- [Array.prototype.forEach() - JavaScript | MDN - Mozilla
](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)
FUZE BASICを触ってみる５（もっと寄り道してVSCシンタックスハイライト拡張機能編）

# 今日やること

前々回、画面描写がきちんとされない現象にぶつかりました。前回(昨日)は一旦棚上げして環境整備したので、今日こそは対応しようと思ったのですが昨日の

> VSCのシンタックスハイライトが欲しい。。。

がどうしても引っかかって…
欲しくなったから今日は初めてのシンタックスハイライト拡張機能を作成しました。

# アンカー

前の記事）[FUZE BASICを触ってみる４（寄り道して環境整備編）](https://qiita.com/suruseas/items/7d7c4e472d99d6cfda32)

参考にした記事）
- [Visual Studio CodeやAtomのシンタックスハイライト拡張機能を作る](https://qiita.com/maxfie1d/items/51af2984b7a628c41a94)
- [Visual Studio CodeでCode Syntax Highlight Extentionを作る](https://www.1915keke.com/entry/vscode-syntax-highlight)

# 作ってみた

ただただ実装しました。公式リファレンス（FUZE_BASIC_Reference_GuideV3.pdf）見ながら作業したのですが、IF・ELSE・ENDIFと言った制御構文やプロシージャ／ファンクション定義構文も `Procedures & Functions` に記載されているのですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144344/e6c3a702-092a-dbb8-8a2d-77222ee891c7.png)

即席で作った割にはいい感じなのでVSCode Marketplaceで公開しました！

https://marketplace.visualstudio.com/items?itemName=YukihiroAmadatsu.fuze

# Private Access Token作成時のポイント

余談ですが、Private Access Token作成時に予想外に時間使ってしまいました。VSCode Marketplaceへの公開手順で、 `create-publisher` が何度試しても `401`

```
Publisher human-friendly name: (YukihiroAmadatsu)
E-mail: suruseas@gmail.com
Personal Access Token: ****************************************************

 ERROR  Failed request: (401)
```

結果として `Private Access Token` の作り方が悪かったです。[公式サイトの情報](https://code.visualstudio.com/api/working-with-extensions/publishing-extension#get-a-personal-access-token) から引用しますが

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144344/02fd8d93-c032-dc28-db33-f56fdb3b8f28.png)

Organizationを `All accessible organizations` を選択しなきゃっだめです。


# 所感

シンタックスハイライト拡張機能を作成していたときに気づいた点。

- 公式のWorksheetで使われている命令がマニュアルにはない、など一次資料がまとまっていない感じがある。
- プロシージャ／ファンクション内で任意の場所で `return` できない？マニュアルに載ってない気が🤔
- 文字列で`"`のエスケープの仕方がわからない
- IF文などで `AND` や `OR` が使えない？マニュアルに載ってない気が🤔
- 明日はおやすみ。明後日はいよいよ画面描写の対応をしたい！
【heroku×MySQL×Rails】herokuでDBリセットしてseedを入れ直すまで

# この記事を書いた背景

いつもAWSでデプロイをしていて、スクールの最終課題ではチームの中でデプロイを担当させてもらってました。ですが、herokuを使ったことがなかったので、一度は使ってみようと思い、ポートフォリオはherokuを使っています。

デプロイをしている中で「heroku」のコマンドはAWSでデプロイするときとコマンドがかなり違う！（当たり前…）
　
AWSでDB：resetをしていた僕もherokuで少し調べてやってみたので、その方法を書いていきたいと思います。

## db:resetをするまでの現状

- MySQLを使用
- ItemsテーブルにネストされたQuestionsテーブルがある
- Itemsテーブルの中の「quiz_typeカラム」をQuestionsに移行したい
- DB構造が代わりseedデータの中身も変更したので、本番でもdb:resetしたい

という流れです。

#実際にherokuでdb:resetやってみた

試しに一度AWS風にやってみたところ…


```terminal

$ heroku run rake db:migrate:reset RAILS_ENV=production

```

<img width="1404" alt="スクリーンショット 2019-08-25 15.39.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434778/a7ae99b1-09bf-7983-8167-c6e7732b362a.png">

途中までは実行されているけど、どうやらActiveRecordのエラーが出ているみたいですね。


##エラー内容と原因

>rake aborted!
ActiveRecord::ProtectedEnvironmentError: You are attempting to run a destructive action against your 'production' database.
If you are sure you want to continue, run the same command with the environment variable:
DISABLE_DATABASE_ENVIRONMENT_CHECK=1

>
>(意訳）
「あなた本番のDB壊そうとしてるけど、Railsに搭載されている防御シールドで撃退されているよ。もし続けたいのなら、”DISABLE_DATABASE_ENVIRONMENT_CHECK=1”の環境変数を使えばいけるはずだよ！」


## ということで再トライ


```terminal
$ heroku run rake db:migrate:reset DISABLE_DATABASE_ENVIRONMENT_CHECK=1
```

<img width="747" alt="スクリーンショット 2019-08-25 16.12.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434778/62c39e71-b7a8-74df-4d80-97893e6c85b6.png">

左の方に注目してもらえるとDBがdropされ、再度createされているのがわかりますね。そして、その後itemsテーブルがcreateされていることがわかると思います。

## seedファイルをアップロード

ここまでくれば、簡単。あとはseedを入れるだけ。

```terminal
$ heroku run bundle exec rake db:seed:item RAILS_ENV=production
```

<img width="1402" alt="スクリーンショット 2019-08-25 16.16.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434778/6aae8906-a042-cd19-b7bb-2756fd86d6d4.png">

気持ちよく入っていきますね。


## なぜRAILS_ENV=productionが使えなかったのか

Railsのgithubにて「本番環境の破壊的アクションへの防止」が、その背景と対策について書かれています。
[Prevent destructive action on production database #22967](https://github.com/rails/rails/pull/22967)

要するに「本番環境でうっかりDBを壊しちゃったから、本番環境でDBを破壊するようなタスクには環境変数をつけたよ」ということですね。


Rails5系から本番環境でDBを破壊するタスクに防止機能が追加されていたようです。僕はRails5系からRailsを触り始めたので、RAILS_ENV=productionなどと、本番やテストなどでは環境を指定しなければいけないといった背景に、このようなことがあったと勉強になりました。


[Railsのリリースノート一覧](https://github.com/rails/rails/tree/master/guides/source)