OmniAICreator/Qiita-1.07M huggingface dataset:
TreasureDataとgraphvizでパス分析（ダイアグラムを出力する）

本家で紹介されている記事に沿ってやる（終了）

* [アクセスログ分析最前線：Treasure Data JavaScript SDK で始めるパス分析 その3](https://tug.red/entry/2016/06/27/155230/)
    * この記事、1〜3までありますが、1は手法の紹介、2はTD上のクエリ実行、3がダイアグラム化という感じの構成です
    * ただ、3で実際に利用してるデータは2で作ったものじゃなく、3で新たに発行したものなので、正直3だけでも良さそうですｗ
* 今回は、上記に沿ってやったことを自分の中でフロー化するためのまとめです

##　やり方

### 1. データ準備

まず、クエリを作るための分析用データを準備します    
大事なのは**決まったカラム**を出力すること。これだけ。
カラム名は任意です。以後のコマンドも変更してもらえれば動きます。

* データ内容
    * 分析対象にしたいアクセスログ
* 必須カラム
    * user_id：ユーザを一意に特定するもの
    * td_url：アクセスURL
        * パラメータ付与されている場合は事前に整形しておいてください
        * URLと言ってますがパスが良ければpath使ってください
        * 整形例： 
            * いろんなところにリンク貼られてたりすると/がついてるかついてないかが違う
            * パス作る人によっては大文字小文字が別
            * 実際に解析するときにエンコードされてるとなんのページかわからない 

              ``` sql
       SELECT URL_DECODE(LOWER(TRIM(td_url, '/'))) as td_format_url
       FROM access_log
              ```
    * time：アクセス日時

必須カラム以外はあってもなくてもダイアグラム抽出には不要ですので、
別途分析したい場合はご自由に追加どうぞ

### 2. クエリを作成する

上記データを整形する
クエリフォーマットは以下の通り
（本家記事にもありますのでそっちから取ってきてください）

``` sql
-- 先月の訪問ユーザのパス分析
SELECT td_format_url_from, td_format_url_to, COUNT(1) AS cnt
FROM (
    SELECT td_format_url AS td_format_url_from,
      LEAD(td_format_url) OVER( PARTITION BY unique_id ORDER BY td_pageviews_time ) AS td_format_url_to
    from (

    --      
    -- ここに上記で準備したデータがSELECTされるようにする 
    -- 

    )pas_all
)pas_format
GROUP BY
  td_format_url_from, td_format_url_to
HAVING ( td_format_url_from IS NOT NULL AND td_format_url_to IS NOT NULL )
ORDER BY cnt DESC
LIMIT 50 -- 出力したい矢印の量だけ設定すれば良い。多すぎるとカオスになるので注意
```

このクエリを実行して、結果を保存します。
ファイル名は`data.csv`とします。

### 3. ダイアグラムにする

graphvizは導入しておいてください。
作業ディレクトリに先程の`data.csv`を入れておきます。

``` shell
#こっからは自分用。作業しやすいように
$ ls your/path
data.csv

#dotファイルに起こす
$ mgv.rb ei=data.csv ef=td_format_url_from,td_format_url_to ev=cnt -el -d o=result_transition.dot

#dotファイルを整形（後述）
$ vim result_transition.dot

#ダイアグラム出力
$ dot -Tpng result_transition.dot > result_transition.png
```

基本的な流れは上記の通りです。




### ＜補足＞ダイアグラムの整形

実際図にしてみると見辛かったりするので、その場合の回避策

#### 上から下の図を左から右に変える

`rankdir=LR`を追加する

``` dot
digraph G {

rankdir=LR;  #これを追加する

n0 [label="https://domain/aaa" height=0.5 width=0.75] 
n1 [label="https://domain/bbb" height=0.5 width=0.75] 
・・・
```

#### ノードを小さくする

上記の`label="https://aaa"`の文字列を短くすればノードも広がらなくなります。
よくやる方法としては、`https://domain/`などのドメインを除いたりするとすっきり。

#### 数値を小数にしない

`label="51.0"`などの.0を一律削除（オプションでできそう）

``` dot
・・・
n0 -> n1 [style="setlinewidth(10.0)",label="51.0"]
n2 -> n2 [style="setlinewidth(7.8936170212765955)",label="40.0"]
n2 -> n0 [style="setlinewidth(5.404255319148936)",label="27.0"]
・・・
```
React Native キャッシュの削除方法

だいたいこれでうまくいく。
ブランチ切替時とか毎回やるようにしてる

```
watchman watch-del-all
lsof -n -P -i :8081 -t | xargs kill
rm -rf ios/build
rm -rf android/app/build
rm -rf node_modules
npm install
# yarn使ってなくても yarn.lockがあったら削除したほうがいいかも
```

`lsof`の行はchromeのデバッガ起動してたらchromeもおちます。


さらにiOSでビルドできない場合は以下も有効な場合があります。React Native自体のバージョンアップ時など。

```
rm -rf ~/Library/Developer/Xcode/DerivedData
```
【C#】初めてのイベントハンドラ

#はじめに
windowsフォームアプリで、自分にとって初めてのイベントハンドラ自作でした。
#やりたかったこと
親フォームのボタンを、子フォームのテキストボックスが空欄だとunable、入力されているとEnableにすることです。実際に作っていたフォームはこのようなフォームです。

![図1.png](https://qiita-image-store.s3.amazonaws.com/0/295196/3a2b721f-172c-cb3b-a8a3-fb71a7cbde26.png)
#方法
子フォームは、親フォームのボタンに触ることができません。よって、子フォームがテキストボックスが空欄でなければイベントを発生させ、親フォームがイベントを受け取り、ボタンをEnableにします。フォーム生成時にボタンはunableにします。

親フォームをForm1、子フォームをForm2とします。
イベントを発生させるのはForm2で、Form1がイベントを受け取ります。
Form2側では、

```CSharp
public EventHandler イベント名 //publicである必要あり

protected virtual void Onイベント名(object sender, EventArgs e)//ここのOnは命名規則に従って付く
    {
       イベント名.Invoke(sender, e);//イベントを起こす宣言
    }
```

Form1側では

```CSharp
this.Form2.イベント名 += new EventHandler(イベントが起こったら行う関数);　//イベントは+=であることに注意

イベントが起こったら行う関数()
{
　　　　.......//何らかの処理
}
```

という手順で行いました。

#詰まったポイント
実はこのやり方だと、通常ならできません。なぜなら、form1側に

```CSharp
form2 hogehoge = new form2();
```
としないとform1にform2に触る手段がないからです。よって、定義する必要があります。しかし、今回の場合はこの定義をするとできませんでした。理由は、windowsフォームの生成時にフォームのコンポーネントを設定するInitializeComponent()の中ですでにform2が定義されていたからでした。今回は、親フォームに子フォームを埋め込んで表示していたため、親フォームに子フォームの宣言が入っており、新たに宣言すると宣言した側にイベントが追加されますが、実際に動作するのはInitializeComponent()の中で宣言されたform2だったという状況です。
また、初歩的なミスですがイベントハンドラの引数をそろえないとエラーが出ますね。
#おわりに
初歩的な内容ですが、もしかしたら同じ状況になる方がいらっしゃるかと思い記事を作成しました。イベントハンドラは、どこで起こるのかということを気を付ける必要があります。フォームのコンポーネントがセットされて、その中に値が入るタイミングがいつかどうかといった、イベントに必要な情報が入っているタイミングかどうかという部分です。
まだ理解が足りない部分があるので、勉強していきます。
MacでVBAを書く時の注意

Excel For MacでVBAを保守する機会がありましたので、メモしておきます。

# MacとWindowsの見分け方
そもそもMacとWindowsで挙動が異なるので、どうしても処理を分ける必要があります。
見分けるために、以下のようなコードを書きました。

```vb
Function isMac()
    Range("F1").Formula = "=INFO(""osversion"")"
    Range("G1").Formula = "=INFO(""system"")"
    
    If InStr(Range("F1").value, "Macintosh") > 0 Or InStr(Range("G1").value, "mac") > 0 Then
        isMac = True
    Else
        isMac = False
    End If
End Function
```

追記：コンパイラ定数を使用した方法はこちらになります。

```vb
Function isMac()
    #If Mac Then
        isMac = True
    #Else
        isMac = False
    #End If
End Function
```

# ファイルパス区切り文字の差分吸収
~~今回のVBAでは、ファイル出力機能がありました。ご存知の通り、MacとWindowsではファイルパスの区切り文字が
異なるので、普通にやっても動かないです。そのため、以下のような関数を作りました。~~
追記：単純にファイルパスの区切り文字が欲しい場合は、下記の関数を書かずとも、Application.PathSeparatorプロパティから取得できます。

```vb
Function FILE_SEPARATOR()
    If isMac() Then
        FILE_SEPARATOR = "/"
    Else
        FILE_SEPARATOR = Chr(92)
    End If
End Function
```


# バックスラッシュが入力できない・・・
Excel For MacのVisual Basic Editorでは、パックスラッシュが入力できず、しかも
Windowsマシンで書いたバックスラッシュ（Asciiコードの5C）が表示すらできない、という悲劇がおきました。
表示されない、かつ文字化けすらしていないので、表示上消えているんですが、存在はしている、という状態です。
そのため、プログラム中のバックスラッシュを全てChr(92)に置き換えました。

# バックスラッシュをファイル出力した時、文字化けする
Chr(92)をutf-8で出力しようとしたのですが、内部的に5C -> C2A5へと変換されてしまいました。
これを防ぐため、Chr(92)ではなく、ChrW(&H5C)でunicodeで指定することで回避しました。

# セル内改行の置換には、vbLfではなくvbCrを使う

```vb
    If isMac() Then
        tmp = Replace(str, vbCr, "new Line")
    Else
        tmp = Replace(str, vbLf, "new Line")
    End If
```
なぜかMacでは、vbCrのようです。

# まとめ
Excel for MacのVisual Basic Editorでは、そもそも、2バイト文字上でキャレットがずれてしまったり、マウスホイールのスクロールが全然効かなかったりなど、Microsoftの嫌がらせかと思うくらいひどかったので、もうやりたくないです。
firewall - CentOS7


**■ゾーン**

ちょっと始める前にゾーンという概念について！

firewalldではゾーンという概念がある。
要するに分類みたいなもの。
このゾーンをNIC毎に適応して運用する。
デフォルトでは9種類のゾーンが存在している。

|項目|内容|
|:----------:|:----------|
|drop |全てのパケットを破棄する。内部から外部へのパケットは許可されるが、返信されてきたパケットも破棄してしまうので実質的に通信不可となる。|
|block |外部からのパケットは破棄される。内部からの通信パケットの返信は許可される。|
|public |デフォルトでは「ssh」と「dhcpv6-client」のみが許可されている。|
|external |デフォルトでは「ssh」のみ許可される。naptが有効になる。|
|dmz |デフォルトでは「ssh」のみ許可されている。|
|work |デフォルトでは「dhcpv6-client」と「ipp-client」と「 ssh」が許可される。|
|home |デフォルトでは「dhcpv6-client」と「ipp-client」と「mdns」と「samba-client」と「ssh」が許可される。|
|internal |デフォルトでは「dhcpv6-client」と「ipp-client」と「mdns」と「samba-client」と「ssh」が許可される。|
|trusted |全てのパケットが許可される。|


----------


###1.サービスの有効化と確認###

基本的にはデフォルトで有効になっている。

```
systemctl enable firewalld
systemctl start firewalld
```

動作状況を確認

```
firewall-cmd --state
```

もしくは

```
systemctl status firewalld
```


---


###2.現状の確認###

現状どうなっているか確認するには、

```
firewall-cmd --list-all
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/415c8c7c-73c9-11b3-ad62-8a454f8fe5c3.png)
現在、NIC「enp0s3」はゾーン「public」に所属していることがわかる。


ゾーンを指定して確認するには、

```
firewall-cmd --zone=<ゾーン名> --list-all
```

<ゾーン名>にblockを指定してみると、
![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/82e2d1e1-911c-2fff-097a-0cbbadc97694.png)
ゾーン「block」には何も所属していないことがわかる。

すべてのゾーンの設定を確認するには以下のとおりだ。

```
firewall-cmd --list-all-zones
```

設定時に指定できるサービス一覧を表示する。

```
firewall-cmd --get-services
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/9e6a71aa-8f09-7d6e-6078-a7f2da106bee.png)


---


###3.変更してみる###

デフォルトゾーンの変更。

```
firewall-cmd --set-default-zone=<ゾーン>
```

デフォルトのゾーンをblockに変更してみた。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/39d397c8-05cc-150f-e0e3-ac81f201a734.png)

インターフェイスのゾーンを変更するには以下の通りだ。

```
firewall-cmd --zone=<ゾーン> --change-interface=<インターフェイス>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/902f41f6-001e-01a8-a968-eaefed7ee27d.png)

恒久的にインターフェイスのゾーンを変更したいときは、インターフェイスそのものの記述を変えてしまう。

```
vi /et/sysconfig/network-scripts/ifcfg-<インターフェイス名>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/2c3d89a9-3271-832c-5ca6-cf80616c7a15.png)
↑ZONEの部分を変更。

ゾーンへサービスを追加する場合は、以下の通りだ。

```
firewall-cmd --zone=<ゾーン> --add-service=<サービス>
```

httpを追加してみよう。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/2777895a-7c67-25bc-62c1-0fd8f03e52c2.png)

今度は逆に削除してみよう。

```
firewall-cmd --zone=public --remove-service =http
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/2bb7016c-ad0d-72dd-800b-efeebd32dcc0.png)


---


###4.permanentオプション###

再起動をするともとに戻ってしまうので、恒久的に設定を反映させるのが、permanentオプションだ。

```
firewall-cmd --zone=public --add-service=http --permanent
```

設定を反映させるには、その後に、

```
fiewall-cmd --reload
```

とする。


---


###5.元のサービス定義ファイルの場所など###

デフォルトで用意されているサービス一覧

```
ls /usr/lib/firewalld/services/
```
API通信でたまにハマるメモ

#はじめに
API通信でデータは取得できてるのにUIに反映されない!って時の見直しポイントのメモです。
#Responceデータのエンコード
###before

```swift:ViewController.swift
//配列に返ってきたurlを取得
let responseImageUrl = Array.imageUrl
```

###after

```swift:ViewController.swift
let responseImageUrl = Array.imageUrl
//返ってきたStringデータをエンコード
let decodeUrl = responseImageUrl.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
```

#最後に
自分はこれで無事にimageUrlを使ってimageを取得することができました。
終わり。。
Java11時代のJDKを考察してみた話

# はじめに
[WebサービスのJava11対応をしてみた話](https://qiita.com/awakuwaku/items/22ba019184b1a3ab3b75) の `Java(JDK)` に関する部分です。
色々な方が記事にしていますが、本記事はあくまで私がOpenJDK11を選択する際の備忘です。

# JDK11の選択肢
少なくとも今のところ以下のJDKの選択肢があります。
- [OracleJDK](https://www.oracle.com/technetwork/java/javase/downloads/index.html)
- [OpenJDK](https://openjdk.java.net/)
- [Redhat OpenJDK](https://developers.redhat.com/products/openjdk/download/)
- [AdoptOpenJDK](https://adoptopenjdk.net/)
- [ZuleOpenJDK](https://www.azul.com/downloads/zulu/)
- [Amazon Corretto](https://docs.aws.amazon.com/corretto/#lang/en_us)


## OracleJDK
言わずとしれたOracle社の公式JDK。安心・安全という点では他JDKを一歩上回ります。
Java11以降は、Oracle社と契約すると手に入ります。(開発用にはダウンロード提供されています)
契約＆代金を支払えば無期限の永遠サポートを受けることもできます。

[Oracle Java SE サポート・ロードマップ
](https://www.oracle.com/technetwork/jp/java/eol-135779-ja.html)

私のいるプロジェクトでは、比較的高額(3年サポート以降にはプレミアム価格上乗せ)代金を支払い続けることは難しいとの判断でNGになりました。


## OpenJDK
Oracle社含むJava開発コミュニティで開発を実施しているJDK。他のJDK実装の基になっているようです。
サポートライフサイクルについて6ヶ月(次期JDKリリースまで)と短いのがネック。
※一時長期サポートをするとの噂も流れましたが以降音沙汰がないですね

私のいるプロジェクトでは、Oracle社の公式JDKに近いという安心感からアップデートコストを支払ってもよいのでOpenJDKを選択するという結果になりました。


## Redhat OpenJDK
RedHat社がメンテナンスするJDK。RedHatLinux上であれば長期サポートが提供されるようです。
RedHatLinuxのライセンス購入が必要なので、導入ハードルはOracleJDKに近いかつOSの制約がある分難しいところです。

私のいるプロジェクトでは、RedHatLinuxを利用していないため導入NGとなりました。


## AdoptOpenJDK
IBM社含む数社、数コミュニティで開発を実施しているJDK。現状のコードベースはOpenJDKでビルド提供のようです。
実際の該当バージョンのサポートライフサイクル終了後にどのように運営されていくかが気になるところです。

私のいるプロジェクトでは、実績面から不安視され導入NGとなりました。


## ZuleOpenJDK
Azure Systems社がメンテナンスするJDK。無償の長期サポートが提供されるようです。
Microsoft社のAzureにてサポートが提供すると話題になりました。
実際の該当バージョンのサポートライフサイクル終了後にどのように運営されていくかが気になるところです。

私のいるプロジェクトでは、Azureを利用していないこととAdoptOpenJDKと同様に実績面から不安視され導入NGとなりました。


## Amazon Corretto
Amazon社(Amazon Web Services)メンテナンスするJDK。無償の長期サポートが提供されるようです。
Amazon Web Servicesに現在いるJava開発者のJames Gosling氏のコメントや既にAmazon Web Services上のJDKとして利用されているとのことから、大きな話題になりましたね。

私のいるプロジェクトでは、現状プレビュー版であることから導入NGとなりました。
正式版になれば将来的には導入検討対象になりそうな予感です。


# 感想
私のいるプロジェクトでは、決定権をもつ人間が比較的安定志向ということもあり、アップデートコストを支払ってもよいのでOpenJDKを選択するという結果になりましたが、2018年春頃に話題になり始めた頃と比べても選択肢も増えています。

条件次第では、過去のJDKと同様に無償の長期サポートを受けつつ利用することが可能なものも多く、悩んでいる方も多いのではないかなと思います。

Java8のサポートが終了する2019年の年明け、またはOpenJDK11のサポートが終了する2019年3月頃に再度話題があがりそうですが、皆様の選択の参考になれば幸いです。
0xコミュニティーリソース・絶対見るべき過去記事やサイト

# モチベーション
0xのコミュニティーリソースと0xを使用しているプロジェクトをまとめます。本記事は[0x doc](https://0x.org/wiki#Community-Resources)に載っているものを日本語にしたものです。（個人的にいくつかコメントも加えている）すべてのクレジットは0x teamに属します。間違い、ご意見あれば[Twitter経由](https://twitter.com/WatanabeSota?lang=en)でご連絡ください。

※ オススメ度は完全に個人の私見です。

# コミュニティーとSNS
* [Discord Chat](https://discordapp.com/invite/d3FTX3M)
    * 0x core teamに直接質問ができる。返信も早いのでわからないところが出てきた時に質問するのにおすすめ。
* [github](https://github.com/0xproject)
    * ソースコードが確認できる。オープンソースで運営されている。
* [Twitter](https://twitter.com/0xproject)
* [Reddit](https://www.reddit.com/r/0xproject)
* [Medium](https://blog.0xproject.com/)

# キーとなる過去記事
* [0xのミッションとバリュー](https://blog.0xproject.com/the-0x-mission-and-values-181a58706f9f)　【オススメ度：★★★★★】
* [0xプロトコルのガバナンス](https://blog.0xproject.com/governance-in-0x-protocol-86779ae5809e)　【オススメ度：★★★★☆】
* [0xコアチームの0xコミュニティーにおける役割](https://blog.0xproject.com/the-role-of-the-0x-core-team-in-the-0x-ecosystem-2d8b50354166)　【オススメ度：★★★☆☆】
* [2018年版0x リレイヤーにおける18個のアイデア](https://blog.0xproject.com/18-ideas-for-0x-relayers-in-2018-80a1498b955f)　【オススメ度：★★★★☆】
* [Peer to Peerトレーディング](https://blog.0xproject.com/compliant-peer-to-peer-trading-4dab8e5c3162)　【オススメ度：★★★★☆】
* [0xプロトコル V2](https://blog.0xproject.com/introducing-0x-protocol-v2-9f5bda04d38d)　【オススメ度：★★☆☆☆】

# 最初に読むべき過去記事/サイト
* [0x Portal](https://0x.org/portal)　【オススメ度：★★★☆☆】
* [0xコミュニティーにようこそ](https://blog.0xproject.com/welcome-to-the-0x-community-9d99dfe0a52b)　【オススメ度：★★☆☆☆】
* [0xビギナーガイド](https://blog.0xproject.com/a-beginners-guide-to-0x-81d30298a5e0) 【オススメ度：★★★★☆】
* [なぜ分散型取引所が大事なのか？](https://medium.com/@FEhrsam/why-decentralized-exchange-protocols-matter-58fb5e08b320)　【オススメ度：★★★★★】
* [RaderRelay学習サイト](https://radarrelay.com/learn/)　【オススメ度：★★★★☆】
    * [Wallet to Walletの取引とはどういうことか](https://wallet2wallet.io/)
    * [Token Allowanceとはなにか？](https://tokenallowance.io/)
    * [WETHとはなにか？](https://weth.io/)
    * [gasとはなにか？](https://ethgas.io/)
* [開発者向けニュースレター](https://0xproject.us15.list-manage.com/subscribe?u=f18a4bf52e634b0da57ada37b&id=019881f2c4)　【オススメ度：★★☆☆☆】
* [リレイヤーレポート](https://0xprotocol.substack.com/)　　【オススメ度：★★★☆☆】

# 0xプロトコルを使っている（使おうとしている）アプリケーション

* Aragon
* Auctus
* Augur
* bZx
* Blocknet
* ChronoBank
* Emoon
* Dharma
* District0x
* dYdX
* EasyTrade
* Gods Unchained
* Hut34 Project
* Lendroid
* Maker
* MelonPort
* OpenANX
* Paradigm Protocol
* Request Network
* Set

# 0xプロトコルを使っている（使おうとしている）リレイヤー
* Amadeus
* BambooRelay
* Dextroid
* ERC dEX
* Ethfinex
* IDT Exchange
* Instex
* Lake Project
* LedgerDex
* MobiDex
* OpenRelay
* Paradex
* Radar Relay
* Shark Relay
* Starbit
* The Ocean
* Token Jar
* Tokenlon
* Weswap

#トレードエクスプローラー
* [0x remote.hr](http://0x.remote.hr/)
* [0x trade viewer](http://0xtrades.info/)
* [0x tracker](https://0xtracker.com/)
PhpStormでPHPのバージョン切り替えができなくてハマってたのはcomposerの設定に引っ張られてた

動作確認環境
PhpStorm: 2018.3

PhpStormでは、 `composer.json` に こんなふうにrequireでPHPバージョン指定の記述が入っていると、
<img width="209" alt="composerjson.png" src="https://qiita-image-store.s3.amazonaws.com/0/18306/bc906e32-3696-8b53-ac56-a3a71da84aee.png">

PHPのバージョン指定ができなくなってしまいます。
この状況に遭遇したの初めてだったので、焦りました。

<img width="762" alt="Kanguages&Frameworks PHP" src="https://qiita-image-store.s3.amazonaws.com/0/18306/0cd0a869-8c88-b1ee-b87b-55171f57f453.png">

この場合、開発環境はPHP5.6なのに、PhpStormにはPHP5.3扱いされています。
PHP5.4で入った array の short syntax とか全滅ですよね。ソースコードを開くと真っ赤っ赤です。

環境設定で composer.json のページを開くと、 `Synchronize IDE Settings with composer.json`
 のチェックをはずしてやります。

![スクリーンショット](https://qiita-image-store.s3.amazonaws.com/0/18306/f6c08ba4-4947-6d93-1272-fe7b90f3dd3e.png)

これで自由にPHPのバージョンを選択できるようになり、PHP5.6と認識させることができました
<img width="743" alt="Preferences_after.png" src="https://qiita-image-store.s3.amazonaws.com/0/18306/47057106-7939-ec7b-7143-51f390f158df.png">
windowsでショートカットコマンドを自作する方法の備忘録


windowsでaliasを.batを使って楽に実現する方法の備忘録

# 先に謝っておきます！！！既出だったらさーせん！！！ｗｗｗ


バッチファイルを使ってwindowsで自作コマンドを作る方法を書きます。
windowsでもaliasさせたく今回行ったのですが、思いの他簡単でしたので共有を。
簡単にできます。


# x.要約

1. PATHを通す
1. 再起動する
1. バッチファルを作る
1. 実行する

応用編
1. 作成した短縮コマンドに引数を与える
1. バッチファイルから別のバッチファイルに引数を付けて呼び出す方法


### 動作環境

- windows10-64bit
- 普段windowsを使っているがコマンド入力が面倒で短縮コマンドを作りたい（aliasさせたい）方を想定して書いています

# 1. PATHを通す

スクリプト置き場までのPATHを通します。

[PATHの通し方が分からない方はこちら](http://www.atmarkit.co.jp/ait/articles/1805/11/news035.html)

私は今回`C:\Windows\System32\`の下に`my-scripts\`という名前のフォルダを作成し、そこまでのpathを登録しました。
この`my-scripts`という名前も場所も好きなもので構いません。今回たまたま便宜上そうしただけです。

![mypath.png](https://qiita-image-store.s3.amazonaws.com/0/102978/d805ba00-8d57-8452-9c24-a422df3b7c67.png)

# 2. 再起動する

PATHを通したらお決まりの再起動です。
環境変数を再読込させる一番簡単な方法がPCの再起動なので…。

# 3. バッチファルを作る

ここまでを一度まとめると

1. my-scriptを作成
2. PATHを通す
3. 再起動

を行いました。

ここから行うことをまとめると

1. デスクトップにスクリプトを作成
2. my-scriptsにコピー
3. cmdでテスト実行

ということになります。


## 3-1 デスクトップにスクリプトを作成

先程作成した`C:\Windows\System32\my-scripts\`に直接ファイルを作ります…、と言いたいのですが、`C:\Windows\System32\`配下は権限がないと作成できません。
デスクトップに一度ファイルを作成・編集を行い、完了したら`C:\Windows\System32\my-scripts\`にコピーする流れになります。

デスクトップに適当なテキストファイルを作成します。名前は`my-echo.txt`とします。

中身を編集します。

```text:my-echo.txt
@echo off

echo aaa
```

次に拡張子を変更します。

`my-echo.txt` → `my-echo.bat`

拡張子を変更する際になにか聞かれてもOKを押して進んで大丈夫です。

## 3-2 my-scriptsにコピー

`デスクトップ`→`C:\Windows\System32\my-scripts\`に`my-echo.bat`をコピーもしくは移動させます。


# 4 cmdでテスト実行

cmdを開いて`my-echo`と入力して下さい。

[cmdの開き方](https://pc-karuma.net/windows7-command-prompt/)

成功すると下図の様になります。

```cmd
C:\Users\ymzk-jp>my-echo
aaa

```


🎉🎊お疲れ様です。完成です🎊🎉

簡単でしたね。

`my-echo`がコマンド名になります。
なので例えば`aaa.bat`という名前でファイルを作った場合は`aaa`と入力することで実行できます。

```cmd
C:\Users\ymzk-jp>aaa
aaa

```

因みに一度PATHを通したので次回以降はPATHを通す作業は省略でき、スクリプト作成からとなります。。



----


# ［応用編］作成した短縮コマンドに引数を与える


引数は%1を使って取得します。
%1は第一引数
%2は第二引数
%3は第三引数
といった具合です。

```text:my-echo2.bat
@echo off
echo %1
```

- 実行

```cmd
C:\Users\ymzk-jp>my-echo aaa
aaa
```



---

# ［応用編］バッチファイルから別のバッチファイルに引数を付けて呼び出す方法

この場合バッチファイルが2つ以上必要になります。
引数を引き継ぐには%1をそのまま渡せばOKです。

`my-echo_arguments.bat`と`my-echo.bat`を作成します。
作成が完了したら`my-scripts\`にコピーし、実行させます。


```text:my-echo_arguments.bat
@echo off

echo %1
```

```text:my-echo.bat
my-echo_arguments.bat %1
```

- 実行


```cmd
C:\Users\ymzk-jp>my-echo aaa
aaa
```


図にするとこんな状況です。

![my-echo_arguments.png](https://qiita-image-store.s3.amazonaws.com/0/102978/81ae2180-0cd5-430c-3514-f70b6c783e1c.png)




# 終わりに

思っていたより簡単でした。結果的にこのQiitaを書いている方が圧倒的に時間が掛かったのはなんともｗ
そもそも動機は`docker-compose`のコマンドが長すぎたためです。bashが使えればどれほど楽なのか…
やろうと思えば可変長引数にも対応できると思います。
ここまで読んでいただきありがとうございました。


tag
---

windows
.bat
bat
バッチファイル
file
argument
引数
渡し方
alias
自作コマンド
短縮コマンド
作り方
やり方
方法
呼び出し
リモート環境をFire HDに切り替えてみた

Retty Advent Calendar 2018 20日目の記事です。
昨日は @shuji-shimooka で [Airflow tutorial解説入れながらやってみた](https://qiita.com/shuji-shimooka/items/88ee7ffbe1090670e32d) でした。

## はじめに
PCが入るようなバックを持って行けないが、PCをもって行かなければ行けない状況ってありますよね。
私もつい最近、友人の結婚式に参列するにあたり、どうしてもPCが手放せないタイミングがありました。

そんな時に手元にFireHDがあったため、これをノートPC同様に使えるように設定して持っていったのでその感想を書いていきます。

## 用意したもの
- [Fire HD 10](https://amzn.to/2QHWaij)
- [ケース](https://amzn.to/2SV1prs)
- [キーボード](https://amzn.to/2EFm2oI)

## やった事
1. FireHDでDebianの設定
1. 会社のPCへの公開鍵認証設定
1. VPN設定
1. その他

※今回の制約として、FireHD自体はkindleを読むために買ったのでUbuntuを入れてとかはやらないようにしました。

### FireHDでDebianの設定
[Kindle Fire HD 8 にLinuxを導入して扱えるようにする。超コスパ Linux タブレット構築方法！！](http://www.webcyou.com/?p=8523)を参考にDebianの設定を行いました。
バージョンの問題で起動できない場合があるので、同じことをやる方はサイトと同様のバージョンを使用する事をオススメします。

### 会社のPCへの公開鍵認証設定
FireHDだけではスペックが貧弱すぎるため、会社のデスクトップPC上でDocker等は動かし使用する様にしました。
この設定周りは拾うまでもないので割愛

### VPN設定
ここが今回の山場でした。
起動できるようにしたDebian上からネットワークを設定しようとすると、Debian側にはネットワーク設定を変更する権限がありませんでした。
そのため、FireHD自体の設定からVPNの設定を入れようとすると、そもそもそんな設定項目がありませんでした。。。
元はAndroidなのだからあるだろうと必死に方法を探した所こんな記事を発見しました。"[Why no VPN settings on Fire HD 10 (7th gen)?](https://www.amazonforum.com/forums/devices/fire-tablets/465413-why-no-vpn-settings-on-fire-hd-10-7th-gen)"

FireHD単体でのL2TP/IPsecによるVPNを使用できない事がわかったため、今回はテザリングするスマホの方をVPNに使用してオフィスにいるPCに接続しました。

### その他
業務で使用できる様にしたいため、Google系のアプリを無理やりインストールして起動した所、使用できませんでした。
スプレットシート等もブラウザからは閲覧はできるが編集はできない状態でフルで使うのはつらいじょうたいでした。
![Screenshot_2018-12-20-16-03-48.png](https://qiita-image-store.s3.amazonaws.com/0/137186/861ced90-77e5-c54e-14ee-8bf8d9b523a2.png)


# まとめ
### 残念だった所
- Debianを起動できる様にした意味が無かった。
- L2TP/IPsecが使えなかった。
- Google系のアプリが使えなかった。
- 外部ディスプレイへの出力に対応していない。

### 良かった所
- 意外と普通に使えた。
- 荷物が軽くなった。
- ローカル環境の依存がなくなった。

# 最後に
今回の残念だった所は、FireHDだから発生したことであり他のタブレットだったら発生しないため、新しいタブレットを購入して今後のメイン端末にしていきたいなと思います。
その場合は、Ubuntuをインストールして使っていく所存です！！！！

明日は@WooNooさんです！
intra-mart 役立ちリンク（非公式編）

お世話になっているintra-mart 役立ちリンクメモです
公式ドキュメント類以外のものだけをまとめました

**株式会社アースリンク 開発者ブログ**
https://www.earthlink.co.jp/engineerblog/
IM-WorkflowのURLなど参考になる情報がいっぱい

**システムトラスト技術ブログ**
https://it-engineer-info.com/category/intra-mart/
情報量が多くて助かります。Apache POIのサンプルにはお世話になりました。

**Code for final**
http://final.hateblo.jp/archive/category/intra-mart
intra-martでajaxを使用する場合のサーバサイドロジックをシンプルに記述する方法が超有用です

**Intra-mart管理に役立つ便利なクエリ集～ユーザ管理編～**
http://life-collections.com/dev/intra-mart/im_query_list_for_user_administrator

IWP7.2用と掛かれていますがAccel Platformでも使えます
共通マスタは期間を考慮に入れないといけないため、IM共通マスタDB構造知識なしでSQLで抽出するのは大変ですので、とても助かります

クエリは有用ですが、IM共通マスタの有効日付範囲指定が間違っているので注意してください
IM共通マスタの有効日付終了日は画面に表示されている日 ＋ 1日でDBに登録されています

``` sql:誤り例
GETDATE() BETWEEN start_date AND end_date
```
``` sql:正解
start_date <= GETDATE() AND GETDATE() < end_date
```

**たちまち。**
http://im.hatenablog.jp/archive/category/intra-mart
トラブルシューティングネタ多し
intra-martはエラーになっても何が原因かエラーメッセージ等から追いにくいのでこういうサイトが増えたらいいなと思います

**Qiita intra-martタグ**
https://qiita.com/tags/intra-mart
ここの情報がもっと増えたらいいな

**CentOS 6.5 に intra-mart をインストールしたときのメモ**
https://www.goro-tsukiyama.com/archives/142
https://www.goro-tsukiyama.com/archives/166
ここを見ながらなんとかCentOSにintra-martを導入出来ました
cassandraがキツイんです・・・

**【intra-mart】[Oracle環境]イントラマートの検証環境をDocker Composeで構築する(Oracle Database版)**
https://www.rinsymbol.net/entry/2019/03/09/172900
手順が詳細。他に例のないOracleでDocker環境作成手順。

**【intra-mart】横配置・縦配置ノードに展開されたノードIDから、展開元のノードIDを取得する方法**
https://www.rinsymbol.net/entry/2018/05/20/105155

**【intra-mart】[IM-FormaDesigner]一覧選択部品のページング数を増やす**
https://www.rinsymbol.net/entry/2020/12/25/221751
IM-FormaDesignerで制約を乗り越えて無理やり実装する例です。とても苦労されている様子が見て取れます。。。他にもIM-LogicDesignerのサンプルが増えてます。

**グローバル・ソリューションズ 開発者ブログ**
https://gsol.hatenablog.com/
CarrierWaveを使っているモデルのfixture作成

## はじめに

Rails5.2でActive Storageが追加されましたが、まだまだファイルアップロードにCarrierWaveを使われている方も多いと思います。

最近ファイルアップロードを必須とするモデルを作ったところ、テストの際にいちいちバリデーションにひっかかって面倒だったので今回の方法を調べました。

基本的には以下のCarrierWaveのwikiに書いてある通りなんですが、少しハマったので記事にしたいと思います。

https://github.com/carrierwaveuploader/carrierwave/wiki/Using-Carrierwave-with-Minitest-and-Rails-5


## バージョン

* Rails 5.2.1
* CarrierWave 1.2.3

## CarrierWaveの設定

```config/initializers/carrierwave.rb
CarrierWave.configure do |config|
  config.root = "/var/www/app"
  config.cache_dir = "/var/www/app/uploads/tmp"
end
```


```app/uploaders/user_icon_uploader.rb
class UserIconUploader < CarrierWave::Uploader::Base

  ## 省略 ##

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

## テスト用の設定

#### carrierwave_helperを作成

CarrierWaveのwikiからコピってきます。

```test/carrierwave_helper.rb
require 'fileutils'

# Carrierwave setup and teardown
carrierwave_template = Rails.root.join('test','fixtures','files')
carrierwave_root     = Rails.root.join('test','support','carrierwave')

# Carrierwave configuration is set here instead of in initializer
CarrierWave.configure do |config|
  config.root = carrierwave_root
  config.enable_processing = false
  config.storage = :file
  config.cache_dir = Rails.root.join('test','support','carrierwave','carrierwave_cache')
end

# And copy carrierwave template in
#puts "Copying\n  #{carrierwave_template.join('uploads').to_s} to\n  #{carrierwave_root.to_s}"
FileUtils.cp_r carrierwave_template.join('uploads'), carrierwave_root

at_exit do
  #puts "Removing carrierwave test directories:"
  Dir.glob(carrierwave_root.join('*')).each do |dir|
    #puts "   #{dir}"
    FileUtils.remove_entry(dir)
  end
end
```

コードを見れば分かると思いますが、やってることはこんな感じです。

* CarrierWaveの対象ディレクトリを ```test/support/carrierwave``` に変更
* テスト開始時に ```test/fixtures/files/uploads``` をコピーして、```test/support/carrierwave/uploads``` を作成
* テスト終了時に ```test/support/carrierwave ``` 以下のディレクトリを全て削除

<br>作成したらtest_helperでrequireします。

```test/test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'carrierwave_helper'  # 追加

### 省略 ###
```

#### テストデータの作成

test/fixtures/files/uploadsにテスト用のファイルを用意します。
また、test/support/carrierwaveディレクトリも作成しておきます。

```
$ tree ${RAILS_ROOT}/test/
test/
## 省略 ##
├── fixtures
│   ├── files
│   │   └── uploads
│   │       └── user
│   │           └── icon
│   │                ├── 1
│   │                │  └── test1.png
│   │                └── 2
│   │                    └── test2.png
│   └── users.yml
├── support
│   └── carrierwave
├── carrierwave_helper.rb
└── test_helper.rb
```

users.ymlでは、ファイル名を指定するだけでOKです。

```test/fixtures/users.yml
user_1:
  id: 1
  name: ユーザー1
  email: test_user1@example.com
  icon: test1.png

user_2:
  id: 2
  name: ユーザー2
  email: test_user2@example.com
  icon: test2.png
```


以上でCarrierWaveを使っているモデルのfixtureが完成です。

## 最後に

CarrierWaveのwikiにはMinitest用の設定と書いてあるんですが、RSpecはfixtureを使わないんですかね？

自分はMintestでしかテストを書いたことがないので、どなたかコメント頂けると嬉しいです。
wordでギリシャ文字を素早く入力する

# 概要
autohotkeyというソフトを使ってwordでギリシャ文字を素早く入力するマクロを紹介します。[前回の記事](https://qiita.com/mu_mura/items/1e35f55d8dcfcbc506ca)とほとんど同じやり方を使っています。具体的な仕様は以下のようになっています。

- <b>;u と入力 ⇒ "μ"が入力される
- <b>;ohm と入力 ⇒ "Ω"が入力される

![26vUMGpwGCXVWRLI4 (2).gif](https://qiita-image-store.s3.amazonaws.com/0/328692/43b806c2-6623-5cf1-5ada-faf8752c079d.gif)
# 参考
autohotkeyを使ったことが無い方はこのリンクを参考にしてみてください。
https://ch.nicovideo.jp/Jinsichi/blomaga/ar455334
http://wg16.hatenablog.jp/entry/autohotkey_001
https://qiita.com/chr/items/47f50e36703d3bb20371
# コード
```c
#Hotstring C * ;*はお好み(無くすとspaceとかで変換)、Cで大文字小文字区別
#Hotstring ? ;文章途中からの入力も対象
#IfWinActive ahk_class OpusApp ;wordを開いている時だけ実行
::;u::
oWord := ComObjActive("Word.Application")
oWord.Selection.InsertSymbol(CharacterNumber:=109, Font:="Symbol", Unicode:=False)
return
::;ohm::
sleep, 50
oWord := ComObjActive("Word.Application")
oWord.Selection.InsertSymbol(CharacterNumber:=87, Font:="Symbol", Unicode:=False)
return
#If ;ワードのみここまで
```
もちろん使う人によって頻繁に使う文字は異なってくると思いますので、是非これを参考に書き換えて使っていただけたらと思います。以下で詳しく説明します。

```c
#Hotstring C * ;*はお好み(無くすとspaceとかで変換)、Cで大文字小文字区別
#Hotstring ? ;文章途中からの入力も対象
```
ここでCを書かなかった場合、ohm以外にもOHMやohMなどと入力しても"Ω"に変換されてしまいます。*を書かない場合、ohmの後にspaceやenterなどの区切るキーを押して初めて変換されます。これは好みの問題だと思います。?を書かないとk;ohmやM;ohmと入力しても"Ω"に変換されません。
二行に分けて書いたのは特に意味はありません。一行にしても大丈夫です。

```c
#IfWinActive ahk_class OpusApp ;wordを開いている時だけ実行
```
この文はword以外（例えばChromeなど）で;uと入力した時にエラーが起きるのを防いでいます。

```c
::;u::
```
これはホットストリングと言って2つのコロンで囲ったフレーズをタイプすると発動します。この場合 ";u" です。

```c
oWord := ComObjActive("Word.Application")
```
この文はスクリプトが長くなるのを防ぐために代入しているだけです。

```c
oWord.Selection.InsertSymbol(CharacterNumber:=109, Font:="Symbol", Unicode:=False)
```
ここでwordのvbaのInsertSymbolを動かします。もし自分用に書き換える場合、CharacterNumberを調べる必要があります。調べ方は以下のようにします。
![26vUMGpwGCXVWRLI4 (3).gif](https://qiita-image-store.s3.amazonaws.com/0/328692/6077af12-48a4-ae83-2a28-6489b733aa61.gif)
ただここで注意したいのが、文字コードの右側にコード体系というのがあるのですが、これを「10進」にしておく必要があります。他のものが選択されていると文字コードが変化します。
ちなみにこのサンプルコードでは入力する文字を文字コードから直接指定しているため、基本的には全角、半角の区別関係なく同じものが出てきます。

```c
sleep, 50
```
ohmの時だけこのコマンドが入っている理由は、入力する文字が3文字以上だと文字の削除が間に合わないためです。かなり長い文字を入力する場合はsleep時間をもっと増やすと安定するかもしれないです。

# まとめ
前回の記事に上げたコードが結構複雑だったので、今回は出来るだけ説明を詳しくすることを心がけました。是非参考にしてもらえると嬉しいです。

もしよければこちらの記事もどうぞ。↓
[通常マウスでコピー,ペースト,戻るなどができるようにするマクロ](https://qiita.com/mu_mura/items/1a519431143f02698421)
[wordで指数を自動で上付き文字に変換させる](https://qiita.com/mu_mura/items/1e35f55d8dcfcbc506ca)
【PostGIS】インストールされているPostGISのバージョンを確認

# SQLで確認

以下のSQLを実行すればOK。

```SQL
SELECT postgis_version();
```

```:出力
            postgis_version
---------------------------------------
 2.1 USE_GEOS=1 USE_PROJ=1 USE_STATS=1
```

この場合、バージョン2.1がインストールされている。

## エラーが出る場合

以下のようなエラーが出力される場合は、PostGISがインストールされていないか、接続しているDBでPostGIS EXTENSIONが有効となっていない。

```
ERROR:  function postgis_version() does not exist
LINE 1: SELECT postgis_version();
```

# psqlのコマンドで確認

`\dx`と入力してEnterキーで、有効化されているEXTENSIONの一覧が表示される。そこで確認できる。

```
postgres=# \dx
                                       インストール済みの拡張の一覧
   名前    | バージョン |  スキーマ  |                                説明
-----------+------------+------------+---------------------------------------------------------------------
 adminpack | 1.0        | pg_catalog | administrative functions for PostgreSQL
 plpgsql   | 1.0        | pg_catalog | PL/pgSQL procedural language
 postgis   | 2.1.3      | public     | PostGIS geometry, geography, and raster spatial types and functions
(3 行)

```
MySQLについての備忘録

# MySQLの備忘録

## コマンド

| 項目|コマンド |
|:-----------------|------------------:|
| バージョン確認|mysql --version|
| MySQL起動|mysql.server start |
| 状態確認|mysql.server status|
| MySQL停止|mysql.server stop|

## Tips
### timestamp型でnullが入らない（デフォルト値が0000-00-00 00:00:00になる）
MySQL 5.6.5 より前のバージョンでは、TIMESTAMPにNULL許可するには、下記のようにNULL属性で明示的に宣言する必要があるとのこと。
`カラム名 timestamp NULL DEFAULT NULL`
https://dev.mysql.com/doc/refman/5.6/ja/timestamp-initialization.html
firebaseのデプロイ時に最低限覚えておくべきこと

# 雑多ですが


## firebaseのコンフィギュレーション

```json:firebase.json
{
  "functions": {
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint",
      "npm --prefix \"$RESOURCE_DIR\" run build"
    ],
    "source": "functions"
  },
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "storage": {
    "rules": "storage.rules"
  }
}
```

各、firebaseサービスの設定キーに対して、リソースファイルをセットすると、対応するコマンドでリソースの設定情報でデプロイが出来る。(rules,indexesなど)
本番環境でのデプロイ先誤認を防ぐため、productionだった時に、プロンプト入力を求めるバッチを入れることを推奨。

```json:.firebaserc
{
  "projects": {
    "default": "sample-proj",
    "development": "sample-proj",
    "staging": "sample-proj-staging",
    "production": "sample-proj-production"
  }
}
```
firebase useコマンドで操作対象のfirebaseプロジェクトの切り替えができる。
keyはalias(例: firebase use development)

###基本

### functionsを全てデプロイ

```shell
firebase deploy --only functions
```

### functionsを単体でデプロイ

```shell
firebase deploy --only functions:${functionName}
```

### 消すとき

消したいfunctionをexportを消した状態でデプロイコマンド
おすすめはコメントアウトしてデプロイ

```ts
// export const onRegisterUser ...
```

```shell
firebase deploy --only functions
```

### indexをlocalにexportしたい

```shell
firebase firestore:indexes > $filepath
```
### indexまたはrulesをデプロイしたい

```shell
firebase deploy --only $serviceName:(rules or indexes)
```

例) firebase deploy --only firestore:rules

### functionsの環境変数のget
```
firebase functions:config:get [keyName]
```

### functionsの環境変数のset
```
firebase functions:config:set $keyName=$value
```
gitで自分の仕事を振り返りたいときに使うワンライナー


```bash
git log --oneline --pretty=format:'%h [%cd] %d %s <%an>' --date=format:'%Y/%m/%d %H:%M:%S' --author=hoge@example.com

# 下記のような感じで表示される
# c20e98963 [2018/08/24 18:28:23]  コミットメッセージ3 <hoge>
# b20e98962 [2018/08/24 18:28:22]  コミットメッセージ2 <hoge>
# a20e98961 [2018/08/24 18:28:21]  コミットメッセージ1 <hoge>
# ...
```

下半期、何の作業してたっけなぁと、振り返りたいときに使えます。

追記：2018-12-20 16:49 会社で色付きをバージョンを作ってくれた方が居たので、許可を得て下記を掲載しました♪

```bash
git log --oneline --pretty=format:'%Cred%h%Creset %Cgreen[%cd]%Creset %C(yellow)%d%Creset %s %C(bold blue)<%an>%Creset' --date=format:'%Y/%m/%d %H:%M:%S' --author=hoge@example.com
```

見やすいです！！
【備忘録】データ構造の基本まとめ

こんにちは。
今回は前回のアルゴリズムに引き続き、データ構造の基礎を自分の中でまとめるための備忘録です。

##データ構造とは
データ構造とはコンピューターの中にデータを格納する型のことを指します。
プログラミングを設計する上で、データの処理の方法を事前に考え、最適なデータ構造を用いる必要があります。

##データ構造の種類
データ構造にはいくつか種類があり、データの扱いによってそれぞれ適した型があります。
ここでは元Googleのソフトウェアデベロッパーとして働かれていた[CSDojo](https://www.youtube.com/watch?v=bum_19loj9A&list=PLBZBJbE_rGRV8D7XZ08LK6z-4zPoWzu5H)というYou　Tuberの動画で挙げられている例を参考に、代表的な配列（Array）とリスト（Linked list）というデータ構造についてまとめていきます。

```
例:
あるところで100人が参加するパーティが開かれます。
主催者はとても忙しく、パーティ当日に来た参加者の名簿を管理する時間がありません。
そこで参加者にひとりひとり自分の名前が書かれたボールを持ってきてもらい、
会場の入り口で用意した箱に自分のボールを入れてもらうことにしました。
```


この箱の形を以下の画像のように一続きに繋がった配列（Array）と、それぞれの箱が独立してその前後の箱同士の情報が連なっているリスト（Linked list）に分けて扱い、データ構造をみていきます。

<img width="1237" alt="スクリーンショット 2018-12-20 15.09.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/301887/c9c69504-0196-0848-e5cd-84657e0cba41.png">


####配列（Array）
画像の上段の配列（Array）によるパーティ出席者の名簿管理方法は、1番から100番までの箱が一つに繋がったものを使用します。
参加者はきた順番に左から自分の名前が書かれたボールを入れていきます。
画像ではDavid、Kevin、Andrewの順番にボールが入れられています。
######配列を使うメリット
もし仮に98番目に来たJamesが自分の名前のスペルを間違えてボールを箱に入れていたとします。
その場合、長い箱の中から順番に数えて98番目の箱にあるボールを正しくスペリングしたものと入れ替えれば良いため、98個目の箱を簡単に探すことができます。
######配列を使うデメリット
今回のパーティの事前予約は100人でしたが、参加者の数名が予約をしていなかった友達を連れてきてしまったため参加者が100人を超えてしまいました。
もともと100個の箱が連なる長い箱を用意しましたが、これでは全ての参加者のボールを格納することができません。
そこで主催者は忙しいにも関わらず次の二つの選択肢から新たな箱を用意しなければなりませんでした。
**1. 既に作っていた100個続きの箱Aとは別に新たな100個続きの箱Bを作って箱Aと箱Bを同時に使う**
**2. 新たに200個の箱が連なった長い箱Cを作り、そこに既に箱Aに入れられていたボール100個を移し替え、そのあとにきた新たな参加者のボールを追加する**

####リスト（Linked list）
画像の下段のリスト（Linked　list）によるパーティ出席者の名簿管理方法は、1番から100番までの箱がその前後同士のみで繋がったものを使用します。
箱が置かれている位置はバラバラで、例えば1番の箱は玄関に置かれており、そこには次の番号である2番の箱の情報が「2番の場所はリビングのソファの下」という風に示されています。
参加者は若い番号の箱に順番に、自分の名前が書かれたボールを入れていきます。
画像では配列(Array)と同様、David、Kevin、Andrewの順番にボールが入れられています。
######リストを使うメリット
配列では新たに予想外の参加者が来た時、大きな手間が発生しましたが、リストの場合必要分の小さな箱を用意し前後の情報を繋げるだけで簡単に対応することができます。
######リストを使うデメリット
配列では98番目に来たJamesのスペルの間違ったボールを簡単に取り替えることができましたが、リストの場合1番から順番に情報をたどって98番目の箱を探しに行かなくてはなりません。
主催者は忙しいにも関わらず**「玄関→リビングのソファの下→トイレの芳香剤の裏→寝室の枕の下...」という風に一つ一つの箱に書いてある次の箱の情報をたどって98番目の箱を探す羽目になってしまいました。**


##まとめ
以上、今回はパーティの例を参考に代表的なデータ構造である配列とリストについてまとめました。
もしこの記事の解釈が間違っているということがあれば気軽にご指摘ください！
nginxでメンテナンスページを表示させる。改良版

# はじめに
以前書いた記事で、「[nginxでメンテナンスページを表示させる。](https://qiita.com/kooohei/items/b0deaf39124e7a47546a)」というのがあるのですが、もっと良いやり方があったので改めて書きます。

# 設定
とりあえず設定内容です。今回もmaintenanceというファイルをincludeしている前提で進めます。

```conf:maintenance
error_page 500 @maintenance;

# Set Env
set $maintenance "on";

# Allow Paths
if ($uri ~ "^/exclude/") {
  set $maintenance "off";
}

# Allow IPs
if ($remote_addr ~ "xxx.xxx.xxx.xxx") {
  set $maintenance "off";
}
if ($http_x_forwarded_for ~ "xxx.xxx.xxx.xxx") {
  set $maintenance "off";
}

# maintenance
if ($maintenance = "on") {
  return 500;
}
location @maintenance {
  rewrite ^(.*)$ /maintenance.html break;
}
```

```conf:nginx.conf(追記)
# include /etc/nginx/conf.d/maintenance;
rewrite ^/maintenance.html(.*)$ https://$host/ permanent
```

# 説明
まず初めの１行目の`error_page 500 @maintenance;`というところでリターンコード500の場合`@maintenance`というところへリライトするように設定しています。
このリライト先というのが一番下の`location`ブロックです。
次に`set $maintenance "on";`で変数`$maintenance`に`on`という値をセットしておきます。
以下の部分ではif文を利用し、Allow Pathsの部分では特定パスへのアクセスに対して`$maintenance`を`off`に、Allow IPsの部分では特定IPからのアクセスに対し`$maintenance`に`off`を設定し直すように記載されています。
そして最後のところで`$maintenance`が`on`ならリターンコードとして500を返すようにしています。
そうすることでメンテナンスを有効にしてもメンテナンスページへリダイレクトされるのではなくメンテナンスページのリライトで済みます。解除すると先ほどアクセスしていたパスが表示されます。

また、nginx.confの方では`include /etc/nginx/conf.d/maintenance;`をコメントアウト(#)付きで記載しておき、#の付け外しで制御するようにしています。
また、その下のrewriteルールでmaintenance.htmlへのアクセスは無条件にサイトのトップへリダイレクトさせることで何か間違ってメンテナンスページへ直接アクセスしてしまった相手に対しての対処もしています。


# おわりに
リダイレクトとリライトをうまく駆使することがポイントだなと感じました。
Unityで標準アセットのEthanのようにキャラクターを動かす

Unityはたまに弄るだけなのですが、GameAssetStudioのフリーのキャラクター「速水 太一」を標準アセットのEthanのように動かせたら楽しそうだな～、ということで試してみました。
Ethanはこれです。ちょっと怖いです。

![4.png](https://qiita-image-store.s3.amazonaws.com/0/222292/5a2e9c8a-0ee1-2a03-eff8-4e8a15c8a807.png)



#開発環境
Windows 10
Unity Ver 2018.2.6f1 Personal

#(1) unityプロジェクトの新規作成

3Dを選択して新規プロジェクトを作成します。

#(2) Assetのインポート
「Window」→「General」→「Asset Store」で「TaichiCharacterPack」を検索して「download」してから「import」します。同様に、Standard Assetsもインポートします。

#(3) キャラクターの配置場所を作る
Standard Assetを利用して床を作ります。 
projectパネルの「Standard Assets」→「Prototyping」→「Prefabs」の中にある「FloorPrototype08x01x08」をHierarchyにドラッグします。Sceneに床が現れます。

#(4) プレイヤーを作る
Projectパネルの「TaichiCharacterPack」→「Resources」→「Taichi」→「Models Legacy」から適当なモデルをHierarchyにドラッグします。今回は、「m01_casualwear_01_h」を選択しました。名前を「Player」に変更して、インスペクターのTagも「Player」に変更します。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/222292/0fe1921a-1799-cda3-ee60-fb5376c18b26.png)

#(5) Ethanのように動かす
Standard AssetのEthanのスクリプトやコントローラーをそのまま使います。
・Projectパネルの「Standard Assets」→「Characters」→「ThirdPersonCharacter」→「Animator」の中の「ThirdPersonAnimatorController」をHierarchyの「Player」の上にドラッグします。
・「Standard Assets」→「Characters」→「ThirdPersonCharacter」→「Scripts」の中の「ThirdPersonCharacter」と「ThirdPersonUserControl」をHierarchyの「Player」の上にドラッグしてアタッチします。
・あとは、Ethanに合わせて、いくつか設定値をいじります。

![2.png](https://qiita-image-store.s3.amazonaws.com/0/222292/5bcd45c4-6f6a-6e54-d325-0926e0173ad7.png)

#(6) 実行
実行すると、Ethanと同じように、矢印キーで動かすことができます。

![3.png](https://qiita-image-store.s3.amazonaws.com/0/222292/e001a2dd-12f4-63e4-1da3-ddc330c4e1fc.png)
累積和について解説(C++)

この記事は[高知工科大学 Advent Calendar 2018](https://adventar.org/calendars/2959)の23日目の記事です．
ここでは，累積和についてザックリ解説します．
※証明等はやりません．

#背景
去年のアドベントカレンダーで競プロを布教する記事を書きましたが，
次はレートが上がる楽しさを知ってもらいたいと思い，
AtCoder頻出かつ蟻本に無い累積和を紹介しようと思いました．

#累積和
整数配列の連続する区間の合計を，O(1)で求められる手法です．
(準備にO(配列の長さ)かかります)
主に，区間の合計を何度も求める際に使用します．
※配列の中身が変わってしまう場合には使えません．セグメント木を使いましょう

例えば配列の長さがN，区間の合計を求める回数がMの場合，
愚直に計算すると計算量はO(NM)になりますが，
累積和を使用するとO(N+M)になります．

##例題を使って解説
例題を解きながら学びます．
###問題文
整数N, Mが与えられます．
N回だけ整数A<sub>i</sub>が与えられます．
M回だけだけ整数L, Rが与えられます．
区間A<sub>L</sub>からA<sub>R</sub>の合計をそれぞれ求めてください．

####制約
``` math
\begin{align}
1 \leq N, M \leq 100000 \\
1 \leq L \leq R \leq N \\
1 \leq A_i \leq 10000 \\
\end{align}
```

####入力例
4 1
5 2 7 1
2 4
####出力例
10

###考え方
愚直に計算すると最悪計算量はO(NM)→O(10<sup>10</sup>)なので間に合いません．
累積和を使いましょう．

まず，長さN+1の配列を作り，1オリジンで入力します．
![スクリーンショット 2018-12-20 14.15.28.png](https://qiita-image-store.s3.amazonaws.com/0/132702/82511408-3def-d289-11d0-debb1e430937.png)
次に，配列を左から右に足していきます．
![スクリーンショット 2018-12-20 14.20.05.png](https://qiita-image-store.s3.amazonaws.com/0/132702/2617da6a-21c3-fa12-8fff-12f8502f658d.png)
これで準備完了です．
最後に，求めたい領域の(右端)-(左端より1つ左側)をします．
![スクリーンショット 2018-12-20 14.34.22.png](https://qiita-image-store.s3.amazonaws.com/0/132702/00c29e25-4f37-bdc0-dcb5-9262cd77c4c9.png)
これで求めたい領域の合計がすぐ求まります．

###ソースコード
```c++
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
using namespace std;

int main() {
    int N, M, L, R;
    cin >> N >> M;
    int A[N+1]; A[0] = 0; // 1オリジン
    rep(i, N) cin >> A[i+1]; // input
    rep(i, N) A[i+1] += A[i]; // 累積和
    rep(i, M) {
        cin >> L >> R;
        cout << A[R] - A[L-1] << endl;
    }
    return 0;
}
```

##応用問題？
これを累積和と言っていいのか分からないですが，
左から右に足していく問題で良いのがあったので紹介します．
###問題文
机の上にリボンをいくつか重ね，ある場所に何個のリボンが重なっているかを求めたいです．
整数L, M, Nが与えられます．
Lは机の長さ，Mはリボンの数，Nは答えを求める回数です．
M回だけ整数l, rが与えられます．
lはリボンの開始座標，rはリボンの終了座標です．
N回だけ整数pが与えられるので，座標pにリボンは何個重なっているか求めてください．
####制約
``` math
\begin{align}
1 \leq L, M, N \leq 100000 \\
1 \leq l \leq r \leq L \\
1 \leq p \leq L \\
\end{align}
```
####入力例
4 3 1
1 2
2 3
1 4
3
####出力例
2
###考え方
リボンの領域すべてを+1する愚直な方法だと，O(LM)→O(10<sup>10</sup>)なのでアウトですね．
累積和を使ってO(M+N)にします．

まず，長さL+2の配列を作り，
リボンの**(開始座標)を+1，(終了座標の1つ右)を-1**します．
![スクリーンショット 2018-12-20 15.03.00.png](https://qiita-image-store.s3.amazonaws.com/0/132702/99d4151b-6782-d26c-9c75-a45c603826a9.png)

次に，左から右に足していきます．
![スクリーンショット 2018-12-20 15.08.51.png](https://qiita-image-store.s3.amazonaws.com/0/132702/b35c8d9b-f05b-3405-b613-507a047815d1.png)
すると各座標のリボンの数が求まります．

###ソースコード
```c++
#include<bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
using namespace std;

int main() {
    int L, M, N, l, r, p;
    cin >> L >> M >> N;
    int A[L+2]; rep(i, L+1) A[i] = 0; // init
    rep(i, M) {
        cin >> l >> r;
        A[l]++; A[r+1]--;
    }
    rep(i, L) A[i+1] += A[i];
    rep(i, N) {
        cin >> p;
        cout << A[p] << endl;
    }
    return 0;
}
```
#おわりに
他にも役立つアルゴリズムは沢山あるので，皆さんも競プロやってみませんか？
JavascriptからHTMLの要素を取得する方法

# はじめに
この記事は、フロントエンド超超超超超超超超超超初心者が書いたものである。
情報が誤っていることが発覚した場合は修正を行う。

## HTMLの要素

例では、下の通りテキストボックスを用意した。
このテキストボックスをJavascriptで取得して、変数に入れたい。

```html:html
<input type="text" id="txtUserId" name="nmUserId" class="csUserId">
```


## JavascriptからHTMLの要素を取得する方法はいろいろある
### document.getElementByIdを使う。
inputのidが"txtUserId"なので、document.getElementById('txtUserId') と書く。

```js:js
var varUserId = document.getElementById('txtUserId');
```

### document.getElementsByNameを使う。
inputのnameが"nmUserId"なので、document.getElementsByName('nmUserId') と書く。
　⇒　getElement **s** ByName と、メソッド名が複数形になっているので、戻り値は配列。

```js:js
var varUserId = document.getElementsByName('nmUserId');
alert(varUserId[0].value); // 配列で帰ってくるので、要素番号を指定
```

### document.getElementsByClassNameを使う。
inputのnameが"csUserId"なので、document.getElementsByClassName('csUserId') と書く。
　⇒　getElement **s** ByClassName と、メソッド名が複数形になっているので、戻り値は配列。

```js:js
var varUserId = document.getElementsByClassName('csUserId');
alert(varUserId[0].value); // 配列で帰ってくるので、要素番号を指定
```

### querySelectorを使う。
querySelectorは、getElement系と違って **引数の書き方** を変えれば、Id名で取得するのかName名で取得するのか変更できる。

###### IDを指定する場合

IDで指定したい場合は、検索対象のIDの名前の先頭に **#** をつける。

```js:js
var varUserId = document.querySelector('#txtUserId');
```

###### Nameを指定する場合

単に検索対象のNameの名前を指定するだけではダメで、
「検索対象はinputのnameで！」 といったような指定がいる模様。
※こちらの場合、戻り値は配列ではない。

```js:js
var varUserId = document.querySelector('input[name="nmUserId"]');
```

###### Classを指定する場合

Classで指定したい場合は、検索対象のClassの名前の先頭に **.(ドット)** をつける。
※こちらの場合、戻り値は配列ではない。

```js:js
var varUserId = document.querySelector('.csUserId');
```

#ここから以下はメモのメモ。

## ぼんやりしかわからないところ
### document って何？
「表示しているHTML」のelementが全て詰め込まれている"オブジェクト"のこと。

### element って何？
要素。 \< で始まり \> で終わっているヤツ。
HTMLに書いてあるモノ一つ一つのこと。

### getElementById とか querySelector って何？
「引数と一致する名前のelementを（documentの中を先頭から末尾にかけて）検索しに行きますよ」っていうメソッド。
elementにidやNameなど、検索対象となる値が指定されていないと検索できない。
ちなみに同じidのelementが複数ある場合は、先頭のほうに記述してあるものを取ってくるらしい。

### getElementById と querySelector 、どっちを使えばいいの？
前者のほうが高速らしい。なので、基本的に前者。
でも後者を使うと便利になるケースもままあるらしい。
この辺は実体験するに至ったら追記。
12-20 alphaTab

https://adventar.org/calendars/3353 の20日目のエントリーです。

alphaTabは5線譜とギタータブ譜のレンダリングを実現する、JavaScript/HaxeやC#のクロスプラットフォームライブラリです。

https://github.com/CoderLine/alphaTab

楽譜のレンダリングについてはLilypond、musescoreをはじめさまざまなライブラリがあるのですが、今回は自分がC#のアプリケーションに組み込めそうなライブラリとして探している時に発見したものを取り上げます。他の言語環境であれば、他にも[lomse](https://github.com/lenmus/lomse)や[VexFlow](https://github.com/0xfe/vexflow)/[VexTab](https://github.com/0xfe/vextab)など、いくつかの選択肢があります。

alphaTabは、基本的にWeb用とクライアントUI用（C#）に分かれていて、Web用には同開発者らのalphaSynth（Web Audio APIとsoundfontを使用したシンセサイザー）を使用して演奏する機能まで統合されているようです。これはJavaScript/Haxeのみです。

「クライアントUI」にはWindows.Forms、WPF、Xamarin.Android、Xamarin.Formsがあります。実際にレンダリングに使用されているのはSkiaSharpです（キャンバスの実装はSkiaとGDI+で分かれます）。JavaScriptとC#の両方で実現できているのはSkia/SVGで一貫性のあるコードが実現できるからでしょう。

スコアのレイアウト構成についてはクロスプラットフォーム部分（`AlphaTab.shproj`の内容）で、レイアウトの適用やレイアウトされたモデルの反映はプラットフォームごとに、という感じで実装されているようです。（そういうわけで、たとえばconstraint layoutのような環境に適した楽譜を生成できるかというと、レイアウト部分にそれなりの変更を加えない限り難しそうだなという印象です。）

スコアのデータソースについては、（ギタータブ譜がメインなのか）Guitar Proのサポートが手厚いです。MusicXmlもサポートしているようです。それと、独自にAlphaTexというTeXライクな言語を用意しており、これでインポートとエクスポートが可能になっています。（TeXと同じで、わたしは人間が入力する言語とはみなさないです…）
Visual Studio 2017 ではじめるTypeScript(3) ~基本的な型~

# はじめに
TSで使用する基本的な型の説明をします。
あくまでも基本的な型のみなので、他の型も知りたい場合は別の記事を読むことをおすすめします。

## プリミティブ型
* `boolean`：真偽値（`true`、`false`）
* `number`：数（整数、浮動小数点数）
* `string`：文字列（`"` または `'` で囲む）
* `null`：Null型
* `undefined`：Undefined型

## void型
* 主に関数の戻り値として使用され、「何も返さない」ことを表す。

## any型
* `any` は従来のJavaScriptの変数型。
* 全てのデータ型。
* やむを得ないような状況でしか使わないほうがいい。

## 配列型
* 配列のデータ型は要素の型`[]`か、`Array<要素の型>`

```typescript
let foo: number[] = [0, 1, 2, 3];

let foo1: Array<number> = [0,, 1, 2, 3];
```

## 列挙型
* 数値、文字列両方の利用が可能。
* 基本的な仕様はC#などと変わらない。

```typescript
enum Direction {
    Up = 1,
    Down,
    Left,
    Right,
}
```

```typescript
enum Direction {
    Up = "UP",
    Down = "DOWN",
    Left = "LEFT",
    Right = "RIGHT",
}
```

## 変数
変数の宣言は`var`、`let`、`const` の三種類がある。

### var
* 関数スコープ。
* 関数のどこで宣言しても、関数の先頭で宣言したものとされる。

```typescript
function func() {
    var num: number = 10;
    if (true) {
        var num = 99; // 関数スコープなので、ここで宣言されたnumは最初に宣言されたnumと同じ
        console.log(num); // -> 99
    }
    console.log(num); // ->99
}
```

### let
* ブロックスコープ。
* `if` `for` 等の　`{}` 内のブロックのみで使う変数が作れるので、スコープが狭いため、影響範囲を狭めることができる。

```typescript
function func() {
    if (true) {
        let num: number = 10;
    }
    console.log(let); // ブロック外なのでアクセスできないのでエラー
}
```

### const
* 再代入不可能な変数を作る（定数にできる）。
* `let`と同じブロックスコープ

```typescript
const str: string = "hoge";

str = "fuge"; // エラー
```

### 変数宣言
* 宣言には以下の三種類がある。
    1. `let` `識別子` `:` `型` `=` `値` `;`
    2. `let` `識別子` `:` `型` `;`
    3. `let` `識別子` `=` `値` `;`

```typescript
let hoge: string = "hoge";
let hoge: string;
let hoge = "hoge";
```

# おわりに
今回は本当に基本的な型を説明しました。他にもタプル型などありますが、いきなり全ては覚えられないので、連載中に使うことがあれば、随時更新したいと思います。
ubuntu16.04にROS2 Bouncyをインストールする

せしまるです。

ubuntu18.04…ではなくubuntu16.04の記事になります。

備忘録として＋日本語ドキュメント少ないと感じたので。
基本的に[ここ](https://index.ros.org/doc/ros2/Linux-Development-Setup/)と同じ流れで書いていきます。

# ROS2リポジトリ追加
使ったっけ？くらい記憶にないですが、公式ドキュメントには書いてあるので一応。

2019年1月22日追記
リポジトリ追加の一文が抜けていました。申し訳ございません。

```console:console
$ sudo apt update
$ sudo apt install curl gnupg2 lsb-release
$ curl http://repo.ros2.org/repos.key | sudo apt-key add -
$ sudo sh -c 'echo "deb [arch=amd64,arm64] http://packages.ros.org/ros2/ubuntu `lsb_release -cs` main" > /etc/apt/sources.list.d/ros2-latest.list'
```

# ツールのインストール
公式ドキュメントの「Install development tools and ROS tools」の部分です。
横に長いですが、$除いてコピペすれば実行できます。

```console:console
$ sudo apt update && sudo apt install -y build-essential cmake git python3-colcon-common-extensions python3-pip python-rosdep python3-vcstool wget
$ sudo -H python3 -m pip install -U argcomplete flake8 flake8-blind-except flake8-builtins flake8-class-newline flake8-comprehensions flake8-deprecated flake8-docstrings flake8-import-order flake8-quotes git+https://github.com/lark-parser/lark.git@0.7b pytest-repeat pytest-rerunfailures pytest pytest-cov pytest-runner setuptools
$ sudo apt install --no-install-recommends -y libasio-dev libtinyxml2-dev
```

それなりに時間かかるのでカップラーメンでも作って待ちましょう

# ROS2コードの取得
ツールのインストールが終わったら、ROS2のコードを取得します。

まずはディレクトリを作成し、作成したディレクトリにソースを落としてきます。
私の環境では/home/user下にディレクトリを作っていますが、別の場所でも大丈夫です（場所によっては管理者権限が必要な場合があります）。

```console:console
$ mkdir -p ~/ros2_ws/src
$ cd ~/ros2_ws
$ wget https://raw.githubusercontent.com/ros2/ros2/release-latest/ros2.repos
$ vcs import src < ros2.repos
```

4行目が結構長いかな？


# 依存関係のインストール
コードの取得が完了したら次はこれです。

sudo rosdep initでエラー出たら、エラーと一緒にファイルパスが表示されるので、そのファイルを削除してから再度実行してみてください。

```console:console
$ sudo rosdep init
$ rosdep update
$ rosdep install --from-paths src --ignore-src --rosdistro bouncy -y --skip-keys "console_bridge fastcdr fastrtps libopensplice67 libopensplice69 python3-lark-parser rti-connext-dds-5.3.1 urdfdom_headers"
```


# ビルド！
optionalは飛ばして~~仮面ライダー~~ビルドです！

ardent？はたしかament buildでしたが、bouncyはcolcon buildで行います。
こるこんこるこん…

```console:console
~/ros2_ws$ colcon build --symlink-install --packages-ignore qt_gui_cpp rqt_gui_cpp
```

これめちゃくちゃ長いです。自環境では30分くらいかかったので、アニメでも見ながら気長に待ちましょう。


# 動作テストと.bashrc
ビルドが終わったら動作テスト！のまえに.bashrcに下記一行追記します。

```
source ~/ros2_ws/install/local_setup.bash
```

保存したらターミナルを立ち上げなおします。ついでにもう一つターミナルを立ち上げておきます。
それぞれT1、T2（ターミナル1、2）とします。

これからやるのは、T1でメッセージを送信（publish）して、T2で受信（Subscribe）するテストです。
うまく受信できればT2のコンソールにメッセージがぽんぽんでます。

まずT1で下記を実行します。

```console:console
$ ros2 run demo_nodes_cpp talker
```

次にT2で下記を実行します。

```console:console
$ ros2 run demo_nodes_py listener
```


実行結果

```console:T1
[INFO] [talker]: Publishing: 'Hello World: 1'
[INFO] [talker]: Publishing: 'Hello World: 2'
[INFO] [talker]: Publishing: 'Hello World: 3'
…
// やめるまで続く
```

```console:T2
// 実行したタイミングによるけど
[INFO] [listener]: I heard: [Hello World: 1]
[INFO] [listener]: I heard: [Hello World: 2]
[INFO] [listener]: I heard: [Hello World: 3]
…
```


# 感想
時間かかりすぎる。ビルド中とか本当に暇になりますw

それでは今回はこの辺で。
よいROS2ライフを？
Envoyのアクセスログを確認する

gRPC-webを利用してサービス開発をしているなかで、つまづいたところを共有していきます。

gRPC-web公式では以下のようにEnvoyを経由してgRPCサーバーと通信します。

```
クライアント（ブラウザ）-> Envoy -> gRPCサーバー
```

実際にEnvoyを入れてみたのですが、Envoyへのアクセスログが表示されず不便でした。
Envoyの設定ファイルを調整することでアクセスログの出力が可能になります。
# envoy.yaml の設定
以下、公式のサンプルyamlを元に設定します。
https://github.com/envoyproxy/envoy/blob/master/configs/google_com_proxy.v2.yaml

```diff
admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address:
      protocol: TCP
      address: 127.0.0.1
      port_value: 9901
static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address:
        protocol: TCP
        address: 0.0.0.0
        port_value: 10000
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        config:
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  host_rewrite: www.google.com
                  cluster: service_google
+         access_log:
+           - name: envoy.file_access_log
+             config:
+               path: /dev/stdout
          http_filters:
          - name: envoy.router
  clusters:
  - name: service_google
    connect_timeout: 0.25s
    type: LOGICAL_DNS
    # Comment out the following line to test on v6 networks
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    hosts:
      - socket_address:
          address: google.com
          port_value: 443
    tls_context: { sni: www.google.com }
```

この設定を行うことで、Dockerで動いているEnvoyの標準出力へアクセスログが流れるようになります。
※ Dockerへ設定が反映されるように再ビルド等必要になるかもしれません。