OmniAICreator/Qiita-1.07M huggingface dataset:
sudo npm i -gによる command not found: npm

npm環境に関するエラーでかなり時間を費やし、悔しい思いをしたので、整理して投稿いたします。

## 現象
下記のようなエラーがどうしても出る。

```bash
$ zsh: command not found: npm
```

## 経緯

久しく触ってなかった環境で `npm i ` したところインストールできず（ここのエラーは覚えてない）、 下記のようにグローバルインストールするとなにやらpermissionに関するエラーが生じた。  

```
npm i -g
```
権限がない？ならば `sudo` すればいけるやんと反射的に下記のように管理者権限での実行を行う

```bash
$ sudo npm i -g
```
すると、npmを認識しなくなりました。


## 経緯の推測

上記のpermission errorが出るようになったきっかけとして下記の3つが候補として挙げられました。

1. Nodeのバージョン変更
2. 自作npmモジュールのpackage.json内のbinの記述ミス
3. 環境変数の$PATHミス（今まで動作していたので関係なさそう）

検索すると一番有力なのは、もちろん1のNodeのバージョン変更でした。（変更したかな？・・・）

ちなみに環境変数の$PATHの指定先、usr/local/share/にnpmディレクトリが存在してませんでした。なぜ。。。


## 解決策
安直に `npm command not found` で検索すると同様なケースが[ちら](https://qiita.com/hoppy/items/6822b78b9b130f030c54)・[ほら](https://stackoverflow.com/questions/31472755/sudo-npm-command-not-found)。

とりあえず下記の手順でいけました。
1. .bash_profileの作成
2. nodebrewのインストール
3. nodeのインストール（同時にnpmもインストールされる）

３番で２度つまづいたので、少し書きます。

## nodeのインストール
1.nodeインストールできない問題
下記のようにバージョンを指定してインストールするのですが、directoryがないというエラーが出てしまいます。

```
nodebrew install-binary v8.9.1
```
ですので、先にdirectoryを作成(mkdir)してあげましょうね。というお話でした。
[Node.jsのインストールに失敗する時の解決策](https://qiita.com/yn01/items/d1fa10dbe4850f7cd693)

2.npmがインストールされない問題
本来であれば上記のコマンドが成功した段階でnpmコマンドを使用できるのですが、

```bash
npm -v
```
 としてもやはり `zsh: command not found: npm` が出てくるというものです。
この問題は、使用する[Nodeのバージョンを指定することで解決](https://qiita.com/ebisennet/items/15c3c9fdb04e66db6323)できました。

```bash
nodebrew use v8.9.1
```
以前にインストールしたNodeのバージョンが優位になってたのかもしれないですね。


## 教訓

- 安易な「権限がない？ならば `sudo` すればいけるやん」はやめて、じっくりエラー文と睨めっこした方が良い
- [`npm i -g` 自体が非推奨であること](https://qiita.com/Mic-U/items/cd456d6bea72937464f8)を理解する
バッチファイルを使って設定確認をテンプレート化する

# はじめに
テスト時の設定値確認などよく使うコマンドをbatファイルにしておいて、作業の手間を減らしたい。
また、テンプレートとして確認する設定項目はbat処理中に入力し、batの中身を都度書き換えないようにしたい。
今回は例として、サービスのステータス確認をするbatを作成する。

## 1.作業前の確認を入れる
batファイルに設定変更コマンドを記述していると、誤った実行で設定変更してしまう可能性があるため、処理の開始前にワンクッション置けるようにする。
「pause」だといずれかのボタン押下で処理が続行してしまうため、特定の文字を入力しないと処理が続行できないようにする。

```bat
echo ------ 作業前確認 ------
REM 作業時刻の取得
echo %date% %time%
echo.
echo ------ 作業前確認 ------
REM 対象サーバのホスト名確認
hostname
echo. 

REM 入力待ち処理
SET /P ANSWER="実行しますか(y/n)？"

REM 「y」or「yes」を入力すると「:yes」へジャンプし、処理を続行
REM 「y」or「yes」以外が入力されると「EXIT」へジャンプし、バッチが終了
if /i {%ANSWER%}=={y} (goto :yes)
if /i {%ANSWER%}=={yes} (goto :yes)

EXIT
:yes
```

## 2.ステータス確認用のテンプレートを作成する
### 実行イメージ
ループ処理を使って、定義したサービス名を一つずつ取り出して実行したい。

```bat
REM %I%にサービス名を一つずつ定義して、コマンドを実行したい。
%I% = サービス名1 サービス名2 サービス名3 
sc query %I% (サービス1)
sc query %I% (サービス2)
sc query %I% (サービス3)
```
### ループ処理(for文)の基本形
```bat
for /f tokens %%アルファベット1文字 in (ループ処理の対象) do コマンド 
```
- for /f はデフォルトでは、スペースやタブで区切って変数に格納することができる。
- オプション:tokens=何番目のトークンを指定するか

今回は「for /f」を使ってサービス名を一つずつ取り出せるようにする。

### 処理の流れ
1. batを実行し、%A%にスペース区切りでサービス名を入力する
2. %A%に定義された文字列を一つずつ取り出して、%I%に定義する。
3. 「sc query %I%」を実行する。
4. 「2~3」の処理を%A%から文字列が取り出せなくなるまで、ループ処理する。

```bat

echo off

REM 入力した文字を変数「%A%」へ定義する
set A=
set /P A="サービス名を入力してください: "
set /P ANSWER="サービス名は %A% です。"

pause

REM ループ処理開始
REM %A%に定義した文字をスペース区切りで取りだして%I%に定義する。
set N=0
:loop
set /a N+=1
set I=
for /f "tokens=%N%" %%I in ("%A%") do set I=%%I
REM 変数が定義されていない場合「:next」へ移動
if not defined I goto next
REM ステータス確認コマンドを実行()
sc query %I%
goto loop
:next

pause
```

## 3.ログディレクトリ作成やエビデンスを出力できるようにする
上記の処理に対してログディレクトリの作成やエビデンスとしてコマンド結果をテキストに出力できるようにする。
記載を省力しているが、冒頭に記載した作業前確認と組み合わせることも可能。

```bat
echo off

:retry

REM 入力した文字を変数「%A%」へ定義する
set A=
set /P A="サービス名を入力してください: "
set /P ANSWER="サービス名は %A% です。実行しますか(Y/N)？"

REM 「y」or「yes」を入力すると「:yes2」へジャンプし、処理を続行。
REM 「y」or「yes」以外が入力されると「:retry」へジャンプし、ループする。
if /i {%ANSWER%}=={y} (goto :yes2)
if /i {%ANSWER%}=={yes} (goto :yes2)
if /i {%ANSWER%}=={n} (goto :retry)
if /i {%ANSWER%}=={no} (goto :retry)

EXIT
:yes2

REM コマンドを再表示する
echo on

REM ログディレクトリ定義
set LOG=C:\work\log
REM ログディレクトリの作成
mkdir %LOG%
cd %LOG%
dir

pause

REM %HOSTN%へホスト名を定義する
set HOSTN=%COMPUTERNAME%
REM 日付をyyymmdd形式で取得する。
set TESTDATE=%DATE:/=%

REM ループ処理開始
set N=0
:loop
set /a N+=1
set I=
for /f "tokens=%N%" %%I in ("%A%") do set I=%%I
REM 変数が定義されていない場合「:next」へ移動
if not defined I goto next
REM サービスステータス確認 「C:\work\log\yyyymmdd_ホスト名.log」にコマンド結果を出力する。
sc query %I% >> %TESTDATE%_%HOSTN%.log
goto loop
:next

pause
```

## 最後に
batの勉強を始めたばかりですが、こういったbatファイルは一度作成しておくと結構作業の手間を減らすのではないかと思い作成してみました。
今回はサービスのステータス確認のみを焦点を置いて書いてみましたが、応用すれば任意のログディレクトリの作成・エビデンス名の指定や他のコマンドなどでも応用が効くと思います
TensorFlow の画像識別チュートリアル　環境構築

## Install Tensorflow Python:
https://www.tensorflow.org/install/install_linux

```
git clone https://github.com/tensorflow/models.git
git clone https://github.com/tensorflow/tensorflow.git

sudo yum install python-pip python-dev python-virtualenv -y

mkdir ~/tensorflow_env/
virtualenv --system-site-packages /home/centos/tensorflow_env
source ~/tensorflow_env/bin/activate
easy_install -U pip
pip install --upgrade tensorflow
source ~/tensorflow_python/bin/activate

sudo yum install numpy -y
cd /home/centos/git/
cd models/tutorials/image/imagenet
python classify_image.py
```

## Output:

```
(tensorflow_env)[centos@zzeng-hdf-1 ~/git/models/tutorials/image/imagenet]$ python classify_image.py

>> Downloading inception-2015-12-05.tgz 100.0%
Successfully downloaded inception-2015-12-05.tgz 88931400 bytes.
2018-03-20 01:29:39.217828: I tensorflow/core/platform/cpu_feature_guard.cc:140] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
2018-03-20 01:29:39.764365: W tensorflow/core/framework/op_def_util.cc:343] Op BatchNormWithGlobalNormalization is deprecated. It will cease to work in GraphDef version 9. Use tf.nn.batch_normalization().
giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca (score = 0.89107)
indri, indris, Indri indri, Indri brevicaudatus (score = 0.00779)
lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens (score = 0.00296)
custard apple (score = 0.00147)
earthstar (score = 0.00117)
(tensorflow_env)[centos@zzeng-hdf-1 ~/git/models/tutorials/image/imagenet]$
```
【Linux】ftpへのファイル転送


##　ftpサーバーへ接続

```shell:shell

#　致命的エラー: gnutls_handshake: An unexpected TLS packet was received.
#　　解決案：

[root@server ~]# lftp -u user,pass -p 21 ftp://sample.jp
lftp user@sample.jp:~> set ftp:ssl-auth TLS
lftp user@sample.jp:~> set ftp:ssl-force true
lftp user@sample.jp:~> set ftp:ssl-allow yes
lftp user@sample.jp:~> set ftp:ssl-protect-list yes
lftp user@sample.jp:~> set ftp:ssl-protect-data yes
lftp user@sample.jp:~> set ftp:ssl-protect-fxp yes
lftp user@sample.jp:~> set ssl:verify-certificate no
lftp user@sample.jp:~> set cmd:fail-exit yes
lftp user@sample.jp:~>
lftp user@sample.jp:~> ls
drwxrws---    6 3003     3003         4096 Jul 26  2017 a
lftp user@sample.jp:/>bye
[root@server ~]# 

```


##　ftpサーバーへファイル転送

```shell:shell

#　shell.sh ファイル転送shell

retcode=0
lftp -c "DEBUG -o /var/www/html/log/`date '+%Y%m%d%H%M%S'`'.log'; \
      set ftp:ssl-force true; \
      set cmd:fail-exit yes; \
      set ftp:ssl-auth TLS; \
      set ssl:verify-certificate no; \
      set ftp:ssl-allow yes; \
      set ftp:ssl-protect-list yes; \
      set ftp:ssl-protect-data yes; \
      set ftp:ssl-protect-fxp yes; \
      open -p $port $host; \
      user $username $password; \
      put $srcfilepath -o $dstfilepath; " 2>&1
if [[ ${?} -ne 0 ]]; then
    echo `date` " [ERROR] 転送失敗" | tee -a '/var/www/html/log/'`date '+%Y%m%d'`'.log'
    retcode=1
else
    echo `date` " [INFO] 転送完了" | tee -a '/var/www/html/log/'`date '+%Y%m%d'`'.log'
fi
exit ${retcode}

```

*参考*
[致命的エラー: gnutls_handshake](https://yuu.nkjmlab.org/diary/20111203-3.html)
Rubyでファイル名に連番をつける（Windows環境、exe化対応）

## 環境
Ruby2.5.0
Windows10

## 参考にしたもの
WindowsにおけるRubyの環境構築は下記を参考
少し試行錯誤した気がします。
https://qiita.com/jnchito/items/08b5be458134073c60e3

作成したコードをexe化するのには下記を参考
http://d.hatena.ne.jp/mirichi/20140323/p1

PowerShellについては下記を参考
http://blog.shibata.tech/entry/2015/11/18/185108

コードの内容については下記を参考
https://qiita.com/kaway/items/ad84d27522c0ee9e8172
https://www.gesource.jp/weblog/?p=444

## 動機
Windows環境で、フォルダ内にある全てのファイルに連番をつける機能がほしい状況になりました。そのため、Windows環境のRubyを使用しています。環境構築などが少し面倒ですが、Rubyでコードを書くのが好きなため、Rubyで記述しました。また、他の人も使用できるようにexe化にも対応しました。

## 作成したコード

~~~ruby:add_serial_num_v1.rb
require 'fileutils'

print "Folder: "
# フォルダ名を入力 （例）C:\hogehoge
dir_name = File.expand_path(gets.chomp)

# フォルダ内にあるファイルに連番をつける
Dir.glob("#{dir_name}/*").each_with_index do |path_name, index|
  file_name = File.basename(path_name)
  index += 1

  if index < 10
    index = "00#{index}"
  elsif index < 100
    index = "0#{index}"
  end

  new_name = "#{index}_#{file_name}"
  puts new_name
  FileUtils.mv("#{dir_name}/#{file_name}", "#{dir_name}/#{new_name}")
end

puts "\nFinish!"
~~~

## リファクタリング後のコード
@scivolaさんに有難いコメントを頂いたのでリファクタリング。
コメントありがとうございましたm(_ _)m

~~~ruby:add_serial_num_v2.rb
require 'fileutils'

print "Folder: "
# フォルダ名を入力 （例）C:\hogehoge
dir_name = File.expand_path(gets.chomp)

# フォルダ内にあるファイルに連番をつける
Dir.glob("#{dir_name}/*").each.with_index(1) do |path_name, index|
  file_name = File.basename(path_name)
  new_name = "#{"%03d" % index}_#{file_name}"
  puts new_name
  FileUtils.mv("#{dir_name}/#{file_name}", "#{dir_name}/#{new_name}")
end

puts "\nFinish!"

~~~

## 実行例
~~~PowerShell:実行例（コマンドプロンプトやPowerShellで実行）
> ruby add_serial_num_v2.rb
Folder: C:\hogehoge
001_bar.docx
002_foo.docx
003_foobar.docx
004_fuga.docx
005_fugafuga.docx
006_hoge.docx
007_hogehoge.docx
008_ふが.docx
009_ほげ.docx
010_ほげほげ.docx

Finish!
~~~

## つまった箇所
下記部分に少しつまりました。

~~~ruby
# フォルダ名を入力 （例）C:\hogehoge
dir_name = File.expand_path(gets.chomp)
~~~
↑を↓のようしてしまうと、windows環境だとパス名取得がうまくできないみたいです。

~~~ruby
dir_name = gets.chomp
~~~

## exe化
RubyInlineとOcraをgemでインストールします。
※RubyInline必要だったのかは不明…

~~~PowerShell:コマンドプロンプトやPowerShellで実行
> gem install RubyInline
> gem install ocra
~~~
↓はadd_serial_num_v2.rbがあるフォルダで実行してください。

~~~PowerShell:コマンドプロンプトやPowerShellで実行
> ocra add_serial_num_v2.rb
~~~

私の環境では、特にエラーが起こることなく**add_serial_num_v2.exe**が出来上がりました。これで、Rubyの環境を構築していない人にも配布可能となりました。

## ちなみに…
PowerShellで同じようなことをしようと思ったら、下記の1行ですみます😅
連番つけたいファイルのあるディレクトリで実行してください。

~~~PowerShell:PowerShellで実行
> ls | sort Name | % {$i = 1} { $NewName = "{0:000}_{1}" -f $i, $_.Name ; mv $_.Name $NewName; $i++ }
~~~

## まとめ
Windows環境でも、簡単な作業ならRubyで色々できそうです。
ただし、Windows環境である必要がない場合は、Windows Subsystem for Linuxなどで作業した方が楽だと思います。
[Delphi] インテントを使用してカレンダーを参照する

インテントを使用したカレンダー データの参照
https://developer.android.com/guide/topics/providers/calendar-provider.html#intent-view
の手法を使って、Android で Google カレンダーを参照してみた

カレンダーのインテントを利用すると、パーミッションの要求を行なう事なく、カレンダーアプリケーション側にユーザーを誘導して、参照や、イベントの挿入などを行なうことができます

## サンプルコード

フォーム上にボタンを置き、ボタンのクリックイベントで以下を記述

```delphi

// uses に Androidapi.Helpers, Androidapi.JNI.APP, Androidapi.JNI.Provider,
//         Androidapi.JNI.JavaTypes, Androidapi.JNI.Net,
//         Androidapi.JNI.GrapicsContentViewText を追加します

// インテントは Intent: JIntent; で定義しています
// uri は uri: JUri_Builder; で定義しています
// カレンダーは mCalendar: JCalendar; で定義しています

// 今日の日付を取得します
mCalendar := TJCalendar.JavaClass.getInstance;

// uri buildUpon を使用して必要なパラメータを設定
uri := TJCalendarContract.JavaClass.CONTENT_URI.buildUpon;
uri.appendPath(stringToJString('time'));
TJContentUris.JavaClass.appendId(uri, mCalendar.getTimeInMillis);

// インテントを作成します
Intent := TJIntent.JavaClass.init(TJSettings.JavaClass.ACTION_VIEW);

// 参照する日付をセットします
Intent.setData(uri.build);

// startActivity を使ってインテントを飛ばします。
TAndroidHelper.Activity.startActivity(Intent);
```


今日から 10 日後という場合は

```delphi

// 今日の日付を取得して +10日します
mCalendar := TJCalendar.JavaClass.getInstance;
mCalendar.add(TJCalendar.JavaClass.DATE, 10);

```

のように記述します。
特定のReactコンポーネントの子要素に親要素からpropsを暗黙的に渡す方法

複数のコンポーネントをワンセットで使いたい/使わせたい場面はしばしばあります。例えばTable関連のコンポーネントは、それぞれ別々に定義したほうが使い勝手は良いですが、tableタグの子要素や孫要素で発生したイベントなどはまとめてtableタグのpropsに渡すハンドラで処理したくなります。ここでは話を単純にするために、２階層の以下のような場面を想定します。

```react:example1
export default class App extends React.Component {
  render() {
    return (
      <TableBody
        onRowSelection={rows => {console.log(rows)}}
      >
        {this.props.users.map((user, i) => {
          return (
            <TableRow key={user.id}>
              <TableRowColumn>{user.id}</TableRowColumn>
              <TableRowColumn>{user.name}</TableRowColumn>
              <TableRowColumn>{user.email}</TableRowColumn>
            </TableRow>
          );
        })}
      </TableBody>
    );
  }
}
```

`TableBody`はtbodyタグを、`TableRow`はtrタグを、`TableRowColumn`はtdタグをそれぞれラップしています。`TableRow`で発生したなんらかのイベントを`TableBody`のpropsに渡したonRowSelectionハンドラで処理しているとします。

具体的には以下のようにします。

```react:example2
class TableBody extends React.Component {
  static displayName = "TableBody";

  public render() {
    return (
      <tbody>
        {React.Children.map(this.props.children, (child, i) => {
          if (
            !React.isValidElement(child) ||
            child.type.displayName !== TableRow.displayName
          ) {
            console.warn(`Children of the TableBody component must be TableRow`);
            return;
          }
          return React.cloneElement(
            child as React.ReactElement,
            {
              rowNumber: i,
              onRowSelection: (isChecked, rowNumber) => {
                this.props.onRowSelection(isChecked, rowNumber);
              },
            }
          );
        })}
      </tbody>
    );
  }
}

class TableRow extends React.Component {
  static displayName = "TableRow";

  render() {
    return (
      <tr>
        <td>
          <input type="checkbox" onChange={e => {
            this.props.onRowSelection(e.target.checked, this.props.rowNumber);
          }} />
        </td>
        {this.props.children}
      </tr>
    );
  }
}
```

Reactの`Children.map`メソッドでchildrenをループで検査して、propsを渡したいコンポーネントなら`cloneElement`でpropsを追加します。Reactコンポーネントにstaticメンバを追加すると、親要素から`child.type.displayName`のようにアクセスできるので、それでコンポーネントを特定します。用意したコンポーネント以外を子要素に入れられたくない場合は、`console.warn`などで警告を出してあげると親切です。
Elastic Beanstalkでflaskアプリをデプロイする時にハマったことまとめ

### 投稿の意義
アプリエンジニアが、初めてアプリケーションのデプロイを０から行った際にハマった事象と解決策を書く。
そして、同じようにAWS EBに初めてアプリをデプロイする人のハマりを解決する。
（解決したらいいねよろしく）

### やったこと 

基本的に公式ドキュメントに添って作業した。

Elastic Beanstalk コマンドラインインターフェイス（EB CLI）のインストール
https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/eb-cli3-install.html  

AWS Elastic Beanstalk への Flask アプリケーションのデプロイ
https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/create-deploy-python-flask.html


### ハマったこと  

**eb init時にNotAuthorizedError が出る** 

- 下記XXXXの認証情報が正しいか確認する

```
vi ~/.aws/credentials

aws_access_key_id = XXXXXX
aws_secret_access_key = XXXXX
```
<br>
**eb create / deploy時にYour WSGIPath refers to a file that does not existエラーが出ている**

- 実行ファイル名がapplication.pyになっていることを確認する
- アプリ名がapllicationになっていることを確認する↓

AWSチュートリアルのサンプルコード
![image.png](https://qiita-image-store.s3.amazonaws.com/0/148503/8b7f36a7-427b-6449-451c-b3f5f8d2c477.png)

**eb logsでログを確認すると、mod_wsgi “Call to 'site.addsitedir()' failed” エラーが出ている**   

- mod_wsgiのバージョンを上げる↓


コンフィグファイルを作成　　

```
cd ~/eb-flask
mkdir .ebextensions
vi wsgi_update.config
```

下記を貼り付け

```
packages:
  yum:
    git: []
    gcc-c++: []
    httpd24-devel-2.4.27-3.75.amzn1.x86_64: []

files:
  "/tmp/update-wsgi.sh" :
    mode: "000755"
    owner: root
    group: root
    content: |
      # update mod_wsgi
      cd /tmp
      wget -q "https://github.com/GrahamDumpleton/mod_wsgi/archive/4.4.21.tar.gz" && \
      tar -xzf '4.4.21.tar.gz' && \
      cd ./mod_wsgi-4.4.21 && \
      sudo ./configure --with-python=/usr/bin/python3.6 && \
      sudo make && \
      sudo make install && \
      sudo service httpd restart

commands:
  mod_wsgi_update:
    command: /tmp/update-wsgi.sh
    cwd: /tmp
```   
   



参考： https://serverfault.com/questions/884469/mod-wsgi-call-to-site-addsitedir-failed-on-aws-elastic-beanstalk-python-3/885445
Immutable.js: オブジェクトのListからMapへの変換

ドキュメントをちゃんと読むと書いてあったけど、頻出な気がするのでここに書き残しておく。ちなみに、ここでやるMapへの変換はOrderedMapへも同様に変換できる。

## Mapの利点
Listにオブジェクトを格納するようなケースだと、比較的Mapが適していることが多い。例えば、以下のように固有の識別子を持つオブジェクトが存在するとする。

```js
class Book {
  constructor(id, name) {
    this.id = id;
    this.name = name;
  }
}
```
アプリケーションの中でListから`id`を指定して任意のBookを取得したいときには以下のようにfindなどを使うかと思う。

```js:List
const findBookById = id => 
  bookList.find(book => book.id === id);
```
ここでMapを使うと、より簡潔に検索処理を実装できるうえ、配列走査が必要なくなるためパフォーマンスの点でも利点がある

```js:Map
const findBookById = id => bookList.get(id);
```
つまり、**アプリケーションで常にユニークな識別子をもつオブジェクト群の格納と検索を行う**場合にはListよりもMapのほうが適している

## Mapの生成
一般的なのはこのようにObjectからMapへの変換

```js
const newMap = Map({ 
  key1: 'value1', 
  key2: 'value2'
})
```
**上に加えて**、ArrayからMapへの変換も用意されている！ これを活用するとListからMapへの変換ができる 

```js
const newMap = Map([
  ['key1', 'value1'],
  ['key2', 'value2']
])
```
## ListからMap
たとえば以下のように`id`などの要素を持っているオブジェクトのListがあるとする。前提として重複しているので、これを`id`でユニークなMapにしたい。

```js
class Book {
  constructor(id, refId) {
    this.id = id;
    this.refId = refId;
  }
}

// ...

const bookList = Immutable.List([
  new Book(1, 2),
  new Book(1, 2),
  new Book(1, 2),
  new Book(2, 3),
  new Book(2, 3),
  new Book(3, 4),
  new Book(10, 4),
])
```
この`bookList`を、`id`をユニークなキーにしたMapに変換したいときにはこのようにする。

```js
const bookListUnique = Immutable.Map(
  bookList.map(book => [book.id, book])
);
```
オブジェクトを要素に持つListだと、単純に`bookList.toMap()`では気を利かしてくれないので、このような変換が必要になる。

## MapじゃなくてSetじゃない？
Immutable.jsはSetを`A Collection of unique values`として定義しているが、実際には以下のようなコードがうごいてしまう。

```js
const bookSet = I.Set([
  new Book(1, 2),
  new Book(1, 2),
  new Book(1, 2),
  new Book(2, 3),
  new Book(2, 3),
]);
```
文字列や数値であればもちろん重複を排除してくれるが、オブジェクトではそうならないため、注意が必要になる。なので、今回自分はMapを使うことにした。
[Python] Django ロケールファイルを追加して日本語メッセージを変更する

##この記事について

PythonのWebアプリケーションフレームワーク「Django」についての解説記事です。

Djangoのエラーメッセージや管理サイトの見出しを、アプリの内容や使うユーザーに合わせて変更したいなと思うときがあります。

そのような場合はロケールファイルの追加で対応すると楽です。日本語の見出しやメッセージを上書き変更することができます。

##作業手順

###手順１．gettextのインストール

Djangoのロケールファイルはバイナリファイルです（.mo）。対になるテキストファイルをコンパイルして作成します（.po）。コンパイル用のツール「gettext」はpythonのパッケージとして提供されていないので、別途インストールが必要です。

WindowsはDjango公式サイトのリンクからダウンロードサイトへ移動できます。
https://docs.djangoproject.com/en/2.0/topics/i18n/translation/#gettext-on-windows

Macはこちらが参考になるでしょう。
[Macで翻訳ファイル*.poをmo形式に変換する](https://qiita.com/tailak/items/0a866aac4cc8f2f8c135)

インストール後に「msguniq.exe」を実行するパスを追加する必要があります。Windowsならインストーラーのオプションで指定すればＯＫです。

###手順２．設定変更

settings.pyに設定を追加します。

```py:setting.py
LANGUAGE_CODE = 'ja'

LOCALE_PATHS = (
    os.path.join(BASE_DIR, 'locale'),
)
```

プロジェクト直下にロケールファイル用のディレクトリを作成する準備ができました。

###手順３．ロケールファイル作成

ここでは例として管理画面のタイトルを変更してみたいと思います。

ビルトインアプリ「admin」のディレクトリ`contrib/admin/locale`をプロジェクト直下にコピーします。言語ごとに大量のフォルダが存在するので`ja`以外は削除してしまいましょう。現時点でこのような構造になります。

```tree
project_root
  └locale
    └─ja
        └─LC_MESSAGES
              django.mo
              django.po
              djangojs.mo
              djangojs.po
```

###手順４．ロケールファイルの編集とコンパイル

コピーした拡張子「.po」をファイルで開きましょう。テキスト形式の翻訳ファイルとなっています。上の方に翻訳者の名前がありますね。テンプレートを調べて修正対象のmsgidを割り出し、msgstrを変更しましょう。

**ちなみに追加したロケールファイルの内容は、ヘッダ部分と対象IDのところだけでＯＫです。admin以外で変更したい場所があったらここに追加で加えていきましょう。**


```django.po
msgid ""
msgstr ""
"Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-01-19 16:49+0100\n"
"PO-Revision-Date: 2017-09-19 16:41+0000\n"
"Last-Translator: （省略）"
"Language-Team: Japanese (http://www.transifex.com/django/django/language/"
"ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ja\n"
"Plural-Forms: nplurals=1; plural=0;\n"


msgid "Django administration"
msgstr "ここを変更します"
```

ファイルを保存して以下のコマンドを実行します。

[要gettext]

```command
manage.py compilemessages -l ja
```

コンパイルの完了後にアプリケーションを起動しましょう。
対象のメッセージの表示が置き換わっているはずです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/217094/ef734f43-1d0c-a5cc-fa85-c76b2ad3de9b.png)
highchartsのAPIを拡張する

# はじめに

以前の記事で[highchartsの紹介＆技術メモ](https://qiita.com/zaki_zaki/items/816eddaaa92e9db9e742)の記事を書きました。
今回は、highchartsで実装されているAPIを拡張するやり方を紹介したいと思います。

というのも、拡張するには、highchartsのソースを確認する必要があったため、
自分の備忘録兼他の方へ参考になればと思い、この記事を書くことに至りました。

ちなみに今回の**API**というのは、[APIリファレンス](https://api.highcharts.com/highcharts/)のツリーに表示されている、
以下のような**API**のことを指します。

- series
- tooltip
- xAxis
- yAxis
etc...

# 公式サイトの見解

[公式サイトで記述されている機能拡張](https://www.highcharts.com/docs/extending-highcharts/extending-highcharts)のことざっくり説明すると以下になります。

- [APIリファレンス](https://api.highcharts.com/highcharts/)に公開しているAPIを拡張できますよ。
- ただし、一部のAPIは公開していないので、`highcharts.src.js`を参照してね。

APIリファレンスで公開していないAPIは直接ソースを調べろってことか。。。
有償ライブラリなら、そういうところも一般公開して欲しかったなあ。。。
それとも、非営利目的（無償）で使用している人向けに少しサポートを控えめにしているのか。。。

# 拡張の方法

拡張の方法は、[公式サイトで記述されている機能拡張](https://www.highcharts.com/docs/extending-highcharts/extending-highcharts)の一番下に記述されています。
（**EXAMPLE EXTENSION**と太字で記載されている部分です。）

公式サイトでは、ツールチップの機能を拡張した実例を記載しています。
実例のコードを説明用に日本語に置き換えたコードが以下となります。

```js

(function (H) {
  H.wrap(H.プロパティ名.prototype, 'API名', function(元の関数){
    元の関数.apply(this);
  });
}(Highcharts));
```
### 機能名
`Tooltip`や`XAxis`などといったプロパティの名前を記載します。
どこを参照するかというと、[APIリファレンス](https://api.highcharts.com/highcharts/)の左ツリーです。

![スクリーンショット 2018-03-20 8.36.47.png](https://qiita-image-store.s3.amazonaws.com/0/140704/6dd28555-49af-41cd-213d-5d63f82118f2.png)

`Highcharts.chart({`のを下にだら〜と書き綴ってあるプロパティ名のことです。
画像上では、小文字始まりですが、大文字始まりに書き換えれば大体OKです。

- `series`　→　`Series`
- `tooltip`　→　`Tooltip`
- `xAxis`　→　`XAxis`
- `yAxis`　→　`YAxis`

てな感じです。

### API名

機能名に紐づき、拡張したいAPI名を記述します。
今回は、公式サイトの機能拡張デモ時に使用されている`Tooltip.hide`を
`highcharts.src.js`から見つける、ということをやってみましょう。

`highcharts.src.js`は[このURL](https://www.highcharts.com/download)から、
以下の**HIGHCHARTS n.n.n**をクリックすることで
ダウンロードすることができます。（会員登録不要、無償です。）

![スクリーンショット 2018-03-20 8.36.14.png](https://qiita-image-store.s3.amazonaws.com/0/140704/a3eafec8-a3c4-5fbc-cbb2-b76cbf8a1f36.png)

ダウンロードしたら、ソースを開き、以下の手順でソース内を検索してみてください。

1. `H.Tooltip.prototype`で検索
2. `H.Tooltip.prototype`ブロック内から`hide:`で検索

すると、拡張目当てであるAPIにたどり着くことができます。
たどり着いたAPIはこんな感じです。

```js
/**
 * Hide the tooltip
 */
hide: function(delay) {
    var tooltip = this;
    // disallow duplicate timers (#1728, #1766)
    clearTimeout(this.hideTimer);
    delay = pick(delay, this.options.hideDelay, 500);
    if (!this.isHidden) {
        this.hideTimer = syncTimeout(function() {
            tooltip.getLabel()[delay ? 'fadeOut' : 'hide']();
            tooltip.isHidden = true;
        }, delay);
    }
},
```

今回はもともと`hide`というAPI名を知っていたからこのような検索方法でたどり着くことができましたが、
本来は「〜したい」という目的があり、そこから拡張対象であるAPI名を探す、という手順になるかと思います。

その場合は、先ほど試した1,2の手順の1「`H.Tooltip.prototype`で検索」でブロックを見つけ、
そのブロック内をスクロールしながら、お目当てのAPI名を探す→拡張してみるということをやらねばなりません。
（他に方法があったら教えてください。。。）

API名公開してほしいなあ。。。

### 元の関数

元の関数が引数として渡されます。
APIの機能自体を無効にしたい場合は`元の関数.apply(this);`しなければOKです。
例えば、Tooltipを表示したままにした場合は、以下のようなコードで実現することが可能です。

```js

(function (H) {
  H.wrap(H.Tooltip.prototype, 'hide', function(defaultFunc){
    //defaultFunc.apply(this);
  });
}(Highcharts));
```

# おわり

おわりです。
拡張関連で他に情報ありましたら、是非是非連絡いただけると助かります！
Capybara の使い方

Capybara を使ってページのリンクを取得する方法のテストです。

次の環境で確認しました。

```text
$ uname -a
Linux iwata 5.0.13-arch1-1-ARCH #1 SMP PREEMPT Sun May 5 18:05:41 UTC 2019 x86_64 GNU/Linux
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]
```

前提となるソフトのインストール

```bash
gem install capybara
gem install selenium-webdriver
```

ドライバーのダウンロード

```bash
wget https://github.com/mozilla/geckodriver/releases/download/v0.24.0/geckodriver-v0.24.0-linux64.tar.gz
```

https://ekzemplaro.org で div id が "items" にあるリンクを取得するプログラムです。

```rb:crawler_screenshot.rb
#! /usr/bin/ruby
# -*- coding: utf-8 -*-
#
#	crawler_screenshot.rb
#
#						Mar/20/2018
# ---------------------------------------------------------------------
require 'capybara'
require 'capybara/dsl'
require 'selenium-webdriver'
require 'uri'

# ---------------------------------------------------------------------
Capybara.current_driver = :selenium
Capybara.app_host = "https://ekzemplaro.org"
Capybara.default_max_wait_time = 20

# ---------------------------------------------------------------------
module Crawler
	class LinkChecker
		include Capybara::DSL

		def initialize()
			visit('')
		end

		def find_links
			@links = []

            within(:xpath, '//*[@id="items"]') do
                all('a').each do |a|
                    uu = a[:href]
                    next if uu.nil? or uu.empty?
                    @links << uu

                    break if @links.size >= 20
                end
            end

			@links.uniq!
			@links
		end
	end
end

# ---------------------------------------------------------------------
STDERR.puts	"*** 開始 ***"
#
base = URI.parse(Capybara.app_host)
crawler = Crawler::LinkChecker.new
links = crawler.find_links
links.each.with_index {|link,index| 
		puts link
}
#
STDERR.puts	"*** 終了 ***"
#
# ---------------------------------------------------------------------
```

実行コマンド (geckodriver　のあるフォルダーで実行）

```bash
export PATH=$PATH:./
#
./crawler_screenshot.rb
```

実行結果

```text
$ export PATH=$PATH:./
$ ./crawler_screenshot.rb
*** 開始 ***
https://ekzemplaro.org/audio_books/
https://ekzemplaro.org/librivox/
https://ekzemplaro.org/audio/
http://www.hi-ho.ne.jp/linux
https://ekzemplaro.org/raspberry/
https://ekzemplaro.org/storytelling/
https://ekzemplaro.org/crowdsourcing/
*** 終了 ***
```
GPGコマンド覚え書き

# はじめに
GPGを一応使っているけれど、普段からがっつり使い込んでいるわけではなく、いざという時にググってばかりだったので、コマンドやリンクをまとめました。

# 初期設定
## インストール
```
brew install gnupg pinentry-mac
```
`pinentry`というのは、ユーザーがパスフレーズを入力する際に、GPGが安全に読み取るためのツールです。
各OSごとに適当なツールをインストールしてください。
https://gnupg.org/software/pinentry/index.html

## ホームディレクトリの確認
```
ls ~/.gnupg
```

# キー操作
## キーペアの生成
```
pgp --full-generate-key
```

## キーの確認
```
gpg --list-secret-keys --keyid-format LONG
```

## 公開鍵のエクスポート
```
gpg --armor --export <key_id>
gpg --armor --export <key_id> --output <file_path>
```

## サブキーの追加
```
gpg --edit-key <key_id> addkey
```

## サブキーの削除
```
gpg --edit-key <key_id>
gpg> key <sub_key_id> # 削除したいサブキーを選択する
gpg> delkey
```

## プライマリーキーの失効
プライマリーキーを失効させるには、失効証明書が必要です。
失効証明書はプライマリーキーの作成時に`~/.gnupg/openpgp-revocs.d/`に自動で作成されます。
ファイル名は`<fingerprint_of_primary_key>.rev`という形式になっています。

失効証明書を利用してプライマリーキーの失効を実行するコマンドは以下です。

```
gpg --import <revocation_certificate>
```

この更新は公開鍵サーバーにも登録する必要があります。

```
gpg --keyserver <keyserver> --sendkeys <key_id>
```




# Reference
[The GNU Privacy Handbook](https://www.gnupg.org/gph/en/manual/book1.html)
[Signing commits with GPG - GitHub](https://help.github.com/articles/signing-commits-with-gpg/)
[gpg (GNU Privacy Guard)の使い方](https://qiita.com/moutend/items/5c22d6e57a74845578f6)
PyMieScatt > Lorentz-Lorenz term | Clausius–Mossotti relation | Kramers-Kronig Relations

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 16.04 LTS desktop amd64
TensorFlow v1.2.1
cuDNN v5.1 for Linux
CUDA v8.0
Python 3.5.2
IPython 6.0.0 -- An enhanced Interactive Python.
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
scipy v0.19.1
geopandas v0.3.0
MATLAB R2017b (Home Edition)
ADDA v.1.3b6
gnustep-gui-runtime v0.24.0-3.1
```

Numpy実装による球粒子の光散乱コードPyMieScatt関連。

### Reference

- Bohren C.F. and D. R. Huffman, "Absorption and Scattering of Light by Small Particles", John Wiley, New York, NY (1983)
- PDF: [MATLAB Functions for Mie Scattering and Absorption, Research Report No. 2002-08, June 2002](https://omlc.org/software/mie/maetzlermie/Maetzler2002.pdf) by Christian Mätzler


### Lorentz-Lorenz term

https://github.com/bsumlin/PyMieScatt/blob/master/PyMieScatt/Mie.py#L132

```py
LL = (m**2-1)/(m**2+2) # Lorentz-Lorenz term
```

Bohren and Huffman (1983) 
Chapter 5 Particles Small Compared with the Wavelength
p131

下記の式などで出てくる複素屈折率の分数のことをLorentz-Lorenz termと呼ぶようだ。

```math
a_1 = -\frac{i2x^3}{3}\frac{m^2-1}{m^2+2}...(5.4)
```

### Clausius–Mossotti relation

関連して思い出したのはClausius–Mossotti relation
Aigen Li氏が講義で紹介していた。

https://en.wikipedia.org/wiki/Clausius%E2%80%93Mossotti_relation

```math
\frac{\epsilon_r - 1}{\epsilon_r + 2} = \frac{N\alpha}{3\epsilon_0}
```

複素屈折率$m$の二乗は誘電率$\epsilon$になるので、式の左の項目はLorentz-Lorenz termと呼べるのだろう。

### Kramers-Kronig Relations

> Aigen Li氏が講義で紹介していた。

[Planetary School 2006](https://www.cps-jp.org/~pschool/pub/21coeps/SCHOOL/2006/2006_ischool_j.html)
の
https://www.cps-jp.org/~pschool/pub/21coeps/SCHOOL/2006/PDF/ps06-aigen1.pdf
p15
Clausius–Mossotti relationではなく、Kramers-Kronig Relationsの方だった。

こちらは複素屈折率の実部と虚部に関連があるという式。
Kronig はクローニッヒという発音。
slackに長すぎるメッセージを投稿すると、メッセージが自動的に分割されるようになっていた

昔は`413 Payload Too Large`が返されていたが、今は受け付けてくれる。
`413`が返されるのは去年の夏くらいに確認したが、その後いつ変更されたんだろうか。

自動分割された場合はレスポンスに`is_auto_split`フィールドが増える。
`is_auto_split`フィールドは、自動分割されなかった場合は存在しない(`false`になるわけではない)ので注意が必要である。
また、自動分割された場合のレスポンスの`message.text`フィールドは、分割された一連メッセージのうち、最後のメッセージのテキストとなり、全文は含まれない。

```json
{
  "ok": true,
  "ts": "1521494094.000437",
  "message": {
    "text": "分割された一連のメッセージのうち、最後のメッセージのテキスト",
    "username": "Slack API Tester",
    "is_auto_split": true,
    "type": "message",
    "subtype": "bot_message",
    "ts": "1521494094.000437"
  },
  "warning": "missing_charset",
  "response_metadata": {
    "warnings": [
      "missing_charset"
    ]
  }
}
```

何文字で分割されるのかは仕様が見当たらなかった。
実測によると**4042文字**である。

```python3
# coding: utf_8
import bisect
import json
import time
import requests


TOKEN = ''


def json_post(char, length):
    time.sleep(3)
    h = {
            'Content-type': 'application/json',
            'Authorization': 'Bearer ' + TOKEN,
        }
    d = json.dumps({
            'channel': 'general',
            'text': ''.join([char] * length),
        })
    r = requests.post('https://slack.com/api/chat.postMessage', headers=h, data=d)
    if not r.json()['ok']:
        raise Exception()
    return 1 if r.json().get('message', {}).get('is_auto_split') else 0


def form_post(char, length):
    time.sleep(3)
    d = {
            'token': TOKEN,
            'channel': 'general',
            'text': ''.join([char] * length),
        }
    r = requests.post('https://slack.com/api/chat.postMessage', data=d)
    if not r.json()['ok']:
        raise Exception()
    return 1 if r.json().get('message', {}).get('is_auto_split') else 0


class Resolver(object):

    def __init__(self, char, post):
        self.char = char
        self.post = post

    def __len__(self):
        return 100000

    def __getitem__(self, key):
        return self.post(self.char, key)


print(bisect.bisect(Resolver('a', json_post), 0))
print(bisect.bisect(Resolver('あ', json_post), 0))
print(bisect.bisect(Resolver('a', form_post), 0))
print(bisect.bisect(Resolver('あ', form_post), 0))
```

```bash
$ pipenv run python _.py
4041
4041
4041
4041
```

`a`と`あ`を個別にチェックしているのは昔の名残である。
以前のSlackはパーセントエンコード後のバイト数で文字数をカウントしていたため、`あ`は**9文字扱い**だった(utf8で3バイト、パーセントエンコード後9バイト)のだ。
今はそういうことはないようだ。
実行可能なブロックチェーン&仮想マシンの自作


Ethereumのコンセプトってすごいな、と思って実行可能ブロックチェーンを自作してみた。なるべくシンプルな設計で、主要な機能を持たせるように努めた。主なコンポーネントは以下の３つ。

 - 言語処理系（FORTHコンパイラ）
 - 仮想マシン（スタックマシン型命令セット）
 - ブロックチェーン（SHA256）

[リポジトリはここです。]( https://github.com/s0sasaki/ExecutableBlockchain)
詳しくはソースコードを見てもらいたいですが、テストケースで試している機能は以下。

 - 簡単な四則演算
 - 簡単な関数定義・呼出し
 - 簡単な条件分岐
 - ネストされた条件分岐
 - ネストされた関数呼出し
 - 再帰関数
 - 末尾再帰関数
 - 過去のブロックに登録した関数の呼出し
 - 揮発性の変数（数値のエイリアス）
 - 不揮発性の変数（ブロックに登録する変数）
 - ブロックチェーンのバリデーション
 - ブロックチェーンの改竄不可能性

普段は主にPythonでデータ分析とかをしているので、C++と戯れるとconst伝播とか変数アクセス制御とかメンバ関数ポインタとか新鮮で楽しい。C/C++の勉強もうちょっとがんばろ。

# 参考資料

 - http://www.zedwood.com/article/cpp-sha256-function

SHA256関数のC++実装。
ブログによる解説あり（英語）。
SHA256関数はここのコードをそのまま使わせて頂きました。

 - https://github.com/teaandcode/TestChain

ブロックチェーンのC++実装。
シンプルで分かりやすい設計。
ブログによる解説あり（英語）。
元ネタはJavascriptで書かれたブロックチェーン。

 - https://gist.github.com/kumaashi/6d4c83b635fdd996fd67bb8f887bec43

ForthコンパイラのC++実装。
シンプルで分かりやすい設計。

 - https://ethereum.github.io/yellowpaper/paper.pdf
 - https://github.com/ethereum/wiki/wiki/Ethereum-Development-Tutorial

Ethereumの仕様などについての定番資料。
LaTexのコンパイルをLatexmkに統一する

最近のlatexのコンパイルには**Latexmk**を使うと良いようです．
``platex`` -> ``bibtex`` -> ``platex`` -> ``dvipdfmx``のような一連の処理をまとめてやってくれます．

カレントのディレクトリに``.latexmkrc``を作成することでプロジェクトごとの設定を行います．適切な設定ファイルを配置することで，WindowsでもUnixでも（たぶんMacでも）常に1コマンドでPDFを生成することができます．

```
$ latexmk TEX_FILE.tex
```

さらに

```:.latexmkrc
@default_files	  = ('TEX_FILE.tex');
```
と指定することで，build対象の指定を省略できます．


(ここでは**TexLive**がインストールされている前提です)

## 英語のみの場合

### ``pdflatex``を使う場合
```:.latexmkfc
#!/usr/bin/env perl
$pdf_mode = 1
```

``pdflatex``でPDFを出力するようにモードを変更します．

### ``latex``を使う場合

```:.latexmkfc
#!/usr/bin/env perl
$pdf_mode   = 3
$dvipdf     = 'dvipdfmx %O -o %D %S';
```
``latex + dvipdfmx``で出力します．



## 日本語を含む場合

### ``platex``の場合

``latex + dvipdfm``でPDFを出力するモード3に変更し，``platex``と``dvipdfmx``を使うように設定します．

```:.latexmkrc
#!/usr/bin/env perl
$pdf_mode	      = 3;
$latex            = 'platex -halt-on-error';
$latex_silent     = 'platex -halt-on-error -interaction=batchmode';
$bibtex           = 'pbibtex';
$dvipdf           = 'dvipdfmx %O -o %D %S';
$makeindex        = 'mendex %O -o %D %S';

```

### ``uplatex``の場合

```:.latexmkrc
#!/usr/bin/env perl
$pdf_mode	      = 3;
$latex            = 'uplatex -halt-on-error';
$latex_silent     = 'uplatex -halt-on-error -interaction=batchmode';
$bibtex           = 'upbibtex';
$dvipdf           = 'dvipdfmx %O -o %D %S';
$makeindex        = 'mendex %O -o %D %S';

```
ElixirSublime で Code completion for modules and functions が効かない

環境
----
macOS Sierra 10.12.6
Sublime Text Version 3.0 Build 3143
Elixir 1.6.3 
Erlang/OTP 20 [erts-9.2.1]

問題
----

1. SublimeText3 で Elixir のコードを書いてみようと思い立つ.
2. [SublimeText3(DevChannel) で Elixirの開発環境を整える (OSX)](https://qiita.com/_mk2/items/a397c03b1c0501f73b24) を参考に ElixirSublime をインストールする.
3. Fix Mac Path を入れても [Code completion for modules and functions](https://packagecontrol.io/packages/ElixirSublime) が機能していないことに気づく.
4. コンソールを見ると, socket まわりでエラーが吐かれている...


解決方法
-------

この問題は [こちらのIssue](https://github.com/vishnevskiy/ElixirSublime/issues/22) で取り上げらており, [nicholasruunu commented on 4 Mar 2016](https://github.com/vishnevskiy/ElixirSublime/issues/22#issuecomment-191809055) のコメントを見て解決できました.

ElixirSublime の Installation には記載されていませんが, ElixirSublime が依存しているモジュールを `mix deps.get` でインストールする必要があるようです.

```
# 下記だと no such file or directory となるので $HOME に置き換える
#cd "~/Library/Application Support/Sublime Text 3/Packages/ElixirSublime/sublime_completion"
cd "$HOME/Library/Application Support/Sublime Text 3/Packages/ElixirSublime/sublime_completion"
mix deps.get
```
プログラミング 1 周年 その 1

　プログラミングを始めて 1 年が経ちました。紆余曲折はあったものの何とか 1 年間続けることが出来ました。今回はその 1 年間を振り返ってみるということでの投稿です。

#:pencil2: どうしてプログラミングを始めたか？


　きっかけは、「近いうちに小中高でプログラミングが必修化する」というネット記事を見たことです。このころは HTML/CSS を少しだけ触れた程度でそれほど深くはやらなかったですが、この際せっかくだからプログラミングを勉強してみようということで、**好奇心とトレンドに便乗する**という感じで勉強を始めました。

#:pencil2: どうやって勉強したか？
### 初期のころ

　当然ながらプログラミングなんてほぼ右も左もわからない状況です。いきなり本からやっても意味が分からないですし、実際使うかどうかも微妙な感じ。そのうえ環境構築ともなるとインストールも設定するのも大変。これではプログラミングする以前に挫折する可能性が大きいです。

　ですので、まずはなにか初心者用に書かれている記事がないか探しました。最初にプログラミングの記事に出会ったのが侍エンジニア塾というブログです。とても分かりやすい記事で初心者の自分でも理解がしやすかったです。勉強法もステップ式で書かれていますので参考になりました。


　この時にメインでやったことは「無料プログラミングサイト」でした。一番しっくり来たのが**「Progate」**というサイトです。面倒な環境構築をしなくてもプログラミングを学ぶことができます。手を動かして、まずはプログラミングに「慣れる」ことを重点におきました。

### 2~3ヶ月目

　各言語にも少しずつ慣れてきて、簡単なプログラムや Web デザインはある程度できるようになってきました。この辺りになると難しい概念が登場し、理解が難しくなってきます。特にオブジェクト指向を理解するのにだいぶ時間がかかった覚えがあります。

　その時、理解もままならない頃に Progate の PHPⅡ から始めて「オブジェクト指向」の概念からいきなり入ってしまったためかなり苦労したのはいい思い出です。

　このあたりを理解するには、**メソッド（関数）とクラスの理解が不可欠**です。Progate の RubyⅢ・Ⅳ 辺りが分かりやすいのでそのあたりを重点的に学習してから挑戦した方がいいかと思います。

　理解がなかなか進まないので、モチベーションも下がり気味ではあったのですが、その時は今まで学習してきたことを復習して定着させる工夫もして進めていきました。


#:star: 次回

あまり長くならないように、分けて投稿していこうかと思います。

次回は

・ プログラミング 4~12 か月目
・ 振り返ってみてからの反省点

を投稿してみようかと思います。
Kubernetes上にLinux OSをコンテナとしてデプロイする

# 目的

Kubernetesは構造が複雑なため、問題が発生した際に調査をするのが大変です。特に通信の問題は調査のためにいろいろなツールを使いたいです。そこで、Kubernetes上に自由に使えるOS環境を作ってみます。

検証環境
- IBM Cloud Private 2.1.0.1 (Kubernetes 1.8)

# 手順

CentOSの例ですが、次のようなYAMLを作ればよいです。/dev/nullをtailし続けてコンテナが終了しないようにしているところがポイントです。

```pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: centos7
spec:
  containers:
    - name: centos7
      image: centos:7
      command: [ "tailf" ]
      args: [ "/dev/null" ]
```

適用します。

```
kubectl apply -f pod.yaml
```

Podが作成されました。

```
kubectl get pod centos7 -o wide

NAME      READY     STATUS    RESTARTS   AGE       IP             NODE
centos7   1/1       Running   0          8m        10.1.173.148   192.168.11.24
```

シェル起動で操作可能です。

```
kubectl exec -it centos7 bash

[root@centos7 /]# 
```

以上です。
Bootstrapを使わないでJumbotronを実装する

# はじめに
cssの勉強のためにBootstrapを使わずにJumbotronを実装してみます。

# html
```html
    <nav class="nav">
        <ul class="nav-menu">
            <li class="nav-child">SITE-LOGO</li>
            <li class="nav-child">このサイトについて</li>
            <li class="nav-child">ログイン</li>
            <li class="nav-child">会員登録</li>
        </ul>
    </nav>
    <header class="jumbotron">
        <h1 class="jumbotron-title">JumboTron</h1>
        <p class="jumbotron-msg">
            これはJumboTronです。CSSで実装しています。<br> CSSの勉強のために自前で実装していますが、普段はBootStrapを使えばいいと思います。
        </p>
        <a href="#" class="btn btn-primary">JumboTronへGo!!</a>
    </header>
```

# CSS

```css
/** ノーマライズ **/

body {
    font-family: 游ゴシック体, 'Yu Gothic', YuGothic, 'ヒラギノ角ゴシック Pro', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, Osaka, 'ＭＳ Ｐゴシック', 'MS PGothic', sans-serif;
}

body,
ul,
li,
h1,
h2,
p,
a {
    margin: 0px;
    padding: 0px;
    font-weight: normal;
    line-height: 1em;
}


/** ナビゲーション **/
.nav {
    height: 50px;
    background-color: darkgray;
    padding: 0 20px;

    color: white;
    font-size: 1.2em;
}

.nav-menu {
    height: 50px;
    list-style: none;
    display: flex;
    align-items: center;
}

.nav-child {
    margin-left: 30px;
}

.nav-menu .nav-child:first-child {
    font-size: 1.5em;
    margin-left: 0px;
    margin-right: auto;
}

/** jumbotron **/
.jumbotron {
    background-color: #e9ecef;
    height: 300px;
    padding: 70px 150px 140px 150px;
}

.jumbotron-title {
    font-size: 4em;
    line-height: 1.5em;
}

.jumbotron-msg {
    line-height: 2em;
    margin-bottom: 60px;
}

/** ぼたん **/
.btn {
    font-weight: bold;
    display: inline-block;
    text-decoration: none;
    padding: 15px 30px;
    border-radius: 5px;
    border-style: solid;

    border-color: rgb(135, 121, 244);
    color: rgb(135, 121, 244);
}

.btn-primary {
    border-style: none;
    background-color: rgb(135, 121, 244);
    color: white;
}
```
# 出来上がりイメージ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178845/08c4f4c4-9882-5389-25e6-d4a02691d98d.png)

以上です。
Slack APIでリンクを開く

# 概要
Slackにリンクを張ると、リンク先が表示される機能(下図のようなイメージ)がありますが、　　
Slack APIからメッセージを送ったときになぜかリンク先が表示されなかったので、　　
表示させる方法を記載します。

![こうしたい.png](https://qiita-image-store.s3.amazonaws.com/0/199997/b80bff37-e023-e305-dad5-9c48657a171e.png)

# リンクが表示されないパターン
[公式ページ](https://get.slack.help/hc/ja/articles/204399343-Slack-%E3%81%A7%E3%83%AA%E3%83%B3%E3%82%AF%E3%82%92%E5%85%B1%E6%9C%89%E3%81%99%E3%82%8B-)によると、  
>・リンクにプレビューデータが含まれていない
>Slack メッセージでリンクを共有する際、リンクのプレビューには Twitter >Cards、oEmbed や Open Graph からの組み込み情報が含まれます。もしその >Web ページがそれらのデータを含まない場合、リンクは展開表示されません。

>・非公開のページやファイルへのリンク
>例えば、YouTube や Vimeo videos で非公開になっているものはプレビューが表示されません。

>・最近、ワークスペースの別のメンバーによって投稿された。
>同じリンクが過去1時間以内に共有されていた場合、リンクは展開されません。ホワイトリストにまだ登録されていないサービスにより管理されているビデオや音声データへのリンクより多くのサービスをホワイトリストに登録するよう、引き続き取り組んでいきます。

>・http:// が含まれていない
>この場合、http:// を追加すると、リンクが展開されるはずです。

>・一つのメッセージに5つ以上のリンクが含まれている 
>もしメッセージが５つ以上のリンクを含む場合、それらのリンクは展開表示されません。

の5つのどれかに該当する場合には表示されないようですが、
今回はどれにも該当しなかったため、次のようにパラメータをつけます。

# パラメータ
メッセージ送信時に、unfurl_linksパラメータをtrueにします。

```python:notify.py
import slackweb

slack = slackweb.Slack(url={URL})
slack.notify(text=msg, unfurl_links='true')
```
https://api.slack.com/docs/message-link-unfurling
PowerShellでファイル出力する際のメモ書き

#目的
PowerShellでファイルの中身を検索し、指定した文字列が含む行を別ファイルに出力したい。

PowerShellにはLinuxでいう「grep」の様な「Select-String」コマンドがあるみたいなので実際に書いてみる。
参考（https://qiita.com/kmr_hryk/items/101c15c8c1c95469f53e）

#実際にファイル出力テスト

### FileSeparate

ファイルパスなどの引数を変数に格納し、一行ずつ確認し、合致したらファイル出力するというコードを作成

```powershell
#===============================================================================
# FileSeparate：ファイルの中から文字列を抽出し新しいファイルに出力 
# Param: 
#   $filepath    : ファイルパス
#   $grepword    : 抽出する文字列
#   $newfilepath : 抽出した文字列が含む行の出力先csvファイル
#
# 使用例
#  $filepath = "C:\work\999.TestDate\02.csv\test_20180315.csv"
#  $grepword = "文字列"
#  $newfilepath = "C:\work\999.TestDate\02.csv\newcsv_20180319.csv"
#===============================================================================

#1 引数を変数に格納
Param([string]$filepath, [string]$grepword, [string]$newfilepath)

#2 ファイルの中から文字列を抽出し新しいファイルに出力
$data=Get-Content $filepath
foreach($x in $data){
$tests = $x | Select-String $grepword
    if($tests -ne $null){
        $x | Select-String $grepword | Out-File $newfilepath
    }
}

#確認
Get-Content $newfilepath
```

- 結果

```powershell

PS C:\work\20. batch\05. FileSeparate> ./FileSeparate.ps1 "C:\work\999.TestDate\02.csv\test_20180315.csv" "文字列" "C:\work\999.TestDate\02.csv\newcsv_20180319.csv"

01,文字列,test



PS C:\work\20. batch\05. FileSeparate> 
```
一行目に空行が入っている。ファイルを確認しても同様。
Select-String　の箇所で空行が入っているように見受けられる。
どちらにしても一行目の空行を削除する必要がある。

### FileSeparate2（空行消去修正）

```powershell
#===============================================================================
# FileSeparate2：ファイルの中から文字列を抽出し新しいファイルに出力 
# Param: 
#   $filepath    : ファイルパス
#   $grepword    : 抽出する文字列
#   $tmpfilepath : 空行が含む抽出した文字列が含む行の出力先csvファイル
#   $newcsvpath　: 抽出した文字列が含む行の出力先csvファイル
#
# 使用例
#  $filepath = "C:\work\999.TestDate\02.csv\test_20180315.csv"
#  $grepword = "文字列"
#  $newfilepath = "C:\work\999.TestDate\02.csv\tmp_20180320.csv"
#  $newcsvpath = "C:\work\999.TestDate\02.csv\newcsv.csv"
#===============================================================================

#1 引数を変数に格納
Param([string]$filepath, [string]$grepword, [string]$tmpfilepath, [string]$newcsvpath)

#2 ファイルの中から文字列を抽出し新しいファイルに出力
$data = Get-Content $filepath
foreach($x in $data){
$tests = $x | Select-String $grepword
    if($tests -ne $null){
        $x | Select-String $grepword | Out-File $tmpfilepath
    }
}
#3 Set-Stringで抽出し出力した場合一行目空行が入るため空行を削除する。
$DelOne = Get-Content $newfilepath
$DelOne[0] = $null
$DelOne | Out-File $newcsvpath

#確認
Get-Content $newcsvpath
```

- 結果

```powershell
PS C:\work\20. batch\05. FileSeparate> ./FileSeparate2.ps1 "C:\work\999.TestDate\02.csv\test_20180315.csv" "文字列" "C:\work\999.TestDate\02.csv\tmp_20180320.csv" "C:\work\999.TestDate\02.csv\newcsv.csv"
01,文字列,test



PS C:\work\20. batch\05. FileSeparate> 
```
最低限の機能としては問題なさそうだが、末尾に3行空行入っているのは要修正。
見返すと纏められる個所など作りが荒い部分が多数・・・。後日修正予定。

## 参考サイト
https://qiita.com/kmr_hryk/items/101c15c8c1c95469f53e
https://orebibou.com/2015/01/powershellでsed相当の処理を行う/
Python空白行削除のワンライナー

Python の組み込み関数の [str.stritp()](https://docs.python.jp/3/library/stdtypes.html#str.strip) が空白文字の削除なのでそれをうまく適用すればよい。

```python
'\n'.join(filter(lambda x: x.strip(), text.split('\n')))
```

抽出する行の余分な空白文字も削除したい場合

```python
'\n'.join(filter(lambda x: x.strip(), map(lambda x: x.strip(), text.split('\n'))))
```
"ffi"が"Failed to build gem native extension"と怒られる時の対処法

#概要

capistranoでデプロイしているときに、
`bundle install`の時に、以下のエラーがでた

```
cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing as ec2-user@54.95.189.234: bundle exit status: 5
bundle stdout: Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

current directory:

(中略...)

An error occurred while installing ffi (1.9.21), and Bundler cannot continue.
Make sure that `gem install ffi -v '1.9.21'` succeeds before bundling.

In Gemfile:
  bootstrap-sass was resolved to 3.3.7, which depends on
    sass was resolved to 3.5.5, which depends on
      sass-listen was resolved to 4.0.0, which depends on
        rb-inotify was resolved to 0.9.10, which depends on
          ffi
```

# 結論

こちらを参考にしました。
https://github.com/ffi/ffi/issues/552

`$ sudo yum install libffi-devel redhat-rpm-config`

ec2上に足りていなかったらしい。
PHPで変数の中身を文字列で表示させる

`var_dump()`で殆ど足りるけど、ログファイル等に出してみたい場合

```php
$array = [
    'test' => 'test',
    1 => [],
    true,
    false,
    null,
    'object' => new stdClass(),
];
```

# var_dump()と全く同じ文字列が欲しい場合は[出力バッファリング](#出力バッファリング)を使用します。

(出力バッファリングのメモリが足りない場合は全て取得できないかもしれません)

```php
ob_start();// 出力バッファリング開始

var_dump($array);// 出力処理 ここではバッファに載るだけで出力されない

$dump_string = ob_get_contents();// 出力バッファ取得

ob_end_clean();// 出力バッファをクリアし、出力バッファリングを終了する
// ob_end_flush()で出力バッファを直接出力することもできます。（変数に載せる必要がないのでその分メモリを抑えられる）

$fp = fopen(__DIR__.'/dump.log', 'a+');// 追記モード・ファイルが存在しない場合には、作成を試みます。
fputs($fp, $dump_string);
```

```php
var_dump($dump_string);

string(174) "array(6) {
  ["test"]=>
  string(4) "test"
  [1]=>
  array(0) {
  }
  [2]=>
  bool(true)
  [3]=>
  bool(false)
  [4]=>
  NULL
  ["object"]=>
  object(stdClass)#1 (0) {
  }
}
"
```

# var_export($array, true)

```php
var_dump(var_export($array, true));

string(144) "array (
  'test' => 'test',
  1 => 
  array (
  ),
  2 => true,
  3 => false,
  4 => NULL,
  'object' => 
  stdClass::__set_state(array(
  )),
)"
```

# print_r($array, true)

```php
var_dump(print_r($array, true));

string(157) "Array
(
    [test] => test
    [1] => Array
        (
        )

    [2] => 1
    [3] => 
    [4] => 
    [object] => stdClass Object
        (
        )

)
"
```

# 出力バッファリング

echoやprintf等の標準出力は毎回出力するのでなく、ある程度まとめてから出力する方が効率が良い。
出力をまとめて保持しておくためのバッファ機能だそうです。

デバッグでしか使わないかもしれませんがvar_dump,var_export,print_rも標準出力なので対象。

[readfile](http://php.net/manual/ja/function.readfile.php)も標準出力なので対象。


[output_buffering](http://php.net/manual/ja/outcontrol.configuration.php#ini.output-buffering)

デフォルトはOffらしいのですが
CentOS7でPHP7.1をインストールしてみたところ以下の設定がデフォルトになっていました。

output_buffering = 4096

上記は最大バイト数

**Onにすると無制限にバッファを使うことになるそうなのでメモリ不足になったりする可能性があります。**
この場合は容量の大きいファイルの中身をレスポンスボディに出力してダウンロードさせる場合等に注意が必要だそうです。
【WPF覚書】ViewModelとデータバインディング

# はじめに
C#、WPFの勉強をしてて覚えたことの覚え書き。
データバインディングがやりたかったけど、初めはなかなか理解できなかったので、自分なりにまとめてみる。


記載しているコードは必要な部分のみの抜粋なのであしからず。

# ViewModel
xaml.csファイルのクラスがViewModelだと思ってたのだが、どうやら違うらしい。
別途ViewModelクラスを作る必要がある。

```csharp:MainViewMode.cs
class MainViewModel
{
	public String BindText { get; set; } = "てきとうな初期値";
}
```
publicなプロパティがXAMLから参照可能なプロパティとなる。

# XAMLと連携するクラス
XAMLと連携するクラスの`DataContext`プロパティにViewModelのインスタンスを突っ込む。

```csharp:MainView.xaml.cs
public partial class MainWindow : Window
{
	public MainWindow()
	{
		InitializeComponent();

		this.DataContext = new MainViewModel();
	}
}
```
こうすると、`DataContext`(ViewModel)のプロパティがXAMLから参照可能になる。

# XAML
XAMLにはどこに何をバインドするか書く。
`DataContext`を使用すれば、ViewModelに関する記述などは不要。

```xml:MainView.xaml
<Grid>
	<Label Content="{Binding BindText}" Margin="0,0,0,0"/>
</Grid>
```
こう書くと`MainView.DataContext.BindText`とバインドされる。

# 完成
出来上がったものがこちら。ビルドして実行しただけ。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/56012/6defeead-2dc0-705e-61bc-8a7f4678f120.png)

`MainViewModel.BindText`を動的に変更すると、それに合わせてLabelのContentプロパティにも自動的に反映される。

# 追記
上で書いたように、自動的に反映されるようにするにはもう少し手を加える必要があったので、別途記事を[書きました](https://qiita.com/TAK_EMI/items/d7991a34f815d9d73e32)。よければご参照ください。
Nuxt.jsで超絶簡単にGoogle Analyticsを導入する

Nuxt.jsで静的ページを作って、GoogleAnalytics(GA)を導入したい！！！ってなったときのメモです。

## 手順１: パッケージをインストールする

```shell
$ npm install --save @nuxtjs/google-analytics
```
または

```shell
$ yarn add @nuxtjs/google-analytics
```

## 手順2: nuxt.config.jsに下記を追記する
```js
{
  modules: [
    ['@nuxtjs/google-analytics', {
      id: 'paste your id here'
    }]
 ]
}
```

あとは、netlifyなりGithub pagesなりにデプロイすれば、GAで値が取得できているはずです。
簡単ですね！

## 参考資料
https://github.com/nuxt-community/analytics-module

Google アナリティクスを使うには？
https://ja.nuxtjs.org/faq/google-analytics#google-%E3%82%A2%E3%83%8A%E3%83%AA%E3%83%86%E3%82%A3%E3%82%AF%E3%82%B9%E3%82%92%E4%BD%BF%E3%81%86%E3%81%AB%E3%81%AF-