OmniAICreator/Qiita-1.07M huggingface dataset:
OpenAI Spinning Up で学ぼうとして、エラーになった話。

# Spinning Upとは
OpenAI Spinning Upは、deep RL(深層強化学習)について学べる無料サイトです。様々なアルゴリズムのソースコードもあります。
[https://spinningup.openai.com/en/latest/index.html](https://spinningup.openai.com/en/latest/index.html)

# Spinnin Up のインストールだけかと思いきや。。。
インストールしたもの

- Spinning Up
- Open AI Gym
- Microsoft MPI
- mpi4py
- swig
- box2d-py


先に書いておくと、上手く準備ができたら、以下のコマンドがうまくいきます。

```
python -m spinup.run ppo --hid "[32,32]" --env LunarLander-v2 --exp_name installtest --gamma 0.999
```

## まずはSpininng Up

Spinning Upを実行したいフォルダを作成。そして `cd`とかでその場所に行き、以下のコマンドを順に実行。

```
git clone https://github.com/openai/spinningup.git
cd spinningup
pip install -e .
```

## 次にgym
Spinning Upではgymの環境がなんとかって書いてあった気がするので`pip`

```
pip install gym
```

## そして、MPI
以下のリンクからダウンロードできます。最新版は、検索してダウンロードしてください。
[https://www.microsoft.com/en-us/download/details.aspx?id=100305](https://www.microsoft.com/en-us/download/details.aspx?id=100305)

## これでいけると思いきや。。。
### できないのでmpi4py
こちらも`pip`でいけました。

```
pip install mpi4py
```

## まだいけない。。。
### ので、swing
この通りにやりました。
[http://rinatz.github.io/swigdoc/install.html](http://rinatz.github.io/swigdoc/install.html)
この通りにやったのにエラーがでる。
解決方法は以下です。

1. swig.exeをPythonインストールフォルダーにコピーします。(ex C：/ python27の場合)
2. swigwin-3.0.12 / Libフォルダーを開き、すべての* .swgファイルを(C：/ python27 / lib)または同等のpythonパスにコピーします。
3. swigwin-3.0.12 / lib / pythonを開き、すべてのファイルを(C：/ python27 / lib)にコピーします。(Python用のMicrosoft Visual C ++コンパイラがインストールされていることも確認してください)
4. また、「typemaps」フォルダーを(C：/ python27 / Lib)フォルダーにコピーする必要があります。

[https://stackoverflow.com/questions/44504899/installing-pocketsphinx-python-module-command-swig-exe-failed](https://stackoverflow.com/questions/44504899/installing-pocketsphinx-python-module-command-swig-exe-failed)

## 最後のpip
box2d-py

```
pip install box2d-py
```

これで完成です!!!!!

## まとめ
結局、上に書いたやつ全部突っ込めば動きます。
たぶんPythonとVisual C++コンパイラ以外、全部不足してましたね。
上から順番にインストールしていき、そのたびにエラーが出てきました。エラーメッセージは当たり前だけど全部英語ですね。英語で検索すると解決方法も英語。Google翻訳先生は偉大でした(笑)。

swigが見つかりませんのエラーが一番時間取られたなぁ。

それにしても、なんでこんなにエラーが出るんだろう。。。


インストール終わったので、お勉強始めます。
[Open AI Spinning Up で深層強化学習のお勉強 -Introduction-](https://coffee-g9.hatenablog.com/entry/spinning_up_introduction)
.NET Frameworkの色々なPackの違い

VisualStudioでポチポチしてれば意識しなくてもよいのですが、ふと気になったので調べました。

# .NET Framework RuntimeとDeveloperPack

MSの.NETのDLページに行くと以下のような選択肢があります。

![Screenshot_2019-09-21 Download NET (Linux, macOS, and Windows).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280975/44bbe93b-4a75-0e20-52ae-bd6d6b6e9107.png)  
[Download .NET](https://dotnet.microsoft.com/download) より

RuntimeBuildはその名の通り、リリースされたアプリケーションを実行すWindowsにインストールするものです。.NETの実行に必要な仮想マシンや、標準ライブラリ（`System.*`とか）が含まれていると思われます。  

一方でDeveloperPackですが、こちらには開発に必要な一式が含です。その中にはSDKとTargetingPackが含まれています。それぞれの中身は後述。

>  Developer Pack には、.NET Framework の特定のバージョンと、それに付随する SDK が、その対応する Targeting Pack と共に含まれます。
> https://docs.microsoft.com/ja-jp/dotnet/framework/install/guide-for-developers

# .NET Framework SDKとTargetingTool

問題はこいつら

これら二つは、Developer Packに含まれていますが、それぞれ単体でも配布されています。気になるのはこの二つの違いですが、名前で何となくわかるものの腑に落ちない点がありました。

SDKはコンパイラや、ツール、サンプルなどが含まれています。しかし、最近のバージョンのものはDeveloperPackに含まれているのでDLページから単体でDLすることはできないようです。

> Microsoft .NET Framework 2.0 Software Development Kit (x64) には、開発者が .NET Framework アプリケーションを作成、ビルド、テスト、および配置するために必要なものすべて (ドキュメント、サンプル、ツール、およびコンパイラ) が含まれています。.NET Framework 2.0 SDK (x64) をインストールする前に、.NET Framework 2.0 再頒布可能パッケージ Version 2.0 (x64) をインストールする必要があります。 
> https://www.microsoft.com/ja-jp/download/details.aspx?id=15354

TargetingToolは.NETアプリケーションまたはライブラリをコンパイルするときに、使える機能を制限するものです。VisualStudioのプロジェクトプロパティやcsprojで設定するターゲットです。例えば.NET Framework 4.5 TargetingPackを使って、.NET Framework 4.5をターゲットとしたアプリケーションを作ったのならば、.NET Framework 4.5の機能しか使っていないことが保証されているので、.NET Framework 4.5および上位互換の環境で実行ができるのです。

ここでふと思うのが、「こんなのSDKの一部じゃないの？」という点です。結局はDeveloperPackという形でまとめてあるわけですが、分けてある意味がまるで分かりません。これは推測ですが、SDKはとてもサイズが大きいので、.NET Framework 4.6のSDKだけインストールしておいて、.NET Framework 4.5をターゲットとしたアプリケーションをビルドする、といったようなことをしたいがためだったのではないかと思います。現在はSDKなんて小さいものなので基本的にはターゲットにしたいバージョンをSDKごとDeveloperPackでまとめて入れてしまうのがスタンダードなんだと思います。

ちなみにVisualStudio Installerの個別コンポーネントを見るとこの二つが分かれています。（そのせいで気になってしまいましたｗ）

https://stackoverflow.com/questions/48147609/whats-the-difference-between-the-net-framework-sdk-and-the-targeting-pack?answertab=votes#tab-top

# ターゲットClientProfile

ClientProfileはASPの機能などを制限することで軽量なアセンブリが作れるそうです。しかし、.NET Framework 4.5以降では存在しません。これは、.NET Framework 4.5で最適化が進んだことに加え、ファイルサイズや処理性能がインフレしたことも理由にありそうな気がしています。

https://docs.microsoft.com/ja-jp/dotnet/framework/deployment/client-profile

# LanguagePack

何の疑問もわかないとは思いますが、ローカライズ用のPackです。エラーメッセージなどがローカライズされます。
（個人的にはエラーメッセージはエンコーディングを考えたくないので英語が好きですが）
少しでも安く楽にPythonエンジニア認定基礎試験をパスする

# はじめに
　本記事は、一般社団法人Pythonエンジニア育成推進協会が実施している民間試験「**Python3エンジニア認定基礎試験**」に少しでもお金をかけず、短時間で合格するためのものです。
　受験者数がまだまだ少ないことやこの試験の対策本がないために、受験を心配される方が多いと思います。私が実際合格するまでの体験談を交えた記事にしているので、ぜひ参考にしてください。

# 試験内容
　細かい試験内容等については他のQiita記事や公式を参考にしてください。
→[Python3 エンジニア認定基礎試験 詳細](https://www.pythonic-exam.com/exam/basic)

# 受験した感想
　1時間で40問の試験ですが、他の方と同意見であまり時間を気にする必要はありません。瞬殺できる問題が多いからです。（1問5秒程度）
　あと模擬試験は沢山解いて正解だなと思いました。試験内容は口外禁止なので細かいことは言えませんが、解き得だということは伝えておきます。さらにこれだけは覚えておいて欲しいのですが、**ドキュメントを読むより模擬試験を沢山解け！！**です。ドキュメント沢山読んでいたら、時間がかかってしまいます。以外とボリューミーです。とはいえども、後述する4つ分の章は確実に目を通しておきましょう。
　実試験は模擬試験より難しいとおっしゃる方が多いようですが、まあほぼ同レベルかなと思います。意地悪な問題は少ないです。（OracleのJava試験とかと比べたら全然）

# 私の勉強日記
　試験1週間前に勉強を開始しました。ちなみに私のPython歴は学生時代ちょっと書いた程度です。そんな私の勉強道具は次の通りです。

- [DIVEINTOCODE Python3エンジニア認定基礎模擬試験 β版](https://exam.diveintocode.jp/exam#exam-list)
- [Python チュートリアル 3.5.4ドキュメント](https://docs.python.org/ja/3.5/tutorial/index.html)

　この2つだけです。上はアカウント作成が手間なくらいで、それ以外は完全無課金です。さらに言及すれば下のドキュメントは全く読んでないです。模擬試験を前日にやりまくってました。
　オススメは、**模擬試験を解いて、わからなかったところはドキュメントを調べにいくという往復作業**です。模擬試験の問題は全部で80問？らしいですが、私は10回弱やって78問しか確認できませんでした。

※ ドキュメントのバージョンが3.5.4なのは、本試験が試験範囲と定めているオライリー・ジャパン「Pythonチュートリアル 第3版」がPython3.5を基準に書かれているからです。まあ3.7と大差ないので気にする必要はないです。

# どこを重点的に勉強するか？
　試験範囲とその中での問題数の割合は公表されています。（先ほどのPython3 エンジニア認定基礎試験 詳細から確認できます。）基本的に、問題が多く出る章に関する内容は**必ずおさえておくべき**です。リストアップしておきます。

| 章 | 内容 | 出題率 | 詳細や所感 |
|:--:|:---|:---|:---|
| 3  | 気楽な入門編 |  15.0%  | 数や文字列型、リスト型について。ここが理解できなければ不合格一直線 |
| 4  | 制御構造ツール |  22.5%  | if文、for文、range()関数、関数など。他言語経験が濃い人は寧ろがっつり読むべき |
| 5  | データ構造 |  17.5%  | Pythonらしさ全開な章。リスト、タプル、シーケンスなど重要度はかなり高い |
| 8  | エラーと例外 |  10.0%  | 問題数はそこまで多くないが、少しの勉強で確実に満点が狙える。一般的な例外処理がわかっていれば余裕 |

　この4章分は必ずドキュメントに目を通しておきましょう。**65%**分もあり、多くの合格者はここを得点源としているはずです。

　その他の章は、基本的には模擬試験だけで対応可能だと思っています。クラスや標準ライブラリなど、一般的なPython技術としては必ず知っておきたい内容です。しかし、本試験の攻略に関して言えば重要度は極めて低いです。内容量もそこそこ多いので、短時間で合格したい方は模擬試験解く程度の知識で十分でしょう。模擬試験で出たワードをドキュメントで軽くチェックする程度でOKです。
9/21 成果報告

## formタグについて
ログイン機能の実装の際など、ユーザーの入力情報をサーバーに送る際には、formタグを用いる。

```index.html
  <body>
  <form action="index.php" method="post">
      <p>名前：<input type="text" name="name"></p>
      <p>パスワード：<input type="text" name="password"></p>
      <input type="submit">
    </form>
  </body>
```

**各属性の説明**

 + action・・・送信ボタンを押した後の遷移ファイルを指定
 + method・・・postかgetを用途によって指定。

送信ボタンを押すと、formタグで囲まれた部分がサーバーに送信される。
この時、name属性を識別子とする連想配列で送信されるので、それをphpで扱う。


```index.php
<?php
$name = $_POST['name'];
$password = $_POST['password'];
echo "お名前は".$name."で、パスワードは".$password."です。";
 ?>
```
[Python備忘録]import時の記述法について

# importする際の記述の方法について
Pythonの標準ライブラリや自分たちのパッケージなど、いろいろimportする機会があるが、
どこからインポートしたものなのかわかりやすくする記述法がある。

以下のようにまとめるのが通常のようである。

```Python_import.py
import collections          #一番上にPythonの標準ライブラリ
import os                   #アルファベット順になるように
　　　　　　　　　　　　　      #スペースを開けて
import third               #サードパーティのライブラリ

import other_team_package  #会社の他のチームが作ったパッケージなど

import local               #ローカルのファイル
```

のような順で書くと、どこからインポートされたのかひと目でわかるので便利。
セキュリティの午後問題 解説と非議 応用情報H31春

応用情報のセキュリティの解説作りました・・・

クレームをいれるとしたら設問１ぐらいです・・
https://www.jitec.ipa.go.jp/1_04hanni_sukiru/mondai_kaitou_2019h31_1/2019h31h_ap_pm_qs.pdf

設１

利用者の生態の特徴を基にしたもの　＝　生体認証に関する問題です。
 選択肢を見ると、虹彩や動脈、体温があります。体温は、変動するもので、個人を特定できるものではない。　血管を認証するものは、一般に動脈ではなく、静脈が使われる。ちなみに動脈は静脈に比べて内側にあるため、読み取りにくいです。消去法で虹彩となります。
ただし、動脈認証というものが存在しないものではないので不正解にするのはどうかなと思う次第です。


B所有物を基にしたものとして　選択肢に　デジタル証明書とパソコンの製造番号が考えられますが、パソコンの製造番号は、セキュリティ面では有用なものではなく、把握する方法がないので、ディジタル証明書が正解となります。

（２）
ア　いずれもインターネット経由で、利用者認証行えます。
イ　できます。
ウ　そうです。最近のPCには、標準で装備されているものも多いですが・・
エ　IPアドレスは関係ありません。変わっても認証できます。

設2
(1)
c = ブルートフォース（総当り攻撃）

項番２が逆[c] となっているから、日本語の[総当り]の方がいいですかね。

(2)
ブルートフォース攻撃の対策としては一般に、
パスワードの入力回数の試行回数によりロックをかけるのが一般的なのでこれを答えれば良いかと

設問3
ハッシュ化する理由？　ハッシュ値から元のパスワードを複合するのが困難だから・・・・

イも正解なのでは？と思いましたが、
答えを見たら[ア]でした、
ソルトとはそもそもパスワードを見破りにくくするためにパスワードに付け加える文字列でして
内部的にIDごとに異なるランダムな文字列をハッシュ化する前に連結させておきます。
これにより、解読したパスワードから他のパスワードを見破るのを阻止します。つまりにレインボーテーブル（ID・パスワード対応表）の作成を困難にさせます。

<img width="540" alt="スクリーンショット 2019-09-22 午前0.05.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426556/1860a2f9-d47d-5c2b-ff7f-9126ba233935.png">

❇︎s0lと5oltがソルト
同じパスワードでも違うハッシュ化になり、Aさんのパスワードが判明されても、
同じハッシュ値でBさんのアカウントへの不正ログインはできない。
AWS上に設置したサーバーのREST APIへ接続時に"The request could not be satisfied.", "400 Bad Request"が発生

# 現象
AWS上にApacheでサーバーを立てました。
・Webサイトの表示OK
・REST APIの呼び出し(GET)OK
よし、問題ないかな。
その後REST APIにPOSTでアクセス。
「あれ？処理がエラーになった」
何故かREST APIを呼び出す時、GETはOKなのに、POSTでNGになる。

# 現象2
REST APIをcurlコマンドで呼び出していましたが、その際以下の様に実行していました。

```
curl -X post -H {設定したヘッダ} -d {POSTデータ} https://XXX.XXX/api/YYYY
```

問題がどこの箇所か分からないのですが、
[CloudFront]--[ELB]--[Apache]
とアクセスされるはずが、ApacheのアクセスログにPOST通信結果がありませんでした。

# 原因
methodの指定が「小文字」だったのがダメだったようです。
以下の様に大文字に変更したら普通に通信ができました。

```
curl -X POST -H {設定したヘッダ} -d {POSTデータ} https://XXX.XXX/api/YYYY
```
いくつか記事を見つけたのですが、
[ここには](http://www.cresc.co.jp/tech/java/Servlet_Tutorial/Att_01.htm)『メソッド名はかならず大文字のこと。』
[ここには](https://software.fujitsu.com/jp/manual/manualfiles/M100013/B1X10038/01Z201/B0038-00-03-02-06.html)『実行するHTTP(HTTPS)のメソッド名を指定する場合、すべて大文字にし』
という表現がありました。

# 結論
あれー、、、method名って大文字でないとダメだったんだ。。。
コマンドラインを書くとき、ダダダダダって書いてしまい気にせず小文字にしたんだけど、全く気にしてなかった。
横着しないでちゃんとSHIFTボタン押して大文字にしてれば、こんな事で何時間も悩まなかったのに。
超反省。
もしも同じ事で悩んでいる人がいた時のために、一応黒歴史として残しておく。
アルゴリズムとデータ構造の要点メモ in ruby（配列）

# 目的

技術面接のために修行を始める。
ウェブでの技術試験時にみやすいようにこのページに全部まとめる。
Rubyでそそくさと実装できることを目的とする。

# 参考

- https://programming-place.net/ppp/contents/algorithm/index.html#header (分かりやすいです、書いた人あざます、この記事をRuby用にまとめてるだけです)

# 配列（データ構造）

## 要点

- 配列は要素の追加・削除が苦手なので、その場合は連結リスト利用を考える
- indexが分かっていればO(1)、線形探索ならO(N)
- 探索の効率は高くない。ソート済みなら、二分探索を使う等して効率を高められる



## アルゴリズム

要素の探索が主

### 配列の中に、目的の値があるかどうか知りたい

```ruby
irb(main):055:0> "Hello, World!!".split("").include?("l")
=> true
irb(main):056:0> "Hello, World!!".split("").include?("X")
=> false
```

### 配列の中に、目的の値が何個あるか知りたい

```ruby
irb(main):034:0> [3, 6, 32, 22, 4].count(6)
=> 1
irb(main):036:0> "Hello, World!!".count("l")
=> 3
irb(main):037:0> "Hello, World!!".count("Hl")
=> 4

# 無駄にscanを使う
irb(main):045:0> "Hello, World!!".scan(/l/)
=> ["l", "l", "l"]
irb(main):046:0> "Hello, World!!".scan(/l/).count()
=> 3

# 無駄にinjectを使う
irb(main):053:0> "Hello, World!!".split("").inject(0) {|res, v| v == "l"? res + 1 : res }
=> 3
```

### 配列のどの位置に、目的の値があるか知りたい。ただし、一番最初に見つけたものだけで構わない

```ruby
irb(main):057:0> "Hello, World!!".index("l")
=> 2
```

### - 配列のどの位置に、目的の値があるか知りたい。ただし、一番最後に見つけたものだけで構わない（逆順の探索）

```ruby
irb(main):012:0> "Hello, World!!".rindex("l")
=> 10
```

### 配列のどの位置に、目的の値があるか知りたい。しかも、すべて抜き出したい

```ruby
irb(main):013:0> "Hello, World!!".split("").each_with_index.inject([]) { |res, (v, i)| res << (i if v == "l")  }.compact
=> [2, 3, 10]
```

### 練習1: 配列の中身を逆順にする

unshift: 配列の先頭要素への値の追加

```ruby
irb(main):014:0> "Hello, World!!".reverse
=> "!!dlroW ,olleH"

# 新しい配列にunshiftでどんどん先頭に要素を追加する、それをjoinして文字列にする
irb(main):018:0> "Hello, World!!".split("").inject([]) {|res, v| res.unshift(v) }.join()
=> "!!dlroW ,olleH"
```

### 練習2: 整数が格納された配列から、偶数の値を持つ要素数を数えるプログラムを作成してください

```ruby
irb(main):030:0> (1..10).map {|v| v if v%2 == 0 }.compact
=> [2, 4, 6, 8, 10]

# selectを使う
irb(main):029:0> (1..10).select {|v| v%2 == 0 }
=> [2, 4, 6, 8, 10]
```

### 練習3: ２つの配列に、共通して含まれている値を探し出すプログラムを作成してください

```ruby
[1, 2, 3, 4, 4].select {|i| [3, 5, 6, 8].include?(i) }.uniq
```

### 練習4: 多次元配列で、任意の行を削除する方法を考えてください

多次元配列削除するのめんどいな、slice!(0..-1)で行ごと空配列にして、
delete_ifで空配列を削除するしかないのか。
2次元以上の配列は使うのはしんどいな。

```ruby
irb(main):093:0> a=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
irb(main):094:0> b=[a.dup,a.dup,a.dup]
=> [[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
irb(main):095:0> b[0].slice!(0..-1)
=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
irb(main):096:0> b.delete_if(&:empty?)
=> [[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
```

# 学び

- rubyは無駄にメソッドが多いので使うものを決める  
  .charsは使わずに.split("")で統一するなど
- 特殊なメソッドにこだわらずに基本的なメソッドのみで考えて書く
サーバーで生成した複数のファイルをjs + ajaxで連続ダウンロードさせる(Chrome)

## 業務システムってエクセルが好きだよね・・・

こんにちは。
今日も今日とて業務システム開発。筆者です。

いきなりですけど、業務システムってエクセル好きですよね。というか。皆さんエクセル好きですよね。:cry:
もちろんCSVとかを生成して結果を返すという動きをすることもあるのですが、Rails側でユーザーの入力値からエクセルファイルに文字列を入力し、その結果のエクセルを返す。（CSVはSQLの実行結果、エクセルは帳票等の出力みたいに使い分けたりしてます）

とかいう処理をすることがあります。
筆者はよく,Rubyでエクセルを編集・作成するときに、[RubyXl](https://github.com/weshatheleopard/rubyXL)というgemを利用させていただくのですが、今回はエクセルを作成した後の話で、

**どうやってユーザーに生成したエクセルファイルをダウンロードさせるか**という内容の記事になります。

### 今回の前提条件

- エクセルファイルはユーザーの入力値により、サーバー側で生成
- ajaxを利用した非同期通信であり、Railsの`send_file`は使えない。
- エクセルは複数個生成される可能性があり、それを**zip等で固めず**個別にダウンロードさせる必要がある
- ブラウザはGoogle Chrome
- エクセル生成後保存先のファイルパスをajaxでjs側に返し、そのパスにアクセスしてダウンロード処理を走らせるような流れ？

というところでやってみました。

### 失敗例

まずは、ダメな例からです。
シンプルに「パスが分かってるから、`window.location.href = "ファイルパス"`」でええやん！と思って失敗したパターン。

```js
$.ajax({
        //ここでサーバーへリクエストを送信
      }).done(function(json) {
        //サーバーから帰ってきたファイルパス群（配列）を受け取って一回一回ダウンロードしようとして失敗
        var downloadUrls = json.path;
        downloadUrls.forEach(function (value, idx) {
            const response = {
              file: value,
            };
            setTimeout(() => {
                window.location.href = response.file;
            }, idx * 50)
        })
      }).fail(function(err){
          console.log('へへ・・・悪い・・・失敗しちまったよ');
      })
```

失敗というか,Chorme側のセキュリティ設定？でエラーメッセーが表示されます。
一度無理やり`window.location.href`でダウンロードさせておけば、しばらく動作させることはできましたが、そもそもワーニングメッセージ出てるし、セキュリティ的にどうなんだっていう話なので却下。


### 成功例（とりあえず）

調べれば、調べるほど`window.location.href`では難しいかなということが分かってきました。
（だってそんなのホイホイ許していたら、ウィルスとか簡単にダウンロードさせてしまえるものね:cry:）

どうも、色々と調べていると、
chromeでファイルをダウンロードさせるときには、**donwload属性**なるものを付与したaタグでダウンロードしてもらえれば良いみたい。

今回はダウンロード処理は自動で行う仕様であるため、ユーザー様にダウンロードボタンをクリックさせるなどいうことはして貰うわけには行きませんので、次のように対応しました。

```js
$.ajax({
     //ここでサーバー側にリクエストを送る
    }).done(function(json) {
      //サーバー側からもらったファイルパスを利用して、一時的に<a>タグを生成し、クリックイベントを起こした後、aタグを除去
      var downloadUrls = json.path;//['url1','url2']みたいに結果が帰ってきている
      downloadUrls.forEach(function (value, idx) {
          const response = {
            file_path: value,
          };
          setTimeout(() => {
              //aタグを生成
              const a = document.createElement('a');
              //href属性にファイルパスを生成
              a.href = response.file_path;
              //download属性にファイル名を付与。
              a.download = 'ファイル名';
              //生成したaタグをクリックするイベント
              a.click();
              //用無しのaタグ君には消えてもらうかな！
              document.body.removeChild(a);
          }, idx * 50)
      })
    }).fail(function(err){
        console.log('失敗じゃない。諦めたときが失敗なんだ。');
    })
```

<u>こいつ、動くぞ！</u>ってなもんでとりあえず期待した動作をしてくれるようになりました。

**zipで固めて返した方が楽だなぁ**と思いましたが、却下されたのでとりあえずこれで動かしてみました。
当たり前ですが、セキュリティの問題があるので、どのような方法が一番良いのかなぁ・・・と悩む日々です。
【Rails】データーベースの物理ファイルの場所

##この記事を書いた経緯
アプリケーションを使用しているときに、問題なくDBが使えているが、その保存してある物理ファイルはRailsのどこに存在するのか気になったため書くことにしました。
##結論
configというディレクトリのdatabase.ymlというのが、DBの物理ファイルになるらしい。

```
development:
  adapter: sqlite3
  database: db/development.sqlite3
  timeout: 5000
```
みたいなふうに書いてあって、DB の実体はルートディレクトリ配下の db ディレクトリの下にある development.sqlite3 が実体になっている。
Google Cloud IoT CoreにpublishするNode.jsとPythonのチュートリアルを試してみた

# はじめに
いまさらかもやけど、Google Cloud IoT Coreでどんなことできるか知っとこうと思って、チュートリアルを試してみることにした。

# Cloud IoT Coreって？
データを収集するときのデバイスの管理するサービス。
デバイスとかエッジ側のゲートウェイとクラウドをつなぐ部分。
IoTサービス全体の中では、ほんの一部。
集めたデータは他のサービスにつないで使うっぽい。
認証とかのセキュリティをサポートしてる。
MQTTとHTTPをサポートしてる。
いわゆるMQTTのブローカー的に使う。
デバイスの登録とかモニターもREST API使って管理できる。

[Cloud IoT Core  |  Cloud IoT Core  |  Google Cloud](https://cloud.google.com/iot-core/?hl=ja)

[モノのインターネットの概要  |  ソリューション  |  Google Cloud](https://cloud.google.com/solutions/iot-overview?hl=ja)

# 環境
クラウド側とローカル（デバイス）側の環境。

## クラウド
- Google Cloud IoT Core

## ローカル
- Chrome OS Version 77.0.3865.56 (Official Build) beta (64-bit)

```
$ gcloud --version
Google Cloud SDK 263.0.0
bq 2.0.47
core 2019.09.13
gsutil 4.42
```

# したこと
## Quickstart
まず、公式のチュートリアルにそって作業した。
日本語と英語が混在してるから、混乱する。
うごいてそう。

[Quickstart  |  Cloud IoT Core Documentation  |  Google Cloud](https://cloud.google.com/iot/docs/quickstart)

- プロジェクト作る
- レジストリ作る
- トピック作る
- Key作る
- デバイス登録
- デバイスとKey交換。
- gcloudでsubscriptionを作成
- node.jsでMQTTでpublish
- gcloudでpull（subscribe）してデータ取得
- Clean upってのは保留。

## Python Client for Cloud IoT API
node.jsとgcloudだけじゃいまいちわからなかったので、Pythonでやってるのないかしらべてみた。
pipでgoogle-cloud-iotってのをインストールしたら割りと簡単にdeviceの情報をとれそう。管理用？
publish/subscribeのコードではなさそう。

[Python Client for Cloud IoT API — google-cloud 9289c52 documentation](https://googleapis.github.io/google-cloud-python/latest/iot/index.html)
[Python Client for Cloud IoT API — google-cloud-iot 0.1.0 documentation](https://googleapis.dev/python/iot/latest/index.html)

## Google Cloud IoT Core Python Samples
Pythonでpublishするサンプル。
中身はpaho.mqtt.client使ってる。
その気になったら、これを変更してセンサーデータとかもっとチープな別の端末から送られてきた情報をpublishしたらよさそう。

[Google Cloud IoT CoreでMQTTを試す - Qiita](https://qiita.com/h-sakano/items/8a4960595e3359ad9ea4)

[python-docs-samples/iot/api-client/mqtt_example at master · GoogleCloudPlatform/python-docs-samples · GitHub](https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/iot/api-client/mqtt_example)

## その他
gcloud使うときの認証
[Authentication — google-api-core 0.1.0 documentation](https://googleapis.dev/python/google-api-core/latest/auth.html)

# わかったこと
デバイスはレジストリで管理。
データはトピックで管理。
そのあとのサービスにつなぐ方法も調べないと使えなさそう。

[Quickstart  |  Cloud IoT Core Documentation  |  Google Cloud](https://cloud.google.com/iot/docs/quickstart?hl=ja)

# 所感
すこし、雰囲気がわかってきた。
認証とかをうまいことサポートしてくれてるの安心感ある。
IoTって言葉がついてるけど、機能的にはすごく狭いところやった。
Google、チュートリアル的にvirtualenvおしやった。しらんかった。
【Linux】awkでのテキスト処理(先頭行/最終行/行指定などの行操作)

Linuxでテキスト処理を行う際にawkをよく使います。
awkを使うと、例えばa b c と並んでいるデータをb a c と並び変えて出力したり、数字をカンマ区切りにしたりできます。

今回はawkを使用してテキストの先頭行/最終行/行指定を行うスクリプト＋αを書いていきます。

サンプルテキスト
============
/rootでls -l > /tmp/txt をした結果です。
12行のテキストファイルとなっています。

```rb
[root@localhost ~]# cat /tmp/txt
合計 12
-rw-------.  1 root root 1898  7月 28 23:20 anaconda-ks.cfg
-rw-r--r--.  1 root root 1926  7月 28 14:23 initial-setup-ks.cfg
drwxr-xr-x. 10 root root 4096  7月 28 15:35 rtl8188eu
drwxr-xr-x.  2 root root    6  7月 28 16:45 ダウンロード
drwxr-xr-x.  2 root root    6  7月 28 16:45 テンプレート
drwxr-xr-x.  2 root root    6  7月 28 16:45 デスクトップ
drwxr-xr-x.  2 root root    6  7月 28 16:45 ドキュメント
drwxr-xr-x.  2 root root    6  7月 28 16:45 ビデオ
drwxr-xr-x.  2 root root    6  7月 28 16:45 音楽
drwxr-xr-x.  2 root root    6  7月 28 16:45 画像
drwxr-xr-x.  2 root root    6  7月 28 16:45 公開
```

先頭行を表示する
============

```rb
[root@localhost ~]# cat /tmp/txt | awk 'NR==1'
合計 12
※NRとはNumber of Recordのこと。

headでも同じことができます。
[root@localhost ~]# cat /tmp/txt | head -n 1
合計 12
```


先頭行を除く
============

```rb
[root@localhost ~]# cat /tmp/txt | awk 'NR>1'
-rw-------.  1 root root 1898  7月 28 23:20 anaconda-ks.cfg
-rw-r--r--.  1 root root 1926  7月 28 14:23 initial-setup-ks.cfg
drwxr-xr-x. 10 root root 4096  7月 28 15:35 rtl8188eu
drwxr-xr-x.  2 root root    6  7月 28 16:45 ダウンロード
drwxr-xr-x.  2 root root    6  7月 28 16:45 テンプレート
drwxr-xr-x.  2 root root    6  7月 28 16:45 デスクトップ
drwxr-xr-x.  2 root root    6  7月 28 16:45 ドキュメント
drwxr-xr-x.  2 root root    6  7月 28 16:45 ビデオ
drwxr-xr-x.  2 root root    6  7月 28 16:45 音楽
drwxr-xr-x.  2 root root    6  7月 28 16:45 画像
drwxr-xr-x.  2 root root    6  7月 28 16:45 公開

※NR>1はNR>=2に変えても同じ結果になります。
```

#

最終行を表示する
============
```rb
[root@localhost ~]# cat /tmp/txt | awk 'END{print $0}'
drwxr-xr-x.  2 root root    6  7月 28 16:45 公開
```

行指定
============
```rb
#2行目を指定する場合
[root@localhost ~]# cat /tmp/txt | awk 'NR==2'
-rw-------.  1 root root 1898  7月 28 23:20 anaconda-ks.cfg

#3行目～5行目を指定する場合
[root@localhost ~]# cat /tmp/txt | awk 'NR>2 && NR<6'
-rw-r--r--.  1 root root 1926  7月 28 14:23 initial-setup-ks.cfg
drwxr-xr-x. 10 root root 4096  7月 28 15:35 rtl8188eu
drwxr-xr-x.  2 root root    6  7月 28 16:45 ダウンロード
```
テキストファイルの行数を確認する
============
```rb
[root@localhost ~]# cat /tmp/txt | awk 'END{print NR}'
12
```

テキストファイルに行数を付けて表示
============
```rb
[root@localhost ~]# cat /tmp/txt | awk '{print NR,$0}'
1 合計 12
2 -rw-------.  1 root root 1898  7月 28 23:20 anaconda-ks.cfg
3 -rw-r--r--.  1 root root 1926  7月 28 14:23 initial-setup-ks.cfg
4 drwxr-xr-x. 10 root root 4096  7月 28 15:35 rtl8188eu
5 drwxr-xr-x.  2 root root    6  7月 28 16:45 ダウンロード
6 drwxr-xr-x.  2 root root    6  7月 28 16:45 テンプレート
7 drwxr-xr-x.  2 root root    6  7月 28 16:45 デスクトップ
8 drwxr-xr-x.  2 root root    6  7月 28 16:45 ドキュメント
9 drwxr-xr-x.  2 root root    6  7月 28 16:45 ビデオ
10 drwxr-xr-x.  2 root root    6  7月 28 16:45 音楽
11 drwxr-xr-x.  2 root root    6  7月 28 16:45 画像
12 drwxr-xr-x.  2 root root    6  7月 28 16:45 公開
```

最後に
============
awkでのテキスト操作はいろいろな書き方がありますのでこれ以外にも表現の仕方があると思います。
データ成型を行うシェルプログラムを行うときには非常に強い味方になります。
私自身、awkを含むテキスト処理をもっと学習しどんどん紹介(アウトプット)していきます。
ダークモード非対応

## iOS13でのダークモードを一時的にしのぐ方法
`Info.plist`で`UIUserInterfaceStyle`キーに~~`light`~~ではなく、`Light`を指定することで、アプリ内では常にライトモード扱いにすることができるようです。
エルは大文字である必要がありそうです。大文字でない場合`Validate`で怒られます(怒られました)
<img width="727" alt="スクリーンショット 2019-09-22 12.42.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171702/8a460c2b-915b-27ef-5c5b-b3e44754f13c.png">

+ 正しい設定  
<img width="365" alt="スクリーンショット 2019-09-22 12.46.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171702/b3b3ff7b-b1fd-0ef2-55e3-beec651958e2.png">
+ 誤った設定  
<img width="470" alt="スクリーンショット 2019-09-21 22.45.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171702/4b903d10-8c80-1c96-0434-b3fac59b5157.png">

## 部分的にしのぐ方法
```swift
override func viewDidLoad() {
    super.viewDidLoad()
    overrideUserInterfaceStyle = .light
}
```

## 注意
appleさんとしては、ダークモードへの対応を強く、**強く**推しているようです。
はやく対応しなくては...

## 参考
[Choosing a Specific Interface Style for Your iOS App](https://developer.apple.com/documentation/appkit/supporting_dark_mode_in_your_interface/choosing_a_specific_interface_style_for_your_ios_app)
Qiita始めました！

はじめまして、たつじと言います。プログラミングをやっていく中で経験したことのアウトプットをしていきたいと思い、この度ブログを始めることにしました！

これから技術的な情報発信および自身への備忘録として、記事を投稿していきたいと思います^_^
私の書いた記事が誰かの役に立てたら良いなと思っています。よろしくお願いいたします！
【Node.js】オブジェクト(連想配列)とクエリ文字列の相互変換

## サンプルコード

`querystring`モジュールを使用する。
Node.jsの標準モジュールのため、事前準備等は不要。

```javascript
const querystring = require('querystring');

// オブジェクト -> クエリ文字列
const obj     = { a: '1', b: '2' };
const result1 = querystring.stringify(obj);
console.log(result1);
// => a=1&b=2

// クエリ文字列 -> オブジェクト
const str     = 'a=1&b=2';
const result2 = querystring.parse(str);
console.log(result2);
// => [Object: null prototype] { a: '1', b: '2' }
```

## 参考

- [【Node\.js】querystring\.parseでクエリ文字列のパース \- Qiita](https://qiita.com/chuck0523/items/d8cff2ecfd208e8e513c)
rails APIモード＋ActiveAdminで、管理者画面にてユーザーを削除しようとしたらNo route matchesのエラーが発生した際の対処法

# 環境
- Rails 5.2.3 (APIモード)
- activeadmin (2.3.1)

# 事象
管理者画面（http://localhost:3000/admin/） にて、管理者を削除するボタンを押したところ、Routing Error No route matches [POST] "/admin/admin_users/２"が発生する。

# 原因
HTTPのPUTメソッド、DELETEメソッドを実現するためのミドルウェアであるRack::MethodOverrideが使用されていなかったため。

# 対応
1. rake middlewareコマンドを実行し、Rack::MethodOverrideがないことを確認
2. application.rbにconfig.middleware.use Rack::MethodOverrideを追加

```
class Application < Rails::Application
　　（中略）
   config.middleware.use Rack::MethodOverride

```

# 参考
- https://github.com/activeadmin/activeadmin/issues/4476
- https://railsguides.jp/rails_on_rack.html#%E3%83%9F%E3%83%89%E3%83%AB%E3%82%A6%E3%82%A7%E3%82%A2%E3%82%B9%E3%82%BF%E3%83%83%E3%82%AF%E3%81%AE%E5%86%85%E9%83%A8
RedisでJobQueueを実装する

最近仕方なくMySQLでジョブを管理するコードを書いたが、[sidekq](https://github.com/mperham/sidekiq)や[Celery](http://www.celeryproject.org/)などメジャーなツールのバックエンドによくRedisが使われているということで調べてみた。


実現方法
--

ジョブはRedisのLISTデータ型に格納する。

ジョブを追加する際はRPUSHでリストの後ろから追加し、ジョブを取得する際はBLPOPを使って先頭から取得する。

BLPOPはリストからの先頭の要素を取得しつつ削除するコマンドだが、リストが空の場合はリストに要素が追加されるかタイムアウトまで待つ（ブロッキング）。このコマンドのおかげでワーカーは何度もジョブの有無を確認（ポーリング）しなくて済むし、ジョブが追加されたら即座に取得して実行できる。


利用コマンド
--

コマンド | 動作
------------------------------|---
BLPOP<br>(Blocking Left Pop?) | リストの先頭から要素を取得しつつ削除する。<br>リストが空の場合は追加されるかタイムアウトまで待つ。
RPUSH<br>(Right Push?)        | リストの後ろに要素を追加する。
CLIENT ID                     | 現在のConnectionを識別するclient_idを取得する。
CLIENT UNBLOCK                | client_idのブロッキングを解除する。


コード
--

Pythonの[Redis](https://github.com/andymccurdy/redis-py)ライブラリを使って実装した。
スレッドでワーカーを2つ動かし、標準入力からの文字列をジョブとしてキューに追加している。

ワーカーを終了時にBLPOPのタイムアウトを待たないと綺麗に終了できず悩んだが、CLIENT UNBLOCKコマンドを使うことでブロッキング状態を解除し、すぐに終了させることができた。


```python
import redis
from threading import Thread


class WorkerThread(Thread):
  def __init__(self, key):
    super().__init__()
    # single_connection_clientにTrueをセットすると、RedisClientが使うConnectionが固定される
    # Connectionを固定しないとclient_idの違うConnectionでBLPOPが実行される可能性があり、CLIENT UNBLOCKが実行できなくなる
    self.client = redis.Redis(
        host='redis', port=6379, db=0, single_connection_client=True
    )
    self.client_id = self.client.client_id()
    self.key = key
    self.running = True

  def run(self):
    while self.running:
      message = self.client.blpop(self.key, timeout=30)
      if (message):
        print("{}: {}".format(self.client_id, message))

  def stop(self):
    self.running = False
    # self.clientはConnectionが固定されているので、ブロッキング中に追加でコマンドを実行できない
    # CLIENT UNBLOCK実行のため新しいクライアントを作成する
    client = redis.Redis(host='redis', port=6379, db=0)
    client.client_unblock(self.client_id)


def main(n_workers=2):
  client = redis.Redis(host='redis', port=6379, db=0)
  threads = [WorkerThread("queue") for _ in range(n_workers)]

  try:
    for t in threads: t.start()
    # 空文字入力で終了
    s = input()
    while s:
      client.rpush("queue", s)
      s = input()
  finally:
    print("waiting for workers stopped")
    for t in threads:
      t.stop()

    for t in threads: t.join()


if __name__ == '__main__':
  main()

```

実行結果
--

文字を入力すると、2つのワーカーが順番にprintすることが確認できた。

```bash
/app # python3 redis_queue.py
A
125: (b'queue', b'A')
B
126: (b'queue', b'B')
C
125: (b'queue', b'C')
D
126: (b'queue', b'D')

waiting for workers stopped
```
【VSCode】Mac OS で 拡張機能が効かなくなったので対処法を探ってみる

## 問題

- 今日も今日とて草を生やそうと意気揚々とVSCodeを起動したが、今日も今日とて拡張機能が効いていない。
- Macで作業しているときに、拡張機能で追加されるサイドバーが非表示になる事象が頻発していた。
- 原因はわからなかったが、しばらく時間がたつと不具合が解消されるので、無視していた。
- 今回は、早く快適な環境での作業に戻りたいので解決方法を探ってみる。。

## 試してみたこと

- アプリ内で拡張機能のアンインストールと再インストール -> 変わんなかった

### ログの確認

VSCodeではパネルの出力タブでアプリケーションのログを確認することができる

`ログ（拡張機能ホスト）`確認してみた感じ、問題の拡張機能は起動はしているようだった。

### 拡張機能フォルダの中身をみてみる

Macの場合、拡張機能はすべて`/home/ユーザー名/.vscode/extentions/**`にあるので確認してみると、気になるところがあった。

フォルダ名は`azemoh.one-monokai-0.3.7`のように後ろにバージョン名が書かれているのだが、バージョンが古いものも残っていた。そこで以下の方法を試してみた。

#### 対処方法

1. 機能しない拡張機能の入ったフォルダ`/home/ユーザー名/.vscode/extentions/**`以下をすべて(現バージョンもまとめて)削除する。
2. VSCodeを開いて拡張機能を再インストールしてみる。

すると、拡張機能が機能した!

## 設定を変更して予防してみる

ここからは想像の話になるので気になる方だけ読んでください
権限の問題などでアップデートが不具合を起こしていることが考えられるので、拡張機能の自動アップデートを無効化してみる。

1. VSCodeの設定`command + ,`をひらく`
2. Extensions: Auto Update`を検索しチェックボックスを外す。

こうすることで、拡張機能ファイルに不用意な変更が起こることはなくなりそう。
アップデートをするときは拡張機能タブから手動でアップデートするようにすればいいと思います。

## まとめ

拡張機能が不具合を起こした場合は、[extensionフォルダから強制的に再インストールする](#対処方法)方法をためしてみるのもよさそうですね。
AWS CDKで既存のS3のObjectCreatedイベントをトリガーにしてLambdaを動かす

AWS CDKでは（というかCloudFormationでは）既存のS3 bucketのイベントへの購読を新たに追加することができない。が、SQS queueに既存のSNS topicを購読させることはできる。

ので、S3のobjectCreatedイベントが発生したらSNS topicにメッセージをpublishするようにあらかじめ設定しておけば、以下の順序でメッセージを伝達していくことで、AWS CDK (with CloudFormation)で作ったAWS Lambdaのトリガーを引くことが可能。

S3 => SNS topic => SQS subscription => Lambda

以下がSQS Subscription以降を作るAWS CDKのConstructの例。

```typescript
import core = require("@aws-cdk/core");
import lambda = require("@aws-cdk/aws-lambda");
import s3 = require("@aws-cdk/aws-s3");
import sns = require("@aws-cdk/aws-sns");
import sqs = require("@aws-cdk/aws-sqs");
import { SqsEventSource } from "@aws-cdk/aws-lambda-event-sources";
import { SqsSubscription } from "@aws-cdk/aws-sns-subscriptions";

export class ExistingS3BucketAndSNSTopicToLambdaThroughSQS extends core.Construct {
  constructor(scope: core.Construct, id: string) {
    super(scope, id);

    const bucket = s3.Bucket.fromBucketName(
      this,
      "ExistingS3Bucket",
      "bucketName"
    );

    const handler = new lambda.Function(this, "lambda", {
      runtime: lambda.Runtime.NODEJS_10_X,
      code: lambda.Code.asset("lambda/dist"),
      handler: "index.main",
      timeout: core.Duration.seconds(30),
      environment: {
        BUCKET_NAME: bucket.bucketName
      }
    });

    bucket.grantRead(handler);

    const topic = sns.Topic.fromTopicArn(
      this,
      "ExistingSNSTopic",
      `arn:${core.Aws.PARTITION}:sns:${core.Aws.REGION}:${core.Aws.ACCOUNT_ID}:existing-sns-topic`
    );
    const queue = new sqs.Queue(this, "queue");

    topic.addSubscription(new SqsSubscription(queue));

    handler.addEventSource(
      new SqsEventSource(queue, {
        batchSize: 1
      })
    );
  }
}
```


AWS CDK v1.6.1 では動いたけどそれ以外のバージョンではもしかしたらAPI変わってるかも。

Gist: https://gist.github.com/katryo/ff3cf8b5e3f12823ad7bc2468db054cd

AWS CDKは流行ってほしい。みんなどんどん自分の作ったConstructを公開していってくれ。

CloudFormation直書きとかもう時間の無駄なので……。
【swift】ダークモード追加

#ios13から搭載したダークモードの確認の仕方

この度リリースされた、ios13からダークモードが搭載されました。
Xcodeもアプリがupdateされ、UIがガラッと変わってますね。

で、ダークモードの実装もできるみたいで、画面の切り替えができるみたいです。

storyboardの下にあるデバイス選択から

<img width="613" alt="スクリーンショット 2019-09-21 22.10.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472705/78ccb83f-bb41-c3e9-7d96-4870540bb47d.png">

下記の部分の右側を選択します。

<img width="113" alt="スクリーンショット 2019-09-21 22.08.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472705/bc2f41c8-8bd9-175a-8f61-d109c5575805.png">

すると。。。

<img width="246" alt="スクリーンショット 2019-09-21 22.12.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472705/78772791-d57b-2594-d72e-66f64d0be1cc.png">

これが

<img width="246" alt="スクリーンショット 2019-09-21 22.12.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472705/26220d81-3914-136e-e218-e3eedc353947.png">

なります。

実装時に確認できるのでやっていこうと思います。

#profile

生まれも育ちも大阪の浪速中の浪速っ子が30才未経験からITエンジニアとして生きるブログもやってます。
よかったらみてください:muscle_tone2:

<a href="https://blogmura.com/profiles/11016817?p_cid=11016817"><img src="https://blogparts.blogmura.com/parts_image/user/pv11016817.gif" alt="PVアクセスランキング にほんブログ村" /></a>
powershellで書籍索引を名寄せする

## 背景
初投稿です。書籍編集者として働いています。
ゲラの校正などが進み、本づくりもいよいよ大詰めという段階で本文とは別に厄介な仕事になるのが索引の作成です。特に厄介なのが **名寄せ** で、これは下記のように Microsoft Excel などに拾った用語とノンブルを「項目－ノンブル」の一対一対応の関係に整形する作業です。
![cap_excel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501098/34a0b93e-50a2-8eff-e7fa-a0fe72d7ef90.png)

↓（面倒！）

```
いちご　　1，5
バナナ　　8，9
みかん　　10
りんご　　1，18
```

正規表現の文字列置換で上記作業を行う編集部秘伝の**紙製**マニュアルもあるのですが、もう少し近代的な方法でこの作業を効率化できないかと編集部の PC に入っている powershell でコマンドレットを作成してみました（実行ポリシーは変更済です）。

## コード

```powershell
function Format-Nayose {
    <#
        .SYNOPSIS
        索引を名寄せする
        .PARAMETER delimiter
        項目とノンブルの区切り文字
        .EXAMPLE
        Get-Clipboard | Format-Nayose
        Get-Clipboard | Format-Nayose -delimiter "," # カンマ区切りからコピーした場合
        $hoge -split "[\r\n]+" | Format-Nayose
    #>
    param (
        [string]$delimiter = "`t"
    )
    $object = $input | ConvertFrom-Csv -Delimiter $delimiter -Header "item", "nombre"
    $object | Group-Object -Property "item" | ForEach-Object {
        Write-Output ("{0}　　{1}" -f $_.Name, ($_.Group.nombre -join "，"))
    }
}
```

## 使い方
```
# Microsoft Excel からコピーして作業する場合
PS > Get-Clipboard -OutVariable cb
いちご	1
いちご	5
バナナ	8
バナナ	9
みかん	10
りんご	1
りんご	18

PS > $cb | Format-Nayose
いちご　　1，5
バナナ　　8，9
みかん　　10
りんご　　1，18

# テキストファイルを読み込んで処理する場合
PS > cat .\hoge.txt | Format-Nayose
……

# カンマ区切りの場合
PS > cat .\fuga.csv | Format-Nayose -delimiter ","
……
```
基本的に一度コンソール上で変数内容を確認してから作業していますので、パイプライン経由での使用のみを想定。自動変数の `$input` でパイプライン経由で入力を取得して `Group-Object` で処理整形しています。

powershell は Windows であれば標準装備ですので非エンジニアにもオススメできそうです（ただしダブルクリック・ドラッグドロップで実行できる `.vbs` や `.bat` に比べるとハードル高）。Officeと一太郎と大量の紙ゲラに埋もれた環境でも、デジタルでの効率化余地は大いにありそうです。
#AWS の料金・請求額を一発で確認できるURLはこれだ！ https://console.aws.amazon.com/billing/home


https://console.aws.amazon.com/billing/home

![image](https://user-images.githubusercontent.com/13635059/65372357-22ecb500-dcaa-11e9-8c6f-c2c0c5bb0f03.png)
![image](https://user-images.githubusercontent.com/13635059/65372361-2aac5980-dcaa-11e9-8b9c-fefaa35203bd.png)

以上。

# ところで

ローソンでGODIVAのチョコレートカフェが半額になってたけど、AWS料金も半額にしてくれないかな？

![image](https://user-images.githubusercontent.com/13635059/65372369-4fa0cc80-dcaa-11e9-9e6a-65958ad5006a.png)


# Original by Github issue

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








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
毎日使うGitコマンド

## 3行で

- ブランチの切り替え
- コミットとプッシュ
- マスターにプル

## ブランチの作成と切り替えを同時に行う

```terminal
$ git checkout -b ブランチ名
```

別々に行う場合は以下。

- ブランチを作成
`$ git branch ブランチ名`

- ブランチの切り替え
`$ git checkout ブランチ名`

## 変更内容を保存してコミットする

```terminal
$ git add .
```

```terminal
$ git commit -m "コメント"
```

```terminal
$ git push origin ブランチ名
```

以下でcurrentブランチ名を省略できる。

```terminal
$ git push origin HEAD
```

## GitHub上でプルリクエストを出したあと

masterにブランチを切り替える。

```terminal
$ git checkout master
```

変更内容をmasterにプルする。

```terminal
$ git pull origin master
```
うすい30パーセントキーボードをつくってみた【完成編】2019/09/21

##前説
残り作業のハンダずけをがんばった。そして完成！
基板が小さいので、たぶん3時間くらいで完成したと思います。
![IMG_1926.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283328/4c8b61e2-cd0e-ca58-374c-22591862d80f.jpeg)

##ビルドログ
表面はくまさん側なのを確認して、ダイオードの足を曲げます。
![IMG-1912.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283328/ac8d957d-d73c-861a-1fac-8ed894eb15e7.jpeg)
ハンダする時はひっくり返すので、マスキングテープでおさえておいたら安心ですね。
今回はJLCPCBで作成したので、都合よくマステが付録でついていたんでそれを使用しています。
![Screenshot_20190921_201920.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283328/b7936150-bf1c-ebde-0bf9-b1b2bc24c097.png)
後はちゃっちゃとハンダ付けですが、ハンダ付け前に向きを確認しておきましょう。
■がわにダイオードの黒線が来てたらOK。これはキーボードの基板では定番ぽいです。
![Screenshot_20190921_201955.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283328/b447123c-d3aa-28d3-bb77-8d91c23fc090.png)
ダイオードをやっつけたら次はスイッチです。同じようにマステで止めてひっくり返してひたすらハンダ付け…
![IMG-1917.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283328/e203bd2f-6055-de85-669f-af9a2ce11268.jpeg)
Promicroはコンスルーを初めて使ってみました。これでモゲマイクロしても大丈夫:thinking:
![IMG-1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283328/67e9737a-fe4b-3ebd-bc34-39af754dffc2.jpeg)
キーキャップをつけてない状態で、入力できるかチェックをしたほうがいいです。このキーキャップは差し込んだらかなり外しにくい。私だけかなぁ:thinking:
![IMG-1921.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283328/0199f674-0a49-84b0-2fe6-3b02142ca855.jpeg)
ぱっと見良さげでしたが、左半分の中行と下行が入れ替わってた。
印刷してた回路図でキーマップの設定を作ったけど、最新回路ではこの場所をいれかえてたのが原因でした。入力はできたので問題ないのでキーキャップをはめて無事完成。
Promicroのところは、グルーガンでキーキャップを貼り付けて一体感を出してみた。
![IMG_1926.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283328/2bcdb4b3-7132-e78d-840c-8557dcb70e1f.jpeg)
キーマップのデバッグ後、入力がおかしくないことを確認して終了かなと思ったけど、バックプレートがあったが良さそうだったので、もう1枚基板を使ってバックプレートにしました。
![IMG-1928.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283328/a1094a41-4ff3-2123-f66d-cd5dfc466667.jpeg)
##後書
基板の設計環境は出来上がってるので、作りたいものに集中できるのはすごいことだと思います。
後はキラキラ化と無線化したいので、ぼちぼち勉強かな。
UnityのCreator Kit: PuzzleをOculusQuestで動かしてみる

# はじめに
Unity Technologiesさんから配布されているCreator Kit: Puzzleという無料アセットをOculusQuestで動かしてみます。

[Creator Kit: Puzzle]
(https://assetstore.unity.com/packages/templates/tutorials/creator-kit-puzzle-149311)
アセットのページです。

[Creator Kit: Puzzleチュートリアル]
(https://learn.unity.com/project/creator-kit-puzzle)
チュートリアルです。

いくつかあるシーンのうちlevel3を動かせるようにしました。
今回作成したソースコードをGitHubに置いています。また、とりあえず動かしてみたい人向けにapkファイルも置いています。
![com.oculus.vrshell-20190921-211735_Trim_Trim_300x300_fps10.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215278/568779dd-cff4-13b1-e9d4-261675966e59.gif)

#開発環境
Unity 2019.2.4f1
Creator Kit: Puzzle - 1.1
Oculus Integration for Unity - 1.40
VrGrabber-v0.0.3 (hecomi氏作)

#ビルド手順
1. GitHubの[CreatorKitPuzzle](https://github.com/SatoshiTakahama/CreatorKitPuzzle) からcloneでファイルをローカルに持ってきます。
2. 持ってきたファイルを指定してUnityでプロジェクトを開きます。
3. Build Settings から Platform を Android に Switch Platformします。
4. Oculus Integrationをアセットストアからダウンロードし、インポートします。
5. Creator Kit: Puzzleをアセットストアからダウンロードし、インポートします。インポートする際、すべてインポートしてしまうとプロジェクトの設定が上書きされてしまうため、ProjectSettingsのチェックを外します。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215278/dd5ea41c-6dc5-58ab-d109-458c88694282.png)
6. オブジェクトをつかむためのアセットVrGrabberを[VrGrabber](https://github.com/hecomi/VrGrabber) からダウンロードし、インポートします。自分がダウンロードしたファイルは"VrGrabber-v0.0.3.unitypackage"ですが、数字の部分はバージョンにより変わります。
7. OculusQuest向けに変更したシーンLevel03Modifyを開きます。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215278/de71a16b-2867-2eae-d496-416165f800d0.png)
8. OVRCameraRigのTarget DevicesをQuestに変更します。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215278/40042519-de1d-b4f6-c256-77472fe9bd36.png)
9. ビルドするシーンを選択し、Build Settings からビルドします。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215278/1671f327-69cd-4233-9d9e-b68f30bc5c98.png)

#操作方法
・左側コントローラー
スティック 前後移動、左右方向転換
~~Y 上移動~~
~~X  下移動~~
・右側コントローラー
スティック つかんだオブジェクトの操作
~~B UIの表示・非表示切り替え~~
A ハンマー、フリッパー等稼働するオブジェクトの操作
HandTrigger オブジェクトをつかむ

#制限事項
・掴めるオブジェクトは１個目のボールだけです。
~~・クリア後の結果表示の画面は表示されません。~~
~~・UIのRestartボタンは機能しません。~~

#GitHubに置いたソースコードについて
DebugUIBuilderHand.csは、Oculus Integrationに含まれているDebugUIBuilder.csをもとに改変したもののため、ライセンスはOculus Integrationに従います(Assets\Oculus\SampleFramework\license.txtをご確認ください)。

そのほかのソースコードはCC0としますので好きなようにご使用ください。
DebugUI.csは、デバッグ用の情報を表示するためのUIを構築するためのもので、DebugMover.csは、キャラクターを操作するためのものです。

#さいごに
本当はPuzzleのオブジェクトを自由に配置する部分までできるようにしてから記事を書こうと思っていたのですが、ちょっと時間がかかりそうなのでいったん今の段階で書くことにしました。
この部分は元のコードではエディター拡張機能を使用して実装されているのですが、VR空間内で実現するためにはランタイムでの処理が必要になるため、簡単にはいかなさそうです。
今はこの部分のソースコードを調査しつつ、どのようにしたら実現できそうか検討中です。
=>記事を追加しました。[UnityのCreator Kit: PuzzleをVR空間内でPuzzleの配置ができるようにする](https://qiita.com/Satoshi_Takahama/items/bac5a85112f39b95a81d)
PowerShellを使って、画面解像度をワンタッチで切り替えるアイコンをデスクトップに作成する

RPAでロボットを開発している際に、画面解像度を切り替えたくなる時が多々あります。
そんな時にデスクトップを右クリックして、画面の設定を開いて・・・とやっていると面倒なので、
デスクトップに解像度変更用のアイコンを置いておいて、良く使う解像度に一発で切り替えられるようにしよう。というお話です。

今回はAutomation Anywhere Enterprise v11で使用する際に便利な画面解像度に切り替えられるものを作ってみます。

#試した環境
Windows 10

#作り方
### 1. Microsoftのスクリプトセンターで公開されている、以下のスクリプトを入手。

[スクリプト Set-ScreenResolution](https://gallery.technet.microsoft.com/scriptcenter/2a631d72-206d-4036-a3f2-2e150f297515#content)

こちらのスクリプトはSet-ScreenResolutionという関数になっていまして、
`Set-ScreenResolution -Width 1024 -Height 768`といった形で解像度を指定して変更することが出来ます。

### 2. メモ帳で以下の4つのテキストファイルを新規作成。同じフォルダに作成する。

1366-768.ps1
1920-1080.ps1
1366-768.bat
1920-1080.bat

#### 1366 x 768 に変更するためのPowerShellスクリプト

```PowerShell:1366-768.ps1
(ここに上記で紹介されているスクリプトを貼りつける）
Set-ScreenResolution -Width 1366 -Height 768
```

#### 1920 x 1080 に変更するためのPowerShellスクリプト

```PowerShell:1920-1080.ps1
(ここに上記で紹介されているスクリプトを貼りつける）
Set-ScreenResolution -Width 1920 -Height 1080
```

#### 1366 x 768 に変更するためのbatファイル
```bat:1366-768.bat
powershell -NoProfile -ExecutionPolicy Unrestricted .\1366-768.ps1
```

#### 1920 x 1080 に変更するためのbatファイル
```bat:1920-1080.bat

powershell -NoProfile -ExecutionPolicy Unrestricted .\1920-1080.ps1
```

画面の解像度変更自体はPowerShellで可能なのですが、ダブルクリックで実行。といった手軽さの実現のために.batファイルを使って呼び出すようにしています。

### 3. デスクトップに上記のbatファイルのショートカットを作成
こんな感じですね。完成しました！
ダブルクリックすると設定しておいた解像度に変更してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/eea1fc65-da1a-61a7-ff34-821447ce752b.png)
お好みでスタートメニューなどに登録しても便利だと思います。

#参考にしたページ

[ダブルクリックだけで画面の解像度を変更する - パソコンサポートの00H ～社長BLOG～](https://www.00h.co.jp/blog/%E3%83%80%E3%83%96%E3%83%AB%E3%82%AF%E3%83%AA%E3%83%83%E3%82%AF%E3%81%A0%E3%81%91%E3%81%A7%E7%94%BB%E9%9D%A2%E3%81%AE%E8%A7%A3%E5%83%8F%E5%BA%A6%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B/)
[Powershellを楽に実行してもらうには - Qiita](https://qiita.com/tomoko523/items/df8e384d32a377381ef9)
Python [線形代数~行列式，逆行列，固有値，固有ベクトル] 

#目次
1.必要なライブラリ一覧
2.numpyを用いた行列表記方法
3.行列式
4.逆行列
5.固有値と固有ベクトル

##1.必要なライブラリ一覧
```python05.py
import scipy.linalg as linalg
from scipy.optimize import minimize_scalar
import numpy as np
```

##2.numpyを用いた行列表記方法

```python06.py
mat=np.array([[1,2,3] , [1,3,2] , [3,1,2]])
print(mat)
```

##3.行列式

```python06.py
mat=np.array([[1,2,3] , [1,3,2] , [3,1,2]])
print(mat)

a = linalg.det(mat)
print("行列式")
print(a)
```

##4.逆行列

```python07.py
b = linalg.inv(mat)
print("逆行列")
print(b)
```

##5.固有値と固有ベクトル

```python0.py
c , d = linalg.eig(mat)

print("固有値")
print(c)

print("固有ベクトル")
print(d)
```
Node.js BookshelfでCRUD処理

#はじめに
UpdateとDeleteに関して情報が少ないように感じたので、
自分が使った基本処理の記述をまとめておく。

#Create
```js:example.js
const rec = {
//カラム名：保存するデータ
    colmn1: req.body.data1,
    colmn2: req.body.data2
}
new Example(rec).save().then((result) => {
//保存後の処理を記述
});
```

#Read
```js:example.js
new Example().where('検索対象のカラム','演算子','検索値')
  .fetch()
  .then((result) => {
  //保存後の処理を記述
  });
```

#Update
{patch:true}は設定したカラムの更新を許可する設定。

```js:example.js
new Example().where('検索対象のカラム','演算子','検索値')
  .save({更新するカラム: 値},{patch:true})
  .then((result) => {
     //更新後の処理を記述
  });
```

#Delete
取得したレコードのメゾットを使用する。

```js:example.js
new Example().where('検索対象のカラム','演算子','検索値')
  .fetch()
  .then((record)=>{
     record.destroy();
  })
  .then((result) => {
     //削除後の処理を記述
  });
```

##参考
https://github.com/bookshelf/bookshelf
https://arjunphp.com/bookshelf-js-deleting-row-related-rows-many-many-relationship/
青空文庫のepub形式からテキストを抜き出して、1つのテキストファイルにまとめる

# はじめに
青空文庫のepubからテキストを抜き出して、1つのテキストファイルにまとめるメモです。青空文庫のepubは下記から探しました。
https://bookwalker.jp/ex/sp/aozora/

抜き出したものから形態素解析もしてみましたが、これは省きます。

# コード
```python3

import ebooklib
from ebooklib import epub 
from bs4 import BeautifulSoup

# 下記でepubファイルを読み込む
book = epub.read_epub('ダウンロードしたepubファイル名')

#メタデータを読み込む
title = book.get_metadata('DC', 'title')
creator = book.get_metadata('DC', 'creator')
publisher = book.get_metadata('DC', 'publisher')
language = book.get_metadata('DC', 'language')

# タイトル
print(title) 
# 執筆者
print(creator) 
# 発行人
print(publisher) 
# 言語
print(language) 

###############################

#ファイルの結合を結合する関数
#章ごとにファイルがわかれていたので、最終的にすべてを一つのテキストファイルに結合するため
def join_file(filepath):
    with open(filepath, 'wb') as savefile:
        #for f in filelist:
        for f in textfileList:
            data = open(f, "rb").read()
            savefile.write(data)
            savefile.flush()

#連番生成のたねの初期値
i = 1

textfileList = []
# 最終的に下記のファイルに出力する
filepath = "all_text.txt"

# epubに含まれている全ファイルを読み込む
items = book.get_items()

for item in items:
    
# ドキュメントが記述されたファイルのみを読み混む
    if item.get_type() == ebooklib.ITEM_DOCUMENT:
        #読み込んだものをhtmlファイルとして保存し、
        #textファイルに変換する
        path = str(i) + '.html'
        path_txt = str(i) + '.txt'

        with open(path , mode = 'w') as file:
             #get_content().decode()でファイルを読み込み
            file.write(item.get_content().decode())
            file.close 
        #一旦保存した、htmlファイルを読み込む
        htmlfile = open(path) 
        #beautifulsoupで読み込ませる
        line = BeautifulSoup(htmlfile.read())
        #get_text()でhtmlのタグを全て除去しテキストのみを取り出す
        line = line.get_text()
        print(line)
        htmlfile.close()
        
        # 取り出したテキストをtextファイルに順次保存
        with open(path_txt , mode = 'w') as file_txt:
            file_txt.write(line)
            file_txt.close
        
        #textファイルを順次、appendしていく
        textfileList.append(path_txt)
        
print(textfileList)
#filepathを下記の関数に渡す
join_file(filepath)

```

# おわりに
雑ですが、こんな感じです。
形態素解析するときに使えそう。
python seleniumで社内ポータルから食堂メニュー表を取得するスクリプトを作った

# 動機
* 普段、私は社員食堂で昼食を取っているのだが、体型を考慮してなるべく高タンパク・低カロリーのメニューを選択したい。
* メニュー表は社内ポータルに公開されているのだが、いちいちログインして取得するのが面倒。（忘れてしまう時もある。）

# 環境
* メニュー表はsharepoint上に、PDFファイルで公開されている。
* 新しいメニュー表は（恐らく）週末にポータルにアップロードされている。
* 社内標準ブラウザはIEである。

# コード
```python
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
import pyautogui
from time import sleep

URL = ''
# webドライバ読み込み
driver = webdriver.Ie("./IEDriverServer.exe")
# ポータルにアクセス
driver.get(URL)
driver.implicitly_wait(10) # 秒
# メニュー表が掲載されているページのリンク取得
link = driver.find_element_by_link_text("食堂メニュー").get_attribute("href")
## 新しいタブでリンクを開く
# driver.execute_script('window.open()')
# driver.switch_to.window(driver.window_handles[1])

# リンクを開く
driver.get(link)
# メニュー表(PDFファイル)へのリンク取得
menu = driver.find_element_by_partial_link_text("週間メニュー表")    #　partialを使用して部分検索
# 右クリックメニューの「名前を付けてリンク先を保存」からファイル保存
ActionChains(driver).context_click(menu).send_keys(Keys.ARROW_DOWN).send_keys(Keys.ARROW_DOWN).send_keys(Keys.ARROW_DOWN).send_keys(Keys.ARROW_DOWN).send_keys(Keys.ENTER).perform()
sleep(5)                    # ファイル保存ダイアログ表示待ち時間
pyautogui.press('enter')    # ダイアログ画面に対してはActionChainsのsendkeyが及ばないのでpyautoguiを利用
# ドライバ終了
driver.quit()

```

# 工夫した点
* リンク先を新しいウインドウ（もしくはタブ）で開いてもいいのだが、リンク元に戻る操作がないことから、都度、driverに与えるURLを更新する方針とした。
* コード内のコメントにもある通り、対象ファイルがPDFのため、seleniumによるファイルダウンロードが行えず、また、ファイルを開いてスクショとして保存しようにもPDFViewer上ではスクショが正しく撮れないため、コンテキストメニューから対象ファイルを保存する方針とした。
    * このとき、「名前を付けて保存」のウインドウを開くまではActionChainsで行えるのだが、最後の保存ボタンのクリックはできないのでpyautoguiを使用してキー入力を送っている。

# 改善点
* 保存先を指定できない。（恐らく、前回ファイル保存したディレクトリが設定される）
* 時間ベースでのwait処理があり、ホストの環境に依存する作りになっている。

# 留意点
これをwindowsのタスクスケジューラに登録することで、所定時刻にポータル上からメニュー表を取得するようにします。
Error starting userland proxy: port is already allocated. と表示される時の対処法・解決法

# Error starting userland proxy: port is already allocated. と表示された

前提条件：筆者はDocker初心者でほとんどわからない・知識がない状態でした。

## 環境

DockerのVerは19.03.2でした。

## どういう手順を踏んだのか？

<https://team-lab.github.io/skillup/step2/02-environment.html>
を参考にしてLaravelを学習しようとしている中で次のコマンド

``` bash
$ docker-compose up -d workspace nginx
```

を実行した時に


```
Starting laradock_nginx_1            ... error
```

となってnginxが立ち上がりませんでした。


## エラーメッセージ全文

```
ERROR: for laradock_nginx_1  Cannot start service nginx: driver failed programming external connectivity on endpoint laradock_nginx_1 (a54e6c0958d89d9c2ae12c891d57433a23395d4662d7575e83b30ff393df6c81): Error starting userland proxy: port is already allocated.

ERROR: for nginx  Cannot start service nginx: driver failed programming external connectivity on endpoint laradock_nginx_1 (a54e6c0958d89d9c2ae12c891d57433a23395d4662d7575e83b30ff393df6c81): Error starting userland proxy: port is already allocated.
ERROR: Encountered errors while bringing up the project.
```

## 原因と対処法

MAMPのApacheが原因でした。そのためMAMPは一度落としてから作業を行うと成功しました。

初歩的なところだと思いますが、もし同じ状況で詰まった初学者の助けになれば幸いです。

## 参考リンク

こちらを参考にして解決しました。
<https://github.com/laradock/laradock/issues/251>
TypeScript言語の特徴


#これはなに
「TypeScriptとは」を説明したもの。

##TypeScriptとは
MicroSoftが開発しているオープンソースのプログラミング言語。
基本的には、Javascriptがベースになっており、その構文を拡張することでJavascriptが苦手である大規模なアプリケーション開発にも使えるようになっている。
TypeScriptをコンパイルするとJavascriptになる。

<b>言語的な特徴</b>

1. 静的な型付け
変数の型を決めた場合、その後に変数の型を変更することができない。
逆にJavascriptは、動的な型付けをすることができる。

```typescript
//typescript
var x: number = 10;
x = "hello"; //エラー発生
```

```javascript
//javascript
var x: number = 10;
x = "hello"; //エラーなし｜動的にデータ型を変更することができる。
```

2. クラスベースのオブジェクト指向
例えば、クラスベース言語はクラスとインスタンスという概念があるのに対し、プロトタイプベース言語はPrototypical Objectというオブジェクトがあるだけ。

|クラスベース(typescript, java)|プロトタイプベース(javascript)|
|---|---|
|クラスとインスタンスは異なる実態|全てのオブジェクトはインスタンス|
|クラス定義を用いてクラスを定義する。また、コンストラクタメソッドを用いてクラスをインスタンス化する。|コンストラクト関数を用いてオブジェクトのセットを定義及び作成する。|
|既存クラスのサブクラスを定義するクラス定義を用いて、オブジェクト階層を構築|プロトタイプチェーンに従ってプロパティを継承|
|クラス定義がクラスの全インスタンスの全プロパティを定義する。実行時に動的にプロパティを追加することはできない。|コンストラクタ関数または、プロトタイプのプロパティの初期セットを指定する。個々のオブジェクトやオブジェクトのセット全体にプロパティを追加したり、プロパティを削除したりできる。|
bundler gem について考察してみる

## 考察しようと思ったきっかけ


競合してしまって作業が止まってしまう。

業務委託する時に、環境構築でつまる


## gemとは？

- Ruby言語用のライブラリ
- RubyGemsとして公開されている
- Ruby のバージョン `1.9 以降` RubyGemsは付属されているよう
　- つまり、`vagrant`などで環境構築した際には、`ruby`をinstallすれば、`gem install ライブラリ`ができるようになるのだろう



## bundlerとは？

https://bundler.io/v2.0/#getting-started

- `bunder`も`gem`らしい。
- 1つの`ruby`に1つの`bundler`
- `bundle install --path vendor/bundle`
  - `.bundle/config`に venderのgemを読み込んでとでる見たい


- `bundle exec` これをつけると`ローカル`のgemを読むらしい
  - システム側
  - ローカル側と言うのがあるらしい