OmniAICreator/Qiita-1.07M huggingface dataset:
module

## 

mosduleとクラスの違い

- 継承が単一か多重継承可能か？
- インスタンス変数持てるかいなか

moduleのメソッドを使う

```
module Mod
  def hello
    puts 'Hello'
  end

  module_function :hello
end

Mod.hello #=> "Hello"

```

クラスメソッド

```
module Mod
  def self.hello
    puts 'Hello'
  end
end

Mod.hello #=> "Hello"

```

module 継承　（Mix in）

- 2種類ある

include

- インスタンスメソッドとして組み込まれまれる

```
module Mod
  def hello
    puts 'Hello'
  end
end

class Obj
  include Mod
end

ins = Obj.new
ins.hello #=> "Hello"
```

extend

- クラスの一部になる

```
module Mod
  def hello
    puts 'Hello'
  end
end

class Obj
  extend Mod
end

Obj.hello #=> "Hello"
```


# クラス名やメソッド名の重複を回避

- 名前空間

```
module Name
  class Hoge
    def self.hello
      puts 'hello'
    end
  end
end

Name::Hoge.hello #=> "hello"

```

# namespaceに使う

```
module Name # 名前空間としてのモジュール
  module Mod  # Mix-inとしてのモジュール
    def hello
      puts 'Hello'
    end
  end
end

class Obj # Mix-in
  extend Name::Mod
end

Obj.hello #=> "Hello"


```
ヘルシオ ホットクック KN-HW24C をどうしても無線LANに接続したい方のための、接続手順

[ヘルシオ ホットクック KN-HW24C](http://www.sharp.co.jp/hotcook/products/knhw24c/)は、無線LAN対応なのですが、接続先の無線LANがプッシュボタン方式(WPS方式)に対応していないと、LANに接続できません。

- [Sharp社 Ｑ＆Ａ情報 「無線LAN接続の初期設定がうまくいかないときは？」](http://cs.sharp.co.jp/faq/qa?qid=170441)

お困りの方も多いので、どうしてもLANに接続したい方のために、接続できる方法を記載します。

# 概要
- 無線LANのSSIDとパスワードを、ヘルシオ ホットクック KN-HW24Cに設定するため、最初だけ、プッシュボタン方式(WPS方式)に対応した無線LAN親機が必要になります。
- ヘルシオ ホットクックが無線LANに接続した後は、プッシュボタン方式(WPS方式)の無線LAN親機は取り外せます。
- 接続先の無線LAN環境は、プッシュ方式(WPS方式)をサポートしない無線LAN環境(Google Wifi)です。

# 1. プッシュ方式(WPS方式)に対応した無線LAN親機の準備

1. プッシュ方式(WPS方式)に対応した安い無線LAN親機を入手します。例として以下の場合で説明します。
 - [BUFFALO 無線LAN親機 エアステーション 11ac/n/a/g/b 433/150Mbps WMR-433W-TB](https://www.amazon.co.jp/gp/product/B06XWKHZXT/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1)
![IMG_4791.jpeg](https://qiita-image-store.s3.amazonaws.com/0/310146/4d3c90c9-0c6e-7f04-6dc5-16f6932815fa.jpeg)

2. 購入した無線LAN親機を、すでにある接続先の無線LANにLANケーブルで接続します。
![IMG_4792.jpeg](https://qiita-image-store.s3.amazonaws.com/0/310146/79834d5e-caf0-c56c-d838-62d3ceb8589d.jpeg)

3. 購入した無線LAN親機を、ブリッジモードで自宅のLANに接続します。
<img width="894" alt="Screen Shot 2018-11-03 at 12.05.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/310146/c6aac9bf-1e62-db8f-84d7-97d142577c12.png">

4. SSIDとパスワードを、接続先の無線LAN環境と同じ文字列を設定します。2.4GHzで設定します。
<img width="887" alt="Screen Shot 2018-11-03 at 12.05.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/310146/041d801b-ce62-48d1-fa84-76be09641887.png">
<img width="876" alt="Screen Shot 2018-11-03 at 12.06.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/310146/337dada5-f318-9aa1-86fc-959b5e298899.png">

5. 購入した無線LAN親機を、一旦再起動します。

# 2. ヘルシオ ホットクック KN-HW24Cからの接続

1. 購入した無線LAN親機の、プッシュボタンを押します。
2. ヘルシオ ホットクック KN-HW24C で、無線LANをONに設定します。
![IMG_4793.jpeg](https://qiita-image-store.s3.amazonaws.com/0/310146/ce21f553-a026-d71d-70cc-0a21af371dde.jpeg)

3. 購入した無線LAN親機の、プッシュボタンが押されて、接続が待機されている状態なので、ヘルシオ ホットクック KN-HW24C側で、そのまま無線LAN接続を試みます。
![IMG_4796.jpeg](https://qiita-image-store.s3.amazonaws.com/0/310146/5365af29-fe78-894e-e9af-9e8336e9d08d.jpeg)

4. しばらく待つと、ヘルシオ ホットクック KN-HW24C の無線LAN接続が成功します。
無線LAN接続が成功しなければ、購入した無線LAN親機が正常に自宅の無線LANに接続されていない可能性があるので、設定を確認してください。

# 3. プッシュ方式(WPS方式)に対応した無線LAN親機を取り除く

1. ヘルシオ ホットクック KN-HW24C の無線LAN接続が成功したら、購入した無線LAN親機の電源ケーブルと、LANケーブルを抜いてしまいます。
2. ヘルシオ ホットクック KN-HW24C で、無線LANを、一旦OFFにして、無線LANを無効化した後、もう一度ONにします。
ヘルシオ ホットクックの無線LANを再起動することで、自宅の無線LANに直接接続させます。無事に接続できれば、設定完了です。
RstudioのGUIでディレクトリ（フォルダ）名やファイル名のフルパスを取得する

Rstudioでは、ディレクトリ（フォルダ）やファイルの選択ダイアログを表示させることが出来ます。
Mac版とWindows版で仕様が異なります。

| コマンド | Mac | Windows | Linux |
|--------------------------------|--------------------------------|----------------|------------|
| ディレクトリ（フォルダ）の選択 | dir.choose() ※関数の定義が必要 | choose.dir() | （未確認） |
| ファイルの選択 | file.choose() | choose.files() | （未確認） |

# Macの場合

## ディレクトリの選択

以下の関数を定義する。osascriptスクリプトを利用している

```
# directory choose
dir.choose <- function() {
  system("osascript -e 'tell app \"RStudio\" to POSIX path of (choose folder with prompt \"Choose Folder:\")' > /tmp/R_folder",
         intern = FALSE, ignore.stderr = TRUE)
  p <- system("cat /tmp/R_folder && rm -f /tmp/R_folder", intern = TRUE)
  return(ifelse(length(p), p, NA))
}
```

以下のコマンドを実行する

```
dirname = dir.choose()
```
ディレクトリ選択ダイアログが開く。ディレクトリを選択する

<img src="https://qiita-image-store.s3.amazonaws.com/0/278468/fa410fd7-5bfe-9080-d425-25cf771dea92.png" width=70%>

ディレクトリ名を確認する

```
> dirname
[1] "/Users/Username/Desktop/tmp/tmp/"
```

## ファイルの選択

Rstudioで以下のコマンドを実行する。file.choose関数は初めから定義されているので、新しく関数を定義する必要はない

```
filename = file.choose()
```

ファイル選択ダイアログが開く。ファイルを選択する

<img src="https://qiita-image-store.s3.amazonaws.com/0/278468/a4198998-4c95-82dd-6915-9621c2862c0c.png" width=70%>

以下のコマンドでファイル名を確認する

```
> filename
[1] "/Users/Username/Desktop/tmp/tmp.txt"
```

# Windowsの場合

## ディレクトリの選択

以下のコマンドを実行する

```
dirname = choose.dir()
```

ディレクトリ選択ダイアログが開く。ディレクトリを選択する

<img src="https://qiita-image-store.s3.amazonaws.com/0/278468/e8501463-6bc1-c37a-94b0-b2385c85aed5.png" width=50%>

以下のコマンドでディレクトリを確認する

```
> dirname
[1] "E:\\tmp"
```

## ファイルの選択

以下のコマンドを実行する

```
filename = choose.files()
```

ファイル選択ダイアログが開く。ファイルを選択する

<img src="https://qiita-image-store.s3.amazonaws.com/0/278468/4e414967-29e5-de21-da1f-31d00fca36c5.png" width=50%>

以下のコマンドでファイル名を確認する

```
> filename
[1] "E:\\tmp\\tmp.txt"
```

# Linuxの場合
未確認です。
スポーツをITする（４）動きの特徴を捉える OpenCV Python

スポーツ・ゴルフのフォームを捉えるもうひとつの切り口として、OpenCVのモーションテンプレートを使ってみました。
[こちらの記事](https://qiita.com/hitomatagi/items/a4ecf7babdbe710208ae)を参考にさせて頂いてます。ありがとうございます。

Pythonはほとんどコピーさせて頂いてます。映像は某女子トッププロの動画を利用しています。

## 特徴
ダウンスイング直前にて、クラブは上がっている（右の緑矢印）のに、腕（左の緑矢印）と体全体（真ん中の黄色い線）は、力が下向きに掛かっているのがわかります。
このことから、体を中心とした回転運動は、まず体が回った後、最後にクラブが付いて行くことがわかります。
この時、どのくらいのモーション座標の動きが最適であるか、またスイング全体でどのようなモーションの方向性を持てばよいのか、を[Posenet](https://qiita.com/Chishiki/items/d11906bc19158f23e724)も絡めながら今後探っていきたいと思います。

![スクリーンショット 2018-11-03 12.04.50.png](https://qiita-image-store.s3.amazonaws.com/0/74852/231aee76-e83c-4605-b9e1-497ab6c6c4a5.png) ![スクリーンショット 2018-11-03 11.13.05.png](https://qiita-image-store.s3.amazonaws.com/0/74852/9e781162-998e-02af-a6df-d486a5104f8b.png)
SORACOM LTE-M Buttonでストロングゼロを注文できるようにする

SORACOM LTE-M Buttonが届いたので使ってみました

![SORACOM-LTE-M_Button_01.png](https://qiita-image-store.s3.amazonaws.com/0/310137/5eead342-347b-4142-48d6-0762ab060b8d.png)

純正のAmazon Dash Buttonにストロングゼロボタンがないので，こいつを使ってワンクリックでストロングゼロが届くようにします

手順は以下の通り

# 1.予めAWS Lambdaで叩かれたら注文する関数を作っておく
Amazonのログイン時に確認コード要求されるページが出ることがありますが，
現状(2018年11月2日現在）その点を美しく突破して購入までこじつけるところまで行っておらず，
確認メールが来た時点でちょっと人手が要るものですが，ひとまずソースについては下記のページにまとめました

> AWS LambdaからAmazonの商品を購入する
> http://nc30mtd.oops.jp/blog/2018/11/aws-lambdaamazon.html

※色々解決できる方法は考えられるのですが，お手軽ベストプラクティスまでは至らず…

# 2.AWS IoT 1-Clickでデバイス登録する
こっちのページに書いてあったので参照しました
下記のページではスマホから登録してますが，QRコードが小さくてスマホから読めなかったのでPC版のコンソールから登録しました

> クラウドの知識なしで試せるIoTデバイス「SORACOM LTE-M Button」をAndroidスマホでセットアップする #soracom #あのボタン
> https://dev.classmethod.jp/soracom/setup-soracom-ltem-button-by-android/

# 3.登録したデバイスを有効化にする
AWS IoT 1-Clickコンソールの

>管理→デバイス

から当該デバイスの有効化を行います

# 4.登録したデバイスからLambdaを呼ぶようにプロジェクトを作成する
# 5.プロジェクトに対応するデバイスを登録する
コンソールでポチポチしたらできました


諸々設定したあとはこんな感じ

リージョンが何故かus-west-2になってますが，動作確認するにOKだったので気にしないで進めました

![Clipboard03.jpg](https://qiita-image-store.s3.amazonaws.com/0/310137/c35a5002-d9ff-c835-8184-9ef923773f7c.jpeg)




# 6.さいごに
それっぽく改造してみました

![Clipboard01.jpg](https://qiita-image-store.s3.amazonaws.com/0/310137/a97671bc-d148-afdc-07fc-e9fe9bfa2ea4.jpeg)


おしまい
Git Bash で error: xxx :Filename too long と表示されてはじかれるときの対処法



[こちら](https://stackoverflow.com/a/22575737/9316234)で言われている通りです。

Windows10の左下にある検索欄にGit Bashと入力し、出てきたGit Bashを右クリック->管理者として実行を選択します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/195174/6ce91c36-fd1d-d212-b728-bfce616a6298.png)

開いたターミナルで以下の一行を実行します。

```
git config --system core.longpaths true
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/195174/aacd1331-f3aa-50d5-e424-68f431e35dc6.png)


これだけです。
内線電話できる環境を作ってみましょう。(Asterisk FreePBX, raspbx, raspberryPi)

家で内線電話ができる環境を作るための手順を記憶するために作成した記事です。

主に参考になった記事は
＠katsuminさんのhttps://qiita.com/katsumin/items/22b13f780a37235d0b18
です。

1.準備物
raspberrypi (私はraspberrypi2を使いました。)
raspbxのimgファイル(http://www.raspberry-asterisk.org/downloads/)
Andoridかiosどっちかの端末(SIP電話の設定できる物ならいい)

2.raspberrypiにraspbxをinstall (mac基準)
　●　microSD cardを macに入れて(reader機などで繋いで)raspbxのimgファイルを書き込みします。

    diskutil list

diskListが表示されたら microSDCardを探してunmountしてください。
    
    diskutil unmountdisk /dev/disk2
imageを書き込みします。

    sudo dd if=./raspbx-06-03-2016.img of=/dev/rdisk2 bs=1m


3.SDCardをraspberryに入れて起動してください。 
● raspbxをupdateをする

    raspbx-upgrade

4.ifconfigを利用してraspberryのipを調べてFreePBXに接続してみてください。
http://xxx.xxx.xxx.xxx/admin/config.php
tf.custom_gradientで自作逆伝播

# はじめに
tf.custom_gradientを使えば簡単に自作の逆伝播ができることを知ったので紹介します。

# 逆伝播
機械学習民には説明が不要ですが、deep neural networkはいくつもの関数（層）をつなぎ合わせて推論する構造をしています。この層を訓練によっていい感じに調整していくのが深層学習です。
訓練時には、次のように、出力側から入力側へパラメータの更新方向を教えていきます。これを逆伝播（back propagation）といいます。
![backprop.png](https://qiita-image-store.s3.amazonaws.com/0/51820/59bf8462-3ed4-4488-e94b-42def1dd8985.png)


通常、逆伝播の計算はほぼワンパターンでライブラリがいい感じにやってくれます。
この記事は、TensorFlowで逆伝播をいじって遊ぶ方法を紹介します。

# tf.custom_gradient
自作の逆伝播を簡単に行うAPIとしてtf.custom_gradientが提供されています。これは次のようにデコレーターとして使います。

``` python
import tensorflow as tf


@tf.custom_gradient
def forward(x):
    y = x  # f(x) = xという関数の逆伝播を改造します

    def backward(w):
        return -w  # 通常wが逆伝播されるところを-wにする

    return y, backward
```

この例では、$f(x)=x$という関数の逆伝播を変更しています。
$w$が出力側から伝わってきた更新方向とします。$f$の部分を逆伝播させると、通常は$wf'(x)$が新しい更新方向です。$f(x)=x$の場合では$w$です。例では、この更新方向を$-w$に変更しています。

forwardの返り値は2つの値からなるtupleです。それぞれ、

* $f(x)$に相当する値
* 自作の逆伝播関数（つまり、$w$に対して$f$の部分を逆伝播させた新しい更新方向を返す関数）

です。
![custom.png](https://qiita-image-store.s3.amazonaws.com/0/51820/c9d6002f-a5b5-9112-5f9b-fd798f8f39fa.png)

# 実例
では、実際にこの自作逆伝播の効果を見てみましょう。
forward(x)をGradientDescentOptimizerでminimizeしてみましょう。通常であれば、xの値が減っていくはずです。

```python
x = tf.Variable(1.0, tf.float32)
y = forward(x)
train = tf.train.GradientDescentOptimizer(0.1).minimize(y)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for i in range(10):
        print(i, sess.run(x))
        sess.run(train)
```

結果は次のようになります。

``` text
0 1.0
1 1.1
2 1.2
3 1.3000001
4 1.4000001
5 1.5000001
6 1.6000001
7 1.7000002
8 1.8000002
9 1.9000002
```

minimizeしているにも関わらず、値が増えています。逆向きに更新するようにした効果が確認できました。


# 備考
## 他の方法
[https://qiita.com/jack_ama/items/8792ff2dcecfc90e029f](https://qiita.com/jack_ama/items/8792ff2dcecfc90e029f#%E7%8B%AC%E8%87%AA%E5%8B%BE%E9%85%8D%E5%AE%9F%E8%A3%85%E3%82%92%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%99)で紹介されているようなtf.RegisterGradientでオペレーションを変更する方法は、通常のオペレーションを書き換える強引な方法で普通は避けた方がいいでしょう。

## 実行環境
* python3.6.6
* tensorflow1.11.0

## リンク
* [公式ドキュメント](https://www.tensorflow.org/api_docs/python/tf/custom_gradient)
AWS エンタープライズサポート費用の計算

投稿内容は私個人の意見であり、所属企業・部門見解を代表するものではありません。

###自分用メモ
AWSエンタープライズサポートの考え方
エンタープライズサポートは、最小15,000 USD(約150万)となるが、一括請求しているAWSアカウントでエンタープライズサポート契約となっているものをまとめて計算することができる。つまり、２つエンタープライズサポート契約のAWSアカウントがある場合、一括請求した場合は、２つの合計の月額使用量に対してサポート費用が一度請求される。
https://docs.aws.amazon.com/ja_jp/awsaccountbilling/latest/aboutv2/consolidatedbilling-support.html

ビジネスサポートを比較してエンタープライズサポートを選択頂いたほうがサポート費用が抑えられる場合がある。

https://aws.amazon.com/jp/premiumsupport/pricing/
>
ビジネス
いずれか大きい方
100 USD または
- 以下の計算結果 -
月額 AWS 使用料のうち最初の0 – 10,000 USD の10%
月額 AWS 使用料のうち10,000 – 80,000 USD に対しては 7%
月額 AWS 使用料のうち80,000 – 250,000 USD に対しては5%
月額 AWS 使用料のうち250,000 USD を超える分に対しては3％

>
エンタープライズ
いずれか大きい方
15,000 USD または
- 以下の計算結果 -
月額 AWS 使用料のうち最初の 0～150,000 USD の 10%
月額 AWS 使用料のうち150,000～500,000 USD に対しては 7%
月額 AWS 使用料のうち 500,000～1,000,000 USD に対しては 5%
月額使用料のうち 1,000,000 USD を超える分に対しては 3%

###月額使用料が、10K USD の場合の例
ビジネスの場合、「月額 AWS 使用料のうち最初の0 – 10,000 USD の10%」に該当するのでサポート費用は、1K USD
一括請求していて、すでに月額使用料が150K USDを超えている状況でだと「月額 AWS 使用料のうち150,000～500,000 USD に対しては 7%」が該当するのでサポート費用は、0.7K USD加算される計算となる。
上記の場合、エンタープライズサポートで契約した方がサポート費用が低くなる。
Alexaスキル開発におけるaskコマンド集（ask-cli)

# 1. はじめに

---

## 参考文献
今回の『Alexaスキル開発におけるaskコマンド集（ask-cli)』は、2018年11月2日（金）にアマゾン目黒新オフィスにて開催された『Alexaハンズオントレーニング（中級）』で紹介された『ASK CLIの基本的な使い方』をまとめ直したものとなります。

---

## このスライドを見てできること
- Alexaスキル開発での、 askコマンド（ask-cli）が理解できるようになる。

---

# 2. askコマンド集（ask-cli)

---

## 2-1. スキルの新規作成
- このコマンドでは、HelloWorldのサンプルプロジェクトが新規作成されます。

```shell:Ubuntuコマンドライン
#作業ディレクトリ（任意）に移動
$ cd /mnt/c/Alexa

#スキルの新規作成
$ ask new
```

---

## 2-2. スキルをテプレートから作成
- このコマンドでは、コマンド実行時に選んだテンプレートのスキル新規作成がおこなえます。

```shell:Ubuntuコマンドライン
#作業ディレクトリ（任意）に移動
$ cd /mnt/c/Alexa

#テンプレート選択でのスキルの新規作成
$ ask new --template
```

---

## 2-3. スキルのデプロイ
- このコマンドでは、Alexaスキル（AlexaスキルおよびLambdaプログラム）をデプロイします。

```shell:Ubuntuコマンドライン
#作業ディレクトリに移動（プロジェクトディレクトリ内に移動してください）
$ cd /mnt/c/Alexa/HelloWorld

#スキルのデプロイ
$ ask deploy

#対話モデルだけをデプロイ
$ ask deploy -t model

#Lambdaプログラムだけをデプロイ
$ ask deploy -t lambda

```

---

## 2-4. スキルのクローン
- このコマンドでは、作成済みの既存スキルをローカル開発環境にコピー（クローン）します。

```shell:Ubuntuコマンドライン
#作業ディレクトリ（任意）に移動
$ cd /mnt/c/Alexa

#スキルのクローン（引数にスキルIDを指定すること）
$ ask clone -s amzn1.ask.skill.xxxxxx-xxxx-xxxx-xxxxx-xxxxxx
```

---

## 2-5. スキルの差分diff
- このコマンドでは、サーバ環境とローカル環境とのスキルの差分diffを表示します。

```shell:Ubuntuコマンドライン
#作業ディレクトリに移動（プロジェクトディレクトリ内に移動してください）
$ cd /mnt/c/Alexa/HelloWorld

#スキルの差分diff
$ ask diff -t all

#対話モデルだけを差分diff
$ ask diff -t model

#Lambdaプログラムだけを差分diff
$ ask diff -t lambda

```

---

# 3. トラブルシューティング

---

## 3.1 ask deploy でコケる場合

- 『ask deploy』または『ask deploy -t lambda』の実行でコケる場合、おそらくAWSコンソールから手作業で保存反映をしたことが原因で"revisionId"が変わってしまっている。
- 対応方法としては、プロジェクトディレクトリ配下の.ask/configファイルを開き、"revisionId": "XXXX" の設定行を削除＆保存してから、再度『ask deploy』または『ask deploy -t lambda』を実行すれば復活できると思います。

---

# 4. おわりに

---

## おわりに
みなさん、Alexaスキル開発におけるaskコマンド集（ask-cli)はいかがでしたか？ちゃくちゃくとAlexaスキルの機能がアップデートされていくなか、数多くのAlexaスキルを開発していくと、効率のよい開発方法をもさくしたくなることもあるかもしれません。みなさんの開発生産性の効率化に、すこしでもお役にたてば幸いです。
メリークリスマス！（Qiita Advent Calendar 2018）

2018/12/21 TAKAHIRO NISHIZONO
ハンズオン準備２：planet.osm.pbf を4096分割する

[ハンズオン準備](https://qiita.com/hfu/items/6026eec6816465d7e7a9)のその２です。ハンズオン準備記事の趣旨については[その1](https://qiita.com/hfu/items/9dfc0ec57c98dffe6f23)をご覧ください。

#大きな問題は分割する。地理空間情報なら空間的に
[https://planet.osm.org/](https://planet.osm.org/)　に示されているとおり、最近の　planet.osm.pbf は 42GB ほどあります。このくらい大きなデータをワンパスで通そうとするのは危険です。メモリあふれのような資源問題で失敗する確率が上がりますし、失敗した時の手戻りが大きくなりすぎたりするからですね。

情報工学の世界では、大きな問題は分割するのが定石です。地理空間情報は地理空間的に局所性があります。この局所性を生かして、データを空間的に分割しましょう。

とりわけ今回のハンズオンでは、$200 PC でもベクトルタイルの生産と消費ができることを実証したいわけですから、問題を適切に分割することは、非常に重要なことです。

今回のシナリオでは、いずれデータはベクトルタイルに分割します。であれば、ベクトルタイルと相性の良い分割の仕方をするのが良いです。つまり、ベクトルタイルの切り方と同じ流儀で切って分割しましょう。

#1024でも16384でもなく、4096に分割する。
全世界を、タイルの切り方と同じように分割することを考えます。つまり、z=0なら0分割、z=1なら4分割、z=2なら16分割です。一般には、4 ** z 分割することになります。

ここで、この指数関数の底が4なのが曲者です。地球全体を相手にする場合、現実的に選べるzは、具体的なユーザーストーリーにもよりますが、多くはありません。

ここでは、次のように単純に考えます。

いま、planet.osm.pbf は 42GB あります。z=5 を選んで1024分割すると、ざっくりと平均42MBくらいになりますね。osm.pbf 形式で42GBというと、ちょっと大きすぎるかもしれません。

z=6 を選んで4096分割すると、ざっくりと平均10MBくらいになります。このあたりがちょうど手頃かなと考えました。

z=7 を選んでしまうと16384分割することになります。ここまでたくさんに分けてしまうと、今度はファイルシステム上の取り回しだとか、進捗管理とかが難しくなりそうです。

というわけで、4096分割することにしました。

# 実装: osmium extract を呼び出すコード
実装ですが、ここは [osmium extract](https://github.com/osmcode/osmium-tool/blob/master/man/osmium-extract.md) を使うことにします。

世界全体を順番に z=6 のモジュールに分割するためのコードを、[GitHub](https://github.com/hfu/extract-all/blob/master/index.js)　に置いています。

# 運用: 実際に使うモジュールだけしか切り出さない
実際には、上記 index.js の実行には、非常に長い時間がかかります。一つのモジュールを切り出すのに、数時間程度かかるからです。

なお、config.json を工夫して、一回の実行で複数のモジュールを切り出すことを試みることができますが、私の環境では、一回の実行で切り出すモジュールの数を3以上にすると、メモリ不足で実行に失敗することがあります。このため、一回の実行でひとつのモジュールを切り出すようなコードにしています。

手元では、世界を覆う全数のモジュールを切り出そうとすることはせず、必要な少数のモジュールを切り出す作業をするようにしています。

ハンズオンはスリランカで行います。スリランカを含む z=6 タイルは、{z}-{x}-{y} という記法(*)で表現すると、[6-46-30](https://hfu.github.io/module-locate/#6/8.403/81.277) です。リンク先を辿っていただくと見えるように、ちょうどよく枠がはまっていますね。この先、6-46-30.osm.pbf を相手にしていきます。

（*) なお、この記法を what3numbers 記法と呼んでいます。

# 次回
次回は、6-46-30.osm.pbf を GeoJSON Text Sequence 形式に変換します。ハンズオン内部環境でどのように共有するかについても考えましょう。
絶対にやってはいけない InterstitialAd の実装例（AdMob）

血迷ってやっていたことのあるインタースティシャル広告のダメな実装例をさらします。
今は反省しています。 

# マネしちゃいけないコード
``` MainActivity.java
public class MainActivity extends AppCompatActivity {
    private InterstitialAd mInterstitialAd;
    private boolean exitFlg;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        exitFlg = false;

        MobileAds.initialize(this, "ca-app-pub-xxxxxxxxxxxxxxxx~xxxxxxxxxx");
        mInterstitialAd = new InterstitialAd(this);
        mInterstitialAd.setAdUnitId("ca-app-pub-yyyyyyyyyyyyyyyy/yyyyyyyyyy");
        mInterstitialAd.setAdListener(new AdListener() {
            @Override
            public void onAdClosed() {
                super.onAdClosed();
                // インタースティシャル広告が閉じられたらアプリを閉じる
                exitFlg = true;
                onBackPressed();
            }
        });
        if (new Random().nextInt(10) % 3 == 0) {
            // 40%の確率で広告ロード
            mInterstitialAd.loadAd(new AdRequest.Builder().build());
        }
    }

    @Override
    public void onBackPressed() {
        // Navigation Drawer などはなく、戻るボタン1回でアプリが閉じられる前提
        if (!exitFlg && mInterstitialAd.isLoaded()) {
            // 退出フラグが false で広告ロード済みならインタースティシャル広告を表示する
            mInterstitialAd.show();
        } else {
            // それ以外ならアプリを閉じる
            super.onBackPressed();
        }
    }
}

```
`exitFlg` 使わなくても、`onAdClosed()` 内で `super.onBackPressed()` を呼べばいいじゃんと今見て思いました。でも、試すのも無駄なので、実際に使っていたコードをほぼそのまま抜粋して載せます。お恥ずかしい。

# 何がダメなのか？
AdMob の[インタースティシャル広告の導入における禁止事項](https://support.google.com/admob/answer/6201362?hl=ja)には、次のように書かれています。

>インタースティシャル広告はアプリの読み込み時や終了時に表示してはいけません。表示が許可されるのはアプリのコンテンツ（ページ）が切り替わるタイミングのみです。また、端末のバックグラウンドで動作するアプリに広告を表示したり、アプリ環境の外部に広告を表示したりすることも許可されません。ユーザーには、広告がどのアプリに表示されたものかを明確に示す必要があります。

本当にその通りですね。ユーザビリティが最優先だと痛切に分かります。
アプリを閉じるタイミングは、他のアプリへ移るタイミングでもあり得ます。
その操作を邪魔するということは、ユーザーに不快感を与えますし、広告主の方にも迷惑をかけてしまいます。

# 何故やったのか？
少しでも収益が上がるかもしれないと欲に負けました。
他のアプリでもやっているものはあるし（AdMob を使っているかどうかは不明で、AdMob 以外の広告ネットワークでの規則は調べていなかったのですが）、表示頻度を下げれば大丈夫だろうと変に自分を納得させていました。
当時、上記の禁止事項も読んではいたのに自分がバカでした。
実験してみたい気持ちもあったので、やってみて判断しようというアホな思考で動いていました。

結果的にインタースティシャル広告での収益はほとんど出ず、「広告多すぎ」という星2個のレビューも付き、なんとなくアンインストール率も高いようでメリットはなかったと思います。
今は猛省しています。

# この記事を読んだ方は同じ過ちをしないように
自戒のためにも投稿していますが、読んでいただいた方でこれから何かしらの広告の実装を考えている方は私を反面教師にしてください。
ルールを守ってユーザビリティを高めましょう。
後悔先に立たずです。
Qiita には「いいね」ボタンがありますが、もしこの記事で「いいね」が付いた場合は「悪いね」として私は捉え、真面目な開発者となるべく、より一層精進していきたいと思います。

失礼いたしました。
【PHP7.0.x】if文で複数の値を比較するときスマートに書きたい

## 背景
フラグのどれか1つでも'1'だったら表示する、というロジックを組むときに
フラグがたくさんあった場合、そのままif文の条件にぶち込むと、かっこ悪い。

### かっこ悪い例

```php
@if ($user->sample1_flag === 1 || $user->sample2_flag === 1 || $user->sample3_flag === 1 ||
$user->sample4_flag === 1 || $user->sample5_flag === 1 || $user->sample6_flag === 1 || $user->sample7_flag === 1)
    <p>表示されたよ</p>
@endif
```

## 結論
in_arrayを使った。

```php
@php
    $sampleFlag = in_array(1, [
        $user->sample1_flag,
        $user->sample2_flag,
        $user->sample3_flag,
        $user->sample4_flag,
        $user->sample5_flag,
        $user->sample6_flag,
        $user->sample7_flag,
    ], true);
@endphp

@if ($sampleFlag)
    <p>表示されたよ</p>
@endif
```

ちなみに変数をあらかじめboolean型で扱うというのもリーダブルコードという点で良い。

## 余談
in_arrayの第三引数には極力trueを入れたほうがいいらしい

定義(PHP 4, PHP 5)

```
bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )
```

falseのままだと==チェック
trueにすると型チェック(===の比較)

詳しくは以下  
https://qiita.com/tadsan/items/2a4c3e6b0b74a408c038
S3バケット作成時のエラー

東京リージョンでs3バケット作成を試みたら下記エラー。

```bash
$ aws s3api create-bucket --bucket test-bucket --region ap-northeast-1
An error occurred (IllegalLocationConstraintException) when calling the CreateBucket operation: The a-northeast-1 location constraint is incompatible for the region specific endpoint this request was sent to.
```

awscliのhelpにもあるが`--create-bucket-configuration LocationConstraint`の指定が必要。


input

```bash
$ aws s3api create-bucket --bucket test-bucket --region ap-northeast-1 --create-bucket-configuration LocationConstraint=ap-northeast-1
```

output

```
{
    "Location": "http://test-bucket.s3.amazonaws.com/"
}
```
Alexaスキル開発におけるディレクトリおよびファイル構成図

# 1. はじめに

---

## 参考文献
今回の『Alexaスキル開発におけるディレクトリおよびファイル構成図』は、2018年11月2日（金）にアマゾン目黒新オフィスにて開催された『Alexaハンズオントレーニング（中級）』で紹介された『ファイル構成』をまとめ直したものとなります。

---

## このスライドを見てできること
- Alexaスキルを askコマンド（ask-cli）を利用し開発する際のディレクトリおよびファイル構成図を理解できるようになる。

---

# 2. Alexaスキル構成

---

## Alexaスキル構成

- プロジェクト名：hello-world

```text:ディレクトリおよびファイル構成図
hello-world/
  ├─ lambda/
  │  └─ custom/
  │     ├─ node_modules/
  │     ├─ index.js
  │     ├─ package.json
  │     └─ package-lock.json
  ├─ model/
  │  └─ ja-JP.json
  └─ skill.json
```

---

## 各種役割

|名称|役割|
|:--|:--|
|lambda|プログラムフォルダ|
|node_modules|使用するNodeライブラリ|
|index.js|音声プログラム本体|
|package.json|使用するライブラリ定義|
|package.json|ライブラリ依存関係定義|
|models|Alexaスキルフォルダ|
|ja-JP.json|インテント、スロット|
|skill.json|スキル公開情報定義など|

---

# 3. おわりに

---

## おわりに
みなさん、Alexaスキル開発におけるディレクトリおよびファイル構成図はいかがでしたか？ちゃくちゃくとAlexaスキルの機能がアップデートされていくなか、数多くのAlexaスキルを開発していくと、ファイル管理がおろそかになることもあるかもしれません。みなさんの開発環境の整理に、すこしでもお役にたてば幸いです。
メリークリスマス！（Qiita Advent Calendar 2018）

2018/12/21 TAKAHIRO NISHIZONO
ハンズオン準備１：ベクトルタイル内で OSM と相互参照なしに混ぜるデータに Share-Alike が適用されないと考えることの整理

# 「[ハンズオン準備](https://qiita.com/hfu/items/6026eec6816465d7e7a9)」シリーズ趣旨
2018年12月に実施される [OSGeo.JP Workshop for UN Vector Tile Toolkit - Let’s make sustainable web maps](http://www.foss4g-asia.org/2018/w11/) の準備をする中で、日本語で共有してみたいものをいくつか Qiita に書いてみたいと思います。

# ハンズオンのモデルストーリー
ハンズオンのモデルストーリーは、[OSGeo.JP の GitHub issues](https://github.com/OSGeo-jp/asia2018/issues/6)　で整理してみました。このモデルストーリーに肉付けする作業をこれからしていくことになります。

上記　issues で整理しているモデルストーリーの項目だけ引き写すと、次の通りになります。

1. ソースデータ(OpenStreetMapおよび地球地図)の入手・下処理（説明のみ）
2. 地物ストリームを処理しながら設計属性を付与
3. tippecanoe で mbtiles ファイルに変換
4. ベクトルタイルサーバ spinel でローカルホストにホスト
5. ローカルホストに設置した maputnik でスタイル付け
6. HTTPS, SPDY 又は HTTP/2 サーバで運用（説明のみ）

# 【今回作業】ODbL の Share-Alike は今回利用でトリガーされるか
ハンズオンでは OpenStreetMap データを使います。一般的には「(c) OpenStreetMap contributors」をつけることが、ライセンスを遵守するために必要なことと理解していますが、今回は、小縮尺では地球地図、大縮尺では　OpenSteetMap を使うということをするので、より詳細な検討が必要です。

小縮尺では地球地図、大縮尺では　OpenSteetMap を使うことで、地球地図データに ODbL の Share-Alike が発動するのか、ちょっと整理してみることにしました。

## Collective Database Guideline Guideline
こういうときには、[Collective Database Guideline Guideline](https://wiki.osmfoundation.org/wiki/Licence/Community_Guidelines/Collective_Database_Guideline_Guideline) をみるのかなと思います。これをみると、次のように書いてあります。

>an OSM dataset used in combination with a non-OSM dataset will be considered a Collective Database, and will not trigger share-alike when:
>the non-OSM and OSM datasets do not reference each other; or (以下略)

今回のハンズオンで、地球地図データと OpenStreetMap データが相互参照をしない限りは、地球地図データに対して Share-Alike が発動されないと理解することができます。

# 次回予定
次回は、planet.osm.pbf を 4096 分割したモジュールを作成する話を簡単に書くつもりです。
read_csvでファイルを読み込む


# 列のデータ型の指定(converters)

`read_csv`で読み込む際にconvertersを使うとデータ型を指定できる。
convertersに変換パターンを辞書型で渡す。

```
pd.read_csv('input_file.tsv', sep='\t', converters={'col_name_a':str, 'col_name_b':str})
```

通常は使うことはまず無いが、読み込みで以下のようなWarningが出た時に試すと良い。
warningの内容(パスはちょっと変更)

```
python3.7/site-packages/IPython/core/interactiveshell.py:2785: DtypeWarning: Columns (23,24,25,33,34,35) have mixed types. Specify dtype option on import or set low_memory=False.
  interactivity=interactivity, compiler=compiler, result=result)
```

ファイルは読み込めているのでWarningっぽい。

データフレームの内容を確認すると、文字列が入る列にNullの代わりに「Nan」という文字列が入っていたのでPandasがstrとfloatが混在する列だと判断したのが原因のようだった。
カラムの列数は出ているので該当箇所をすべてstrでしたらwarningは消えた。
UbuntuとRaspberry PiをUSB-TTLで接続する

UbuntuとRaspberry Pi 3をシリアルで接続したい。ディスプレイやネットワークを使わず、Raspberry Pi 3（のコンソール）を使いたい。Windows 10ではドライバをインストールする必要があったが、Ubuntuでは何も必要なかった。「[Ubuntu でラズパイとシリアル接続](http://dotnsf.blog.jp/archives/1071983142.html)」の通りにやったらなんの問題もなく接続できた。

# 手順

## RasPiでは、Bluetoothを潰してシリアルを使う設定に

[Raspberry Pi 3 シリアルコンソール＆シリアル通信](http://invalid-log.blogspot.com/2017/01/raspberry-pi-3.html)が詳しく解りやすい。

## /boot/config.txt

末尾に``dtoverlay=pi3-miniuart-bt``を追加した。

上記サイトでは、``enable_uart=1``を追加している。私は設定しなくてもシリアルコンソールが使えた。設定しなくても自動で認識するのかもしれない。

安定させるためには、``core_freq = 250``も設定したほうがいいみたい。設定しなくてもシリアルコンソールは使える。私としては、リアルタイム性の確認をしたいので、後で追加することとする。

## /boot/cmdline.txt

1行目は、末尾の``quiet splash plymouth.ignore-serial-consoles``を削除した。

```text:編集前（購入直後）
dwc_otg.lpm_enable=0
console=serial0,115200 console=tty1
root=PARTUUID=f8d5a75e-02 rootfstype=ext4
elevator=deadline fsck.repair=yes rootwait
quiet splash plymouth.ignore-serial-consoles
```

```text:編集後
dwc_otg.lpm_enable=0
console=serial0,115200 console=tty1
root=PARTUUID=f8d5a75e-02 rootfstype=ext4
elevator=deadline fsck.repair=yes rootwait
# これも設定したが要らないかもしれない。
dhci_bcm2708.enable_llm=0
```
``console=serial0,115200``は削除しなくてもシリアルコンソールは使えている。

``serial-getty@ttyS0.service``を止めなくてもシリアルコンソールは使えている。

## RasPiとホストをUSB-TTLケーブルで接続する（ホスト）

Ubuntuでデバイスが認識されているか確認する。

```bash
ls -al /dev/tty* | grep USB
# /dev/ttyUSB0
ls -l /dev/serial/by-id/
# usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0 -> ../../ttyUSB0
sudo chmod 666 /dev/ttyUSB0
```

## ターミナルを用意する（ホスト）

```bash
sudo apt install cu
```

## 接続（ホスト）

```bash
sudo cu -s 115200 -l /dev/ttyUSB0
# 終了するときは「~.」と入力。
```

# 参考

  * [Ubuntu でラズパイとシリアル接続](http://dotnsf.blog.jp/archives/1071983142.html)
  * [Raspberry Pi 3 シリアルコンソール＆シリアル通信](http://invalid-log.blogspot.com/2017/01/raspberry-pi-3.html)
slackのルールみたいなもの

この記事は，[研究室slack化のすすめ](https://qiita.com/nkchan/items/04ae0f0cdc61346cd804) の続編です．


slack導入から半年くらいたって，研究室内では，いい感じにみんなが使ってくれるようになってきたのでここらへんで，最低限のポリシーを展開しておいて，
来年度に備えようかなと思っています．


# ルールに共通すること
**「見えるところで話をしましょう」**です．

どんな些細なことも見えるとこで言いましょう．

というか会話もブロードキャストなんだから，チャットもブロードキャストでいいのでは？という感想も個人的にはあります．


ではでは以下からルール

## プライベートチャンネルは作らない
これは組織の構造にもよりますが，基本的に同一組織の人しかworkspaceにはいないので別に見えても問題はないでしょう  

情報をオープンにするという点でもプライベートチャンネルは邪魔です．

むしろ，ちらっと入ってきて，そこがなにをしているか知るというの使い方大歓迎です．

## パワポアップロードしないこと
これはwindowsとかmacとかだと，なんでや，みたいになるかもしれません．

**Linuxの人もいるんですよ!!**

言いたかっただけで，本筋はここではなく，

- パワポを見るのがメインなのにDLをさせられる．
- 最新版ができて，またDLすることで複数Versionのパワポが端末内に存在してしまう．

こういう理由から，パワポのアップロードではなくpdfを上げてほしい．

もしもpptxのファイルが必要になったらcloudとかに上げたらいいと思います．


## スレッドを使う
これは

- 極端な速度でTLが流れないようにさせる
- 複数の話題が同時進行しても話がごちゃごちゃにならない

という2点を考慮してます．話の流れも見やすいですしね．

んで，もう一度その話題で話があるときは，以前の話をshareしたらいいと思います．

## DMを使わない
**DMでやりとりするのは悪口とパスワードだけにしましょう**

これくらい縛りを入れてないと **なんでslackなんですか，LINEじゃだめなんですか** と言われてしまう．

たかが2人の日程調整もみんなで見えるところでやるだけで．まわりや上司(ここ大事)が「あー　ここで作業するのね」と把握することができる．(スレッドでやればTLも荒らさないし)

これの意見が聞きたい．わからんからききたい，みたいなのがあっても絶対分かる人にDMするのではなく，みんなの見えるとこで聞くことでその人が反応できなくても，他の人が反応するかもしれない．(どんなことで困っているかもわかります)
その会話のやりとりを見た人が新たな知見を得るかもしれない．

これをDMでやってしまうと自分しか，何かを得られないのでもったいない．

誰か一人に頼るのではなく，みんなに頼りましょう

## 通知をしましょう
反応してほしいことや，大事なことにはメンションをつけましょう．

これで，通知がなくて気づけなかったみたいなことが防げます．

別に気づかなくていいことはメンションなくていいのですが....


# ここからは，しなくてもいいけど守ってくれると嬉しいし，便利
## メッセージを変更しない
一文字くらいのtypoの修正はいいですが，例えば，集合時間が変更になったから編集したりということが見受けられました．

編集しても通知は飛びません．みんなは変更した時間にあつまることができません．

## リマインダーを使う
用事の前日に手動でリマインダーを飛ばしてるところをよく見ました．

すごいなぁ　俺はめんどくさくてやりたくないなぁという側の人間です．

なので日程が確定した時点でリマインドの設定をして，投稿したい時間にslackbotくんにお任せしてます．

リンクは参考文献に

# 最後に
とりあえずこんな形で書いてみました．身内だけでなく，いろいろな組織，会社のかたからも，うちはこうしてるよみたいなのを是非教えていただけると幸いです．

ps: アイコンの設定してないひとはなんでもいいからしてくれるといいなぁと思う
# 参考文献
[Slack運用時に企業が決めている、やっていいこととダメなこと](https://businesschatmaster.com/slack/slack-unyou-kigyou)
(一概にいいこと，悪いことと言い切るのもどうかと思うけど，まあ言ってることは今回の記事と同じなので載せました．)


[リマインダーの設定をする](https://get.slack.help/hc/ja/articles/208423427-%E3%83%AA%E3%83%9E%E3%82%A4%E3%83%B3%E3%83%80%E3%83%BC%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B)

[slackのリマインダー設定方法まとめ](https://businesschatmaster.com/slack/slack-reminder)
WebサイトのUI/UXデザイン – ソーシャルアカウントでのログイン方法は一択にしなさい (初期登録のハードルをゼロにする)(ScrapBoxの例)

# 題材

[Scrapbox](https://scrapbox.io/)

# サービストップ

「はじめる」ボタンがある。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/6c5acbc6-7ad3-7d8f-0e2b-140fbc21e9ee.png)

これを押すとGoogleアカウントのログイン画面に飛ばされる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/fbb97693-d144-ff54-c016-5d748cf29830.png)

# すごい！

あとから思い出して「あれ、俺なに経由でアカウント作成したっけ‥？」と分からなくなって、確認したぐらい。

何がすごいか分かるだろうか。

まず、サービストップにはGoogleアカウントの「ぐ」の字もないということだ。

これはサービス側が狙っていないと出来ない作りだ。

# ユーザーが迷う選択肢がない

すごいのは「ユーザーが登録方法を一切迷わなくて良い」ということ。

普通、ソーシャルログインというと、いくつかの選択肢があるのが普通だ。

- どのソーシルアカウントで登録するの？ Googleアカウントなのか、Facebookアカウントなのか、Twitterアカウントなのか。
- それともメールアドレスで登録するのか。
- いずれかの方法で登録したとして、それを今後、覚えておけるのかどうか。

この選択肢があるだけで、ユーザーに「迷いのコスト」＝「初期登録のハードル」を上げている‥！ ということに、今回逆に気づいた。

ソーシャルログインはなんでもかんでも、種類を用意すれば良いというわけではないという教訓になった。

# 1種類 VS 2種類以上で圧倒的に違う

- ログイン方法が1種類
- ログイン方法が2種類、3種類、4種類

この前者と後者では、まったく違う。

前者は「全くユーザーが選択しなくて良い」。
後者は「ユーザーが何らかの選択をおこなう」。

ユーザーが「選択する余地」を0%にすることで、選択のハードルを下げるどころか、ゼロにしてしまうことが出来る。

# 1種類にできる場合、出来ない場合

このサービスでは「Googleアカウントを持ってない or 作りたくないユーザー」を切り捨てる覚悟が出来ている。

おそらく「想定ユーザーのほとんどはGoogleアカウントを持っている or 作成ぐらいはする」という「想定」があるはずだ。

その上で「ユーザー選択肢を減らす」という「サービス上の選択」をしているわけだ。戦略的にトレードオフをおこなっていると思われる。

# ということで

実際にサービスを使い始める前に、UXすごいなと思ったのでQiitaしてみた。

# 参考

- [エンジニアのアウトプット？Scrapboxで決まりでしょ！ - Qiita](https://qiita.com/Tommy_/items/f881c1658dfe02f65b69)








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
jsdoでtensorflow.js その16

#概要

jsdoでtensorflow.jsやってみた。
dqn見つけたので、やってみた。

#写真
![image.png](https://qiita-image-store.s3.amazonaws.com/0/18104/f100a4e3-37db-1e3d-e490-847004003e97.png)


#成果物

http://jsdo.it/ohisama1/IxzV

以上。
プログラムとバイナリ

@kazuki_sumi さんの『[「プログラミング言語」って何？](https://qiita.com/kazuki_sumi/items/aa6e401ac3bab0cac618)』の記事に[コメント](https://qiita.com/kazuki_sumi/items/aa6e401ac3bab0cac618#comment-95bca46bb8326b7bf8d5)したのですが、せっかくなので記事にさせていただきます。

# プログラム

「プログラム (program)」の語源は、pro-gram、pro-=前/先に、gram=文/書を書く。事前に書く、実行/実演する前に書いたもの、これから実行/実演する内容。
運動会でこれから子供たちが実行することが書かれているプログラム。
演奏会でこれから実演する内容が書かれているプログラム。
コンピュータにこれから実行させることが書かれているプログラム。

# コンピュータ

コンピュータの動作原理は、電気を流すか流さないかで電球を点灯・消灯させるようなもの。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/29070/f5381849-6358-9a47-5d4e-4c71f2c2779d.png)

電球をディスプレイのドットにして、ドットに赤緑青(RGB)の色を付けて無数に並べ、オンオフで明るさを調整して、フルカラー動画を見せることができる。
スピーカーにつなげて音を鳴らしたり、ネットワークに信号を流して通信したり、すべて電気のオンオフで仕事してる。

# バイナリ

電気の オン か オフ、それを数値の 1 と 0 で表現。
1 か 0 を並べた数値は「2進数=バイナリ=binary」。bi=2、2輪＝バイク、バイシクル。
1 か 0 かの情報1個を「ビット」。4個で「ニブル」、8個で「オクテット」。「[バイト](https://ja.wikipedia.org/wiki/%E3%83%90%E3%82%A4%E3%83%88_(%E6%83%85%E5%A0%B1))」はアーキテクチャ依存だったけれど、現在は8ビット=1バイト。
「ニブル」で表現できる2進数は 0000 ～ 1111。10進数にすると 0 ～ 15、16進数にすると 0 ～ F (0～9とA～Fの16個を使用)。
2進数で表現すると長くなるから、2進数8桁を16進数2桁に短くした表現が使われる。
16進数は「ヘキサデシマル=hexadecimal」。「hexa」は6、「deca」は10だけど、「hex」だけで16進数という意味に使われる。
hexagon＝6角形、deciliter＝10ml、decade=10年=一昔。december=旧10月=現12月。

# 機械語

コンピュータに仕事をさせるために0と1の組合せで作った「命令」が「機械語」。
8ビットCPUであれば、8ビットの組合せで様々な命令が作られている。64ビットCPUであれば1命令64ビット。
機械語はバイナリ(0と1の羅列)なので、機械語命令を保存した実行ファイルを「バイナリファイル」と呼んだりもする。

# プログラミング言語

機械語は人間が理解しにくいので、機械語と1対1で文字にしたのが「アセンブリ命令」「ニーモニック」。
機械語/アセンブリ命令は単純な仕事をさせる命令。単純な命令を組み合わせて複雑な仕事をさせる。
複雑な仕事を機械語/アセンブリ命令でプログラムすると膨大になり、人間が理解するのが難しい。
複雑な仕事を人間が理解しやすいように書ける多種多様なプログラミング言語が存在する。
フォルダにファイルが追加されたら通知するAppleScript

## フォルダアクション  
macOSには**フォルダアクション**という機能があり、設定したフォルダに対しなんらかのアクションがあった際にスクリプトが発火します。今回はその中でファイルやフォルダが追加されたときに動作する**adding folder items**を利用したいと思います。（notificationがFAXになっているのはTwitterのTLで見かけたから……）


## 設定  
**/Library/Scripts/Folder Action Scripts/**に下記スクリプトを任意の名前で保存します。  

アクションを設定したいフォルダを選択し、コンテキストメニューから**フォルダアクション設定...**をクリック。（スクリーンショットではinフォルダに設定）
![コンテクストメニュー](https://qiita-image-store.s3.amazonaws.com/0/7001/5d7d3b42-53e9-c3e9-c27a-bb11764ef3fa.png)  

先ほど保存したスクリプトを選択し関連付けすれば設定終了です。
とっても楽チンにフォルダ監視ができました。
![フォルダアクション設定](https://qiita-image-store.s3.amazonaws.com/0/7001/75b24fa6-91a3-abcb-5e3e-f14add831648.png)

他にも、フォルダ内のファイル等が削除されたとき、フォルダを開いたとき・閉じたときに動作するのもありますので[公式サイト](https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/reference/ASLR_folder_actions.html)をご参照してください。

## サンプルコード

``` AppleScript
on adding folder items to theFolder after receiving theList
	
	set timestamp to my getTimestamp()
	set moveFolder to POSIX path of (path to desktop) & "out/" & timestamp
	my makeFolder(moveFolder)
	
	my moveFiles(POSIX path of theFolder, moveFolder)
	
	display notification "FAXが届きました" with title "FAX受信" subtitle "" sound name "Ping"
	
end adding folder items to

on moveFiles(addFolder, moveFolder)
	do shell script "mv " & quoted form of addFolder & "*" & space & quoted form of moveFolder
end moveFiles


on getTimestamp()
	do shell script "date +%Y%m%d_%H%M%S"
end getTimestamp

on makeFolder(moveFolder)
	do shell script "mkdir -p " & quoted form of moveFolder
end makeFolder
```
SORACOM LTE-M ButtonでChaosMonkey

# はじめに
タイトルそのままですが、SORACOM LTE-M Buttonをクリックすることで、ChaosMonkey的にランダムにEC2インスタンスを落とすようにしてみました。
一応障害テストにも使えますが、「押すなよ押すなよ」的な使い方に最適かと思われます。

#実装
##　クリック時の動作
シングルクリックで1インスタンス、ダブルクリックで2インスタンス、ロングクリックで3インスタンスがterminateされます。
実装によっては、ロングクリックで全消し、というバルスボタンを作ることも可能です。

## ボタンのセットアップ
ボタンを1Clickサービスに登録してアクションを紐づけるところまでは、こちらのエントリに詳しく書かれています。
https://dev.classmethod.jp/soracom/setup-soracom-ltem-button-by-android/

こちらのエントリでは、SMSを送信するアクションを選択していますが、今回は以下で実装するLambdaを選択します。

## AWS Lambdaの実装
Javaで書いてありますが、このような実装になります。

```java
public class ChaosMonkeyButton implements RequestHandler<ClickEvent, String> {

  AmazonEC2 ec2;

  public ChaosMonkeyButton() {
    ec2 = AmazonEC2ClientBuilder.standard().withRegion(Regions.US_EAST_2).build();
  }

  @Override
  public String handleRequest(ClickEvent input, Context context) {

    DescribeInstancesResult describeInstances = ec2.describeInstances();

    //terminateするインスタンス数をクリックタイプによって変える
    int terminateNum = input.deviceEvent.buttonClicked.clickType.ordinal() + 1;
    context.getLogger().log("terminateNum:" + terminateNum);

    //インスタンスリストからランダムにterminate対象を取り出す
    List<Instance> terminateList = describeInstances.getReservations().stream()
        .flatMap(res -> res.getInstances().stream()).filter(this::isRunning)
        .collect(Collectors.collectingAndThen(Collectors.toList(), collected -> {
          Collections.shuffle(collected);
          return collected.stream();
        })).limit(terminateNum).collect(Collectors.toList());

    if (terminateList.isEmpty() == false) {
      //インスタンスをterminate
      List<String> idList = terminateList.stream().map(t -> t.getInstanceId()).collect(Collectors.toList());
      idList.stream().forEach(i -> {
        context.getLogger().log("terminate " + i);
        ec2.terminateInstances(new TerminateInstancesRequest().withInstanceIds(i));
      });
    } else {
      context.getLogger().log("There are no running instances");
    }

    return "OK";
  }

  private boolean isRunning(Instance instance) {
    return InstanceStateName.Running.toString().equals(instance.getState().getName());
  }
}

```

ソースコードやビルドスクリプトは以下に置いておきます。リクエストは1Clickボタンで共通なので、Javaの方であれば簡単にカスタマイズできると思います。
https://github.com/c9katayama/soracom-lte-m-button-lambda

## 動作確認
先輩、システム構築終わりました！！
![スクリーンショット 2018-11-03 9.56.14.png](https://qiita-image-store.s3.amazonaws.com/0/43668/eeec938b-da10-b600-f1d7-875340601593.png)


おー、よくできたね。どれどれ　ポチー(ロングクリック）
![15411830590660.jpg](https://qiita-image-store.s3.amazonaws.com/0/43668/b131bcac-80cc-5eed-7111-07e2cbc40ce9.jpeg)

ギャーーー！
![スクリーンショット 2018-11-03 9.56.48.png](https://qiita-image-store.s3.amazonaws.com/0/43668/c548b5ad-6eb7-9848-947c-f7d6896989da.png)

#おわりに
今回は、EC2を落とすという使い方でしたが、SORACOM LTE-M ButtonはLambdaを直接叩けるので、適切にLambdaにロールを割り当てることで、自分のAWS環境のリソースをボタンクリックで変化させることができます。
例えばセキュリティグループを一瞬開けるとか、IAMに権限を一時的に付与するといった、承認を得て作業するようなシチュエーションの場合に、ハンコを押す感覚で上司が操作できるのは面白いかなと思いました。
またボタンの場合、認証はハードウェアに内蔵されたeSIMに任せることができます。このため、例えばボタンを押す人を変える場合も、AWSのクレデンシャルやその他の認証情報を人に渡す必要がなく、複数人で利用するようなユースケースでは便利に使えるケースもありそうです。
pythonで東証から株価をAPI取得して、データをChartに表示させる

# はじめに
めざせ不労所得！目指せ億り人！目指せ、現代のゴールドラッシュ！
という前置きはさておき、普段はPythonでプログラムを書いています。

株価を取得して、機械学習して、株価予測のプログラムなり、Webサービスってできないかな？
と業務中に思い立ちました（パチパチ）

さらっと調べて、とりあえず株価をAPIでとってグラフ表示するまではできたので、
メモ程度にQiitaに置いときます。

今後は機械学習ライブラリと組み合わせてデータを予測対象とする予定。
webアプリ化なども検討か。。？

まずはグラフ表示
# こんな感じ
![persol_stock_ave.png](https://qiita-image-store.s3.amazonaws.com/0/190712/01de0570-7dd3-1bcd-47f7-242a88952971.png)

# ソースコード
以下で動きます。

```python:chart.py
import quandl
import pandas as pd
import  matplotlib.pyplot as plt

quandl_data = quandl.get("TSE/2181")
quandl_data.to_csv('Persol Data.csv')

stock = pd.read_csv('Persol Data.csv')

stock['100MA'] = stock['Close'].rolling(window = 100, min_periods=0).mean()
stock['200MA'] = stock['Close'].rolling(window = 200, min_periods=0).mean()

fig = plt.figure()

axes = fig.add_axes([0.1, 0.1, 0.8, 0.8])

axes.plot(stock['Close'][-365:], 'black', lw = 1)
axes.plot(stock['100MA'][-365:])
axes.plot(stock['200MA'][-365:])
axes.set_xlabel('Time')
axes.set_ylabel('Price')
axes.set_title('Persol Holdings(2181) 1 Year')
axes.legend()

plt.show()
```
## ライブラリについて
- API取得先:quandl
- データ保存・整形:pandas
- データ表示:matplotlib

## Quandlについて
Quandlは、世界の金融情報や統計情報をまとめているサイトです。
大きな特徴として、各種情報を取得するためのPythonやRubyのAPIを提供しており、しかもかなりの部分を無料で使用することができます。
日本の金融関係のサービスではAPIを提供しているものは少なく、あったとしても有料であることがほとんどです。

Quandlで取得できる情報の大部分は外国株式や海外の統計情報ですが、実は日本株も取得する事ができます。
東証がデータを提供していて、API経由で東証のデータ（日経平均や各種日本株式）を取得できます。

QuandlからAPI経由でデータを取得する前準備として、APIキーを発行する必要があります。Quandlのサイトで無料会員登録を行い、事前にAPIキーを入手してください。
Javaの開発環境をEclipseから変更するとしたら

最近の仕事で使っている言語は、JavaとJavaScriptなんだが、その開発環境はWindows7のeclipse3.7という「枯れた技術こそ至高」とか「実績ある環境しか認めません」って感じの**堅実な**開発環境だ。

うちの職場の時代遅れ自慢をするなら勝ち残る自信がかなりあるんだが、そのたびに虚しくなる。そんな現状を打開したくてならないので、今回はJava/JavaScriptの開発環境をいまどきなものに一新することを考えてみた。

# IntelliJおすすめだよ
知ってる。
個人で使う分にはいいんだが、仕事で使うとなると別。残念だが、Eclipseに比べると明らかに実績がないため、うちの職場では広まらないだろう。
納品先に開発環境まで報告しないといけなかったり、開発風景を査察に来たり、とんでもなく品質にうるさいお客さんを相手にするとおとなしく今までどおりEclipseを使えばいいや、ってみんな妥協する。
有償版を利用するのであればあるいは、とは思うのだが、そこにかかる費用対効果の証明が・・・とかまた別の問題が出てきそう。

# NetBeansは？
ひとつの案ではある。公式のIDEだし、堅実重視の開発環境の一つとも言えるだろう。デフォルトで用意されているサンプルプロジェクトが多いのも嬉しい。
ただ、なぜGradleはデフォルトで対応していないのかがちょっとだけ気になった。MavenとGroovyはデフォルトで対応しているのに。

# 最新のEclipseを使えば問題解決では？
たしかに、それだけで十分なんだが、JavaScriptの開発を兼任させようとすると好きになれない。.jsファイルを編集しているとなんとも言えない重さを感じる。補完も中途半端だし、フォーマッターが効いてくれなかったりもする。

あと、EclipseでTypeScriptの開発したときは、補完が本当に遅くてイライラした。Visual Stuido 2015でTypeScript書くと、めちゃくちゃ気持ちよく書けるので、それを知ってしまうと二度とEclipseでTypeScriptは書かないだろう。

# 今後に期待のVisual Studio Code
密かに期待しているのはこれ。実態はテキストエディタであってIDEではないが、Visual Studioのネームバリューは嬉しい。TypeScript/JavaScriptの開発は申し分ないので、Javaの開発環境がどれくらい強力になるかが鍵だと思う。

早速Java Extension Packをインストールして試してみた程度だが、機能的には問題なさそう。ただ、画面の表示がリアルタイムではないのが気になった。
言葉では伝えにくいが、変数`aaa`を`bbb`にリファクタリングしたくて、`bbb`の最後のbを入力してEnterを押したのに、画面上はまだ`aaa`のままの表示になっていて、変更されたように見えない（表示が反映されていない）。
けど、ファイルを閉じようとすると「変更を保存しますか？」と聞いてくるので、内部的には更新された状態のようだ。ここで保存して開きなおすと`bbb`にちゃんとリファクタリングされている。
おそらく本格的に使い始めればもっとたくさん気になる点が出てくるだろう。

いずれにせよ、VSCode自体の成長がまだまだ止まらないと思うで今後に期待したい限りだ。
ruamel.yamlで順序を保持してyamlファイルの入出力を行う

# 概要
## やりたかったこと

yamlファイルの一部だけを変更して、別のyamlファイルとして出力する

## ruamel.yamlについて

- ruamel.yaml は PyYAML のフォーク。PyYAMLに比べてこまめにアップロードされている
- コメント保持にも対応している

# 実行環境
- python 3.7.1
- ruamel.yaml 0.15.76
- Windows10 Pro
- Visual Studio Code

# 実装

インストール

```shell
pip install ruamel.yaml
```

スクリプト

```python
from pathlib import Path
from ruamel.yaml import YAML, add_constructor, resolver
from collections import OrderedDict


# 入力時に順序を保持する
add_constructor(resolver.BaseResolver.DEFAULT_MAPPING_TAG,
    lambda loader, node: OrderedDict(loader.construct_pairs(node)))

yaml = YAML()
yaml.default_flow_style = False

# ファイルから入力
with open(Path("in.yaml"), 'r', encoding='utf-8') as f:
    data = yaml.load(f)
    # 色々項目を変更する
    # (略)

# ファイルに出力。出力順序はデフォルトで保持される
with open(Path('out.yaml'), 'w', encoding='utf-8') as f:
    yaml.dump(data, f)
```

# 参考記事
- [ドキュメント](https://yaml.readthedocs.io/en/latest/index.html)
- [リポジトリ](https://bitbucket.org/ruamel/yaml)
- [【PyYAML VS ruamel.yaml】PythonからYAMLファイルを触ってみた](https://dev.classmethod.jp/server-side/python/getting-started-with-pyyaml-and-ruamel-yaml/)
- [PyYAMLで順序を保持して読み込む](https://qiita.com/tkyaji/items/842840fa090fb7c6a095)
- [PyYAMLでyamlをload/dumpする時の振る舞いを変えてみる方法とその詳細について](https://qiita.com/podhmo/items/aa954ee1dc1747252436)
php-master-changes 2018-11-02

今日は死ぬほどエモいコミットと ext/opcache の組み込み関数呼び出し最適化のバグ修正があった！

# 2018-11-02
## zsuraski: Update email addresses.  We're still [@Zend](), but future proofing it...
- https://github.com/php/php-src/commit/54dc07f3dc9fa2fcfeb2d2c6aebf79bd34ab041c
- [Zend](https://ja.wikipedia.org/wiki/%E3%82%BC%E3%83%B3%E3%83%89%E3%83%BB%E3%83%86%E3%82%AF%E3%83%8E%E3%83%AD%E3%82%B8%E3%83%BC%E3%82%BA)（を 3 年前に買収した [Rogue Wave](https://www.roguewave.com/)）を退職することになった Zeev と Dmitry、及び一足早く 2 年前に退職して今は [AWS](https://aws.amazon.com/) にいる Andi のメールアドレスを、zend.com から php.net のものへ変更
- 20 年以上前のこと、当時イスラエルの学生だった Zeev と Andi が PHP の生みの親 Rasmus のとこに殴りこみをかけ、PHP 3 を開発（元の PHP/FI 2.0 がびみょかったので）
- PHP 4 で更に書き直したエンジンを、Zeev の Ze と Andi の nd から Zend Engine と名付ける
- Zeev と Andi で Zend Technologies を創業
- PHP 5 が出たり 6 が出なかったり 7 が出たりしつつ、 PHP はだいぶ普及
- 2015 年に Rogue Wave が Zend を[買収](https://www.roguewave.jp/company/news/2015/zend-acquisition)
- 2016 年に Andi が[退職](https://www.linkedin.com/pulse/starting-new-journey-andi-gutmans)
- 時期は分からないがこれから Zeev も[退職](https://zsuraski.blogspot.com/2018/10/the-future-of-zend-engine-and-zend.html)
- 今後たとえ Zend の名前は残ったとしてもそこに Ze と nd はおらず、これからの Zend Engine を改修するのももはや Zend の中の人ではない
- という、死ぬほどエモい色々が詰まっているような**気がする**、[12 年ぶりくらい](https://github.com/php/php-src/commits?after=429c5a0a82d211cc90756c72570531ed2a53ab2b+0&author=zsuraski)のコミット
- なお Zeev 自身は今現在特にコード触ってないので、Zend Engine の開発には Dmitry が今後もフルタイムで開発に関われるかの方が大事かもしれず

## zsuraski: Future-proof email addresses...
- https://github.com/php/php-src/commit/67e0138c0dfd966624223911a0821f6c294ad1c6
- [7.3~]
- エモさが足りなかった
- Zend ディレクトリ下以外のファイルについても同様にメールアドレスを変更

## nikic: Fixed bug [#77092](https://bugs.php.net/bug.php?id=77092)
- https://github.com/php/php-src/commit/4daa413898948dad90bc797ccab200115326efc7
- [7.2~]
- ext/opcache で、opcache が有効な場合に [array_diff_key()](http://php.net/manual/ja/function.array-diff-key.php) で SEGV が出る問題の修正
- [SSA](https://ja.wikipedia.org/wiki/%E9%9D%99%E7%9A%84%E5%8D%98%E4%B8%80%E4%BB%A3%E5%85%A5) を入れて[導入](https://github.com/php/php-src/commit/2a286ad5991ba06385b11e31dfdf59a31badb7b6#diff-fda74c110719855bc66cd828578e87ac)した [SCCP](https://ja.wikipedia.org/wiki/%E7%96%8E%E3%81%AA%E6%9D%A1%E4%BB%B6%E5%88%86%E5%B2%90%E3%82%92%E8%80%83%E6%85%AE%E3%81%97%E3%81%9F%E5%AE%9A%E6%95%B0%E4%BC%9D%E6%92%AD) 最適化コードのバグ
- opcache はスクリプトのコンパイル時にキャッシュへコンパイル済のオペコードを保存するが、保存前に幾つかの最適化を行う
- 超雑に言うと、定数引数での一部組み込み関数呼び出しをコンパイル時（オペコード生成後の最適化フェーズ）に行って定数畳み込みを行うような処理があり、この関数呼び出し部分の処理がバグっていた、んだけど、多くの組み込み関数は [fast_zpp](https://wiki.php.net/rfc/fast_zpp) へ移行済だったことでこのバグの影響を受けず、移行していなかった array_diff_key() では SEGV につながった、みたいな感じかな
- EG(current_execute_data) が旧来の zend_parse_parameter() 内で参照されており、このバグは関数呼び出し時に EG(current_execute_data) を適切に扱っていないというものだった
- その理屈だと他に fast_zpp に移行してなくてこの最適化の対象となる関数があるとダメそうだけど、何かあるのかなあ
hello again

#how much *iq* is needed for the following:
0.just being able to use emacs (casuals)
    ex: using built in programs (calc, calendar, etc.)
1.customizing emacs using internet searches (serious users)
    ex: setting variables and global keys
2.customizing emacs by configuring packages (professionals)
    ex: custom abbrev tables, font locks, fixing broken code if necessary
3.customizing emacs by writing own lisp (hackers)
    ex: macros, shell calls, defadvices

do you think its **iq** or **experience**, or little bit of both?

serious users are programmers of other languages and often experts of other engineering disciplines (electrical, mechanical, chemical, etc).  they have high iq by their trade.

professionals are routine workers with high skills, often dedicated to office automation.  these days, reading/hearing english is becoming a requirement, another factor pushing iq upward.

for doing productivity enhancing customizations, i think you need to be a hacker level.  this is where the question of iq becomes important; for all honesty, i think you need around 120 (top 10% of population).
Windowsバッチでファイル内の特定文字を置換する方法

# はじめに
今回ファイル内の特定文字を置換したい時に使えるWindowsバッチをご紹介します。

# 1. サンプルコマンド
まずサンプルとして、「こんにちは」と記載されたinput.txtを「HELLO」と置換し、
output.txtへ出力する場合のコマンドを紹介します。

```input.txt
こんにちは、Aさん
こんにちは、Bさん
こんばんは、Cさん
```

```sample.bat
set BEFORE_STRING=こんにちは
set AFTER_STRING=HELLO

set INPUT_FILE=input.txt
set OUTPUT_FILE=output.txt

setlocal enabledelayedexpansion
for /f "delims=" %%a in (%INPUT_FILE%) do (
set line=%%a
echo !line:%BEFORE_STRING%=%AFTER_STRING%!>>%OUTPUT_FILE%
)
```

```output.txt
HELLO、Aさん
HELLO、Bさん
こんばんは、Cさん
```

このように上記コマンドを実行することで「こんにちは」という文字列が「HELLO」に置換されます。

# 2. 構文
# 2-1. ファイル読み込み
まず、ファイルを一行ずつ読みこむ際にはfor文を使用します。
for文を使用するときは以下のコマンドをあらかじめ実行します。

`setlocal enabledelayedexpansion`

ERRORLEVELコマンドを使用してエラー判定したいときなどに
このコマンドがないと正常終了してもエラーとしてリターンコードが返却されてしまいます。

理由としては、for文を実行している間にERRORLEVELコマンドが実行されるためです。

まあここはfor文を使うときはおまじないと思っていただければと思います。
なくても動きますが、for文を使用するときは記載するくせをつけましょう。

次にfor文の解説をします。
以下の構文でファイルを一行一行読みこむことができます。

`for /f "delims=" %%a in (ファイル) do (set line=%%a)`

各オプションは以下の役割をしてます。

|オプション|役割|
|:--:|:--|
|/f|ファイルを行単位で変数に読み込み繰り返し処理が行えるオプションです。|
|delims="|デリミタ(区切り)を無効にする。|

対象ファイルのレコードを一行一行読み込み、
読み込んだ内容を%%aに一時的に格納しています。

# 2-2. 置換
文字列を置換する際は以下の構文となります。

`!変数名:置換対象の文字列=置換後の文字列!`

今回サンプルでは置換したレコードをechoコマンドでテキスト出力してます。

テキスト出力するときの注意点は以下の2点です。

・　「>>」で追記モードにする。
・　「>>」の前後はスペースを入れない。

追記モードにしないと最後の１レコードしか出力されませんし、
「>>」の前後にスペース入れるとテキスト出力した際、レコードの最後にスペースが入ってしまいます。

最後にもう一度サンプルプログラムをのせておきます。

```sample.bat
set BEFORE_STRING=こんにちは
set AFTER_STRING=HELLO

set INPUT_FILE=input.txt
set OUTPUT_FILE=output.txt

setlocal enabledelayedexpansion
for /f "delims=" %%a in (%INPUT_FILE%) do (
set line=%%a
echo !line:%BEFORE_STRING%=%AFTER_STRING%!>>%OUTPUT_FILE%
)
```

ぜひ活用してみてください。

# さいごに
2020年から個人ブログはじめました！

フリーランスエンジニアになって得た知識と経験をもとに、フリーランスエンジニアに関する情報をはじめ、IT技術情報や業界情報、エンジニアライフハック等のコンテンツを配信していく予定です。

まだまだ記事数は少ないのですが、週単位で更新してますので、もしご興味ございましたら、みていただけると嬉しいです。

https://yacchi-engineer.com/

さいごまでお読みいただき、ありがとうございました。
ETL文字データベース (etlcdb)を画像に変換する

日本版MNISTとも言えるETL文字データベース

  * http://etlcdb.db.aist.go.jp/?lang=ja

を、機械学習の学習・モデルの教育などに使用されている方も多いと思います。
ですが、こちらの配布データは古き良き時代を思い出させるバイナリファイルで、モダンな私たちが扱うにはいささか苦痛を伴います。

  * https://qiita.com/takamon9/items/27b27af0eb5b18638859

にETL8B用の解説がありますが、他のデータに対するモノが見つかりませんでした。
きっと、いろんな人が沢山の車輪を作ってきたことと思うので、超絶雑なコードですが、メモ代わりに上げておきます。
元々のデータは64 x 63と中途半端なので、64 x 64または128 x 128にresizeしてもよいかも。その辺はお好みで。
要Python3, Pillow, Numpy。

  * ETL1, 6, 7兼用

「あ」と「A」が両方「A」というディレクトリに入ったりするが、そんなに多くないから(A, I, U, E, O, N)、適当に手動で修正してください。

```python

#!/usr/bin/env python3

import struct
import numpy as np
import os
import sys
from PIL import Image

assert(len(sys.argv) == 2)
filename = sys.argv[1]

RECORD_SIZE = 2052
i = 0
print("Reading {}".format(filename))
with open(filename, 'rb') as f:
    while True:
        s = f.read(RECORD_SIZE)
        if s is None or len(s) < RECORD_SIZE:
            break
        r = struct.unpack(">H2sHBBBBBBIHHHHBBBBHH2016s4x", s)
        img = Image.frombytes('F', (64, 63), r[20], 'bit', (4, 0))
        img = img.convert('L')
        img = img.point(lambda x: 255 - (x << 4))
        i = i + 1
        dirname = r[1].decode('utf-8')
        dirname = dirname.replace('\0', '')
        dirname = dirname.replace(' ', '')
        dirname = dirname.replace('\\', 'YEN')
        dirname = dirname.replace('+', 'PLUS')
        dirname = dirname.replace('-', 'MINUS')
        dirname = dirname.replace('*', 'ASTERISK')
        try:
            os.makedirs(f"extract/{dirname}")
        except:
            pass
        imagefile = f"extract/{dirname}/{filename}_{i:0>6}.png"
        print(imagefile)
        img.save(imagefile)
```


  * ETL 8G, 9G用

JISこーど…。

```python

#!/usr/bin/env python3

import struct
import numpy as np
import os
import sys
from PIL import Image

assert(len(sys.argv) == 2)
filename = sys.argv[1]

RECORD_SIZE = 8199
i = 0
print("Reading {}".format(filename))
with open(filename, 'rb') as f:
    while True:
        s = f.read(RECORD_SIZE)
        if s is None or len(s) < RECORD_SIZE:
            break
        r = struct.unpack(">HH8sIBBBBHHHHBB30x8128s11x", s)
        img = Image.frombytes('F', (128, 127), r[14], 'bit', (4, 0))
        img = img.convert('L')
        img = img.point(lambda x: 255 - (x << 4))
        i = i + 1
        dirname = b'\x1b$B' + r[1].to_bytes(2, 'big') + b'\x1b(B'
        dirname = dirname.decode("iso-2022-jp")
        try:
            os.makedirs(f"extract/{dirname}")
        except:
            pass
        imagefile = f"extract/{dirname}/{filename}_{i:0>6}.png"
        print(imagefile)
        img.save(imagefile)

```