OmniAICreator/Qiita-1.07M huggingface dataset:
SwiftUIのチュートリアル日記2

# この記事は何？
[前回](https://qiita.com/chino_tweet/items/fca4c904ecefe98bc897)からの続きです。

## セクション2: テキストビューをカスタムする
2つの方法で、ビューの見え方をカスタマイズする

1. コードを変更する
2. インスペクタを使用して利用可能なものを見つけてコードを書く

どの開発ツールを使用しても、コードは常に更新される。

- ソースエディタ
- キャンバス、またはインスペクタ

### 手順1
インスペクターを使ってテキストビューを変更してみる

````Swift:エディタから反映されたコード例
// １つ目の構造体（コンテンツとレイアウト）
struct ContentView: View {
    var body: some View {
        Text("Turtle Rock")  // 文字が変更
        .font(.title)        // 太さや大きさがタイトルのスタイルに
        .color(.green)       // 色が緑に
    }
}
````

プレビュー上にある挨拶メッセージを、コマンドキーを押しながらクリックする。
すると、構造化されたエディタがポップオーバーするので、_Inspect_ を選択する。
このポップオーバーには、ユーザーが選択したビューごとに異なるカスタム可能なアトリビュートが表示される。

### 手順2
インスペクタから、テキストを「Turtle Rock」に変更する。
`"Turtle Rock"` は、アプリに最初に表示されるランドマーク名です。

### 手順3
フォント修飾子を `.Title` に変更する。
システムフォントがテキストに適用され、ユーザーの好みの設定に最適化される。

### 手順4
SwiftUIビューをカスタマイズするには、__修飾子__ メソッドを呼び出す。
コードを編集して、`.color（.green）` 修飾子を追加する。 
修飾子はビューやその他のプロパティを変更するためにビューをラップする。
各修飾子は新しいビューを返す。
一般的に、複数のモディファイアを縦に積み上げて、チェーン化する。

コードこそがビューの実態。
インスペクタ上のカスタマイズと一致するように、Xcodeがコードを更新する。

### 手順5
コードエディタの _Text declaration_ をCommandキーを押しながらクリックする。
インスペクタが開くので、ポップオーバーから _Inspect_ を選択する。
_ Color_ ポップアップメニューをクリックする。
_Inherited_ を選択して、テキストの色をもう一度黒に戻す。

### 手順6
Xcodeがコードを自動更新して、`color（.green）` 修飾子が削除されたことを確認する。
Vueのmain.jsについて



```ruby:main.js
  import Vue from "vue";
  import App from "./App.vue";
  import router from "./router";
  import store from "./store";

  Vue.config.productionTip = false;

  new Vue({
    router,
    store,
    render: h => h(App)
  }).$mount("#app");
```

# render: h => h(App)とは
`render: h => h(App)`については、こちら
https://qiita.com/teinen_qiita/items/ed1bb1909a17f9ca9daa


# .$mount("#app")とは
以下、ガイドより引用
https://vuejs.org/v2/api/index.html#vm-mount

<b>Vue インスタンスがインスタンス化において el オプションを受け取らない場合は、DOM 要素は関連付けなしで、
”アンマウント(マウントされていない)” 状態になります。vm.$mount() は `アンマウントな Vue インスタンスの
マウンティングを手動で開始する`ために使用することができます。</b>

```ruby:
   # インスタンスを生成し、#app にマウント(#app を置換)
   new MyComponent().$mount('#app')
```
<br>
【バッチファイル】管理者権限が無い場合に付与して実行

#要約
管理者権限が必要なバッチファイルを起動したい、かつ、毎回「右クリック > 管理者として実行」を行うのが困難or面倒な場合によく用いる起動用バッチファイル。

```bat:start.bat
@echo off
openfiles > NUL 2>&1
if NOT %ERRORLEVEL% EQU 0 (
    REM　管理者権限が無いのでstart-process -verb runasで権限付与する
    powershell start-process 起動したいバッチファイル -ArgumentList "引数1","引数2" -verb runas
) else (
    REM 管理者権限があるのでSTARTあるいはCALLコマンドで起動できる
    START 起動したいバッチファイル 引数1 引数2
)
```
#解説
基本的には`参考`元のURLを参照すればだいたい解決する。
`openfiles`は管理者権限が無い場合に`ERRORLEVEL`に値を入れるので、`0`ならば管理者権限があり、それ以外の値なら権限が無いと判定できる。これ以外にも権限の確認方法はあるので適当なものを選べばよいと思う。
権限がある場合は`START`コマンドによりバッチファイルが(別ウィンドウで)起動する。なお例では`START`としているが、私自身は別ウィンドウの起動が邪魔なので`CALL`コマンドを使う場合も多い[^1]。
権限が無い場合、`powershell`の`start-process`を用いる。`-verb runas`オプションが管理者権限を付与する。`.bat`ファイルはそのものが実行ファイルなので、別ウィンドウで起動してくる。なお引数を与えたい場合は例の様に`-ArgumentList`オプションを付与した上で`""`で囲み、`,`区切りで配置すれば良い。

#動機
最初は条件分岐せず`powershell start-process -verb runas`で常に起動しても良いかと思っていたが、微妙に遅くてもにょったので。

#参考
[バッチファイルが管理者権限で動作しているか確認](https://www.rootlinks.net/2014/08/28/%E3%83%90%E3%83%83%E3%83%81%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%8C%E7%AE%A1%E7%90%86%E8%80%85%E6%A8%A9%E9%99%90%E3%81%A7%E5%8B%95%E4%BD%9C%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E7%A2%BA/)

[コマンドプロンプトから管理者権限のコマンドプロンプトに切り替える](https://qiita.com/fjtter/items/4b7fe797ae1155c69dd9)


[^1]: `start.bat`が以降に処理を行わないことが前提
QtCreatorでコンパイラのバージョンを指定したかった

## 環境

Ubuntu18.04
QtCreator4.9.1

## 問題

QtCreatorで`ツール->オプション->Kits->キット`の中で使用したいコンパイラを切り替えても(例えばg++-8)GCCであればg++,Clangであればclang++が使われてしまう。

下の方に`CMake設定`があるが`CMAKE_CXX_COMPILER`を書き換えてもどうも無視される模様。

## 対処法

とりあえず`update-alternative`でg++をすり替えることで対処できた
[論文読み] Mobile Mapping SystemのMobileMappingSystemの三次元点群処理に関する研究(精密工学会 2011秋)

# Mobile Mapping SystemのMobileMappingSystemの三次元点群処理に関する研究(精密工学会 2011秋)

###### description: 論文読んでそのまとめ

自分なりに解釈したメモになります。
ミスがあったら優しく教えてください。
---

- Title
Mobile Mapping Systemの三次元点群処理に関する研究 複数レーザを利用した対向車除去
- Conference
2011年度精密工学会秋季大会学術講演会講演論文集

- Authors
小倉徹也，石川貴一朗，天野嘉春，橋詰匠（早稲田大学）

---

## どんなもの?
**車に取り付けた三次元点群センサで環境を計測した際に映り込む車の点群を除去する。
さらに、取り除いた部分の点群を周囲の点群を用いて補完する。**[^1][^2]

![img1](https://i.imgur.com/3GcLNco.png)

## 先行研究と比べて何がすごい？
車両前後方向に計4台のレーザを搭載した従来よりもレーザが多い新型のMMSが増えてきている。
このタイプは今までのタイプよりも車の影になる部分の点群も取れるようになる。
この研究はそのタイプに特化している点が今までと違うらしい。

## 技術の手法や肝は？
**路面をメッシュで区切り、メッシュ内の点群の高さの分散を利用する。**
まず車両進行方向に対して平行かつ垂直な1辺が1m四方のメッシュを配置する。
![img2](https://i.imgur.com/qtHEzs5.png)
黒枠がメッシュ，青線が走行軌跡，灰色の点が三次元点群，赤点が対向車両の点群を示している。

ここで、メッシュの内部については以下のようになると考えられる。

- 道路のメッシュ
平らなので点群の高さが均一であり、高さの標準偏差は小さくなる
- 車を含むメッシュ
車は立体物なので、高さの標準偏差は大きくなる

![img3](https://i.imgur.com/QJUD8qF.png)
閾値を超えたメッシュ内において路面の高さより高い点群を抜き出すことで、対向車両の点群を除去する。
この際、路面高さには近接するメッシュの中で路面のみの点群を含むメッシュの高さ平均値を用いる。

$$
Th = \frac{\sigma_{road} + \sigma_{sedan}}{2}
$$

## どうやって有効だと検証したか
MMSの計測データを用いて評価試験を行い，従来手法と比較を行った。
- 評価試験
2車線区間の国道約2.5kmにおいて，対向車88台を対象に行った。
(背景の誤検知の有無や評価基準についての言及はない)
- 試験の結果
  - 本手法
    88台全ての対向車の検出と除去を行うことができた．
  - 従来手法(グルーピング)
    79台のみが検出された．

## 議論
- 著者曰く
    - 問題
タイヤのように路面付近の高さの点群を全て除去することができないことがある。
    - 原因
近接する路面の高さ平均と、対象メッシュ内の路面の高さに差があることが考えられる。
    - 解決策
対象メッシュ内のヒストグラムから，路面のピーク値を検出し，ピーク値の高さを閾値に設定することが挙げられる．

- 私見
    - 問題
標準偏差を見ていることから壁と平面は閾値を超えないが、
例えば斜面45度の山があったとしたらそれは誤検知してしまうのではないか？
    - 解決策
画像を合わせて使うアプローチも考えられるかもしれない。

## 次に読むべき論文は？
MMS用の点群処理という需要があることが分かったため、
その分野の関連する論文を読んでみても良いかもしれない。

## 参考文献
[^1]: https://ci.nii.ac.jp/naid/130004660068/
[^2]: https://www.jstage.jst.go.jp/article/pscjspe/2011S/0/2011S_0_719/_pdf/-char/ja
Python3を初めて触ってみる

#初めてのPython3

ついさっきPython3を触る機会があったので書く。
きっかけとしてはBitFlyerで自動売買を自作したかったから。

##環境

MacPro
Atom

##Ver確認

```
python --version
```

を起動しPythonの2.2が入っていることを確認。
3系（Ver3以降）を使いたかったのであとでインストールする。

##まず最初に

よくわからないが、Homebrewというものが必要らしいのでインストールする。

```
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
調べてみるとパッケージマネージャーらしい（詳しくはわからない）

###Python3のインストール
```
 brew install python3
```

最初から読むとBrewでInstall何をPython3をと読める。

##ライブラリのインストール

よくわかっていなかったので調べまくって入れまくってしまった。

```
$ pip3 install numpy  
$ pip3 install scipy  
$ pip3 install matplotlib 
```
など実際に使ってるのかもわからず入れた。
正直入れなくてもよかった感がある。

##Atomのインストール

https://atom.io/

この公式サイトからDLできる。

しかし、後々後悔したのはJetBrainsの
https://www.jetbrains.com/pycharm/
にしておけばよかった。（元々JetBrains好き）

##インストール後
Atom内にplatformio-ide-terminalというプラグインをDL。
その後再起動したら、左下に＋マークが出てくる。
押したら、ターミナルみたく使えるから便利。

そしたらFile->NewFileを押し、自分の好きな名前でファイル作成
test.py(拡張子は調べた方がいいかも)

##HelloWorld
そしたら、

```test.py
print("HelloWorld")
```
と入力

その後コマンドにでディレクトリを合わせる
保存場所を/DeskTop/test/test.pyにしたので

```
cd DeskTop/test/test.py
```
を入力

その後

```
python3 test.py
```

を実行してあげればHelloWorldの完成

###感想

正直AndroidStudioやXcode、JSなどを普段触っている身としては
開発環境すごいめんどくさかった。
一番慣れていないのがコマンド操作。
正直cd ls ぐらいしかコマンド覚えていない身としてはハードルが高すぎた。
Pythonというものを理解していないので、あまり変なことは言えないが、
機械学習しないのなら触る必要はないのかなと思った。
空間的不変性を与えるモジュール、SpatialTransformerNetworks(NIPS2015)

# SpatialTransformerNetworks(NIPS2015)

###### description: PointNetの重要な基盤であるSTNについてのまとめ
###### url: https://arxiv.org/abs/1711.07399

概要しか書いていません。
よち詳しい説明を知りたい方は[論文解説記事](https://qiita.com/nkato_/items/125bd2e7c0af582aa32e)や論文を見に行くことを推奨します。

---

- Title  
**Spatial transformer networks**  [論文リンク:link:](http://papers.nips.cc/paper/5854-spatial-transformer-networks.pdf) [Github:link:](https://github.com/oarriaga/STN.keras) [ムービー:link:](https://drive.google.com/file/d/0B1nQa_sA3W2iN3RQLXVFRkNXN0k/view)
- Conference  
NIPS (Advances in neural information processing systems) 2015
- Authors  
Max Jaderberg, Karen Simonyan, Andrew Zisserman, Koray Kavukcuoglu
ファーストオーサーは**DeepMindAI**のリサーチサイエンティスト.

---

## どんなもの?
**入力画像の空間的補正(アフィン変換など)のパラメータを予測するモジュール**

予測に必要な部分は一部だけであるような画像(下図)に対しては、余分な箇所が予測に悪影響を及ぼす可能性がある。
他にも、入力画像に含まれる対象物が傾いている場合や、歪んでいる可能性も存在する。
筆者らは本研究で紹介する`Spatial Transformer`モジュールにより空間的不変性の問題を解消する。

![図1](https://i.imgur.com/hs6lTb1.png)
図1:歪んだMNISTデータに対する実験。画像から認識に必要な箇所のみを切り出し、その箇所の空間的歪みを補正している。(a)から(c)への変換が `Spatial Transformer` であり、ここで歪みを補正する。後に(c)から(d)で後続の`CNN`へとデータを流して推定している。

![図2](https://i.imgur.com/jzni1Mv.png)
図2：STNの概略図

## 先行研究と比べて何がすごい？
一応先行研究としては画像から必要そうな部分を切り取ったり、向きを補正したりするというアイデアはあるものの、end to endで学習できますという研究はこれが初めてらしい。

## 技術の手法や肝は？
**入力画像に空間的補正を行う微分可能なモジュールであること。
`CNN`など既存のネットワークにそのまま接続するだけで、学習方法などは特に変更することなく
補正能力を与えることができる。**

入力部分に接続するのが一番それっぽい使い方だが、論文中でも実験されていた通り、複数回モデルの途中に挿入するといった使い方や、`STモジュール`を並列に並べて画像中の複数のオブジェクトに対して変換をかけることもできる。

## どうやって有効だと検証したか
3つやってる。

### 1. 歪んだMNISTへの適応
MNISTに対して以下の歪みをそれぞれ与える。

  - R: 回転 (Rotation)
  - RTS: 回転、拡大、移動 (Rotation, Scale, Translation)
  - P: 射影変換 (Projective transformation)
  - E: 弾性的な歪み (Elastic warping) (場合によっては STNs で完全に戻すことが不可能になる)

以下の8種類のネットワークで実験を行った。

- `FCN` (Fully-Connected Net)
    ベースライン
- `CNN` (Convolutional Neural Net)
    ベースライン
- `ST-FCN` (STNsを導入したFCN)
  - Aff (アフィン変換)
  - Proj (射影変換)
  - TPS (Thin Plate Spline (画像上の特定の点(本実験では16点)を任意の場所にズラし画像全体を歪曲させる変換))
- `ST-CNN` (STNsを導入したCNN)
  - Aff
  - Proj
  - TPS

STNを導入することで、いづれの歪みに対しても誤答率が減少していることが分かる。
![](https://i.imgur.com/dEbnwbe.png)

### 2. Street View House Numbers
数字が書かれている看板なんかの、より現実に近いデータに対して実験を行う(StreetViewHouseNumbersデータセット)。
state-of-the-artを3.9%から3.6%へ更新した。
MultiModelではSTNを追加することにより6%遅くなった。

### 3. Fine-Grained Classification
CUB-200-2011 birds datasetに対して、筆者らの既存手法(CNN)に対して平行に並べたSTNを追加した。
精度の向上が見られた。

## 次に読むべき論文は？
PointNet、及びPointNetを読む上で必要になった論文

## etcs
論文で使った全てのネットワーク構造の詳細はまとめて付録につけていた。
実に$\frac {10}{15}$ページが付録であった。
SwiftUIのチュートリアル日記1

# この記事は何？
[Apple Developerサイトに掲載されているSwiftUIチュートリアル](https://developer.apple.com/tutorials/swiftui/creating-and-combining-views)で実践したことを忘備録として残しました。

## 実行環境
Xcode11 beta
macOS10.15 Catalina beta

# Creating and Combining Views
_Landmarks_ アプリを作る最初のチュートリアルです。

## セクション1: プロジェクトを作成して、キャンバスを理解する
SwiftUIを使用できる新しいXcodeプロジェクトを作成します。
キャンバスによるインタラクティブなプレビュー機能を使用するには、XcodeがmacOS 10.15 beta上で動作する必要があるようです。

### 手順1
Xcodeを起動して、_Create a new Xcode project_ を選択する。

### 手順2
プラットフォームのiOSタブから、_Single View App_ を選択して、_Next_ をクリックする。

### 手順3
Product Name に「Landmarks」と入力する。
_SwiftUI_ のチェックボックスをオンにする。
_Next_ をクリックする。
任意の場所にプロジェクトを保存する。

### 手順4
プロジェクトナビゲータにある _ContentView.swift_ ファイルをクリックして表示する。

````Swift:ContentView.swift
import SwiftUI

// １つ目の構造体（コンテンツとレイアウト）
struct ContentView: View {
    var body: some View {
        Text("Hello World")
    }
}

// 2つ目の構造体（プレビュー）
struct ContentView_Preview: PreviewProvider {
    static var previews: some View {
        ContentView()    // ← 1つ目の構造体のインスタンスかな
    }
}
````

- SwiftUIビューファイルには、デフォルトで２つの構造体が宣言されている。
- `View` プロトコルに適合した構造体で、コンテンツとレイアウトを定義している 
- ビューをプレビューする構造体

__あとで調べたいこと__
これまでの基本的なSwiftプログラミングでは、あまり見ない記述があったので...

- _View プロトコル_ とは
- _PreviewProvider_ プロトコルとは
- 構造体のプロパティは、計算プロパティなのかな
- `var body: some View` って、プロパティの型アノテーションにプロトコルを記述してる？

### 手順5
キャンバスにある　_Resume_ ボタンををクリックして、プレビューを表示する。
キャンパスは「Editor > Editor and Canvas to show it」から表示できる。

### 手順6
`body` プロパティにある `"Hello World"` を適当に変更する。（`"Hello SwiftUI"` とか）
コードを変更すると、プレビューに反映される。

__思ったこと__

- _ContentView.swift_ ファイルが、_UIKit_ の _ViewController.swift_
 に該当するのかな。
- 画面に行くつもコントロールを配置するときは、`ContentView` 構造体のプロパティとして定義するのかな。
- テキストのビューは__レイアウトに関して何も定義してないが、画面の中心になっている__なぁ。
シェア数つきはてブボタンを自分で作成した時のメモ（2019年6月現在）

緒事情によりシェア数つきのはてブシェアボタンを自作しなければいけなくなって
探しても古い情報が出てきたりしてつまづいたのでメモ

```html:html
<button class="hatebu">
    <a href="http://b.hatena.ne.jp/entry/【URL】" target="_blank">
        <p>ブックマーク<span class="number">100</span></p>
    </a>
</button>
```

CSSは省略

```javascript:javascript
var hatebuNum = $('.hatebu .number');

function countHatebu(url, selector) {
	var currentUrl = location.href; //URL取得
	var shareUrl = 'https://api.b.st-hatena.com/entry.count?url=' + encodeURIComponent(currentUrl); //UTF-8 文字エンコーディング
	$.ajax({
		url: shareUrl,
		dataType:'jsonp',
	})
	.then(
		//成功時
		function(res) {
			$('.hatebu .number').text( res || 0 );
		},
		//失敗時　非表示にする
		function(){
			$('.hatebu .number').css("display","none");
		}
	)
}
countHatebu('url', 'hatebuNum');
```

##はてぶシェア数取得
はてブのシェア数取得URLはb.hatena.ne.jpのドメインではなく**api.b.st-hatena.com**からはじまるものを使用。
https://api.b.st-hatena.com/エンコードしたURL を叩くとそのURLのシェア数が表示されます。
2019年6月現在、b.hatena.ne.jpでもリダイレクトされるため表示はされるものの、将来的に使えなくなる可能性があるらしいのでapi.b.st-hatena.comを使用した方がよさそうです。

- [はてなブックマーク件数取得API](http://developer.hatena.ne.jp/ja/documents/bookmark/apis/getcount)

> なお、API のエンドポイントのドメインは api.b.st-hatena.com となっていますが、現時点(2009年08月11日)では b.hatena.ne.jp ドメインでもアクセス可能ですが、将来的にはこの GET リクエストのAPIではb.hatena.ne.jp ドメインでは使えなくなる可能性がありますので、api.b.st-hatena.com をご利用ください。

##JS
今回はjQueryのオプションを使用しています。

`location.href`を使用してURLを取得
そのURLを`encodeURIComponent`でUTF-8へエンコーディングしたものへ置き換える
上記の通り、ちゃんとエンコードしないと表示されません。

通信成功時には「ブックマーク」の後ろ（`span.number`にあたる箇所）にシェア数が表示され、
通信失敗時にはdisplay:noneを使用してカウント数の項目を非表示にしています。

---
間違っている点、改善点があればやさしく教えてください。

参考にさせていただいた記事

- [はてなブックマーク件数取得API](http://developer.hatena.ne.jp/ja/documents/bookmark/apis/getcount)
- [おじさんが若い時はね$.ajax()のオプションでsuccessとかerrorとか指定していたんだよ（追憶）](https://qiita.com/tonkotsuboy_com/items/0722ad92f370ab0c411b)  
古い書き方をして書いてしまったので参考になりました。
[論文読み] Towards Viewpoint Invariant 3D Human Pose Estimation(CVPR2016)

# Towards Viewpoint Invariant 3D Human Pose Estimation(CVPR2016)
###### description: 論文読んだまとめ記事
###### url: https://arxiv.org/abs/1603.07076
自分なりに解釈したメモになります。
ミスがあったら優しく教えてください。

---

- Title  
Towards Viewpoint Invariant 3D Human Pose Estimation
- Conference  
CVPR2016
(Computer Vision and Pattern Recognition)
- Authors  
Albert Haque, Boya Peng*, Zelun Luo*, Alexandre Alahi, Serena Yeung, Li Fei-Fei
スタンフォードのコンピュータサイエンスをテーマにする研究室からの論文。
ファーストオーサーAlbertはポスドクで毎年のようにNIPS、ICCVへ論文を通している。
**音声認識や画像認識を医療分野に適応する研究**を行っており、特にデプス情報に関する研究が多い。
**デプスマップから患者が何時起きていつ寝たなどの行動を推定して記録するようなシチュエーションに関係する研究が多く**、この論文もその一環であるように考えられる。
また、ポケモンについても論文書いているなどおちゃめな側面もある。
> https://arxiv.org/pdf/1902.06208.pdf
---

## どんなもの?
頭上にあるデプスカメラの情報から人間の位置姿勢を推定する


## 先行研究と比べて何がすごい？
- 天井からの視点  
ポーズ推定を正面視点や側面視点のカメラで行うような研究は活発であるが、多くのカメラは高い位置に付いている。（ex. 商店や病院など）
**上部視点からの認識はオクルージョンのために従来手法で検出が難しく**、あまり研究されていない。
本手法は天井視点という困難な問題に対して、単一のデプスカメラによって人間の三次元位置推定をおこなう。


## 技術の手法や肝は？
3Dの空間的な情報から推論するだけではなく、視点に対してもロバストなネットワークを設計した。

![Fig.1](https://i.imgur.com/gTUnRq5.png)

- multi-task learnin  
- `CNN`、`RNN`、`1フレーム前に推定したポーズ`を組み合わせたモデル構造  

---

![Fig.3](https://i.imgur.com/co4L78i.png)

- `glimpse`(垣間見えるという意味) [ecurrent models of visual attention. NIPS 2014]  
本研究ではJ個のボディーパーツに対応する`glimpse`画像J枚を入力として利用する。
`glimpse`は特定の領域以外をぼやけさせて、強制的にモデルに対して特定の領域を重要視させる。

- 視点に対して不変な特長空間取得  
1. `glimpses`をpoint cloudに変換する  
2. A spatial transformer [STN(NIPS15)]を用いてモデルにとって解釈しやすいように切り出される(三次元の線形変換)  
**人工的オクルージョンが作られる**(?)
3. 移動したポイントクラウドは視点に対して不変な特長量となる  

---

![Loss](https://i.imgur.com/gKbEyQz.png)
頭上カメラはオクルージョンの問題が激しいため、損失関数を工夫していた。
具体的にはオクルージョンを考慮したボディーパーツの誤差（オクルージョンがあるときはlog(p)、無いときにはlog(1-p)となる）と、一般的なLocalizationの誤差の和を用いている。
~オクルージョンには推定した時の値が入っておらず、どういう意味でつけているのかがよく分からないので、よく論文を読み込んで確かめたい。~

## どうやって有効だと検証したか
![](https://i.imgur.com/quuGr6m.png)
推定座標と正解座標が10cm以内であれば正しいとしている。

## 参考文献
http://www.eccv2016.org/files/posters/P-3B-47.pdf
https://www.alberthaque.com/
http://vision.stanford.edu/feifeili/
https://www.alberthaque.com/projects/viewpoint_3d_pose/
#ruby ( #Rails ) の Date の期間同士を比較して「歯抜け」の日付を探す例

-  range を全て、日毎の配列要素に変える
- 配列から配列を引き算する

```rb
[63] pry(main)> base_days = [*Date.current .. Date.current + 1.week]
=> [Mon, 10 Jun 2019,
 Tue, 11 Jun 2019,
 Wed, 12 Jun 2019,
 Thu, 13 Jun 2019,
 Fri, 14 Jun 2019,
 Sat, 15 Jun 2019,
 Sun, 16 Jun 2019,
 Mon, 17 Jun 2019]

[64] pry(main)> diff_days =  [Date.current - 1.day, Date.current , Date.current + 3.days , Date.current + 6.days, Date.current + 1.year]

=> [Sun, 09 Jun 2019,
 Mon, 10 Jun 2019,
 Thu, 13 Jun 2019,
 Sun, 16 Jun 2019,
 Wed, 10 Jun 2020]

[65] pry(main)> rack_days = base_days - diff_days
=> [Tue, 11 Jun 2019,
 Wed, 12 Jun 2019,
 Fri, 14 Jun 2019,
 Sat, 15 Jun 2019,
 Mon, 17 Jun 2019]

```

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2170








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Bot Builder v4 : Microsoft Team に接続する

この記事では、開発したボットを Microsoft Teams に接続する方法を紹介します。

# 前提

すでに Microsoft Teams を使っていることとします。まだ使っていない場合は、以下のサイトから Office 365 E3 体験版を申し込んでください。

https://products.office.com/ja-jp/business/office-365-enterprise-e3-business-software
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/5989899b-bf5e-9562-f5f9-921b9a79ca08.png)

# 利用するボットの準備

今回は手軽につかえる Azure Bot Service で作成します。既にボットがある場合はスキップ。

1\. https://portal.azure.com より Azure ポータルにログイン。任意のリソースグループで「Web App Bot」を作成。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/037fd47c-4cfd-7b89-36eb-d18f46c37ee0.png)

2\. 任意のボットを作成。ここでは C# 基本ボットを選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/bd22fe06-e961-3466-d45a-60da979ba914.png)

3\. 作成完了後、Web チャットテストで動作を確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/143916c0-a4d9-ba79-adeb-dd24cf5d8179.png)

4\.「チャネル」メニューより「Teams」を選択して保存。特別な設定は不要。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/224022d5-d2e3-5c62-78d0-f50b0d4cd581.png)


# Teams への展開

Teams へ展開するには、サイドローディング用のパッケージを作成します。今回は GUI ですべて構成してみます。

1\. Teams より「アプリ」を選択し、「App Studio」を検索。インストール。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/a84f30e5-2a80-74be-3455-27480647965f.png)

2\. アプリで「開く」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/8cc5681d-f5f3-2683-0a69-a7a41973c75d.png)

3\. Manifest editor タブから「Create new app」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/7e754fdc-3229-22db-bf12-f4ef16e4f484.png)

4\. 名前や説明、パッケージ名、バージョンを設定。App ID は「Generate」から自動生成。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/5d5bd094-2108-2da3-e064-d2a02d74012d.png)

5\.「Capabilities」より「Bots」を選択し「Set up」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/aee06549-85db-4cf8-3824-6e7d5b473361.png)

6\.「Existing bot」を選択し、既存のボットから接続したいボットを選択。名前やスコープを設定して保存。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/84fd1342-9e08-1e45-d63f-2b2bfcb34162.png)

7\.「Finish」より「Test and distribute」を選択し、「Install」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/6cff5e93-7c8d-a7a8-c2c1-c654f7c651bc.png)

8\.「インストール」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/bcb02565-3c6b-0536-9d0c-4a63bb12da5d.png)

9\. ボットに話しかけて動作を確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/c38daef7-f700-2cae-14d2-bdda947b47ab.png)

10\. 全体への展開は「Finish」の「Submit」をクリック。ウィザードに従って公開。

# まとめ

Microsoft Teams はサイドローディングが必要という点で少し特殊ですが、それが分かれば他のチャネル同様に扱えます。是非お試しください。

[目次に戻る](https://qiita.com/kenakamu/items/6dc043cfc1f199032883)
DVD-RAMとは何か？その特徴、寿命、容量、価格は？

DVD-RAM（ディーブイディー・ラム）とは記録型DVDの規格の一つです。DVDフォーラムにより策定され、1998年4月に松下電器産業（現・パナソニック）と日立製作所から最初の製品が発売されました。
![DVD-RW.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432052/8eb9db5c-b5cf-33ba-c113-5e686a915e91.jpeg)


特徴は下記の通りです。

* 書き換えが可能で何度も記録できるディスクで、記録できる容量は片面1層で4.7GBです。
* およそ10万回の書き換えが可能で、DVD-RWやDVD+RWの100倍になります。
* Windows XPでは標準サポートされ、特別なライティングソフトを使用することなく、ハードディスクやフロッピーディスクなどと同じように使うことができます。

詳細は、https://b.hatena.ne.jp/entry/s/www.macxdvd.com/blog/suteki-what-is-dvd-rw.htm　までにご参照ください。

DVD-RAMの容量
12cmのDVDと同じく、DVD-RW容量が四つある。片面一層のDVD-RWは4.7GBで、ユーザファイルなどで実に利用できる容量は4.25GB。片面二層なら8.54GBで、両面一層は9.4GBで、両面二層の場合に最大17.08GBの容量が搭載されています。もちろんユーザーファイルと計算方式などで実に利用できる容量も引き下がります。

DVD-RAMの価格
もちろん配布用のDVDは一番安いものですが、DVD-RWもやすいです。むしろDVD-RW とはコーストパーフォーマンスが一番のDVDです。1回だけ書けるDVDと比べるとあまり高くないが、1000回も書き直しできます。録画でなくてデータ用繰り返しDVDのDVD-RAMは最大10万回にデータを変更できますが、価格が高めて、互換性も低いです。

DVD-RAMのファイル保存形式
データ用DVDとされるDVD-RWにはファイルの保存形式はパソコンと同じで、パソコンで順調に認識して利用できます。が、DVD-RW とは動画の記録用DVDので、映画などを保存する時に市販の映画DVDと同じく、拡張性が高いUDFで、Video_TSフォルダとAudio_TSフォルダで映画・動画を保存しています。

DVD関連情報：https://itroomsite.wordpress.com/category/dvd%E9%96%A2%E9%80%A3/
Swift：配列へのアクセス範囲など上限と下限のチェックが必要な時の条件文

今までout of rangeを避けるために

```swift:
if 0 =< value && value < 100 {
    // let v = array[value]
}
```

のように条件文を書いていたのですが，SwiftにはRangeという便利なやつがあるので，

```swift:
if (0 ..< 100).contains(value) {
    // let v = array[value]
}
```

という風に書けば良いことに今更気づきました．
switch文の中では普通に使っていたのですが，なぜかif文では律儀に条件２つのANDにしていました．．．
Android Q Beta4をWindows環境から書き込んだら失敗した（備忘録）

結論からいうと、Linux環境で書き込んだら上手くいった。

# 更新が降ってこない
Pixel 3aをAndroid Q ベータプログラムに登録したが、更新が降ってこないので、https://developer.android.com/preview/download.html にあるファクトリーイメージをダウンロードし、手動でインストールすることにした。

# 手動で焼いてみる at Windows10
Windows10からインストールすることにした。

Pixel 3aなので、*sargo-qpp4.190502.018-factory-348acd3a.zip*をダウンロードし、解凍。
中身は以下の通りだった。
- bootloader-sargo-b4s4-0.2-5402313.img
- flash-all.bat
- flash-all.sh
- flash-base.sh
- image-sargo-qpp4.190502.018.zip
- radio-sargo-g670-00019-190426-b-5509456.img

まず、Pixel 3aの開発者向けオプションを有効にし、OEMロック解除を有効にする。
次に、コマンドプロンプトで```adb reboot bootloader```を実行。
ブートローダーの画面になったら、```fastboot flashing unlock```を実行し、Pixel 3a側で音量ボタンと電源ボタンでブートローダーのアンロックを選択する。
そして、上記の*sargo-qpp4.190502.018-factory-348acd3a.zip*を解凍した中にある*flash-all.bat*を実行して終わったら再起動すればOK。

# これで焼けるはずだったが
*flash-all.bat*実行中に、```archive does not contain 'boot.sig'```のようなエラーが何行か書かれていた。
（メモしていなかったが、他にはuserdataだのrecoveryだの書かれていたので、諸々書き込みに失敗していた模様）
解凍したファイルの中にある*image-sargo-qpp4.190502.018.zip*か、imgファイルからの書き込みで失敗しているようだが、何度やっても上手く行かなかった。
zipを一度解凍し、再度圧縮するなんてこともしてみたが上手く行かず。
一度Android 9に戻そうともしたが、同様の理由で書き込みに失敗。

この状態では起動しても「端末おかしいぞ」的なエラーが出て起動できず、Pixel 3aが一度文鎮になりかけた。

# そういえばshファイルもあった
Windows環境がだめなら、Linux環境でいいんじゃね？と思い、DVD-RWにUbuntu 18を書き込み、DVDドライブから起動。
adbをインストールし、今度は*flash-all.sh*を実行すると、先程のエラーもなく、すんなり書き込めた。
無事に起動し、見事Android Q Beta4を拝むことができた。

# 結論：Linux環境から焼こう
もしかしたらWindows環境で上手くいった人もいるかも知れないが、少なくとも自分の環境ではダメだったので、黙ってLinuxから書き込んだほうがいいかも。
git commit --amendで3つのコミットを1つのコミットにまとめる

本稿ではgitで直近3つのコミットを1つのコミットにまとめる方法を説明する。

本稿で詳解する方法には次の特徴がある。

1. 最初のコミットのコミットメッセージだけが残る。
2. `git rebase -i`を使わない。

ちなみに、本稿で紹介する手順を手元の環境で[再現できるシェルスクリプトをGitHubで公開している](https://github.com/suin/git-playground/blob/master/squash-two-commits-into-one.sh)ので、実験してみたい方はそちらを試してみて下さい。

## やりたいこと

```
* 4999520 3つ目のコミット ──┐
* fbe2de7 2つ目のコミット ──┴──┐ この2つのコミットを
* 6669c6b 1つ目のコミット ←────┘ こっちにまとめ上げたい
* 0d75409 init
```

## ステップ1: git resetで直近2つのコミットをコミット履歴から除く

まず、コミットメッセージを捨ててもいい2つ目のコミットと3つ目のコミットを、コミットログから取り除きます。

```console
git reset --soft @~2
```

こうすると、直近2つのコミットはステージだけされた状態になります:

```diff
$ git status -s
M  file

$ git diff --staged
diff --git a/file b/file
index c39d3eb..1b45f5b 100644
--- a/file
+++ b/file
@@ -1 +1,3 @@
 改修1
+改修2
+改修3
```

また、コミットログは1つ目のコミットだけ残った状態になります:

```console
$ git log --oneline --graph --all
* 6669c6b (HEAD -> master) 1つ目のコミット
* 0d75409 init
```

## ステップ2: `git commit --amend`でもう一度コミットする

次に、git resetした対象を下記コマンドでコミットしなおします。

```console
$ git commit --amend --no-edit
```

これにより、元々3つあったコミットが最終的に1つのコミットになります。

```console
$ git log --oneline --graph --all
* 050afa9 (HEAD -> master) 1つ目のコミット
* 0d75409 init
```

差分:

```diff
$ git diff @~
diff --git a/file b/file
new file mode 100644
index 0000000..1b45f5b
--- /dev/null
+++ b/file
@@ -0,0 +1,3 @@
+改修1
+改修2
+改修3
```

以上で作業は完了です。
[Go]ベンチマーク関数で回数を指定する方法

Go1.12からベンチマーク回数を指定できるようになった。
`-benchtime`はベンチ実行時間であったが、指定した数値に`x`を付与することで「実行回数」として扱うことが出来る。

### 回数を指定する場合
```
go test -bench . ./app/... -benchtime 10000x
```

### 時間を指定する場合
```
go test -bench . ./app/... -benchtime 1h30s
```


参考
https://golang.org/cmd/go/#hdr-Testing_flags
pythonの便利な関数を3つ紹介！組み合わせや順列の計算を簡単に行いたい方必見

今回はpythonで組み合わせや順列の計算を行う際に便利な関数を紹介します。
しかし、プログラミング初心者であるため、内容に誤りがあるかもしれません。
誤りがあれば、どんどん指摘してください。

### combinations関数
組み合わせを列挙する際に便利な関数です。下記のコードは、3枚の数字カード（0,1,2）から2枚引いた時に取れるカードの組み合わせを出力します。

コード

        import itertools
        list(itertools.combinations(range(3),2))
結果

        [(0, 1),(1, 2),(0, 2)]

### permutaitons関数
順列を列挙する際に便利な関数です。下記は、3枚の数字カード（0,1,2）の並び順のパターンを出力します。
コード

        import itertools
        list(itertools.permutaitons(range(3)))

結果

        [(0, 1, 2),  (0, 2, 1),( 1, 0, 2), ( 1, 2, 0), ( 2, 0, 1), ( 2, 1, 0)]   #6パターン

### join関数
  
リストの中身を連結する際に便利な関数です。下記では、testリストの文字列を連結しています。

コード

        test = ['ab', 'c', 'def']
        result = ''.join(test)
        print(result)

結果

        abcdef
Rustの非同期フレームワークtokioを少しずつ試しながら勉強する　その２


> *注意事項（2019.8.19追記）*
> 本記事で使っている Future は、futures-rs( https://github.com/rust-lang-nursery/futures-rs )の0.1です。
> 今は Future もstdに取り込まれ、async/await も実装間近ですので、この記事の内容は参考程度に考えてもらうと良いかもしれません。

前回( https://qiita.com/mas-yo/items/17848c0bc35474a7db5d )から、随分時間が経ってしまいました・・・。

前回Futureをtokioから呼んでみるところまで行きましたが、今回は、ただ呼ぶだけでなくて、時間がかかる処理を実行して、その結果を受け取るというのをやってみましょう。

前回のソース

```Rust
use tokio::prelude::*;

struct FutureTest {

}

impl Future for FutureTest {
    type Item = ();
    type Error = ();
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        println!("poll called!");
        Ok(Async::Ready(()))
    }
}

fn main() {
    let f = FutureTest{};

    tokio::run(f);
}
```

Futureを実装するstructを作って、tokioに渡すと、poll()を呼んでくれるのでした。
さて、このFutureは何を意味するのか？
tokioのチュートリアルの、この辺りに書いてあります。

https://tokio.rs/docs/getting-started/futures/

簡単に説明すると、Futureは、時間のかかる処理（DBクエリなど）や、何かを待つ処理（ソケットからのデータ受信など）を表すのに使うということです。

そして、poll()メソッドが返す値が、処理の状態を表します。
リファレンスによると
https://docs.rs/futures/0.1.27/futures/type.Poll.html

- Ok(Async::Ready(結果)) --- 結果でた
- Ok(Async::NotReady) --- まだ結果出てない
- Error(エラー内容) --- なんか失敗した

ですね。
前回、Async::Readyを返して試してみましたので、今度は、NotReadyを返してみましょう。

```Rust
use tokio::prelude::*;

struct FutureTest {

}

impl Future for FutureTest {
    type Item = ();
    type Error = ();
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        println!("poll called!");
        Ok(Async::NotReady)   //まだ結果でてない！を表す
    }
}

fn main() {
    let f = FutureTest{};

    tokio::run(f);
}
```

これを実行してみると、poll()は呼ばれるのですが、プログラムは停止したままで、終わることがありませんでした。
NotReadyを返したので、結果が出るのを待ってるんですね！

では、結果が出たよ、ということを伝えるには、どうしたら良いのでしょうか？
そのためには、Task
https://docs.rs/futures/0.1.27/futures/task/struct.Task.html
これを使います。


```Rust
use tokio::prelude::*;
use std::thread;
use std::time;

struct FutureTest {
    poll_count: i32, //pollが呼ばれた回数
}

impl Future for FutureTest {
    type Item = ();
    type Error = ();
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        println!("poll called!");
        self.poll_count += 1;

        let task = task::current(); //現在のTaskを取得

        //別スレッドで時間のかかる処理を実行
        thread::spawn(move || {
            thread::sleep(time::Duration::from_millis(1000));
            task.notify(); //処理が終わったことを通知
        });

        if self.poll_count <= 1 {
            println!("not ready");
            Ok(Async::NotReady)   //一回目呼ばれた時は NotReady
        }
        else {
            println!("ready!");
            Ok(Async::Ready(()))  //次に呼ばれたら、Ready
        }
    }
}

fn main() {
    let f = FutureTest{poll_count:0};

    tokio::run(f);
}
```

実行結果

```
poll called!
not ready
[１秒後]
poll called!
ready!
```

実行結果を見てわかるとおり、notify() を呼ぶと、poll()が呼ばれることがわかります。

このように、メインスレッド（pollした方）は、待ち状態となっていて、別のスレッドで時間のかかる処理を実行し、結果が出たら、再びメインスレッドからpoll()が呼ばれる、という仕組みになっています。

tokioが何をしたいのか、だんだんわかってきた・・・！
その３につづきます。

今回作ったソース：
https://github.com/mas-yo/learn-tokio-step-by-step/tree/master/learn-tokio-2
stripeをfirebaseで使うときidempotency_keyをつけよう

先日firebase functionsとstripeの[サンプルコード](https://github.com/kboy-silvergym/stripe-payments-firebase)を公開したときに、

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Cloud Functionsでの決済の実装にはidempotency_keyを利用した方が安全ですよ！</p>&mdash; nori 村本章憲 (@1amageek) <a href="https://twitter.com/1amageek/status/1135463663408599040?ref_src=twsrc%5Etfw">June 3, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

てな感じで、noriさんにアドバイスを頂きました。その話をまとめます。

## Cloud Functionsは複数回呼び出される可能性がある

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Cloud Functionsは<br><br>&quot;複数回呼び出される可能性がある&quot;<br><br>これはみんな知っておいてください！！！！！！<a href="https://twitter.com/hashtag/Firebase?src=hash&amp;ref_src=twsrc%5Etfw">#Firebase</a> <a href="https://t.co/ztU14Q48q1">pic.twitter.com/ztU14Q48q1</a></p>&mdash; nori 村本章憲 (@1amageek) <a href="https://twitter.com/1amageek/status/1135468049073442816?ref_src=twsrc%5Etfw">June 3, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

なので、stripeで決済処理をする際、複数回叩かれて２重決済になったりしないように、対策が必要なわけです。

## stripe.jsのidempotency_key

順当にstripeのドキュメントを見ていくと、`idempotency_key`の実装については触れずに進んでいってしまうのですが、**github.com/stripe/stripe-node**の[Passing-Options](https://github.com/stripe/stripe-node/wiki/Passing-Options)に書いてありました。

idempotentは**べき等**という意味で、**べき等**とは、ある操作を1回行っても複数回行っても結果が同じであることをいう概念です。つまり`idempotency_key`をつければ、そのkeyがついたリクエストを複数行ったとしても１回だけの処理にしてくれるということです。

これをつけたコードがこちら。

```typescript
exports.createStripeCharge = functions.https.onCall((data, context) => {
    const customer = data.customerId;
    const source = data.sourceId;
    const amount = data.amount;
    const idempotencyKey = data.idempotencyKey;

    return stripe.charges.create({
        customer: customer,
        source: source,
        amount: amount,
        currency: "jpy",
        { idempotency_key: idempotencyKey } // これ！
    })
});
```
https://github.com/kboy-silvergym/stripe-payments-firebase/blob/master/functions/functions/src/index.ts#L29

すべてのstripe.jsのメソッドに対して、追加の引数として渡すとべき等にしてくれます。決済などの重複してはいけない処理にはつけた方が良さそうですね。

## 関連記事
- [「Firebase + stripe + iOS」でクレジットカード決済機能を作る](https://qiita.com/k-boy/items/c99cc681c29a1b250b4a)
- [stripeでephemeralKeysを作るときにエラーになった話
](https://qiita.com/k-boy/items/456f755d4775200b2c45)
低価格APDS9960互換モジュールをArduinoで使用

## はじめに
先日、ebayで購入した「APDS9960 APDS-9930 RGB and Gesture Sensor Module I2C IIC Breakout for Arduino」が到着したので、早速ダウンロードしたライブラリ (APDS-9960_RGB_and_Gesture_Sensor) を使用して、サンプルを実行してみましたが、下記のエラーが表示されてしまい、正しい値が表示されませんでした。

"Something went wrong during APDS-9960 init!"

##対策
調べた結果、モジュールとライブラリに登録されているDevice IDとが異なっていることがわかり、値を変更することで、それらしく動かすことができました。
修正は、ライブラリのsrcディレクトリにあるヘッダファイル SparkFun_APDS9960.h を下記のようにします。

####修正前
```
/* Acceptable device IDs */
#define APDS9960_ID_1           0xAB
```

####修正後
```
/* Acceptable device IDs */
#define APDS9960_ID_1           0xA8     // 0xAB → 0xA8
```
##おわりに
下記のサンプルを実行したところ、それなりの結果を得ることができました。

ColorSensor		センサーが認識した色のRGBそれぞれの値を取得
GestureTest		センサーの前で手を動かした際の移動方向の取得
stripeでephemeralKeysを作るときにエラーになった話

先日書いた[「Firebase + stripe + iOS」でクレジットカード決済機能を作る](https://qiita.com/k-boy/items/c99cc681c29a1b250b4a)において、

以下のようなワンタイムトークンを作るメソッドがあったのですが、

```typescript
exports.createStripeEphemeralKeys = functions.https.onCall((data, context) => {
    const customerId = data.customerId;
    const stripe_version = data.stripe_version;
    return stripe.ephemeralKeys
        .create({
            customer: customerId,
            stripe_version: stripe_version
        })
});
```

cloud functionsは一回のリクエストにも関わらず何回も実行することがあるという話を聞いて、安全のために[Passing Options](https://github.com/stripe/stripe-node/wiki/Passing-Options)に書いてある`idempotency_key`をつけることにしました。

以下のような感じ。

```typescript
exports.createStripeEphemeralKeys = functions.https.onCall((data, context) => {
    const customerId = data.customerId;
    const stripe_version = data.stripe_version;
    return stripe.ephemeralKeys
        .create({
            customer: customerId,
            stripe_version: stripe_version
        }, { idempotency_key: data.idempotencyKey })
});
```

そしたらstripeでエラーを吐くようになってしまいました。

<img width="796" alt="スクリーンショット 2019-06-10 11.55.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111366/a2da1325-6e4e-e443-a5c5-8c802b5fd624.png">

慌てて`idempotency_key`を外したりしてみたが、どうにもエラーがとまりませんでした。

## 結局

以下のような書き方で解決しました。[Passing Options](https://github.com/stripe/stripe-node/wiki/Passing-Options)に関しては、createの２つ目の引数に書いた方がいいみたいです。(TypeScripte, node.jsの知識足りない)

```typescript
exports.createStripeEphemeralKeys = functions.https.onCall((data, context) => {
    const customerId = data.customerId;
    const stripe_version = data.stripe_version;
    return stripe.ephemeralKeys
        .create({
            customer: customerId
        }, {
                stripe_version: stripe_version,
                idempotency_key: data.idempotencyKey
            })
});
```

以上。
Kotlin で MariaDB 10.4 に接続する

最近人気の [Kotlin](https://kotlinlang.org/) で MariaDB Connector/J (JDBCドライバ)を用いて MariaDB 10.4 に接続してみました。

[Java to Kotlin conversion](https://try.kotlinlang.org/#/Kotlin%20Koans/Introduction/Java%20to%20Kotlin%20conversion/Task.kt) を用いて，以前に書いた記事の Java サンプルコードを Kotlin に変換し，若干手作業で修正を行いました。

[MariaDB Connector/J で MariaDB 10.4 に接続する](https://qiita.com/cherubim1111/items/1267731ef92f6779d160)

# サンプルコード

```kotlin:src/main/kotlin/jdbc_sample/App.kt
import java.sql.*
import org.mariadb.jdbc.internal.util.constant.Version

object jdbc_sample {
    @JvmStatic fun main(args:Array<String>) {
        var conn: Connection? = null
        var stmt: Statement? = null
        var resultSet: ResultSet
        try {
            Class.forName("org.mariadb.jdbc.Driver")
            println("MariaDB Connector/J: " + Version.version + "\n")
            print("Connecting to DB...")
            conn = DriverManager.getConnection(
                    "jdbc:mariadb://192.168.2.104/mysql",
                    "db_user", "db_passwd")
            println("done.")
            stmt = conn.createStatement()
            resultSet = stmt.executeQuery("SELECT user, host FROM mysql.user")
            println("\nList of MariaDB users:")
            while (resultSet.next()) {
                var user = resultSet.getString(1)
                var host = resultSet.getString(2)
                println(user + "@'" + host + "'")
            }
        }
        catch (ex: SQLException) {
            ex.printStackTrace()
        }
        catch (ex: Exception) {
            ex.printStackTrace()
        }
        finally {
            try {
                if (stmt != null) {
                    conn?.close()
                }
            }
            catch (ex:SQLException) {}
            try {
                if (conn != null) {
                    conn.close()
                }
            }
            catch (ex: SQLException) {
                ex.printStackTrace()
            }
        }
    }
}
```

# build.gradle.kts

今回 [Gradle](https://gradle.org/) を使ってビルド，実行しました。
最初に以下のコマンドを実行します。

```
gradle init --type kotlin-application
```

以下の build.gradle.kts を以下のように修正しました。

```gradle:build.gradle.kts

plugins {
    id("org.jetbrains.kotlin.jvm").version("1.3.21")
    application
}
repositories {
    jcenter()
}
dependencies {
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    implementation("org.mariadb.jdbc:mariadb-java-client:2.4.4")
}
application {
    mainClassName = "jdbc_sample"
}
```

[MariaDB Connector/J](https://mariadb.com/kb/en/library/about-mariadb-connector-j/) は 2019-10-06 時点で最新版の 2.4.4 を用いました。

# ビルド

まずは gradle build でビルドだけ行ってみます。

```
C:\Users\foo\kotlin\jdbc_sample>gradle build

BUILD SUCCESSFUL in 1s
6 actionable tasks: 5 executed, 1 up-to-date
```

# 実行結果

gradle run でサンプルプログラムを実行します。

```
C:\Users\foo\kotlin\jdbc_sample>gradle run

> Task :run
MariaDB Connector/J: 2.4.4

Connecting to DB... done.

List of MariaDB users:
db_user@'%'
mysql@'localhost'
root@'localhost'

BUILD SUCCESSFUL in 2s
2 actionable tasks: 1 executed, 1 up-to-date
```

問題ないようです。
Cloud Functions APIを使ったPythonからのデプロイ


# はじめに

GCPのCloud Functionsに作成したZIPファイルをデプロイする際に、APIを使う方法のメモ。記事っぽく色々書こうと思ったけど時間が無いので一旦流れのみ。そのうち、時間を見つけて親切に書くかもしれない。

# サービスアカウントの用意

コンソールから`APIとサービス`を開き、`認証情報`を`認証情報を作成`で、`サービスアカウント キー`を選択。

役割の項目から、`Cloud Functions 開発者`と`ストレージのオブジェクト作成者`の権限をつけたサービスアカウントを作成して、JSONファイルをダウンロードする。

# 目的の関数をzip化

一旦は以下のような簡単なものを使うことにする。`test_function.zip`という名前で保存。

```python
def handler(request):
    return 'OK'
```

# Deployしよう

### セッションの立ち上げ

```python
credentials = service_account.Credentials.from_service_account_file('service_account.json')
scoped_credentials = credentials.with_scopes(
    [
        'https://www.googleapis.com/auth/cloud-platform',
        'https://www.googleapis.com/auth/cloudfunctions'
    ])

authed_session = AuthorizedSession(scoped_credentials)
```

### アップロードURLの取得

```python
url_base = 'https://cloudfunctions.googleapis.com/v1/'
```

```python
url = url_base + 'projects/{project_id}/locations/{location_id}/functions:generateUploadUrl'

response = authed_session.post(url,  headers=headers)

ret = json.loads(response.content.decode('utf-8'))

uploadUrl = ret['uploadUrl']
```

### zipのアップロード

```python
with open('test_function.zip', 'rb') as f:
    img_byte= io.BytesIO(f.read())

headers ={
    'content-type': 'application/zip',
    'x-goog-content-length-range': '0,104857600'
}

ret = requests.put(uploadUrl, data=img_byte.getvalue(), headers=headers)
```

### 最初のデプロイ

```python
url = url_base + 'projects/{project_id}/locations/{location_id}/functions'

headers ={
    'content-type': 'application/json'
}

body = {
  "name": "projects/{project_id}/locations/{location_id}/functions/{function_name}",
  "description": "test_upload",
  "entryPoint": "handler",
  "runtime": "python37",
  "sourceUploadUrl": uploadUrl,
  "httpsTrigger": {}
}

ret = authed_session.post(url, json=body, headers=headers)
```

### デプロイしたモデルを更新する場合

```python
url = url_base + 'projects/{project_id}/locations/{location_id}/functions/{function_name}'

ret = authed_session.patch(url, json=body, headers=headers)
```
2017プロジェクトをunity2019にあげたときに出たエラー

 declaration' is not available in C# 6. Please use language version 7.0 or greater.

Ａｓｓｅｔの下のmcsファイルの中身消せばいけた

language6みたいなことかいてある

プロジェクトを2017から2019にいきなり上げようとするなるみたい

ＵＮＥＴ系のライブラリーが抜けるっぽい？

過去のものをアップグレードするなら2018をはさんでわざわざ、一個ずつコンバートしなきゃいけないかも

めんどい
IE11 の initKeyboardEvent の使い方

やり方をいつもすぐに忘れてしまうので、備忘録として書いておく。今更感満載だけど、未だに需要があるので。


[MDN の Keyboard​Event​.init​Keyboard​Event()]
(https://developer.mozilla.org/ja/docs/Web/API/KeyboardEvent/initKeyboardEvent)ページではダメ。

[technet](https://technet.microsoft.com/en-us/windows/ff975297(v=vs.60)) とか [MSDN](https://msdn.microsoft.com/en-us/kb/ff975945(v=vs.80)) を見ないといけない。


```javascript
    const keyevent = {
      keydown: 'keydown',
      keypress: 'keypress',
      keyup: 'keyup'
    };

    const key_ie = {
      Backspace: 'Backspace',
      Tab: 'Tab',
      Enter: 'Enter',
      Shift: 'Shift',
      Control: 'Control',
      Escape: 'Esc',
      Space: 'Spacebar',
      End: 'End',
      Home: 'Home',
      ArrowLeft: 'Left',
      ArrowUp: 'Up',
      ArrowRight: 'Right',
      ArrowDown: 'Down',
      Delete: 'Del',
    };

    // 半角スペースで区切る
    const modifiers = 'Alt Control Shift';

    const event = document.createEvent('KeyboardEvent');

    // https://technet.microsoft.com/en-us/windows/ff975297(v=vs.60)
    event.initKeyboardEvent(
      keyevent.keydown,
      true,
      true,
      document.defaultView,
      key_ie.Tab,
      0,
      modifiers,
      true,
      ''
    );
    
    elem.dispatchEvent(event);
```
フロントにRazor(ASP.NET Core 2系)を使わないWebアプリでログアウトを実装

# フロントにRazor(ASP.NET Core 2系)を使わないWebアプリでログアウトを実装
## 概要
ASP.NET Core Identityのテンプレートでは、ユーザー登録、ログイン、ログアウトが実装されており実装方法を確認することができます。
ただ、SPAでWebアプリを組むとなるとRazorを使われている方は少数派でしょう。
私もフロントには、Vue.jsを使用しています。
Razor構文で、書かれたログアウト処理をどのように、Vue.jsで実装したら良いのか、調べてみました。

## Razor構文の確認
まず、Razorで書かれたテンプレートを見てみます。
実行して、HTMLにレンダリングされた結果も確認してみたのですが、Vue.jsへ簡単に移植するのは、難しそうです。

```:_LoginPartial.cshtml
@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
    <li class="nav-item">
        <a  class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @User.Identity.Name!</a>
    </li>
    <li class="nav-item">
        <form  class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Action("Index", "Home", new { area = "" })">
            <button  type="submit" class="nav-link btn btn-link text-dark">Logout</button>
        </form>
    </li>
}
else
{
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
    </li>
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
}
</ul>
```

## サーバーの処理で、ログアウトを行う。
Razor構文とASP.NETの処理を自前で、実装することにします。
HomeController::Logoutを呼び出して、URLをルートへ移動します。
このままだとブラウザをリロードするとログアウト処理されないので、タイミングをズラして、ブラウザリロードしています。
（理由は、良くわかりません・・・）

```:logout.vue
<template>
  <el-main>
    <el-button type="primary" plain @click="clickHandle">ログアウト</el-button>
  </el-main>
</template>

<script>
  export default {
    methods: {
      clickHandle() {
        this.$http.post(`${window.location.origin}/Logout`);
        this.$router.push('/');
        setTimeout(() => {
          location.reload();
        },
        500);
      },
    },
  };
</script>
```
HomeControllerでは、SignInManager.SignOutAsync()メソッドとクッキーの削除処理を行います。

```:HomeController.cs
namespace App.Controllers
{
    public class HomeController : Controller
    {
        private SignInManager<IdentityUser> signInManager;

        public HomeController(SignInManager<IdentityUser> signInManager)
        {
            this.signInManager = signInManager;
        }

        [Authorize]
        [HttpPost("Logout")]
        public async Task<IActionResult> Logout()
        {
            await this.signInManager.SignOutAsync();
            this.HttpContext.Response.Cookies.Delete(".AspNetCore.Cookies");

            return this.RedirectToAction(nameof(HomeController.Index), "Home");
        }
    }
}
```
とりあえず、この処理で、ログアウト後に、ログイン画面へ飛ばすことができました。
もっとスマートな実装方法があれば、コメントの方、よろしくお願いいたします。
ActiveStorageを用いて、画像を複数枚アップロードする方法

# ActiveStorageを用いて、画像を複数枚アップロードする

`ActiveStorageは、Rails 5.2以降のみ利用可能。`
Rails 5.2以降であれば、標準装備されております。
また、画像アップロード機能を実装する上でActiveStorageを利用される際は、**画像を保存するためのカラムやテーブルをご自身で用意する必要はありません。**
下記手順の中で自動生成されます。

## 本記事の対象
表題の通り、ActiveStorageを用いて、画像を複数枚アップロードする際の方法を**手順**を中心に説明しております。

## 手順
1. まずは、ターミナルにてActiveStorageをインストールするコマンドを入力。そして、マイグレート。

       
        $ rails active_storage:install

        $ rails db:migrate
                                 //このマイグレーションによって、以下のテーブルが自動生成される。
                                       * active_storage_blobs
                                       * active_storage_attachments


2.  該当するモデル（今回はItemモデルとする）に **has_many_attached :images** と記述する。
　　この **:images**というのはファイル名です。こちらは好きな様に命名することができます。

        (models/Item.rb)

        　　　　class Item < ApplicationRecord
  	      　　　　　 has_many_attached :images
        　　　　end


3. 次にコントローラーの編集を行う。

         (controllers/items_controller.rb)

              def create
                  @item = Item.create.params.require(:item).permit(:name, images: [])
              end

                       //今回は画像を複数枚取り扱うため、「 images: [] 」と配列型で記述する必要があります。

4.  フォームのtext_field内に手順2で記載したファイル名を記述する。

	      <%= form_with model: @item, local: true  do |f| %>
  		     <%= f.file_field :images, multiple: true %>
  		     <%= f.submit %>
	      <% end %>

                               //multipleとは、複数の値を取得できる様にするオプションです。



以上が、ActiveStorageを用いて、画像を複数枚アップロードする手順となります。
フォームで送信されたファイルは、コントローラーのcreateアクションを介して、今回自動生成された２つのテーブルに保存されます。


## 参考

https://qiita.com/hmmrjn/items/7cc5e5348755c517458a
https://qiita.com/narikei/items/d20e64ce3ae5b45bfa2d
Automation AnywhereのMetabotについて

##Metabotとは
Automation Anywhere上で使用できるプログラムをひとまとめにしたもの。
所謂ライブラリのようなもの。
現在は、Bot Storeにて提供が行われている。

##Metabotをインストールしてみる
まず、Automation AnywhereのBot Storeにアクセスする。
Bot StoreへはControl Roomか検索エンジンからアクセスすることができます。

例)Control Roomからアクセスする場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430538/fb6d5779-b4cb-fb20-f140-c15ebe2200ea.png)

VISIT BOT SOTREをクリックすることでBot Storeページへ遷移できます。

・Bot StoreのTOPページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430538/71155526-c722-88fd-5217-c588fbc02f32.png)

ここから用途に合ったMetaBotを探し、インストールしていきます。
MetaBotのダウンロードおよびインストールにはBotStore用のアカウントが必要なので作成しておきましょう。

インストールしたいMetaBotが見つかったら、詳細ページからインストーラをダウンロードします。

・MetaBot詳細ページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430538/95e28900-026f-ee51-c082-cfef4af4223c.png)

Get BotボタンをクリックすることでMetaBotインストーラのダウンロードが始まります。

インストーラを実行し、進めていくとライセンスキーの入力を求められます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430538/fb7bccaa-69ea-161b-38c1-d4f43b13f771.png)

ライセンスキーは、アカウントの「MyDownLoad」から入手できます。
BotStoreページ右上のボタンからMyDownLoadページへアクセスできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430538/1d40c944-8deb-5d8a-2667-43160203b3ab.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430538/02b68a12-beb9-0ef3-5d17-56d1dcb40ba6.png)

ここでMetaBotごとのライセンスキーを入手できるので、ライセンスキーを入力してインストールを進めます。

##MetaBotを使ってみる
インストールされているMetaBotは、AutoMation Anywhereのスタートページなどで確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430538/1f11baf6-f97a-4b52-6fbe-4fb6a5119074.png)

MetaBotを使用する際は、タスク編集画面右からMetaBotsタブをクリックし通常のコマンドと同じようにドラッグ＆ドロップすることでコマンド編集画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430538/182deae9-330a-d76c-e7b1-d9eb0ce6395a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430538/3f6e92af-1ef0-1c11-1f01-87e81d43e0b2.png)

編集画面でInput/Outputパラメータをそれぞれ設定しSaveすることで、そのコマンドを実行するようになります。

MetaBotを駆使することでより様々な自動化を実現できます。
C++でglobして、ついでにその中にあるテキストファイルを読み込む

初投稿です。
C++でPythonの `glob.glob()` みたいなことがしたいなーと思って軽く困ったので、tipsとして残しておきます。また、その中にあるテキストファイルの読み込みも少し詰まったのでそれに関してもついでに載せときます。

## C++のglobでディレクトリ内のファイルを取得
まず、ディレクトリ構造は以下の通りです。

```
$ tree
.
├── input
│   ├── sample01.txt
│   ├── sample02.txt
│   ├── sample03.txt
│   └── sample04.txt
└── main.cpp
```

`input` ディレクトリ下のテキストファイル4つを `glob` を用いてワイルドカードで取得します。

``` c++:main.cpp
#include <iostream>
#include <string>
#include <vector>
#include <glob.h>
using namespace std;

vector<string> get_file_path(string input_dir) {
    glob_t globbuf;
    vector<string> files;
    glob((input_dir + "*.txt").c_str(), 0, NULL, &globbuf);
    for (int i = 0; i < globbuf.gl_pathc; i++) {
        files.push_back(globbuf.gl_pathv[i]);
    }
    globfree(&globbuf);
    return files;
}

int main(int argc, char* argv[]) {
    string input_dir = argv[1];
    vector<string> files = get_file_path(input_dir);
    string f;
    for (const auto& f : files) {
        cout << f << endl;
    }
    return 0;
}
```

``` :出力
$ g++ -o main main.cpp
$ ./main ./input/
./input/sample01.txt
./input/sample02.txt
./input/sample03.txt
./input/sample04.txt
```

正常に取得できました。

## テキストファイルを読み込む

次に、 `fstream` を用いてテキストファイルを読み込んで行きます。
まず、テキストファイルの内容はそれぞれ以下のようになっています。

``` :sample01.txt
5
```

``` :sample02.txt
3.6
```

``` :sample03.txt
9 19 75 2
```

``` :sample04.txt
100 23 9.2
0.1
```

コードは以下の通りです。先ほどのコードに `read_text` 関数を加えました。

``` c++:main.cpp
#include <iostream>
#include <string>
#include <vector>
#include <glob.h>
#include <fstream>
#include <cmath>
using namespace std;

vector<string> get_file_path(string input_dir) {
    glob_t globbuf;
    vector<string> files;
    glob((input_dir + "*.txt").c_str(), 0, NULL, &globbuf);
    for (int i = 0; i < globbuf.gl_pathc; i++) {
        files.push_back(globbuf.gl_pathv[i]);
    }
    globfree(&globbuf);
    return files;
}

double read_text(string f) {
    ifstream ifs(f);
    string l;
    double sum_val = 0;
    int first, last, count = 0;
    while (getline(ifs, l)) {
        count = 0;
        first = 0;
        last = l.find_first_of(" ");
        while (first < l.size()) {
            string subStr(l, first, last - first);
            sum_val += atof(subStr.c_str());
            first = last + 1;
            last = l.find_first_of(" ", first);
            if (last == string::npos) {
                if (count == 0) break;
                else last = l.size();
            };
            count++;
        }
    }
    return sum_val;
}

int main(int argc, char* argv[]) {
    string input_dir = argv[1];
    vector<string> files = get_file_path(input_dir);
    string f;
    for (const auto& f : files) {
        cout << f << endl;
        cout << "sum = " << read_text(f) << endl;
    }
    return 0;
}
```

``` :出力
$ ./main ./input/
./input/sample01.txt
sum = 5
./input/sample02.txt
sum = 3.6
./input/sample03.txt
sum = 105
./input/sample04.txt
sum = 132.3
```

出力は、テキストファイル内の数字の和を返しています。

## 参考ページ
* [C言語でglob](https://qiita.com/sassy_watson/items/03c16bd03b56e5579477)
* [C++でファイル読込み パターン別まとめ](https://fa11enprince.hatenablog.com/entry/2014/04/03/233500)