OmniAICreator/Qiita-1.07M huggingface dataset:
Boostnote（Markdown）に詰まって2時間格闘した話

## まずはじめに
Boostnote、すごくいいです。
Markdown記法は慣れると簡単かつ自分好みに、わかりやすい形でメモを取れるので非常に便利。
Boostnoteは動作が軽いしオシャンでシンプルなレイアウトがすごくいい。

### 導入の経緯
@yakipuddingさんの[アウトプットを習慣化させる](https://yakipudding.qrunch.io/entries/4WVtBzaX4x0WPNFx)という記事を読んでいて
> インプットを記録する習慣をつける
> ブックマークでも本に付箋でも、学びが合ったところに印を付ける
> 学びがあったことのメモをとる（個人的にはBoostnoteとかおすすめ）

ほーBoostnoteって聞いたことないけど調べた感じ良さそうじゃーん！
Evernoteの代わりになりそうだしスマホにも入れちゃおー☆ﾐ

### 詰まった内容
#### 1.iOSアプリが全然見つからない。
~~**結論から言うと、2019/01/19現在何らかの理由でApp Storeの検索にヒットしないようになっている、または存在しないと思われます。**~~

これに30分格闘しました。
iOSとAndroidをリリースしたよ！みたいな記事や、数ヶ月前にアップデートしている履歴もあるのにApp Storeで検索しても全く引っかからない。
なにこれどういうこと？とGoogleさんに問い続けてみた結果、なんとなくふんわりとした内容で教えていただきました。

~~**公式の情報ではないので間違っている可能性はあります。ただただ僕がアホで見つけられなかっただけかもしれません。もし見つかったらなんでもいいので連絡ください。**~~

追記
jutaroi01さんから情報提供をいただきました。
>モバイルアプリについては開発が凍結されているとのことです。
>>Temporary stop of Boostnote-mobile · Issue #201 · BoostIO/boostnote-mobile · GitHub
https://github.com/BoostIO/boostnote-mobile/issues/201

2019/05/15現在も開発凍結中のようです…。


#### 2.Markdown記法に慣れるためにやったこと
ここQiitaやはてなブログやらで当たり前のように使われているMarkdown記法。
HTMLをめちゃくちゃ簡易的に書けます。みたいなもんだと僕は思っています。間違っていたらごめんなさい。
数年前に知って使ってみたときは文末に半角スペース二回打たなきゃ改行できなかったので日本語ではぜってーはやんねーわ淘汰されてしまえとすら思っていました。ごめんなさい。

ということで知ってはいたけど用法用量は知りませんという状態だったので[こちらの公式ブログ](http://boostnote.hatenablog.com/entry/2017/09/25/123956)をノートにコピペしてチートシート代わりにして今書いています。
リスト（箇条書き）やチェックボックスが使えることは知っていたのですが、Boostnoteは更に下図のようなフローチャートも作れるようです。

![20170923181108.png](https://cdn-ak.f.st-hatena.com/images/fotolife/j/junp0819/20170923/20170923181108.png)

**全く素晴らしい。Boostnote及びMarkdownバンザイですね。**

### まとめ
そんなこんなでMarkdown記法に慣れるためにこうして記事を書いてみてわかったことですが
* Markdownは慣れると非常に書きやすい。
* というかほんの数時間で意外と慣れる。
* ~~フローチャートとか一生使わんわ…~~
* **もっと流行れ。**



### 参考文献
* [@yakipudding](https://qiita.com/yakipudding)(2018) [『Boostnoteはいいぞ』 - Qiita](https://qiita.com/yakipudding/items/14f4304ca6196c956e85)
* [@sea_ship](https://qiita.com/sea_ship)(2018) [『Markdown+UMLが書きたいならBoostnoteがおすすめです！』 - Qiita](https://qiita.com/sea_ship/items/d387f1a44a6cfe611888)
*  [Boostnote公式ブログ](http://boostnote.hatenablog.com/)(2017) [『仕事効率、学習効率を加速させるMarkdown記法の紹介』 - Boostnote](http://boostnote.hatenablog.com/entry/2017/09/25/123956) 


こうやって参考文献をまとめるとむちゃくちゃ面倒でした。
無理してアカデミックな感じだしてかしこを演じようとしてごめんなさい。
【fastlane】ビルドナンバーを自動生成する際に前回よりも番号が減った問題の原因を探る

# 経緯

fastlaneでビルドナンバーを自動で設定する際に、
なぜか前のバージョンよりも数が減ってしまう現象に遭遇しました。

根本的にfastlaneやgitの知識がないことが原因ではありますが
はじめは何が起きているのかがわからず
原因を調べていく中で知らなかったことがたくさん知ることができたので
記録として残しておきます。

# ビルドナンバーの設定方法

number_of_commitsというメソッドを使っており、
↓の記載にあるような設定をしていました。
https://docs.fastlane.tools/actions/number_of_commits/

```ruby

build_number = number_of_commits(all: true)
increment_build_number(build_number: number_of_commits)
```

ドキュメントにも書いてある通り
**全コミット数をカウントする**
ということなので
開発を進めてコミット数が増えれば
自動でビルドナンバーは増えていくものだと思っていました。

しかし
あるタイミングで自動生成をしたときに
**なぜかビルドナンバーが減っていました。**

# 原因を探す

最初は何を調べればよいかもわからない状況ではありましたが
fastlaneのドキュメントからソースコードを見てそこからヒントが得られました。

```rb

def self.run(params)
  if is_git?
    if params[:all]
      command = 'git rev-list --all --count'
    else
      command = 'git rev-list HEAD --count'
    end
  else
    UI.user_error!("Not in a git repository.")
  end
  return Actions.sh(command).strip.to_i
end

```

今回はパラメータにallにtrueを設定していたため

```shell

git rev-list --all --count
```

がというgitのコマンドを叩いていることがわかりました。

# git rev-list

これが何をしているのかを調べたところ

```
List commits that are reachable 
by following the parent links from the given commit(s),
```

つまり、ある特定のコミットの親のリンクを辿って発見できたコミットのリストを表示するというものでした。

# --all

--allを付けることで

```
Pretend as if all the refs in refs/, along with HEAD, 
are listed on the command line as <commit>.
```

refs/の下にあるreferenceを全て対象とすることになります。

※そもそもrefsって何だということに関しては↓を参照
https://git-scm.com/book/ja/v1/Git%E3%81%AE%E5%86%85%E5%81%B4-Git%E3%81%AE%E5%8F%82%E7%85%A7

要はブランチとタグの数だと思っています。(間違っていたら教えてください:sweat_smile:)

# --count

最後にcountが付いているのでこのリストの合計数を数えています。

# 原因がわかる

ちょっと前にブランチの運用方法が変更され、
過去に作業していたブランチの整理が行われていました。

これによってブランチの数が減っていたためcount数が減っているようです。

また
開発はブランチを切ってmasterへマージをするような運用で
定期的に不要なブランチの削除も行われるため
数が必ずしも増え続けていくという訳ではないこともわかりました。

# 対策案

代替案を見つけなければと思っていた際に
↓のドキュメントから辿れるExampleの中で時間をビルドナンバーに設定しているものがありました。
https://github.com/fastlane/examples/blob/master/Artsy/eidolon/Fastfile

上記の例のポイントとしては、使用したビルドナンバーをgitにコミットしてプッシュしている点です。

これはbitriseなどのCIで実行する場合に必要な処理で
下記のファイルのビルドナンバーが変更がされたかどうか(逆にこれら以外は変更されていないこと)を
fastlaneの方でチェックしているようです。

```
All .plist files
The .xcodeproj/project.pbxproj file
```

https://github.com/fastlane/fastlane/blob/ba72a484f81c09eac616ac821b0186667835843f/docs/Actions.md#using-git


まだやってみたという段階ですが、
ビルドナンバーの更新やgitへのプッシュは無事にできているようです。


# まとめ

知識がないため
最初は何を調べていいのかもわからない状況でしたが
調べていく中で原因が見えてきてスッキリしました。

こういった開発環境構築の知識は
言語やフロントサイド、サーバサイドなどの領域を超えて活かせますので
これからもコツコツと知識を増やしていけたらいいなと思っています。


参考資料
https://stackoverflow.com/questions/35801385/can-git-rev-list-all-count-ever-go-down
sequelizeでDATE_FORMATを使った処理を書く

`sequelize`で`DATE_FORMAT`を使ったSQLを書きたい場合の備忘録。
集計するときとかに`DATE_FORMAT`使って書くけど、それを`sequelize`ではどうやって実現するのか？と調べてみたメモです。

こんな感じで、今月作成したユーザ情報を取得する`SQL`を`sequelize`を使って書きたい。
(実際に集計する場合は`COUNT(*) as count`になるでしょうか)

```sql
SELECT
  *
FROM
  users
WHERE
  DATE_FORMAT(createdAt, '%Y%m') = DATE_FORMAT(NOW(), '%Y%m')
```

`node.js with sequelize`で書くと下記のようになる。

```js
(async () => {
  /*
  ・
  ・ sequelizeの読み込みなどの処理は割愛します
  ・
  */

  // 現在の日付を参照するため、ここではmomentを使おうと思います
  const moment = require('moment');
  
  /*
   * UserはModelです
   * http://docs.sequelizejs.com/manual/tutorial/models-usage.html
   */
  const users = await User.findAll({ 
    where: sequelize.where(sequelize.fn('DATE_FORMAT', sequelize.col('createdAt'), '%Y%m'),  moment().format('YYYYMM'))
  });
  
  // 今月作成したユーザ情報のmodel instancesが表示されます
  console.log(users)
})();
```

以下、メモ。と参照したドキュメントのURL。

`sequelize.where`を使って`where`を作成している。
`moment().format('YYYYMM')`で取得した今日の日付の`YYYYMM`形式を、引数として渡している。
http://docs.sequelizejs.com/class/lib/sequelize.js~Sequelize.html#static-method-where

`sequelize.fn('DATE_FORMAT',`を使って`DATE_FORMAT`を実現できるよう。
http://docs.sequelizejs.com/class/lib/sequelize.js~Sequelize.html#static-method-fn

`sequelize.col`は引数に対象となる`column`を入れることで、対象DBのカラムを表現してくれるobjectを返してくれる。
ここでは`createdAt`を指定することで、`ユーザの作成日`を対象としている。
http://docs.sequelizejs.com/class/lib/sequelize.js~Sequelize.html#static-method-col


```js
    where: sequelize.where(sequelize.fn('DATE_FORMAT', sequelize.col('createdAt'), '%Y%m'),  moment().format('YYYYMM'))
```

`sequelize`を使い始めて半年、未だにドキュメントを読むのに苦労している自分です(遠い目)
JavaScriptで文字列から一意の値を生成する関数

文字列から一意の値を生成する、ハッシュ関数[^1]のような処理をいくつかまとめます
どれもお遊び程度のものなので実際に使うときは自己責任で！

[^1]: と呼べるか怪しいが...

## 文字列の長さ

```js
const hash = str => str.length
```

名前などを入力して、同じ入力だと同じ結果が返ってくるおみくじ系のアプリ[^2]ではおなじみですね！[^3]

[^2]: っていうのかは知らん
[^3]: なお、サンプル数１。

## 文字コードの合計

```js
const hash = str => Array.from(str).reduce((prev, current) => prev + current.charCodeAt(), 0)
```

`Array.from`で一文字ずつに分割して、それを`reduce`で文字コードに変換しながら足していくだけ。
lengthよりかは想像しづらいし、一文字変えただけで変わってしまうなんともハッシュ関数っぽい！

今はまだ２つですが思いついたらどんどん追加していく予定です！
Shell Scriptでcatに文字列を渡す

言語処理系のテストを書いていると、ファイルにプログラムを保存して処理系に渡すまでをシェルスクリプト内で完結させたい時があります。
catコマンドは、ターミナルでなら、入力し、Ctrl+Dで終了できますが、シェルスクリプトで同じことをしようとすると、そのままだと標準入力に書き込むことができません。
結論を言うと、`<< 任意の文字列`をコマンドの最後に書き込み、入力したい文字列を改行した後に書き、最後に`任意の文字列`で締めくくると、標準入力に文字列を書き込むことができます。

```shell:test.sh
#!/bin/bash
cat > testfile.txt << EOI
Hello, world
EOI
```

記号の`<<`は、囲まれた文字列を標準入力にリダイレクトする効果があります。
変種として、`<<-`があり、これはtab文字を無視する以外は、`<<`と同じです。

PythonのREPLなどの対話型プログラムでも有効です。

```shell
#!/bin/bash
python << EOI
print("hello")
print("goodbye")
n = 1 + 1
print(n)
EOI
```

# 参考サイト

http://tldp.org/LDP/abs/html/here-docs.html
いらすとやから始めるARKit

### みなさんARKit触っていますか？
- 3Dモデルがないと触ってもつまらなさそう
- そもそも3D難しそう

などの理由で触っていない方も多いと思いますが、
今回は少ないコードでいらすとやの画像1枚から始めるARKitを解説しようと思います。

#### プロジェクト作成
まずはARKit用のプロジェクトを作成するところから。
Augmented Reality Appを選択してプロジェクトを作成します。
<img width="500" alt="スクリーンショット 2019-01-19 1.20.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/45477/0ef1de88-39ac-c3bb-efcd-ac558f5a667f.png">

プロジェクトを作成したら何も変更せず、実機インストールしてみましょう。
Qiitaの記事などでよくみる例の飛行機がでてきますね。
これでプロジェクトの作成ができたので次はいらすとやの画像をARオブジェクトとして表示しましょう。

#### ARオブジェクトの作成

私はイチゴが好きなのでこの画像をARオブジェクトとして表示させます。
皆さんはイチゴじゃなくてりんごやバナナ、メロンでもいいです。
カバやゴリラでも問題ありません。
<img width="200" src="https://qiita-image-store.s3.amazonaws.com/0/45477/08ca4fcc-0b15-6c11-348c-b06bb4164eeb.png">

ARオブジェクトにする画像を決めたらAssets.xcassetsの中に入れます。
<img width="500" alt="スクリーンショット 2019-01-19 1.30.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/45477/da8963d5-1945-ecec-d55c-b538da21af1d.png">

次に平面オブジェクトをコードで作成します。
ARKitの世界では`1 = 1メートル`なので下記のコードでは、
`横20cm x 縦20cm`の平面オブジェクトが生成されます。

```swift

func addPlane() {
    guard let image = UIImage(named: "strawberry") else { return }
    let node = SCNNode()
    let plane = SCNPlane(width: 0.2, height: 0.2)
    plane.firstMaterial?.diffuse.contents = image
    node.geometry = plane
    node.position = SCNVector3(0, 0, -0.5)
    self.sceneView.scene.rootNode.addChildNode(node)
}
```

- オブジェクトのサイズ指定（横20cm x 縦20cm）  
  `let plane = SCNPlane(width: 0.2, height: 0.2)`

- 画像を平面オブジェクトのテクスチャとして指定
`plane.firstMaterial?.diffuse.contents = image`

- AR空間のどこに配置するか指定（x: 0cm, y: 0cm, z-50cm）
`node.position = SCNVector3(0, 0, -0.5)`
細かい説明は省きますが-0.5でカメラ位置から50cm奥に配置されます。
※0.5だと50cm手前に配置される
詳しく知りたい方は@k-boyさんの[ARKitのための3D数学](https://qiita.com/yamataku29/items/a14810585149b4dcb260)が非常にわかりやすいので是非読んでみるのをお勧めします。

- 作成した平面オブジェクトを描画
`self.sceneView.scene.rootNode.addChildNode(node)`

これでオブジェクトの作成は終わりなのでこの関数をViewDidLoad()で呼び出すと画像がARとして表示されます。

#### おわりに
今回はARKitや3Dに関しての知識がなくても簡単にARKitを使えるというテーマで書いたのでだいぶ内容が簡素な感じになりました。
GitHubで複数リポジトリに存在する同じパスのファイルを追加、変更するPRをまとめて複数作る

# やりたいこと
以下の3つのリポジトリが存在するとします。
* user/repo1
* user/repo2
* user/repo3

これらは別のリポジトリですが、全てのリポジトリに`./source/test/file.txt`というファイルが存在するとします。
ファイルの内容は以下です。

```
aiueo
abcde
12345
```

これを

```
aiueo
abcde
12345
XYZ
```

にするPRをuser/repo1、user/repo2、user/repo3全てに作成します。

#やったこと

[multi-repos-pr](https://github.com/inabajunmr/multi-repos-pr)をチェックアウトし、reposファイルに当該のリポジトリ名一覧を設定、sourceディレクトリ配下に変更するファイルを配置して、commits.shを実行します。

## commits.sh

```shell
#!/bin/sh

BRANCH_NAME=BRANCHNAME # 作成されるブランチの名前
COMMIT_COMMENT="COMMITCOMMENT" # コミットコメント
PR_COMMENT="PRTITLE\n\nPRCOMMENT" # PRのタイトルと内容
while read line
do
  git clone git@github.com:${line}.git
  cd "$(echo ${line} | sed -E s/^[^\/]+.//)"
  git branch ${BRANCH_NAME}
  git checkout ${BRANCH_NAME}
  rsync -r ../source/ ./
  git add .
  git commit -m "${COMMIT_COMMENT}"
  git push -u --set-upstream origin ${BRANCH_NAME}
  echo ${PR_COMMENT} | hub pull-request -F -
  cd -
done < repos

```

パワープレイです。何かこういうことをするのによさげなツールがあったら教えてください。

`repos`ファイルに記載したリポジトリを1つずつgit cloneして、branchを作成し、sourceディレクトリ配下をチェックアウトしたディレクトリにrsyncで同期しています。
その後git addしてコミットしてプッシュし、[hub](https://github.com/github/hub)コマンドでPRを作成しています。

詳細な利用方法は[README.md](https://github.com/inabajunmr/multi-repos-pr)を参照ください。
IntelliJ IDEAでなんらかのプロジェクトを開いた状態で違うプロジェクトをインポートする

# File -> New -> Project from Existing Sources
<img width="684" alt="スクリーンショット 2019-01-19 2.16.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/220908/698f024a-afa6-80bf-ed7d-19785e0e885f.png">

# Import project from external model
<img width="708" alt="スクリーンショット 2019-01-19 2.17.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/220908/f12e20b2-da1c-09d1-d486-b6ceca9c2036.png">
きーたのとれんどをゆるふわにする

なにかいろいろとありますが、とりあえずとれんどがゆるふわになればみんなさんあらそうきもおきなくなるんじゃないでしょうか。
なのでゆるふわにしてみました。

![qqq.gif](https://qiita-image-store.s3.amazonaws.com/0/42193/ffe04f05-4a84-dfc2-b539-a14e070e55eb.gif)

## かいせつ

[くろもじ.js](https://github.com/takuyaa/kuromoji.js)をつかってよみをしゅとくし、ひらがなにへんかんしています。

## そーす

```js:script.js
(function (d, script) {
    function kanaToHira(str) {
        return str.replace(/[\u30a1-\u30f6]/g, m => String.fromCharCode(m.charCodeAt(0) - 0x60));
    }
    function yurufuwa(token) {
        // 数はそのまま
        if (token.pos_detail_1 === '数') {
            return token.surface_form;
        }

        const target = token.reading || token.surface_form;
        return kanaToHira(target);
    }

    // 辞書読み込み時のurlがおかしいのでとりあえずの方法で回避
    const open = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function (m, url, b) {
        if (url.indexOf('https:/yaegaki') == 0) {
            url = url.replace('https:/yaegaki', 'https://yaegaki');
        }
        return open.call(this, m, url, b);
    }

    script = d.createElement('script');
    script.type = 'text/javascript';
    script.async = true;
    script.onload = function () {
        const builder = kuromoji.builder({'dicPath': 'https://yaegaki.github.io/yurufuwa-qiita/bower_components/kuromoji/dict'});
        builder.build((e, tokenizer) => {
            // デバッグ用
            window.tokenizer = tokenizer;

            if (e !== null) {
                console.warn(e);
                return;
            }

            document.querySelectorAll('.tr-Item_title').forEach(a => {
                a.innerHTML = tokenizer.tokenize(a.innerHTML).map(yurufuwa).join('');
            });
        });
    };
    script.src = 'https://yaegaki.github.io/yurufuwa-qiita/bower_components/kuromoji/build/kuromoji.js';
    d.getElementsByTagName('head')[0].appendChild(script);
}(document));
```
[ゆるふわきーた](https://github.com/yaegaki/yurufuwa-qiita)
【Looking Glass】Looking Glassでもっと奥を描こう（おまけ）

訂正
値はCustom View Coneですね
本文は修正しましたが、画像は勘弁してくださいー

#おまけ

この記事の続きになります
https://qiita.com/toqkz/items/b0851763dc926ce4994b

TwitterでCustom View Coneの値を調整してみればとの意見を頂いたのでいじってみました。

RenderTextureの背景をビューボリュームの一番奥に置き、Custom View Coneを40（デフォルト値）・20・0にした場合のLooking Glass の表示になります。

手前の２車線が3D、それより後はRenderTextureによる背景になります。

![190119_UseCustomViewCone40.png](https://qiita-image-store.s3.amazonaws.com/0/227733/9b522a53-c3e2-77ee-2d16-6393f23b9557.png)
![190119_UseCustomViewCone20.png](https://qiita-image-store.s3.amazonaws.com/0/227733/94439570-767a-8d16-e252-24ed01601bab.png)
![190119_UseCustomViewCone0.png](https://qiita-image-store.s3.amazonaws.com/0/227733/cc62af7a-6e2e-b076-e8de-28ea81c73389.png)

さらにRenderTextureの解像度を128x80とかなり小さくしてぼかした場合はこんな感じになります。

![190119_UseCustomViewCone40dof.png](https://qiita-image-store.s3.amazonaws.com/0/227733/c9a84f7e-1dbe-4c45-eae6-34be46b60d61.png)
![190119_UseCustomViewCone20dof.png](https://qiita-image-store.s3.amazonaws.com/0/227733/329c428f-bca7-0889-0747-383dcbdb2751.png)
![190119_UseCustomViewCone0dof.png](https://qiita-image-store.s3.amazonaws.com/0/227733/197dd736-c37b-e90c-7244-1d77d6a68f08.png)

Custom View Cone の値はLooking Glassのボタンで常に調整出来るようにしておくと便利かもしれませんね。
テンプレートリテラルで文字連結

いまさら感がありますが、テンプレートリテラルについてです。

#これは何
> 組み込み式を扱うことができる文字列リテラル
(引用元：https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/template_strings)

これだけですと「何が違うの」となりそうですが、「組み込み式」がポイントだと思います。
実際に使うと、その便利さがよくわかります。

#どう使うの？
「`」（バッククォート）で囲みます。

```javascript
const text = `hoge`;
```

#出来る事
・改行や複数行を表現できます。
テンプレートリテラルでない場合、`＋`などで連結させる必要があります。

・変数や計算式が書けます。

```javascript
const text = 'hoge';
const texts = `${text},huga,piyo`;
// 出力結果：hoge,huga,piyo
```

今までだと、`＋`や、配列と`join()`で文字列を連結させ、また変数を展開していましたが、
テンプレートリテラルを使用すると非常に簡単に対応できます。

・エスケープは`\`が使えます。
・`String.raw`～``で、未加工（エスケープされていない）の文字列が出力されます。

#注意する事
単なる連結の簡略化として使う分にはマイナスは無いかと思います。
IEがだめだったと思いますが、そのくらいです。

ただ、こちらにある「マニアック」といくつか弱点があります。
https://qiita.com/kura07/items/c9fa858870ad56dfec12


#参考
テンプレート文字列：
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/template_strings
JavaScript の テンプレートリテラル を極める！：
https://qiita.com/kura07/items/c9fa858870ad56dfec12
【JavaScript 】constに関する注意点

# constに関する注意点

```javascript:
'use strict';

// 値の変更はできる
const xyz = [10, 20, 30];
xyz[2] = 40;
console.log(xyz); // [10, 20, 40]

// 値の再代入はできない
xyz = 50; // Error
```
※Google Chrome で確認
※ES8
【JavaScript 】アロー関数

# アロー関数

```javascript:
const add = (x, y) => {
  return x + y;
};
console.log(add(10, 5)); // 15

// 1行で
const sub = (x, y) => x - y;
console.log(sub(10, 5)); // 5

// 仮引数が１つのとき
const x2 = x => x * 2;
console.log(x2(10)); // 20
```
※Google Chrome で確認
※ES8
Arduino同士で文字列をシリアル通信する方法

本ドキュメントは、Arduino同士でシリアル接続して文字列を送受信する方法についての解説です。
![arduino2.png](https://qiita-image-store.s3.amazonaws.com/0/40217/b82c6f46-4b8a-d4d0-14c6-2fbf433eee03.png)
上記写真の様にお互いに TX<->RX, RX<->TX をクロスさせてジャンパーピンを接続します。これだけでシリアル通信が可能になります。ただし、ArduinoのSketchを書き込み時はこのシリアル通信が書き込みの邪魔になってエラーを起こすので結線を外して書き込みし、結線して受信側をシリアルモニタで確認するという手順を繰り返しながら実装して行くという流れになります。

## 送信側プログラム
どちらかのArduinoを送信側と決めて、下記のスケッチをアップロードします。

```c++
int LED = 13;
String sendstr = "arduino";

void setup(){
  Serial.begin(9600);
  pinMode(LED, OUTPUT);
  Serial.println("Start writeing.");
}

void loop(){
  digitalWrite(LED, LOW);
  for (int i = 0; i < sendstr.length(); i++){
    Serial.write(sendstr.charAt(i)); 
  }
  Serial.write(0);
  digitalWrite(LED, HIGH);
  delay(2000);
}
```

## 受信側プログラム
もう一方のArduinoを受信側として下記のスケッチをアップロードします。アップロードしたら、TX,RXをクロスして結線し、両方のUSBケーブルをパソコンに接続します。

```c++
char buff[255];
int counter = 0;
int LED = 13;

void setup(){
  Serial.begin(9600);
  pinMode(LED, OUTPUT);
  Serial.println("Start reading.");
}

void loop(){
  while(Serial.available()){
    char inChar = char(Serial.read());
    //Serial.print(inChar);
    buff[counter] = inChar;
    counter++;  
    if (inChar == '\0'){
      Serial.println(buff);
      digitalWrite(LED, HIGH);
      counter = 0;
    }else{
      digitalWrite(LED, LOW);
    }
  }
}
```
## 受信側モニタ状況
Arduino IDEで受信側をシリアルモニタにしてモニタの通信速度はシリアル接続に設定した値と同じにします。すると以下の様に送信側から送られて来る文字列が表示されます。

```
Start reading.
arduino
arduino
arduino
arduino
arduino
arduino
arduino
```
SIM7500のGPSを利用する

# 環境

- NanoPi NEO 2
- Armbian
- SIM7500JC
- [GPS Antenna - External Active Antenna - 3-5V 28dB 5 Meter SMA](https://www.adafruit.com/product/960)

```shell-session
$ cat /etc/armbian-release 
# PLEASE DO NOT EDIT THIS FILE
BOARD=nanopineo2
BOARD_NAME="NanoPi Neo 2"
BOARDFAMILY=sun50iw2
VERSION=5.49
LINUXFAMILY=sunxi64
BRANCH=next
ARCH=arm64
IMAGE_TYPE=user-built
BOARD_TYPE=conf
INITRD_ARCH=arm64
KERNEL_IMAGE_TYPE=Image
$ cat /etc/debian_version 
9.4
```

# アクティブアンテナの電源回路

sim7500a_sim7500e_sim7500je_sim7500jc_sim7500s_sim7500sa_hardware_design_v1.01.pdf 39pに記載のFig30 より。

<img width="826" alt="スクリーンショット 2019-01-19 0.09.26_bordered.png" src="https://qiita-image-store.s3.amazonaws.com/0/26038/0301734d-6c85-1f35-1449-2a9b3eaba20c.png">

最低限オレンジで囲ったところだけつくればとりあえずアクティブアンテナに電源を供給することはできる。
（πマッチの定数どう決めばいいかよくわかんなかったのでマッチング回路は省略した）

# GPSの有効化

GPSは工場出荷値ではOFFのようなので、

```shell-session
$ screen /dev/ttyUSB2 115200
```

でSIM7500のATポートを開いて、

```at
AT+CGPS=1
```

でスタンドアロンモードでGPSセッション開始。
（AGPSも使えるようだが、今回はLTEがoffの状態でもGPSを使用する必要があったのでスタンドアロンモード）

```at
AT+CGPSAUTO=1
```

を設定しておくと、次回モジュール起動時からGPSセッションが自動的に開始される。

```shell-session
$ cat /dev/ttyUSB1
```

でNMEAセンテンスがずらずら流れてきていたらGPSは動いている（実際に衛星を捕捉できているかどうかは別として）

# gpsdのインストール

NMEAセンテンスについて学んで自力でパースしてもよさそうだけど、それはちょっとやりたくなかったので定番のgpsdを使う。

```sh
sudo apt-get update
sudo apt-get install gpsd gpsd-clients
```

# gpsdの設定

デフォルトのunitファイルが設定ファイルとして`/etc/default/gpsd`を読みにいくようになっているのだが、`/etc/gpsd/gpsd.conf`を読みにいくように変更したいので、デフォルトのunitファイルを上書きする設定を作成する。
参考: https://qiita.com/nvsofts/items/529e422bb8a326401c39

```shell-session
$ sudo systemctl edit --full gpsd
```

Nanoが起動して嫌なので、

```shell-session
sudo update-alternatives --config editor
```

して、vimを選択するとvimで編集できる。

内容は以下のようにする。

```conf
[Unit]
Description=GPS (Global Positioning System) Daemon
Requires=gpsd.socket
# Needed with chrony SOCK refclock
After=chronyd.service

[Service]
#EnvironmentFile=-/etc/default/gpsd
EnvironmentFile=/etc/gpsd/gpsd.conf
ExecStart=/usr/sbin/gpsd -N $GPSD_OPTIONS $DEVICES

[Install]
Also=gpsd.socket
```

`/etc/gpsd/gpsd.conf`は以下のようにする。

```conf:/etc/gpsd/gpsd.conf
# Start the gpsd daemon automatically at boot time
START_DAEMON="true"

# Use USB hotplugging to add new USB devices automatically to the daemon
USBAUTO="false"

# Devices gpsd should collect to at boot time.
# They need to be read/writeable, either by user gpsd or the group dialout.
DEVICES="/dev/ttyUSB1"

# Other options you want to pass to gpsd
GPSD_OPTIONS=""
```

# gpsdの動作チェック

```sh
cgps
```

左側の枠の中に、

```
Status:     3D FIX (X secs)
```

と出ていれば、測位できている状態です。
コールドスタートになるので、3D fix まで数分程度かかる。

# 緯度経度高度を読む

cgpsでも出力されているJSONっぽい部分だけほしい場合、`gpspipe`コマンドを使います。

```sh
gpspipe -w
```

続く・・・
【JavaScript 】テンプレートリテラル

# テンプレートリテラル

プレースホルダー`${expression}`を含めることができる

```javascript:
'use strict';

var a = 10;
var b = 5;
console.log(`a + b = ${a + b}`); //  a + b = 15
```
※Google Chrome で確認
※ES8
[エラー解決] Error: Duplicate column name ''"、カラムの重複、SQL



## エラー内容


カラムが重複しとるで！ それはアカンで！っていうエラー

1. $ rails db:migrate
2. (最初の)エラーが発生する
3. しかし、エラーのはずが、カラムがmigrationされてる。
4. もう一度、$ rails db:migrate すると、下記のようなエラーが出る。
5. 「なんでやねん！(最初の)エラーで、はじき出されたはずやろ？！」 謎やん！

```Terminal.
StandardError: An error has occurred, all later migrations canceled:
Mysql2::Error: Duplicate column name ''
Caused by: ActiveRecord::StatementInvalid: Mysql2::Error: Duplicate column name '': ALTER TABLE `` ADD ``
Caused by: Mysql2::Error: Duplicate column name 'likes_count'
```

## 解決策
####こういうときは migration ファイルを空にすればえーで！ 

<現状>

```20190118141743_add_nickname_to_users.rb
class AddNicknameToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :nickname, :integer
  end
end
```

↓　
<これに変える>

```20190118141743_add_nickname_to_users.rb
class AddNicknameToUsers < ActiveRecord::Migration[5.0]
  def change
# ココを空欄にする！！
  end
end
```
1. Save
2. $ rails db:migrate
すると、
== 20190118141743 AddNicknameToUsers: migrating ============================
== 20190118141743 AddNicknameToUsers: migrated (0.0000s) ===================

### migration成功！！

そのあと、下記の通りに戻しておく！

```20190118141743_add_nickname_to_users.rb
class AddNicknameToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :nickname, :integer
  end
end
```

以降、$ rails db:migrate してもエラーでぇ〜へんやろ？？


## 参考URL
http://mooooooooooriiiiii.hatenablog.com/entry/2017/04/07/170344
Macにpyenvを使ってPythonをダウンロードする

Pythonを使う機会があったので、設定方法のメモ

## 必要なもの

- Homebrew

## Homebrewのインストール

[公式サイト](/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)")を参考にすること

HomebrewをインストールするとXcode Command Line Toolも入ってくれる

## pypenvを使うための準備

`.bash_profile`や`.zshrc`に書きを追記

```sh
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
source ~/.bash_profile
```

## pypenvのインストール

```sh
$brew install pyenv
```

たぶん、ここまでは問題なく来れるはず。

## pythonのバージョンを確かめる

```sh
$pyenv install --list

// バージョンが出てくる
```

## pythonのバージョンを指定してインストールする

よーし、あとはpythonのバージョン指定してインストールして完了♪


```sh
$pyenv install -v 3.7.1

// なんかすごい量のログがコンソールに表示される
// しばらく待つ。そして。。。。
zipimport.ZipImportError: can't decompress data; zlib not available
make: *** [install] Error 1

BUILD FAILED (OS X 10.14 using python-build 20180424)
```

あれま。。。`zlib not available`ですと。

[wiki](https://github.com/pyenv/pyenv/wiki/Common-build-problems)を見てみると


On Mac OS X 10.9, 10.10, 10.11 and 10.13 you may need to set the CFLAGS environment variable when installing a new version in order for configure to find the zlib headers (XCode command line tools must be installed first):

```sh
CFLAGS="-I$(xcrun --show-sdk-path)/usr/include" pyenv install -v 2.7.15

pyenv versions
* system (set by /Users/tsurukazuhito/.pyenv/version)
  2.7.15
  
// helpコマンドにインストールしたらやれみたいにあるのでrehashする
pyenv rehash
```

これだとうまくいけた。

## pythonのバージョンを指定する

### デフォルト(global）で使用するバージョンを決める

```sh
pyenv global 2.7.15

python -V
=> Python 2.7.15
```

### そのフォルダ配下での利用したいPythonのバージョン指定方法

```sh
pyenv local 3.7.0
```
そのフォルダ配下に`.python-version`が作成される
【Golang】配列とスライスの違いについて

配列と参照型のスライスの勉強したのですが自分なりにまとめてみました。
まだ書籍で勉強し始めた程度なので思いつけば随時更新していければと思っています。

### 環境

- golang v1.11.4


## 配列とスライスの違い

### 配列

 - 格納する要素数を増やすことができない
 - 値を指定しない場合
   - int型=0
   - string型=""
   - bool型=false

### スライス
 - 参照型
 - 値を指定しない場合　nil
 - スライスを扱う際注意すること
  - 要素数
  - 容量
  - 要素の各値

容量は必要に応じて自動的にスケールするが、パフォーマンスを考えてハンドリングすべき<br>

### 配列の生成


```golang
// 要素指定なし、容量3
array := [3]int

// [0 0 0]
```

```golang
// 要素指定、容量3
array := [3]int{1, 3, 5}

// [1 3 5]
```




### スライスの生成
```golang
// int型、要素数10、容量10を指定
slice1 := make([]int, 10) // -> [0 0 0 0 0 0 0 0 0 0]

// int型、要素数10、容量5を指定
slice2 := make([]int, 10, 5) // ->[0 0 0 0 0]
```

要素の各値を指定する場合は配列の生成と激似

```golang
// [1, 3, 5]の要素を収納。要素数3、容量3
slice3 := []int{1,3,5}
```

下記にのように変数を書き換える時は配列型と参照型が全く別の挙動を取るので注意。

```golang
package main

import "fmt"

// 配列を2乗する関数
func arraySquare(numbers [3]int) {
	for i, v := range numbers {
		numbers[i] = v * v
	}
	return
}

// スライスを2乗する関数
func sliceSquare(numbers []int) {
	for i, v := range numbers {
		numbers[i] = v * v
	}
	return
}

func main() {
	// 配列で宣言をし、関数で2乗、もとのarrayAを出力
	arrayA := [3]int{1, 2, 3}
	arraySquare(arrayA)
	fmt.Println(arrayA)  // [ 1 2 3]

	// スライスを宣言し、関数で2乗、もとのsliceAを出力
	sliceA := []int{1, 2, 3}
	sliceSquare(sliceA)
	fmt.Println(sliceA)  // [1 4 9]
}
```
逆に考えるんだ、ループを末尾再帰に変換すればいいやって


元ネタ：[Haskellをかける少女](https://qiita.com/jzmstrjp/items/11dcd3ec26027ff30214)

# ワイ君のコード

```fibo.js
const fibo = n => {
  const arr = [0, 1];

  for (let i = 2; i <= n; i++) {
    arr.push(arr[i - 1] + arr[i - 2]);
  }

  return arr[n];
};
```

# 配列の最後の要素を返す

`n !== 0`のとき、`arr[n]`は配列の最後の要素なので、そのことが明示的になるように`fiboA`のように書き直してみる。

```fiboA.js
const fiboA = n => {
  if (n === 0) {
    return 0;
  }

  const arr = [0, 1];

  for (let i = 2; i <= n; i++) {
    arr.push(arr[i - 1] + arr[i - 2]);
  }

  return arr[arr.length - 1];
};
```

# 配列の最後の要素と、最後から2番目の要素で更新する

また、`arr[i - 2]`は最後の要素、`arr[i - 1]`は最後から2番目の要素になっているから、下記の`fiboB`のように書き直せる。

```fiboB.js
const fiboB = n => {
  if (n === 0) {
    return 0;
  }

  const arr = [0, 1];

  for (let i = 2; i <= n; i++) {
    arr.push(arr[arr.length - 2] + arr[arr.length - 1]);
  }

  return arr[arr.length - 1];
};
```

# 配列いらなくね？

最後の要素と最後から2番目の要素しか登場していないので、下記`fiboC`のように、それぞれ`arrLast1`、`arrLast2`の変数に書き換えられる。ただし、値の更新には一時変数が必要になる。

```fiboC.js
const fiboC = n => {
  if (n === 0) {
    return 0;
  }

  let temp;
  let arrLast1 = 1;
  let arrLast2 = 0;

  for (let i = 2; i <= n; i++) {
    temp = arrLast1;
    arrLast1 = arrLast2 + arrLast1;
    arrLast2 = temp;
  }

  return arrLast1;
};
```

# 添字いらなくね？

配列がなくなったため、添字としての`i`は不要になる。`n`を直接更新することで、下記の`fiboD`ようにループを書き換えられる。

```fiboD.js
const fiboD = n => {
  if (n === 0) {
    return 0;
  }

  let temp;
  let arrLast1 = 1;
  let arrLast2 = 0;

  for (; n !== 1; n--) {
    temp = arrLast1;
    arrLast1 = arrLast2 + arrLast1;
    arrLast2 = temp;
  }

  return arrLast1;
};
```

# `for`から`while`へ

```fiboE.js
const fiboE = n => {
  if (n === 0) {
    return 0;
  }

  let temp;
  let arrLast1 = 1;
  let arrLast2 = 0;

  while (n !== 1) {
    n = n - 1;
    temp = arrLast1;
    arrLast1 = arrLast2 + arrLast1;
    arrLast2 = temp;
  }

  return arrLast1;
};
```

# 末尾再起にする

ここまでくれば、下記`fiboF`のような末尾再帰に変換できる。計算量を変えないように関数を変換していったので、`fiboF`も計算量は$O(n)$になっている。

```fiboF.js
const fiboF = (n, arrLast1 = 1, arrLast2 = 0) => n === 0 ? 0 : n === 1 ? arrLast1 : fiboF(n - 1, arrLast2 + arrLast1, arrLast1);
```

# おわり

ちなみに、引数累積するなら下記のコードのほうが短い。
あと、$F_{78}$ < `Number.MAX_SAFE_INTEGER` < $F_{79}$ なので、スタック・オーバーフローよりも先に計算誤差が問題になる。

```fib.js
const fib = (n, a = 0, b = 1) => n === 0 ? a : fib(n - 1, a + b, a);
```
Railsでhamlを導入する！

何かと便利なhaml。
今回はRailsで取り入れてみる。

#Gem導入
```ruby:Gemfile
  gem 'haml-rails'
```

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

すると、、、

```ruby:application.html.haml
!!!
%html
  %head
    %meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
    %title ChatSpace
    = stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true
    = javascript_include_tag 'application', 'data-turbolinks-track' => true
    = csrf_meta_tags
  %body
    = render partial: 'layouts/flash'
    = yield
```

```ruby:mailer.html.erb
!!!
 %html
   %head
     %meta{:content => "text/html; charset=utf-8", "http-equiv" => "Content-Type"}/
     :css
       /* Email styles need to be inline */
   %body
     = yield
```

```ruby:mailer.text.erb
= yield
```

の３つのファイルが出現。設定ファイルだと思って大丈夫です。

# 拡張子がerbのファイルをhamlに変換する

```terminal:ターミナル
$ rails haml:erb2haml
```

上記のコマンドを打てば後は自動的に拡張子をhamlに変えてくれます。

# 終了！
Elixirで符号付整数値を16進数表示する方法


# Elixirで符号付整数値を16進数表示する方法

符号付10進数の数字を16進数で表記する手法をご紹介します。
マイナス値を「２の補数」表現を行う方法になります。

結論から書きます。パターンマッチを使って、一旦バイナリで取り出してBase16でエンコードすればOKです。

```elixir
iex(1)> ( <<x::binary>> = <<-100::integer-signed-32>> ) |> Base.encode16
"FFFFFF9C"
iex(2)> ( <<x::binary>> = <<-100::integer-signed-64>> ) |> Base.encode16
"FFFFFFFFFFFFFF9C"
```

上記の例では、-100をそれぞれ符号付32bit整数、符号付64bit整数として解釈しています。

```elixir
iex(3)> <<x::binary>> = <<-100::integer-signed-32>>
<<255, 255, 255, 156>>
```
単なるバイナリ変換の場合は、上記の表記になるのでBaseモジュールが必用になります。

# モジュール化

以下はモジュール化したものです。ご参考まで。

```elixir

defmodule IntHex do
  def i32_hex(val) do
    ( <<x::binary>> = <<val::integer-signed-32>> )
    |> Base.encode16
  end
end
```

リスト化した数値をmapで16進数変換しています。

```elixir
iex(4)> [-883353469, -788829382, 1699715283] |> Enum.map( &IntHex.i32_hex &1 )           
["CB591883", "D0FB6B3A", "654F98D3"]
```

---

16進数をHexという名前はElixir/Erlangのパッケージ管理ツールと被ってるので、微妙にネット検索がしにくいですよね。それにしても、バイナリパターンマッチは非常に強力ですね。
【PHP】str_pad()関数でいろいろな値を5桁になるよう左側0埋めしてみた大全


# してみる

```php
str_pad($value, 5, 0, STR_PAD_LEFT);
```

この`$value`にいろんな値いれてみます

# 大全

```php
<?php

echo "\n\n-【 int 123 】------------------------------------\n\n\n";

$value = 123;
$res = str_pad($value, 5, 0, STR_PAD_LEFT);
var_dump($res);

echo "\n\n-【 string '' 】-------------------------------------\n\n\n";

$value = '';
$res = str_pad($value, 5, 0, STR_PAD_LEFT);
var_dump($res);

echo "\n\n-【 null 】-------------------------------------\n\n\n";

$value = null;
$res = str_pad($value, 5, 0, STR_PAD_LEFT);
var_dump($res);

echo "\n\n-【 string AAA 】-------------------------------------\n\n\n";

$value = "AAA";
$res = str_pad($value, 5, 0, STR_PAD_LEFT);
var_dump($res);

echo "\n\n-【 string 漢（漢字） 】-------------------------------------\n\n\n";

$value = "漢";
$res = str_pad($value, 5, 0, STR_PAD_LEFT);
var_dump($res);

echo "\n\n-【 string あ（ひらがな） 】-------------------------------------\n\n\n";

$value = "あ";
$res = str_pad($value, 5, 0, STR_PAD_LEFT);
var_dump($res);

echo "\n\n-【 string カ（カタカナ） 】-------------------------------------\n\n\n";

$value = "カ";
$res = str_pad($value, 5, 0, STR_PAD_LEFT);
var_dump($res);

echo "\n\n-【 string 🍣（絵文字） 】-------------------------------------\n\n\n";

$value = "🍣";
$res = str_pad($value, 5, 0, STR_PAD_LEFT);
var_dump($res);

echo "\n\n-【 string 𩸽（サロゲートペア） 】-------------------------------------\n\n\n";

$value = "𩸽";
$res = str_pad($value, 5, 0, STR_PAD_LEFT);
var_dump($res);

echo "\n\n-【 bool true 】-------------------------------------\n\n\n";

$value = true;
$res = str_pad($value, 5, 0, STR_PAD_LEFT);
var_dump($res);

echo "\n\n-【 bool false 】-------------------------------------\n\n\n";

$value = false;
$res = str_pad($value, 5, 0, STR_PAD_LEFT);
var_dump($res);

echo "\n\n------------------------------------------------------\n\n\n";
```

# 出力結果

```
[Output for 7.2.13 | took 158 ms, 14.93 MiB]

-【 int 123 】------------------------------------

string(5) "00123"

-【 string '' 】-------------------------------------

string(5) "00000"

-【 null 】-------------------------------------

string(5) "00000"

-【 string AAA 】-------------------------------------

string(5) "00AAA"

-【 string 漢（漢字） 】-------------------------------------

string(5) "00漢"

-【 string あ（ひらがな） 】-------------------------------------

string(5) "00あ"

-【 string カ（カタカナ） 】-------------------------------------

string(5) "00カ"

-【 string 🍣（絵文字） 】-------------------------------------

string(5) "0🍣"

-【 string 𩸽（サロゲートペア） 】-------------------------------------

string(5) "0𩸽"

-【 bool true 】-------------------------------------

string(5) "00001"

-【 bool false 】-------------------------------------

string(5) "00000"

------------------------------------------------------
```

ちょっと驚いたのは`null`いれてもこけないことですかね

# 参考リンク
- https://3v4l.org/OfEQb
- [PHP: str_pad - Manual](http://php.net/manual/ja/function.str-pad.php) 公式ドキ
【JavaScript 】文字列と数値の演算

# 文字列と数値の演算

```javascript:
'use strict';
console.log('10' * 5); // 50
console.log('10' / 5); // 2
console.log('10' % 5); // 0
console.log('10' - 5); // 5

// 足し算は文字列の連結になる
console.log('10' + 5); // 105

// 文字列を10進数の整数に変換
console.log(parseInt('10', 10) + 5); // 15
console.log(parseInt('str', 10) + 5); // NoN
```
※Google Chrome で確認
※ES8
Bitriseでpuppeteerを動かすTips

Bitriseにnpmとnodejsがインストールされているのを知り、
「これは定期的にpuppeteerでスクレイピングできるのでは？」
と思いチャレンジしてみた。

## 完成品

BitriseのWorkflow EditorにScriptステップを追加し、以下でpuppeteerが動かせた。

```
# 必須、updateしないとinstallがエラーになる
sudo apt-get update -y

# これがないとChromiumがエラーで起動しない
sudo apt-get install -y libgtk-3-0

# npmインストール、Chromiumもダウンロードされる
sudo npm i

# スクリプト実行、puppeteerでスクレイピング
sudo node index.js
```

## 解説
### sudo apt-get update -y
updateを行わないと apt-get install でエラーになるため必須

### sudo apt-get install -y libgtk-3-0
何も考えずpuppeteerを動作させようとするとエラーログに「libgtk-3-0が必要」と出るので追加した

### sudo npm i
nodejsプログラムの準備
puppeteerのインストールと共にChromiumもインストールされる

### sudo node index.js
メイン処理
ここでpuppeteerにスクレイピングさせ、結果をSlackに通知なりクラウドに保存なりする。
自分は毎日定時にSlackに通知させてる

##　感想
Bitriseのログを眺めてるとDockerが動いてるようなので、
BitriseというよりDockerでpuppeteerを動作させる、という表現が正しいのかもしれない。

こういう定期実行はAWSやHerokuで行うのが最適かもしれないが、Bitriseの無料枠で出来るなら使用するのもアリだと思う。

Bitriseの弱点は、１日１回しか動かせない制限がある。
１日複数回の定期実行を希望するならAWSかHerokuをオススメする。
robotframework + seleniumlibrary 参考情報まとめ

# モチベーション
robotframework(RFと略す) + seleniumlibraryでwebアプリケーションのテスト自動化を検討している際に
参考としているサイトとtipsをまとめます。

# 環境や前提条件
windows10
PowerShell
python3.7
pipでいうとこういうこと↓

```
PS C:\robot> pip list
Package                        Version
------------------------------ ----------
certifi                        2018.11.29
pip                            18.1
pipenv                         2018.11.26
robotframework                 3.1.1
robotframework-seleniumlibrary 3.3.1
selenium                       3.141.0
setuptools                     40.6.2
urllib3                        1.24.1
virtualenv                     16.2.0
virtualenv-clone               0.4.0
```

# リンク集
## web driver download元
- chromedriver : http://chromedriver.chromium.org/downloads
- geckodriver(fireforx) : https://github.com/mozilla/geckodriver/releases
- IE : https://goo.gl/9Cqa4q
- Edge : https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
win10のbuild番号にバージョンを合わせる必要があります。

## keyword一覧

seleniumlibraryのkeyword一覧：こういうことできるはずだよねと言ったときにここからkeywordを探します。
http://robotframework.org/SeleniumLibrary/SeleniumLibrary.html

BuiltIn keyword一覧：RFの基本文法で迷ったらこちらを参照します。
http://robotframework.org/robotframework/latest/libraries/BuiltIn.html

String keyword一覧：文字列操作
https://robotframework.org/robotframework/latest/libraries/String.html

xpath:ちょっと賢くweb elementを指定しようとするとxpathの知識が必要。following-siblingの使い方など忘れてしまうので、参考にさせてもらってます。
https://qiita.com/rllllho/items/cb1187cec0fb17fc650a

書いたxpathが妥当かを確認するにはchromeのF12でxpathを入力して、意図したelementが検索にヒットするか試しますね。


# Tips(あとで個別の記事にするかも)
デフォルトで robot xxx とかすると、コマンド実行したフォルダにファイルがどんどん溜まっていって煩雑になるので、現在時間のフォルダ名に結果を出力して、テストが終わったら、自動で結果を表示するようにしてます。

```doRFTest.ps1
# usage doRFTest.ps1 Test/test.robot
$time = $(Get-Date).ToString("yyyyMMddHHmmss")
$file = "file:///"+$PSScriptRoot+"/result/"+$time+"/report.html"
robot -d result/$time $Args[0]
start "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" $file
```

# やりたいけどできてないこと
- スクロールしてページ全体のsnapshotをとる。Capture Page Screenshotはディスプレイに表示されている画面のsnapshotを取る機能。エビデンスとしてページ全体を撮りたいが、方法まだ見つかってません。
- web driverのバージョンはブラウザーのバージョンに依存しているため、手動で合わせこむのが大変ですね。自動で合わせこむ仕組みを作りたいです。
【JavaScript 】定数と変数

# 定数と変数

基本`const`を使う。
再代入が必要なものだけ`let`を使う。

```javascript:
'use strict';

// 定数
const c = 100;
console.log(c); // 100

// 変数
let l = 200;
l = 300;
console.log(l); // 300
```
※Google Chrome で確認
※ES8
Dockerコンテナ起動時に「cannot execute binary file」となる問題とCMD・ENTRYPOINTの違いについて

# 概要

公式のDockerイメージなどをPullして
**docker run -it [イメージ名] /bin/bash**　
とすると、まれに
**/bin/bash: /bin/bash: cannot execute binary file**
となる問題について。

# なぜ起きるのか

結論を先に言うと、Dockerfile上の**ENTRYPOINT**が原因。

**※ENTRYPOINTとは**
コンテナ起動時に実行したいコマンドを設定できる。
詳しくは公式のリファレンス参照
http://docs.docker.jp/engine/reference/builder.html#entrypoint

# ENTRYPOINTとCMDの違いについて

実行コマンドを設定できるものとして、**CMD**というのも存在する。
http://docs.docker.jp/engine/reference/builder.html#cmd

ENTRYPOINTとCMDの違いについて、よく話題にあがるので説明する。

わかりやすいよう、比較用のDockerfileを用意する。

```
.
├── cmd
│   └── Dockerfile
└── entrypoint
    └── Dockerfile
```

**./cmd/Dockerfile**

```Dockerfile
FROM centos:latest
CMD ["/bin/bash"]
```

**./entrypoint/Dockerfile**

```Dockerfile
FROM centos:latest
ENTRYPOINT ["/bin/bash"]
```

それぞれビルド。

```
$ docker build -t entry_centos ./entrypoint/
$ docker build -t cmd_centos ./cmd/
```

それぞれ**docker run**させてみる。
→違う結果に。

```
$ docker run -it --rm cmd_centos /bin/bash
[root@627d9a396552 /]#

$ docker run -it --rm entry_centos /bin/bash
/bin/bash: /bin/bash: cannot execute binary file
```

なぜ上のようなログが出るのか？
**→CMDは設定したコマンドを上書きできるのに対して、ENTRYPOINTのコマンドはデフォルトとして設定される（上書きがされない）ため。**
http://docs.docker.jp/engine/reference/builder.html#cmd-entrypoint

なので、**entry_centos**では**/bin/bash /bin/bash**というコマンドが実行されたような状態となっている。

ということでタイトルの原因に繋がる。

# 補足
**ENTRYPOINT**と**CMD**ですが、下記のように組み合わせて、デフォルトの振る舞いを設定するという書き方がよく出てきます。↓例

```Dockerfile
FROM centos:latest

ENTRYPOINT ["/bin/bash"]
CMD ["-c", "ls"]
```

```
$ docker run -it --rm cmd_entry_sample
anaconda-post.log  dev  home  lib64  mnt  proc  run   srv  tmp  var
bin                etc  lib   media  opt  root  sbin  sys  usr

$ docker run -it --rm cmd_entry_sample -c "cat /etc/redhat-release"
CentOS Linux release 7.5.1804 (Core)
```

# まとめ
なんかコンテナがうまく起動しないときはめんどくさがらず**Dockerfile**を確認する。（自戒）
FOOBARキーボードを作る 【キーマップ】2019/01/18


![Screenshot 2019-01-18 at 23.10.11.png](https://qiita-image-store.s3.amazonaws.com/0/283328/93393da4-c9b7-bfbf-9463-ef9e16331a6c.png)
なかなかいいマップができないけど、30個のキーで意外と使えるキーができると認識できた。だからと言ってこれが終わりではない。

今回はタップダンスを使ってESCとBackSpaceを定義してみた。配置的にはPキーなんだけど、Pの連打って結構使うののでDキーに割り当てた。
スペースキーはBキーにあてたいけどなんかうまくいかないので、いまいまは未定義。
SSH接続できているのにgit cloneがうまくいかないのはファイルの権限が問題かも

git clone
を実行した時に

```terminal
$ git clone
fatal: could not create work tree dir '***': Permission denied
```
と表示されてしまう。
一番怪しいのはSSH接続がうまくいってないパターンなので確認。

```terminal
$ ssh -T git@github.com
Hi ***! You've successfully authenticated, but GitHub does not provide shell access.
```

繋がっているようだ。
調べてみるとフォルダの権限が違うユーザ等になっているとcloneできないみたい。
以下コマンドで権限を変更。

```terminal
chown 【ユーザ名】 【cloneで配置するフォルダ】
```

もう一度clone

```terminal
$ git clone
```

でうまくできた。
路線図とかのAPIを使ってみた

# 経緯
個人的に作ろうと思っているおもちゃ(商用ではない)に鉄道系のAPIを使う必要がありそうなので、どんなものがあるのかなぁと。
[ここの記事](https://qiita.com/kou/items/e0d3fab106e4c52a7f26)を参考に調べてみた。

# APIの提供元
### 乗換案内オープンAPI
→ [乗換案内オープンAPI](https://norikae.jorudan.co.jp/openapi/)
思い立って調べて最初に行き着いたのがジョルダンの提供するAPI。
利用するための登録が必要となるようで、サービス予定のURLを登録して審査的な物をパスしなければならないらしい。
今回は検証だけなのでパス。

### HeartRails Express
→ [HeartRails Express](http://express.heartrails.com/api.html)
次にたどり着いたのはHeartRails Expressが提供するAPI。
こちらは無料で利用できるようなので、今回はこれを使ってみようと思う。

### 他にも色々
- 国土交通省
- 国土地理協会
- リクルート
- 駅すぱあと

などなど

# 使ってみる
特に環境の指定はないけど、勉強中だからPythonでやってみる。
今回は路線名を取得。

### リクエスト送信に必要なモジュールをインストール

```shell
pip install requests
```

### リクエスト送信

```python:
>>> import json
>>> import requests
>>> url = 'http://express.heartrails.com/api/json?method=getLines&prefecture=埼玉県'
>>> response = requests.get(url)
>>> resp_json = json.loads(response.text)
>>> resp_json
{'response': {'line': ['JR京浜東北線', 'JR八高線', 'JR埼京線', 'JR宇都宮線', 'JR川越線', 'JR武蔵野線', 'JR湘南新宿ライン', 'JR高崎線', 'つくばエクスプレス線', '上越新幹線', '埼玉新都市交通伊奈線', '埼玉高速鉄道', '東京メトロ有楽町線', '東京メトロ副都心線', '東北新幹線', '東武伊勢崎線', '東武日光線', '東武東上本線', '東武越生線', '東武野田線', '秩父本線', '西武山口線', '西武新宿線', '西武池袋線', '西武狭山線', '西武秩父線', '北陸新幹線', 'JR上野東京ライン']}}
```
すんなり取れた。
どうでもいいけど東武野田線は現在では東武アーバンパークラインだから、少し古いかも。

urlのパラメータを変えることで駅情報とかも取れるみたい。
[Mamo Naku]乗り過ごし防止/目的地到着お知らせアプリ

#電車またはバスでの目的地到着お知らせアプリ
●電車やバスでの移動中、目的地に近づくとお知らせします。
●簡単なUIで残り距離や現在の位置を地図で確認できます。
●バックグラウンドで動くのでゲームや音楽などが楽しめます。
●目的地制限ない、通知回数や間隔調整できます。
●Cloud利用でどのデバイスでも同期できます。

アプリダウンロード: https://itunes.apple.com/jp/app/mamo-naku/id1437742743?mt=8&ign-mpt=uo%3D2
WebPage: https://kimseungwon77.wixsite.com/mamonaku

![base2-1.png](https://qiita-image-store.s3.amazonaws.com/0/166098/c16f56c8-3e53-0ca2-2219-c1a2d3433ba5.png)
![base2-2.png](https://qiita-image-store.s3.amazonaws.com/0/166098/812da889-7d06-8f13-0fd5-b12b53aedca0.png)
![base2-3.png](https://qiita-image-store.s3.amazonaws.com/0/166098/5f1b4b11-8472-f0f2-eb98-b328d80833be.png)
![base2-4.png](https://qiita-image-store.s3.amazonaws.com/0/166098/9dda70d5-71f5-f2d4-a892-5191117fa215.png)
![base2-5.png](https://qiita-image-store.s3.amazonaws.com/0/166098/06eb007c-e8bf-215e-14c7-b8fdc6963de5.png)
rails newしてからGitHubのリモートリポジトリに上げるまでの手順

# この記事を書いたきっかけ
久しぶりにアプリ作るときに「あれ？どうやるんだっけ？」となるので、メモ。

# アプリ作成
```terminal
$  rails new アプリ名 -d mysql
$  cd アプリ名
$  bundle exec rake db:create
```

この後でしっかりとリモートリポジトリを作るので、この時点では、GitHub上にリモートリポジトリは作らなくて大丈夫です。

# ローカルリポジトリを作成する

GItHub Desktopからローカルリポジトリを作成してください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/301628/d48482ac-1ddd-cfd9-11b2-e86401965951.png)

# コミットする
ローカルリポジトリにある全てのファイルを選択してコミットしましょう。
その際のコミットメッセージは、最初のコミットなので「Initial commit」としておきましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/301628/f6e40847-01bd-5f15-ab1f-58066d7bae06.png)

# リモートリポジトリを作成しよう
コミットしたので、リモートリポジトリに反映させましょう。
まだリモートリポジトリを作っていないのですが、GitHub Desktopでは、Publishボタンを押すとリモートリポジトリが作られていない場合にリモートリポジトリも作ってくれます。



![image.png](https://qiita-image-store.s3.amazonaws.com/0/301628/148cd9a6-a833-2007-97d4-cc0503ae9f46.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/301628/9a2b9845-32d4-4edc-cc68-41572ae2bdbc.png)


GitHubのYour repositoriesの欄にgit-appがあれば上手く行っています。

# 終了です！　お疲れ様です！
ksnctf 29 Double Blind 50pt

#問題

https://ksnctf.sweetduet.info/problem/29

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/a166e2aa-bdf1-daf9-4442-4564b4431e9d.png)

#解いてみた

ワードファイルの作成者を答える問題。
とりあえずファイルをダウンロードしてみます。

ファイルを開く前に　作成者はプロパティに書いてあるだろうと思ったので確認してみましたが、書いてませんでした。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/639ff544-047c-5e65-bd54-4c04e18126b7.png)

ファイルを開いてみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/97d2bbe5-b92e-a2db-285f-a981cb12ea6a.png)

「No Author Given」ですって。
下の方まで流してみてみましたが、作成者っぽいことは書かれていません。
wordのプロパティもあったっけな。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/690dff95-388e-2d58-a130-1d334049b8fe.png)

作成者なし。
とりあえずファイル開いた状態から調べられることは終わった感ある。
docxはzipファイルなので解凍してみます。

そしてすかさず「FLAG」でgrep。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/95864668-5ea7-37e5-95c6-3815f1217d06.png)


なし。
本文が書かれている「\paper\word\document.xml」を見てみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/7fc9453f-54fc-ddde-6e5f-d226faadf52a.png)


図2のファイルパスにWindowsのユーザ名が書いてあってflagっぽいですね。
grepできないように「FLxAG_」になってますが。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/aaf37e93-ae53-3b53-0115-0c9a2fed8490.png)
HTTPSのリスナーをもつELBにWordpressのインスタンスをぶらさげるときのTIPS

AWS上でALBの下にWordpressのインスタンスをぶらさげようとしてちょっとはまったのでメモ

- 構成
    - EC2(Amazon Linux 2) + RDS(MySQL) + ALB というごくごくふつうの構成
- はまった点
    - ふつうにHTTPSのリスナーをもつALB配下にWordpressをいれたEC2をぶらさげたら、インストール画面がHTTPのみのときとなんか違う
    - Chromeのデベロッパーツールでのぞいてみたら mixed content の山になっていた
    - どうやらCSSとかをHTTPで返してくるようだ
- 解決策
    - ALB(CLBでもいっしょだけど)から転送されてきたときの `HTTP_X_FORWARDED_PROTO` を見て `$_SERVER['HTTPS'] ` と `$_ENV['HTTPS']` を `on` にしてやればいいみたい
    - wp-config.php に下記の構文を入れる

```
if($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
  $_SERVER['HTTPS'] = 'on';
  $_ENV['HTTPS'] = 'on';
}
```

以上です
Vue-CLI3 で作成した WebComponentsに、UIフレームワークを適用し、かつ、 IE11対応にする



# ElementUI編



## 結果


```html
<style scoped>
/* @import "../../node_modules/element-ui/lib/theme-chalk/index.css";  ←これだと容量多くて遅くなる */
@import "../../node_modules/element-ui/lib/theme-chalk/button.css";
</style>
```


```shell
yarn add element-ui
npm i
```



```js:main.js
import Vue from "vue";
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
import App from "./App.vue";

Vue.config.productionTip = false;
Vue.use(ElementUI);

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





## SVG Icon
```
yarn add fortawesome/fontawesome-svg-core fortawesome/free-regular-svg-icons fortawesome/free-solid-svg-icons

```
メモ > Vuetify  アイコン



src/plugins/vuetify.js

```js:src/plugins/vuetify.js
import Vue from "vue";
import Vuetify from "vuetify";
import "vuetify/dist/vuetify.css";

import "@fortawesome/fontawesome-free/js/fontawesome";
import "@fortawesome/fontawesome-free/js/solid";
import "@fortawesome/fontawesome-free/js/regular";

Vue.use(Vuetify, {
  iconfont: "fa4"
});
```


<v-icon>fa-dog</v-icon>

<v-icon>far fa-calendar-check</v-icon>
npm経由からTypeScript環境をインストール時、Permission Errorとなる時の対処法

下記のサイトを参考にnpm経由でtypescript環境をインストールしようとしたところ、次のエラーが表示されました。
https://code.visualstudio.com/Docs/languages/typescript

`$ npm install -g typescript`

```
npm WARN checkPermissions Missing write access to /usr/local/lib/node_modules
npm ERR! path /usr/local/lib/node_modules
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall access
npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
npm ERR!  { [Error: EACCES: permission denied, access '/usr/local/lib/node_modules']
npm ERR!   stack:
npm ERR!    'Error: EACCES: permission denied, access \'/usr/local/lib/node_modules\'',
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'access',
npm ERR!   path: '/usr/local/lib/node_modules' }
npm ERR! 
npm ERR! The operation was rejected by your operating system.
npm ERR! It is likely you do not have the permissions to access this file as the current user
npm ERR! 
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator (though this is not recommended).

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/*****/.npm/_logs/2019-01-18T13_16_12_727Z-debug.log
```
メッセージ中に表示されている、`/usr/local/lib/node_modules`のパーミッションがrootになっているのが原因のようです。

```
$ pwd
/usr/local/lib
$ ls -l
drwxr-xr-x  3 root  wheel   96 12 26 14:40 dtrace
drwxr-xr-x  4 root  wheel  128  1 18 22:23 node_modules
```

下記のようにsudoでコマンドを実行すると、問題なくインストールできました。

`$ sudo npm install -g typescript`
AWS IoT CoreのATSエンドポイント取得でaws cliがエラーになった時の対処メモ

# はじめに
2018年８月ごろAWSから以下のようなお知らせがありました

- Google, Apple および Mozillaが2018年10月からSymantecのルート認証局を信頼性を無効化すると発表しているよ
- モバイルアプリやWEBアプリからAWS IoTへの接続できなくなるかも
- AWS IoTではAmazon Trust Serviceが署名したサーバ証明書とそれにひもづくエンドポイントを用意してるよ
- 新しい証明書とエンドポイントを使用することを推奨するよ

元記事は[この辺](https://aws.amazon.com/jp/blogs/news/aws-iot-core-ats-endpoints/)に掲載がありQiitaでも[解説してる記事](https://qiita.com/is_ryo/items/b96e0b641a457a604a54)が上がってて証明書とエンドポイントの取得方法もこちらに載ってます。結構前のことなんですが自分は最近になって更新しようとしてはaws cliの使用ではまったことがあったのでちょっとメモがてら書こうと思います。自分が間抜けだった説あり

# エンドポイントの更新と発生したエラー
- aws cliの導入。[この辺](https://qiita.com/yuyj109/items/3163a84480da4c8f402c)の記事を見てやった
- aws cliのconfigureの設定。同上
- aws iot describe-endpoint --endpoint-type iot:Data-ATSを実行

とこれでエンドポイントが取得できるはずだったが以下のようなエラーが発生

```
An HTTP Client raised and unhandled exception: __init__() got an unexpected keyword argument 'ssl_context'
```

悲しい

# 解決方法
解決方法としてはなんのことはないaws cliをpython2で実行するとダメだったっぽい。
python 3.6.5にして実行すると問題なくエンドポイントの取得ができた。
pyenv環境でやっていたためpythhon3でやっていたつもりがsystemのpython2で起動していたようだった。

## aws cliをpython2からpython3へ変更しエンドポイントを取得する
[この記事](https://qiita.com/takech9203/items/8dc14c366abe8892d6e5)参考
- 環境をpython2に変更し、aws cliをアンインストールする

```
$ pyenv global system
$ sudo pip uninstall awscli
```

- 環境をpython3へ変更し（自分の場合は3.6.5をインストール済みだった）、aws cliを再インストールする

```
$　pyenv global 3.6.5
$　sudo pip install awscli
```

- aws iot describe-endpoint --endpoint-type iot:Data-ATSを実行すればATSのエンドポイントが手に入る

# まとめ
今回のエラーはAWS IoTだけではなくてS3やlambdaへのアクセスでも起きたのでpython2では使えなくなったのかな？とも思ったけど[このドキュメント](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-install.html)では2.6.5以降は使えそうな様子（自分のsystem環境のpythonは2.7.12だった）。
詳しい原因は不明のままだったけどpython3でアクセスするのが安定かなーとは思う