OmniAICreator/Qiita-1.07M huggingface dataset:
【メモ】H-V曲線を用いて、実測の貯水位から貯水量を算出

自分の忘備録です。
H-Vというシートにダムの既知のH-V曲線があるとします。
Sheet1に自動観測装置かなんかで計測した貯水位データ（毎時・日平均など）があるとします。

+ この計測水位データを、H-V曲線のプロットと比較
+ ある2点のプロットの間に収まるならば、2点間の直線の式と計測水位データから貯水量を計算

```vb
Sub 貯水量()

Dim h() As Variant
Dim v() As Variant
Dim i_hvarry As Long
Dim i_row As Long

Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual '手動計算にする

'H-Vデータを配列に格納。この配列を使用するときは次元も指定。
Sheets("H-V").Select
h = Range2Array(5, 7)
v = Range2Array(5, 8)


'水位データH_measuredから、HVのプロットを用いて貯水量を算出（線形補間）
Sheets("Sheet1").Select

For i_row = 2 To Cells(2, 2).End(xlDown).Row
H_measured = Cells(i_row, 2)
    For i_hvarry = 1 To UBound(h, 1) - 1 '-1しないと繰り返し範囲がエラー
        If h(i_hvarry, 1) <= H_measured And H_measured < h(i_hvarry + 1, 1) Then
            V1 = v(i_hvarry, 1)
            H1 = h(i_hvarry, 1)
            V2 = v(i_hvarry + 1, 1)
            H2 = h(i_hvarry + 1, 1)
            v_cal = ValueBetween2(V1, H1, V2, H2, H_measured) '自作関数
        End If
    Next i_hvarry
    Cells(i_row, 5) = v_cal
    v_cal = Empty

Next i_row

Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic '自動計算に戻す

End Sub
```

```vb

'レンジを配列に変換する。
'Range2Array(始行、始列)
Function Range2Array(start_row, start_column) As Variant
    Range2Array = Range(Cells(start_row, start_column), Cells(Cells(start_row, start_column).End(xlDown).Row, start_column))
End Function

```
```vb

'未知の貯水量Vを求める（２点の直線の傾きと既知のHを使って）
Function ValueBetween2(V1, H1, V2, H2, H_measured)
    ValueBetween2 = V1 + ((V2 - V1) / (H2 - H1)) * (H_measured - H1)
End Function
```
Heisei

- [Heisei](https://yukicoder.me/problems/no/779)

## [解法1(愚直な方法)](https://yukicoder.me/submissions/313149)

- 1989年から2019年の間かどうかを判定する。trueなら答えはまだわからない。falseなら答えは`No`
- これ以降は1989年から2019年の間の場合を考える。
- 1989年1月8日より前なら答えは`No`
- 2019年5月以降なら答えは`No`（4月は30日までしかないから5月以降の判定でOK）
- それ以外なら答えは`Yes`

```cpp
#include <bits/stdc++.h>
using namespace std;

#define int long long

signed main() {
  int y, m, d;
  cin >> y >> m >> d;

  if (1989 <= y && y <= 2019) {
    if (y == 1989 && m == 1) {
      if (d < 8) {
        puts("No");
        return 0;
      }
    }

    if (y == 2019 && m >= 5) {
      puts("No");
      return 0;
    }
    
    puts("Yes");
  } else {
    puts("No");
  }

  return 0;
}
```



## [解法2(賢い方法)](https://yukicoder.me/submissions/313151)

- `{1989, 1, 8}`と`{2019, 4, 30}`を作る
- 判定する日付を`{y, m, d}`として格納する
- 配列同士を比較する

```cpp
#include <bits/stdc++.h>
using namespace std;

#define int long long

vector<int> low = {1989, 1, 8};
vector<int> high = {2019, 4, 30};
vector<int> now(3);

signed main() {
  cin >> now[0] >> now[1] >> now[2];

  puts((low <= now && now <= high) ? "Yes" : "No");

  return 0;
}
```

### メモ

- 配列同士を比較できるの知らなかった。
- 最初に年が判定され、年が同じなら月が判定され、月が同じなら日が判定されるって感じだと思う。
- 文字列の比較と同じ感じ（なんか直感的にわかりづらいけど）
僕はArrow functionが読めない

###はじめに

RubyからJavascriptに手を広げている時、Rubyに比べてJSはコードが読みにくいと感じた。
特に `Arrow function(無名関数)` についてはしっくり理解できるまで時間がかかったので、同じ道を通るかもしれない人に向けて記録を残しておこうと思う。 また、関数で頻繁に使用されている、省略記法が基礎が出来ていない状態で障害になっていたと感じる。

---

###対象となる読者

Javascriptを初めたばかりの方

---

###Arrow functionの利点
#####1. 短く記述出来る

`function(){...} vs. () => {...}`

#####2. 関数名を記述しなくて良い

Arrow functionは　`Anonymous` である。

Anonymous functions usually don't have a named `identifier`

1については、メリットが理解しやすいが、2については文章を見ても直ぐにはしっくり来なかった。
2について具体例を出して考えていく。

```js

function blastoff() {
  console.log("3...2...1..blastoff!");
}

blastoff();
```
```
結果
=> 3...2...1..blastoff!
```

ここでは関数名に `blastoff` という固有の名前がつけられている。
次は、1秒後にconsoleの中身が返ってくるように `setTimeout()メソッド`　を例に考える。

```js

setTimeout(function() {
  console.log("3...2...1..blastoff!");
}, 1000)
```

```
結果
=> 3...2...1..blastoff!
```

上記の例では、 `blastoff` の名称を用いた関数の呼び出しは行なっていないが問題なく動作する。
`Arrow function` を用いると以下のように記述出来る。

```js

setTimeout(() => {
  console.log("3...2...1..blastoff!");
}, 1000)
```

結果は同じである。
もし、無名関数ではなく、固有の名前を与えたいなら以下のように記述してあげれば良い。

```js

const blastoff = () => {
  console.log("3...2...1..blastoff!");
}

blastoff()
```

```
結果
=> 3...2...1..blastoff!
```

次に、配列の数字に1を加えるメソッドを例に考える.

```js
let points = [10, 11, 12]

let addOne = function(element) {
  return element + 1;
}

points = points.map(addOne);

console.log(points)
```

```
結果
=> [11, 12, 13]
```

上記の例は `Arrow function` を用いると以下のように記述出来る。

```js
let points = [10, 11, 12]

let addOne = () => {
  return element + 1;
}

points = points.map(addOne);
```

mapメソッドの引数に addOneの中身を記述すれば、更に短く記述が出来る。

```js
let points = [10, 11, 12]

points = points.map((element) => {
  return element + 1;
})
```

Arrow functionに渡す `引数` が1つの場合は、 `()` を省略出来る。

```js
let points = [10, 11, 12]

points = points.map(element => {
  return element + 1;
})
```

Arrow functionのbodyがexpressionの場合は `{}` 及び `return` を省略できる。

```js
let points = [10, 11, 12]

points = points.map(element => element + 1)
```

expression vs statement についてはこの動画がわかりやすい。

https://www.youtube.com/watch?v=WVyCrI1cHi8

同じ表現を省略してかなり短く記述することが可能だ。
CircleCIがパスしない時にローカルでデバッグする方法

# 問題
* CircleCIがパスしない
* ログを見ても原因がよくわからない

# 解決策

* `circleci build`でCIをローカル上のDockerコンテナで実行する
* CIが終わってもコンテナを破棄しないよう`.circleci/config.yml`を変更する
* Dockerコンテナに接続してデバッグする

## Docker Desktopのインストール

手順略

## circleciコマンドのインストール

Macの場合はHomebrewでインストールします。

```
brew install circleci
```

## circleci build

以下のコマンドによりCircleCIのタスクをローカルのDockerコンテナで実行します。

```
circleci build
```

このままだとCIが成功しても失敗しても終わったらコンテナは終了するため、デバッグすることができません。

## CIが終わってもコンテナを破棄しないようにする

正確にはCIプロセスが終わらないようにします。

まず、失敗するstep以降をコメントアウトします。

次に、以下の設定を`.circleci/config.yml`のjobs/build/stepsの最後に追加します。

```
      - run:
          name: for debug
          no_output_timeout: 120m
          command: |
            tail -f /dev/null
```

`.circleci/config.yml`の全体は例えば以下のようになります。

```
version: 2
jobs:
  build:
    docker:
      - image: circleci/node

    steps:
      - checkout
      - run:
          name: install npm packages
          command: |
            npm install --verbose
      ...
#      - run:
#          name: unit test
#          command: |
#            npm run test
      - run:
          name: for debug
          no_output_timeout: 120m
          command: |
            tail -f /dev/null
```

## Dockerコンテナに接続する

上記設定を加えた後に`circleci build`を実行すると、CIの実行コンテナが残り続けます。

`docker ps`コマンドでコンテナ名を確認し、コンテナに接続します。

```
$ docker ps
$ docker exec -it [container] bash
```

以降、リモート実行時に失敗したコマンドを手動で実行するなどしてデバッグします。

## タイムアウトを設定する

上記の設定ではno_output_timeoutの指定により120分後にコンテナは自動停止します。
デバッグに必要な時間を余裕を持って設定しましょう。

# 別の方法

リモートのCircleCIには`Run job with SSH`ボタンにより、
SSHを有効にした状態でビルドを走らせることができます。
こちらの方法もデバッグに使えますが、SSH接続中は実行時間が消費される点に注意しましょう。
freecodecampのWrite Higher Order Arrow Functionsを解いたメモ

##　実際の問題へのリンク
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/es6/write-higher-order-arrow-functions

##　問題概要
与えられた配列から正の整数を取り出し、取り出された正の整数で自乗された(squared)配列を新たに作成する。

##　自分の回答

```javascript:javascript
 const realNumberArray = [4, 5.6, -9.8, 3.14, 42, 6, 8.34, -2];
 const squareList = (arr) => {
   "use strict";
   // change code below this line
   const squaredIntegers = arr.filter((num) => num > 0 && Number.isInteger(num) ).map(filteredNum => filteredNum ** 2);
   // change code above this line
   return squaredIntegers;
 };
 // test your code
 const squaredIntegers = squareList(realNumberArray);
 console.log(squaredIntegers);
```

##　解説
引数arrが与えられた配列で、まずこの配列からfilter()を使用し正の整数を取り出す。
numに配列の各値が入る。このときnumの変数名は自由につけてOK。
Number.isInteger(値) で整数を取り出す。
整数には負の数も含まれるため 値 > 0 で正の整数に絞り込む。

```javascript:javascript
 const squaredIntegers = arr.filter((num) => num > 0 && Number.isInteger(num) );
```

ここまでで正の整数は取り出せた。
次は取り出した値で自乗を行いつつ、その結果を配列として生成する。
map()を使用して新たな配列を生成。
filteredNumに配列の各値が入ってくる。
「なにかしらの処理」の部分に今回でいうと自乗を行うコードを書く。

```javascript:javascript
 const squaredIntegers = arr.map(filteredNum => なにかしらの処理);
```

べき乗の計算は ** を使う。 (Math.pow() もOK)
今回の問題では、取り出した値の2乗を行えばOK。

```javascript:javascript
 const squaredIntegers = arr.map(filteredNum => filteredNum ** 2);
```

`const squaredIntegers = arr.filter((num) => num > 0 && Number.isInteger(num) );`
と
`const squaredIntegers = arr.map(filteredNum => filteredNum ** 2);`
をがっちゃんこ。

```javascript:javascript
 const squaredIntegers = arr.filter((num) => num > 0 && Number.isInteger(num)  ).map(filteredNum => filteredNum ** 2);
```

以上。

##　参考にしたもの
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
- https://lab.syncer.jp/Web/JavaScript/Reference/Global_Object/Number/isInteger/
- https://mseeeen.msen.jp/javascript-map-function/
- https://qiita.com/tonkotsuboy_com/items/12436de8c6f3a289d3af
Ruby on rails で間違って :id を設定してprimary_keyと重複した場合の対策

新規にアプリを作成してモデルのテーブルに間違って`:id`をマイグレーションすると
下記のようなエラーをはかれます。

```
rake aborted!
StandardError: An error has occurred, all later migrations canceled:

you can't redefine the primary key column 'id'. To define a custom primary key, pass { id: false } to create_table.
```

作成した`id`がprimary_keyの`id`と重複して邪魔しているということらしい。

`id: false`をcreate_tableに書け、ということだけどどこに書いたらいいの？で探してブログ[Rails4 db:migrateでid以外のカラムにプライマリキーの設定を行う](https://blog.takanabe.tokyo/2014/11/30/47/)
を参考にして下記のように書いて解決。primary_keyを追加で書いた`id`に改めて追加してしてます。

```
create_table :モデル名, :id => false do |t|
      t.integer :id, :primary_key => true
```
へっぽこWebエンジニアが誕生するまで（自己紹介）

## この記事について
これは私が未経験からWeb制作会社に入社するまでのプロフィールをまとめたもの。
入社してから右往左往する様についてはこちらをご覧ください。
投稿：[へっぽこWebエンジニアが入社1ヵ月目を振り返る](https://qiita.com/tgsmsk/items/8507c5da375639b80d43)

## なぜWebエンジニアに？
### ◆Web制作との出会い
平成1桁生まれ、[NHKの平成ネット史（仮）](http://www4.nhk.or.jp/nethistory/)は懐かしいというよりも、もはや黒歴史を想起させるだけのパンドラの箱と言っても過言ではないほど、ネットが身近にあった世代。
小学校～中学校当たりで、自分のホームページを持ちたいと思い、HTMLとCSSの勉強をした。インラインフレームに、読めるか読めないかぎりぎりの薄く小さい文字で文章を書き、もちろんアクセスカウンターとキリ番報告用のBBSとWeb拍手も設置した。これ以上の詳細は封印されし左目が疼き出すので割愛したい。
### ◆Web業界へのあこがれ
当然のことながらWeb制作への興味は、職業へのあこがれとなる。HTMLやCSSのコーディングが楽しくてしょうがなかったので、これを仕事にしたいと思った。そんなとき出会ってしまった本が「13歳のハローワーク」。本自体はもう手元にないのだが、どんな内容が書かれていたかは下記の記事がわかりやすい。
抜粋：[SE/プログラマは「13歳」に夢を与えない？](https://tech.nikkeibp.co.jp/it/free/ITPro/OPINION/20040129/139079/)
>目次をよく探してみると，巻末近くの「P.S. 明日のための予習 13歳が20歳になるころには」という章の中に，IT［Information Technology］という項目があり，そこでSE/プログラマが紹介されていることが分かった。“なんだ，追伸扱いかよ”と少しがっかりしながら，該当ページを読むとさらにがっかりした。（中略）
>ITの章の終わりには，13歳は，ITブームとやらに乗っかってどっかの企業に雇用してもらおうといった甘い夢は見るな，というメッセージが書いてある。もっともな話だが，いささかバイアスがかかりすぎている気がする。


これを「バイアスがかかりすぎている」とも思わずに、なぜか鵜呑みにした私は、Web業界への就職をあっさりとあきらめた。Web制作は趣味で続ければいいや、と思いながらも、高校を卒業する頃にはほとんど飽きていた。

## わたしの履歴書
### ◆学歴
Web業界へのあこがれを忘れた私は、まったく関係ない文系の学部に進学。紆余曲折あって言語学を専攻し、生成文法やらチョムスキーやらといったことを夢中で学び、大学院に行ってさらに学問の道を進もうと思っていた。
しかし、ふと気付いた。大学院でPh.Dまで取ったとして、スムーズにいっても30歳。「言語学を勉強していました」と言って、それを専門として採用してくれる職種はとても少ない。また、学部生と院生の新卒がいたとして、同じスペックなら就活で有利なのは初任給が低い学部生だ。
そんなわけで、言語学も趣味で続ければいいや、といつぞや思ったようなことをまた考え、学部新卒で就活に臨んだ。書くまでもないことかもしれないが、私は飽き性だ。

### ◆職歴
#### 新卒～2015年：大手IT企業（マーケティング・企画職）
- 偶然にもインターネットサービスに関わることになったが、特に就活中こだわりを持っていたわけではない。
- 大手なだけあって、とにかく新卒の研修がしっかりしていたのが有り難かった。電話＆メール応対から名刺交換、ExcelやPowerPointの使い方、見やすい会議資料の作り方などなど、ビジネスマナーもビジネススキルも、一般の新卒よりもかなり速いスピードでスタートダッシュをかけることができた。
- それと同時に、当時はまだ働き方改革なんていうものはなく、深夜残業も当たり前。もともと心身ともにお豆腐だった私は、あっという間に体調を崩した。このままではいけない、と思い転職活動。

#### 2015年～2018年：レジャー関係企業（マーケティング・企画職）
- 自分の好きなことを仕事にしてみるのはどうだろう、と思い、レジャー関係の企業に就職。運よく企画職になれたので、新卒から培ってきたExcelやPowerPoint、マーケティング分析スキル等がそのまま生かせた。
- 残業はほぼなかったものの、自分の好きなことだから、という理由が仇となり、知らず知らずに無理をしていたらしく、またもお豆腐メンタルが限界を迎える。転職活動をしようかとも思ったが、まずはちょっと休みが必要だ、と思いアルバイト求人を探す。

#### 2018年：家電量販店（EC業務）
- 週3日、近場で働ける事務職を探して、見つけた求人に応募。面接に行ってみたら、EC業務の人手が足りない、ということでWeb業界に戻ってくる形となった。
- 商品ページを作ったり、トップページをカスタマイズしたり、メルマガを作ったり。中学生のころ、無我夢中で勉強したHTMLやCSSの知識がここに来て生きた。そして、あらためて勉強してみたいという気持ちになり、HTMLやCSS、Javascriptの教材を見始めた。
- 10年たって様変わりしたWeb制作の世界。13歳のハローワークでは「ITブーム」と一過性のものだと評されていたが、現在でもたくさんのプログラマー/エンジニアが活躍している。EC業界が大幅に拡大し、企業はWebサイトをただ設置するだけではなく、競合他社と比べて、より魅力的なページを作り、コンバージョンを高める施策を必要としている。

#### 2019年：Web制作会社へ
- 「あれ？もしかして、これまで勉強したマーケティング分析の知識と、Webコーディングのスキルを合わせたら、かなり需要の高い人材になれるんじゃない？」と思った。まあ、それは事実かどうかは置いておいて、その考えのもと、私は転職サイトに登録し、未経験（独学）でも採用してくれるWeb制作会社を探し始めた。これがかなり難しく「業界経験3年」というハードルがほとんどの企業で課せられていた。
- その中で運良く巡り合えたのが今の会社だ。履歴書でも面接でも、上記のようなビジョンを語ったところ採用してくれた。

### ◆その後の話
投稿：[へっぽこWebエンジニアが入社1ヵ月目を振り返る](https://qiita.com/tgsmsk/items/8507c5da375639b80d43)

### ◆転職活動～現在までに活用した教材一覧
投稿：[新人Webエンジニアの学習が捗るリンク集](https://qiita.com/tgsmsk/items/5bc9a2a5fd2d4cb155c2)

## おわりに
ポートフォリオ的なものがあれば、そのリンクを張れば良いのだろうが、未経験なので制作物もまだないため、しばらく形になりそうにないので、とりあえず自己紹介記事を作成した。Qiitaのポリシー的にはあまり良くないかもしれないが、未経験からエンジニア職へ転職を検討する人の助けには多少なればと思う。

いずれイカしたポートフォリオが出来上がったら、そちらへのリンクに差し替えます。
→鋭意制作中：https://tgsmsk.github.io/index.html
SwiftとObjective-Cの定数を共有

Objective-Cで書かれたプロジェクトのswift化を進めています。進め方としては、既存のObjective-Cのコードはそのままに、新規に作る画面や機能をswiftで書くというやり方。

Objective-C側で書かれたdefineの定数。よくNSUserDefaultsなどのKeyとしてまとめてたりしますよね。

あれをSwiftからも使えるようにすべく、ラッパーをかいてみました。

まず、Objective-CのコードをSwiftで呼べるようBridging-Header.h に一行追加します。

```Bridging-Header.h
#import "Defines.h"
```

そして、Objective-C用の定義ファイルであるDefines.hにクラスを追加します。今までは#defineだけの塊のファイルです。

```Obective-C:Defines.h

#define kUSERDEFAULTS_HOGEHOGE @"UserDefaults_HOGEHOGE"

@interface Defines : NSObject

+ (NSString *)hogehogeUserDefaults;

@end
```


```Obective-C:Defines.m

#import <Foundation/Foundation.h>
#import "Defines.h"

@implementation Defines

+ (NSString *) hogehogeUserDefaults { return kUSERDEFAULTS_HOGEHOGE; }

@end

```

そして呼び出し側からは、


```Hogehoge.swift
UserDefaults.standard.set(password, forKey:Defines.hogehogeUserDefaults())
```

というところまで書いて、できたできたと、なる予定だったのですが、

```Hogehoge.swift
UserDefaults.standard.set(password, forKey: kUSERDEFAULTS_HOGEHOGE)
```

でもOKでした。あれれ？ラッパーいらなかった？
っていうお話でした。
Windows 10 Proでディアルブート環境を作るときにはBitLockerの回復キーを控えておこう

# はじめに
以下の記事を参考にさせて頂いたときにBitLockerでつまずいたのでメモします。
[Windows10とUbuntu16.04のデュアルブート環境構築]
(qiita.com/medalotte/items/4bb5cfa709e93d044f1c)

# 環境
- ThinkPad X1 Carbon（2017モデル）
- Windows 10 Pro

# BitLockerの回復キーを控える
Windows10 Proの場合、BitLockerというドライブ暗号化機能がついています。

暗号化しているドライブ（Cドライブ）をパーテーション分割してUbuntuをインストールするときに
BitLockerが作動してWindowsにアクセスできない状況になる可能性があります。

そうした状況に備えて、あらかじめBitLockerの回復キー（数字）を入手しておきましょう。

BitLockerの回復キーはこちらの手順に従って取得します。
私は「Microsoftアカウントに保存した場合」の方法で入手しました。
[BitLocker 回復キーを探す]
(https://support.microsoft.com/ja-jp/help/4026181/windows-10-find-my-bitlocker-recovery-key)

なお、管理者コマンドプロンプトで下記のコマンドを入力すると「回復パスワード」が得られますが、
こちらは「回復キー」とは違いますので気をつけましょう。
```manage-bde.exe –protectors –get C:
```

私の環境ではBIOSの設定でSecure Bootをdisabled、CSMをenabledとしてもBitLockerの回復キーを要求されました。
回復キーさえ入力すればSecure Bootをenableにしても起動しましたのでそのままにしています。

=== 2019/02/01 追記 ===
久しぶりにWindows 10を立ち上げたところBitLockerの回復キーを要求されたので、[こちらを参考](https://www.dell.com/support/article/jp/ja/jpbsd1/sln314412/bitlockerを無効にする方法?lang=ja)にし、BitLockerを無効にしました。
Jenkinsの「成果物を保存」で.appの保存に失敗した時の備忘録

# 状況

UnityでMac用アプリを書き出す時の話。

「保存するファイル」に以下を指定

```
target/*.app
```

コンソール出力

```
成果物を保存中
ERROR: Step ‘成果物を保存’ failed: 指定されたファイルパターン「target/YourProject.app」に合致するファイルがありません。設定ミス？
Finished: FAILURE
```

# 原因

`.app`の実態はディレクトリなので、ディレクトリとしてパスを指定する必要があった。

# 解決策

「保存するファイル」に以下を指定

```
target/*.app/
```

コンソール出力

```
成果物を保存中
Finished: SUCCESS
```
Pythonista3のfolium導入方法

pythonista3でfoliumが使えなかったのでメモ。

Pythonistaでfolium使おうと思った時に、`ImportError` `cannot import name 'uses_netloc'`が出た人向け。

追記：2020年5月20日
最近pythonのことが少しつつわかるようになってきていろいろと作って楽しんでおります。
数学的なことは詳しくありませんが機械学習にも手を出しつつあります。
久しぶりにfoliumを入れて遊ぼうと思ったら使えなかったので追記。
<B>最新の0.11.0は使えなかったのでfolium 0.7.0を使用しています。

#環境
・Pythonista3(python3.6)
・folium 0.7.0
・StaSh

#原因
sixライブラリというpython2.x系とpython3.x系を橋渡しするものが問題を起こしている様子。

#解決方法
1. StaShを導入してからpipコマンドでfoliumをインストール

    ```
    pip install folium
    ```

2. brancaというパッケージも必要なようなのでbrancaもインストール

```
pip install branca
```

3. foliumパッケージのutilities.py　14行目を以下のようにする

    ```utilities.py
from （six.moves.）urllib.parse import urlparse, uses_netloc,uses_params, uses_relative 
#（）内を消す
```

4. これでfoliumが楽しめます

```
import folium
```
これでインポートエラーがでなかったら問題ないと思います。



#職業Pythonistaの方へ
不学ゆえ至らぬ点がございますが、上記事項に関しましてご指導いただけますと幸いです。
【C#】同じ値の羅列、連続する値の羅列を生成する方法

同じ値の羅列や、連続する値の羅列が必要な場合は、Enumerable.Repeat()とEnumerable.Range()を使うと簡単に所望のデータを生成することができます。

for文を使わずに1行で簡単に書けるので、例えば単体テスト用のデータを生成する際にも使いやすいと思います。


# 同じ値の羅列を生成する

```c#
// 要素数が10で、値が「あいうえお」の配列を生成する
var array = Enumerable.Repeat("あいうえお",10).ToArray();

// 要素数が10で、値が「あいうえお」のリストを生成する
var list = Enumerable.Repeat("あいうえお",10).ToList();
```

# 連続する値の羅列を生成する

```c#
// 5から始まり、7個の連続した値（5,6,7,8,9,10,11）の配列を生成する。
var array = Enumerable.Range(5, 7).ToArray();

// 5から始まり、7個の連続した値（5,6,7,8,9,10,11）のリストを生成する。
var list = Enumerable.Range(5, 7).ToList();
```

Enumerable.Range()をEnumerable.Select()と組み合わせると、以下のようにfor文を使わなくても少し複雑な処理ができます。

```c#
// 「1番目,2番目,...10番目」という文字列を作成する。
var txt = string.Join(",", Enumerable.Range(1, 10).Select(num => num.ToString() + "番目"));
System.Console.WriteLine(txt);
// 1番目,2番目,3番目,4番目,5番目,6番目,7番目,8番目,9番目,10番目
```
【入門者向け】機械学習で使う数学は、むずかしくないよ！（たぶん）

5年後にはAIの進化により、人間はこのへんの数学も覚えなくても機械学習ができるようになっていくと言われています。

#データサイエンスで必要な数学
特に「機械学習」では、次の数学が必要となります。
（１）微分・積分
（２）線形代数
（３）統計・確率
※すべてが完璧に分かる必要はありません。基礎や概念さえ理解できれば、ひとまずOK。プログラミングする際には、このへんの計算を自動処理してくれる仕組みがあるため。ただ、よりステップアップしたい方は、もちろん、より専門的な数学を勉強が必要です。

##簡単な説明
私もまだ確認、勉強中ですが、簡単な説明です。


●微分（曲線の接線の傾きを求める）
　→機械学習では、予測値の誤差を減らすために使う。予測値の最適化。

●積分（さまざまな面積や体積を求める）
　→機械学習では、微分と同じように予測値の誤差を減らすために使うと思う（まだ勉強中）

●数列（数の列のこと。一定の数を加えていく数列と、一定の数を掛けていく数列がある）
　→線形代数で使う行列の理解に、数列の理解が必要。

●線形代数（大量のデータ<行列>をまとめて扱う）
　→機械学習では、大量のデータを行列で扱うこうとができ、線形代数で表現できるため相性がよい。
　→統計・確率では、線形代数が使われるので、先に理解が必要。

●統計（大量のデータからモデルを作る）
　→機械学習では予測モデルをつくるため、モデルをつくるという点で密接した関係。

●確率（ある物事が起こる可能性の割合を求める）
　→機械学習では予測モデルをつくるために使う感じか（まだ勉強中）

※この辺の数学は、Pythonでプログラミングしていくと、数学と機械学習の関係のイメージが掴めるようになると思う。

#数学を学ぶには、むずかしく考え過ぎないこと
数学は、明確な答えと計算プロセスがあるため「できた」「できなかった」が、はっきりとわかる学問です。人によっては、正解にたどりつけない時に、自分には「向いていない」「才能がない」と思ってしまうことがあります。しかし、数学を学ぶ際には**「できた」「できなかった」という結果にこだわる**必要はありません。

明確な答えと計算プロセスがあるため、自分の回答が間違っていた場合には、どこで間違ったのかを検証することができます。これは**「論理思考」**だけではなく**「自分の思考や感情を客観的に把握、制御する能力（メタ認知）」**を育てることができます。**「論理思考」や「メタ認知」は、ビジネス上のハイパフォーマーには必須のスキルです。**

数学では、**「できた」「できなかった」という結果を重視するのではなく、検証するというプロセスを重視する**ように考えましょう。また、自分の結果と人の結果を比較する必要もありません。自分より他人が早く、間違いなく正確にたどり着いても気にする必要はありません。自分のペースで、間違いを検証しながら学べればOKです。

分からない時は、ひとまず、その問題は置いておくのも良いでしょう。別の勉強をして、もう一度挑戦してみることや、そこは飛ばして先に進んでしまっても良いでしょう。もちろん、先輩にアドバイスや意見を求めてもOKです。また、Pythonでプログラミングを進めている内に、分かるようになるということもあります。むずかしく考え過ぎず、**「分からないことが、分かるようになること」**を楽しんで学んでください。


#参考
図解眠れなくなるほど面白い数と数式の話（書籍）
https://www.nihonbungeisha.co.jp/book/b384161.html

AI・機械学習には数学が必要って本当？（株式会社キャパ）
https://www.capa.co.jp/archives/18629

機械学習をこれから始める人の線形代数を学ぶモチベーション（HELLO CYBERNETICS）
https://www.hellocybernetics.tech/entry/2017/07/14/223325

【第4回】メタ認知について学ぼう【認知心理学のすすめ（全5回）】（LearnTern（ラン・タン））
https://learn-tern.com/cog-psy-encouragement-4/

メタ認知とは？ 意味、重要性、具体例、高める方法について【メタって何？】（カオナビ人事用語集）
https://www.kaonavi.jp/dictionary/metacognition/
Python内のデフォルトパスを通す方法（Windows, Linux）

### やりたいこと

自分のpyファイルを`sys`などのモジュールのようにimportして使いたい。

次のような書き方を、

```py
import sys
sys.path
```

例えば自分が作った`mypy.py`でもやりたい。

```py
import mypy
mypy.func()
```

つまり、**Pythonの中でパスを通したい**。

2019年の今、色んなページにこの方法（全部または一部）が書かれていますが、ちょっとハマってしまったのでQiitaに書きます。

`venv`で[仮想環境](https://www.python.jp/install/windows/virtualenv.html)を作るほどでもないときに使うのだと思います。


### 方法

`PYTHONPATH`というPythonが使用する環境変数があります。

`PYTHONPATH`の値に、自分のpyファイルが置いてあるフォルダのパスを入力すればOKです。

`PYTHONPATH`の公式の説明が読みたい方は、こちらへ。

https://docs.python.jp/3/using/cmdline.html#envvar-PYTHONPATH


##### Windowsで`PYTHONPATH`を新規作成する

例えば、自分のpyファイル`mypy.py`が`C:\script`にあるとします。

フォルダ構成は次のようなものだとします（sub_scriptフォルダはsub-scriptのように-を含むとエラーになりますので注意）。

```
C:
    \script
        \mypy.py
        \mypy2.py

        \sub_script
            subpy.py
```

エクスプローラーを開いて、

左ナビゲーションバーのPCを右クリック > プロパティ > システムの詳細設定 > 環境変数 > 新規

にて環境変数`PYTHONPATH`を入力し、値にフォルダのパスを入力します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/197109/683f6407-2f73-15c1-4f89-68a179332003.png)

複数のフォルダを指定したい場合は、`C:\script;C:\script2`のように`;`つなぎです。

そして、もし、SpyderやAnaconda Promptを起動していたら、**再起動**してください（Windowsの再起動は不要です）。

##### パスが通せたか確認する

その後、

```py
import sys
sys.path
```

を実行すれば、`C:\\script`がパスに追加されていることが確認できます（`\`は自動で`\\`になります）。

```
In[11]: sys.path
Out[11]: 
['C:\\Users\\maech',
 'C:\\script', ...  <-- 追加されている
```

##### 自分のpyファイルをimportする

これで、`C:\script\*.py`のすべてのpyファイルがimportできます。

```py
# C:\script\mypy.pyをインポート
import mypy
# mypy.pyに定義したfunc()を使う
a = mypy.func()
# mypy.pyに定義したクラスmypyのfunc()を使う
a = mypy.mypy.func()
# この場合は from mypy import mypy とすると a = mypy.func() で呼び出せる

# C:\script\mypy2.pyをインポート
import mypy2

# C:\script\sub_script\subpy.pyをインポート
import sub_script.subpy
```


### Linuxでやりたい人

bashを使っているのなら、`~/.bashrc`を開き、次の文を追加してください。ここでは`/home/user/add`内にimportしたいpyファイルがあるとします。複数パスがある場合は`:`でつないでください。

```
export PYTHONPATH="/home/user/add:$PYTHONPATH"
```

その後、ターミナルとSpyderを再起動すれば反映されます。

ターミナルの起動時に`.bashrc`を読み込むのでターミナルを新たに起動する必要があります。


### 参考

* PYTHONPATH — 1. コマンドラインと環境 — Python 3.6.5 ドキュメント https://docs.python.jp/3/using/cmdline.html#envvar-PYTHONPATH

* Pythonでimportの対象ディレクトリのパスを確認・追加（sys.pathなど） | note.nkmk.me https://note.nkmk.me/python-import-module-search-path/

* python - Setting PYTHONPATH on Windows under Anaconda without elevated privileges - Stack Overflow https://stackoverflow.com/questions/43099096/setting-pythonpath-on-windows-under-anaconda-without-elevated-privileges
Vue.js初めて触るときに参考にしたもの・作ったもの

 jQueryでプラグインちょっと作れるレベルの人です。

## Udemyで入門コース買った

年始の新春セールをやっていたので。

- [Vue JS入門決定版！jQueryを使わないWeb開発 \- 導入からアプリケーション開発まで体系的に動画で学ぶ \| Udemy](https://www.udemy.com/learn-vuejs/learn/v4/overview)

聞きとりやすい声だし、ゆっくり話すし、サポートサイトもあるのでおすすめのコースです。

このコースの先生がまずは[jsFiddle](https://jsfiddle.net/)での作業をおすすめしていたので、アカウントを作成。
初めて作るアプリも大方はJSFiddleで作った。
エラーとかがわかりやすいし、scss使えるし、ボイラープレートが最初から用意されているしでフロントの人がVue.jsを使う時にはまずおすすめしたい。
※普段codepen派なので、エディターのレイアウトは「Bottom results」が一番使いやすい気がしました。

まだ見終わってないです。

## 初めてのアプリに手を付ける

Udemyのセクション２のセッション16を聞いたところで、何か作ってみたくなったので一旦jQueryで作ったものをVue.js＋SCSS＠jsFiddleで作ってみることに。

難しいサブウェイの注文内容をあらかじめ決めるジェネレータ：[サブウェイのじゅもん](https://jsfiddle.net/ituki_b/ar9kn8h2/)
（参考：[「サブウェイ」が苦境と聞いてガチ勢が注文のフローチャートを作ってみたら愛が重すぎた \- Togetter](https://togetter.com/li/1230409)）

※いつもオリーブ抜きで、くらいしかカスタムしてなかったんですが、オリーブはアクセント野菜という追加をお願いしないと追加されないやつでした。

## ググった

初めてのアプリで詰まったときに。

- [Vue\.js ｖ\-forでインデックス（カウンタ）を付けるサンプル（v\-for でindex） \| クルーデザイン](http://clue-design.com/vue/v-for-index)
- [Vue\.jsで条件によって:classの値を変える \- Qiita](https://qiita.com/Yorinton/items/408d8e5be760b9f443fb)
- [Vue\.jsのv\-bind:classで動的なクラス割り当て \- 親バカエンジニアのナレッジ帳](https://ti-tomo-knowledge.hatenablog.com/entry/2018/06/21/111721)
- [テンプレート構文 — Vue\.js](https://jp.vuejs.org/v2/guide/syntax.html?)
- [vue\.js tips \- v\-bind:class を使って class の on/off を切り替えよう \| phiary](http://phiary.me/vue-js-tips-v-bind-class-toggle/)
- [FN1702008 \| Vue\.js入門 05: 項目を数えて表示する \| HTML5 : テクニカルノート](http://www.fumiononaka.com/Business/html5/FN1702008.html)

## 本を読んだ

初めてのアプリで詰まったときに、家にあったので。

- [基礎から学ぶ Vue\.js](https://www.amazon.co.jp/%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E5%AD%A6%E3%81%B6-Vue-js-MIO-ebook/dp/B07D9BYHMZ)
UEFI BIOS UtilityにSVM Modeが表示されない

#ROG STRIX GL702ZCでvirtualboxの仮想イメージを開いたらエラー

Ryzen1700搭載のゲーミングラップトップ ROG STRIX GL702ZCで
Virtualboxを使おうとしたところ

`AMD-V is disabled in the BIOS`

とエラーで仮想起動せず
Hyper-V同様にAMD-V仮想ハードウェア拡張をBIOSから有効にしてあげれば良い

AMD-V Ryzen bios utility CPU設定から

AMD系製品 -  AMD-V (AMD SVM)
Advanced > CPU Configuration >　SVM > [Enabled]

でいけるはず。
と思ったが、メニュー表示にSVM項目が無い。

ここで嵌った。

結果的にBIOSをバージョンUPしたら表示されました。
面倒な施策を避けるのは良く無いですね。

無事に動作しました。
Dart x Flutter : RenderObject を StatelessWidget 上に表示させてみる

StatelessWidget と StateWidget は、よく話題にあがりますが、
RenderObjectWidget は、話題上がらないでの、補完します。

英語圏でも情報がないので、そんなものとして、扱ってください

![ezgif-3-99636bd7e2fd.gif](https://qiita-image-store.s3.amazonaws.com/0/54192/304344fc-57da-4d53-2f16-c5e101ba8217.gif)

こんな感じで、3Dっぽい表現を、Flutterアプリに簡単に追加できます。

コード 
  https://github.com/kyorohiro/memo_flutter_2019


# 四角形を表示するRenderObject を StatelessWidget に 貼り付ける

```dart
import 'package:flutter/material.dart' as ma;

import 'package:flutter/material.dart' as sky;
import 'package:flutter/widgets.dart' as sky;
import 'package:flutter/rendering.dart' as sky;
import 'package:vector_math/vector_math_64.dart' as vec;
import 'dart:async';

main() async{
  await new Future.delayed(Duration(seconds: 2));
  ma.runApp(MyApp());
}
class MyApp extends ma.StatelessWidget {
  // This widget is the root of your application.
  @override
  ma.Widget build(ma.BuildContext context) {
    return ma.MaterialApp(
      title: 'Flutter Demo',
      theme: ma.ThemeData(
        primarySwatch: ma.Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}
class MyHomePage extends ma.StatelessWidget {

  @override
  ma.Widget build(ma.BuildContext context) {
    return new ma.Scaffold(
      appBar: ma.AppBar(title: ma.Text("Hello")),
      body: createBody(context),
    );
  }

}


ma.Widget createBody(ma.BuildContext context) {
//  return  DrawRectWidget();
  return ma.Row(children: <ma.Widget>[
    ma.Text("Hello"),
    DrawRectWidget(),
    ma.Text("Render"),
  ],);
}


//
// Rect
//
class DrawRectWidget extends sky.SingleChildRenderObjectWidget {
  sky.RenderObject createRenderObject(sky.BuildContext context){
    return new DrawRectObject();
  }
}

class DrawRectObject extends sky.RenderBox {

  @override
  bool hitTestSelf(sky.Offset position) => true;

  @override
  void performLayout() {
    this.size = sky.Size(50,50);
  }

  @override
  void handleEvent(sky.PointerEvent event, sky.BoxHitTestEntry entry) {}

  void paint(sky.PaintingContext context, sky.Offset offset) {
    print("${offset} ${this.size}");
    sky.Paint p = new sky.Paint();
    context.canvas.transform(vec.Matrix4.translation(vec.Vector3(offset.dx,offset.dy, 1.0)).storage);
    p.color = new sky.Color.fromARGB(0xff, 0x55, 0x55, 0x55);
    sky.Rect r = new sky.Rect.fromLTWH(0.0, 0.0, 50.0, 50.0);
    context.canvas.drawRect(r, p);
    context.canvas.transform(vec.Matrix4.translation(vec.Vector3(-offset.dx,-offset.dy, 1.0)).storage);
  }
}
```

こう書くと、以下のような感じで四角形が表示されます。
<img width="381" alt="スクリーンショット 2019-01-27 9.30.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/54192/12e9662e-ffa9-fcf0-58c1-ec84c138da7e.png">
【AWS入門】料金アラート〜AWS料金の見積もり day1-2

UdemyのAWSコースの学習ログです。

# Udemy コース
手を動かしながら2週間で学ぶ AWS 基本から応用まで
https://www.udemy.com/share/100taiB0EfeFtSRnQ=/

講座の動画を見ながら、料金アラート〜AWS料金の見積もりを学習した。

# 料金アラート
AWSで発生した料金が指定額まで達した時に、メールで教えてくれる

- CloudWatchで設定する
- AWSの利用料金が〜＄を超えたら通知するよう設定できる

「請求アラートを受け取る」設定する
### CloudWatchで料金アラートを設定する手順

請求ダッシュボード＞設定
請求アラートを受け取る をチェックON
<img width="1552" alt="スクリーンショット 2019-01-27 8.36.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/52227/3a51d45e-7e53-1581-29af-3ceb8a7e0049.png">
CloudWatch＞請求＞アラームの作成
今月の AWS の合計料金がの欄
超過：とりあえず5を入力
通知の送信先：メールアドレスを入力
入力したメールアドレスに確認メールが送信されるので、リンクをクリック
AWS側でメールが確認されるので[確認]をクリック
CloudWatchのメニュー＞アラームがOKになればよい



## AWS料金の見積もり方について
２種類ある

- AWS公式＞AWS サービス名 pricingで検索する方法
- Simple Monthly Calculatorを利用（簡易計算機）

### AWS公式＞AWS サービス名 pricingで検索する方法
例えばEC2の料金
https://aws.amazon.com/jp/ec2/pricing/
オンデマンドインスタンスの料金を確認する »
リージョン：アジアパシフィック(東京)
表のLinux/UNIX の料金を見る
<img width="1552" alt="スクリーンショット 2019-01-27 8.53.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/52227/037ff8c6-7529-650a-3e8e-cb6091ac53e3.png">
t3.nanoの月の料金を計算すると 0.0068*24*31=$5.0592 (料金*時間*日)
t3.nanoは月$5.059、という見積もりができる

### Simple Monthly Calculator
https://calculator.s3.amazonaws.com/index.html

リージョンの指定を忘れずに
無料枠の計算の有無を指定できる

<img width="1552" alt="スクリーンショット 2019-01-27 9.01.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/52227/1f7d893e-aa7a-832c-976d-e6e42432cfcb.png">
Macを使って壊れたSDカードの修復を試みた手順のまとめ

# はじめに

撮影が終わって、意気揚々と事務所でSDカードをパソコンに差し込んだ時...

![スクリーンショット 2019-01-27 10.07.04.png](https://qiita-image-store.s3.amazonaws.com/0/114240/a6a23c69-fae4-9496-5436-925d3127d735.png)

「セットしたディスクは、このコンピュータで読み取れないディスクでした。」...って何？
カメラではきちんと見れたのになぁ...とSDカードを差し込むとカメラでもフォーマットするように指示が...

そして「終わった...」と落胆する。

そんな経験はございませんか？

最近、ドローンやカメラでの撮影、RaspberryPIを使ったIoTシステムの構築などmicroSDカードを多用するようになったことから、壊れたカードのデータを取り出す作業が時々発生するので、その手順をまとめてみます。

今回はビデオカメラで使用したSDカードからのデータサルベージです。

# 認識しないSDカードのデータを丸ごとコピー

認識できないカードは何か壊れているので、そのまま使用するのではなく、データを物理データで丸ごと取り出します。

以下のコマンドを実行し、対象のSDカードのデバイスを探します。

```
ls /dev/disk*
```

```
/dev/disk0	/dev/disk0s2	/dev/disk1s1	/dev/disk1s3	/dev/disk2	/dev/disk3	/dev/disk4s1
/dev/disk0s1	/dev/disk1	/dev/disk1s2	/dev/disk1s4	/dev/disk2s1	/dev/disk4
```

ここでは、disk3が対象のSDカードだったことから、以降disk3をサンプルとして使用します。
以下のコマンドでイメージファイルを作成します。

```
sudo dd if=/dev/disk3 of=sd.img bs=1m
```

終了したら壊れたSDカードを取り外します。

# 未使用のSDカードにデータを復元

先ほど取り出したデータを未使用のSDカードに入れ直します。

新しいSDカードを接続してみると、これもまたdisk3として認識されました。
もともと作成されていたパーティションがUNTITLEDとしてマウントされたので、マウントを解除します。

```
sudo umount -fv /Volumes/UNTITLED
```

続けて、以下のコマンドを実行してイメージを書き込みます。

```
sudo dd if=sd.img of=/dev/disk3 bs=1m
```

# ファイルの取り出し

TestDiskというオープンソースソフトウェアを利用します。
まず、以下のURLにてTestDiskをダウンロードします。

[TestDisk](https://www.cgsecurity.org/wiki/TestDisk_Download)

解凍し、photorecを実行

```
tar -xvjf testdisk-7.0.mac_intel.tar.bz2
cd testdisk-7.0
./photorec
```

後はphotorecの指示に従ってサルベージファイルの出力先を指定し、ファイルのサルベージを実行。
指定したフォルダにサルベージできたファイルが保存されていきます。

以下のURLもあわせてご参照頂くと参考になります。

https://pctrouble.net/software/photorec.html

# サルベージしたファイルの結合

今回の症例では、xxx.mp4とxxx_mdat.movというファイルが見つかったが、普通にカメラで撮影したデータにはmovファイルは含まれていないことから、一つのファイルが二つに分割されているのかなと想像。

mp4ファイルは全て524KBで、movファイルは数100MBから数GBあることから、mp4はヘッダー情報でmovが動画の情報ではないかと予測。

mp4とmovは元のものとは異なるファイル名になっていることから、日付順に並べ替えた状態でmp4とmovを一つのペアと仮定し、以下のようにファイル名の先頭に「a1」や「a2」などを付与。

```
mv xxx.mp4 a1_xxx.mp4
mv xxx_mdat.mov a2_xxx_mdat.mov
```

ファイル名を変更後、catコマンドでファイルを結合。

```
cat a* > ~/a.mp4
```

I've got it!

ただし、いくつかペアが成立しないmp4ファイルがあり、これはもしかするとサルベージできなかったものかもしれない...でも全滅は免れた！！

# おわりに

大変ニッチな作業手順ですが、SDカードが壊れて読み込めなくなって、復旧ソフトを使ってみたけどmp4とmovが見つかり、取り出したファイルが読み込めなかったという事象に心当たりのある人にとっては大変貴重なお話のはず！

- SDカードの読み込みに3時間
- SDカードの書き込みに3時間
- 市販のソフトを購入してそれっぽくファイルを取り出すのに2時間
- 取り出したファイルを調査し、がっかりするまでに1時間
- mp4の仕様を調べて、movファイルをバイナリーエディタで開いて調査するのに2時間
- バイナリを調査して、mp4とmovを結合すれば良いことに気が付いてからデータを取り出すのに2時間
- 取り出したファイルの結合作業に1時間

合計14時間の大仕事だったけど、今なら最短で3時間あればできそうです！

僕が失った貴重な時間をこの記事を読んだ方が節約され、有意義に活用できることを心から願っています。
phpbrewでインストールしたphpがdyld: Library not loaded: ...で動かなくなった

# はじめに

phpbrewでインストールしたphpが`dyld: Library not loaded: ...`のエラーを出して動かなくなった。phpbrewコマンド自体も中でphp呼ぶ事が多くそれはswitchで選んでいたphpが使われるようでちょっと焦る。なにしろhelpも見られない。

```console
% phpbrew --help
dyld: Library not loaded: /usr/local/opt/readline/lib/libreadline.7.dylib
  Referenced from: /Users/matsui/.phpbrew/php/php-7.3.0/bin/php
  Reason: image not found
```

めったにないけどいつかは次もありそうなので対処方法をメモしておく。

# 原因

homebrewのupdateをした影響で、phpbrew管理下のphpをビルドしたときにリンクしたライブラリがなくなっていた。今回はreadlineが7から8になったので、libreadline.7.dylibがなくなってかわりにlibreadline.8.dylibができていた。

# 対処

## phpbrew switch-off

まずはこれでシステムのphpに切り替える。

### (追記) switfh-offがうまくいかない場合

phpbrewの最近のバージョンではこのような場合に`phpbrew switch-off`もできなくなってしまいました。(switch-offの処理にもphpが必要になったらしい)

代わりにphpbrewが内部で使用するphpを指定できるので、`phpbrew system /usr/bin/php`などとしてやればphpbrewが動作するようになります。

## (方法1)再インストール

だいたいインストールしたときのvariantとか忘れてるので`phpbrew list -v`で確認する。

```console
% phpbrew list -v
* (system)
  php-7.3.1
    Variants:  +bz2=/usr/local/opt/bzip2  +zlib=/usr/local/opt/zlib  +xml +opcache \
              +bcmath +calendar +cli +ctype +dom +fileinfo +filter +ipc +json +mbregex \
              +mbstring +mhash +mcrypt +pcntl +pcre +pdo +pear +phar +posix +readline \
              +sockets +tokenizer +curl +openssl +zip
  php-7.3.0
    Variants:  +bz2=/usr/local/Cellar/bzip2/1.0.6_1  +zlib=/usr/local/Cellar/zlib/1.2.11  \
              +xml +opcache +bcmath +calendar +cli +ctype +dom +fileinfo +filter +ipc \
              +json +mbregex +mbstring +mhash +mcrypt +pcntl +pcre +pdo +pear +phar \
              +posix +readline +sockets +tokenizer +curl +openssl +zip
  php-7.2.13
    Variants:  +bz2=/usr/local/Cellar/bzip2/1.0.6_1  +zlib=/usr/local/Cellar/zlib/1.2.11  \
              +xml +opcache +bcmath +calendar +cli +ctype +dom +fileinfo +filter +ipc \
              +json +mbregex +mbstring +mhash +mcrypt +pcntl +pcre +pdo +pear +phar \
              +posix +readline +sockets +tokenizer +curl +openssl +zip
```

あとはこれを見ながら再インストール。いい機会なのでもう使いそうにないのは整理するのもいい。

# (方法2)なくなったライブラリを戻す

homebrewは古いバージョンも/usr/local/Cellerの下に残っているので、そちらから足りなくなったファイルをみつけてsymbolic linkを張るなどする手もある。

たとえば今回の場合なら

```console
% ln -s /usr/local/Cellar/readline/7.0.5/lib/libreadline.7.dylib /usr/local/opt/readline/lib
```

ただしこちらの方法を使ったときはうっかり`brew cleanup`で古いパッケージをまとめて削除などしないように気をつけること。
Apatch-Airflow v1.10.2をインストールしてみた

#はじめに
Apatch-AirflowはAirbnbがOSSとして公開した、ジョブスケジューリングソフトです。
普通のジョブスケジューリングツールとして使ってみたのですが、少し癖があります。
特徴としては
　・プログラマー向き。スケジュール設定はCrontabの書式で書き、起動処理はPythonで書きます。
　・ジョブの依存関係の変更が簡単で、視覚化してWebで確認できます。
　・Web画面からは起動とステータスの確認のみ。ジョブのキャンセルはできません。
機能はデータ連携に特化しているという感じです。

##Airflowのインストール
[本家のURL](https://airflow.apache.org/installation.html)
まずpipを使ってインストール。pip install airflowは古いバージョン用なので、apache-airflowとapacheを入れる

```
pip install apache-airflow
```

次にDBの初期設定。レポジトリのSQLiteが作成されます。
実行するとConfigファイルが作られるので、他のDBを使用する場合もまず実行します

```
airflow initdb
```

インストールフォルダ直下にairflow.cfgができるのでそれを編集。
sql_alchemy_connのパラメータを修正。

mySQLの場合はこんな感じになります。
sql_alchemy_conn = [DB名]://[ユーザ名]:[パスワード]@[ホスト名]/[DB名]

```
sql_alchemy_conn = mysql://myName:myPassword@localhost/myDB
```
mySQLを使うので```pip install apache-airflow[mysql]```でmysqlのサブパッケージを取り込んでおく。
その後もう一度```airflow initdb```を実行。

1.8系のときはOracleを使っていたのですが、1.10.2になってOracle未対応の設定が多くなり、
修正しきれなかったので、断念してmySQLを使用した。
DBのログ削除とかWebからできないので、使い慣れたDBを使えるに越したことはないです。
airflowはmySQLとPostgresを推奨。

##起動
Webサービスの起動。これでWebサイトから確認できます

```
airflow webserver
```
Scheduleサービスの起動。これがないとスケジュール起動しないです。

```
airflow scheduler
```

その他分散処理をするためには、CeleryのWorkerというサービスを起動します。
そのCeleryを使うにはRedisというインメモリ型のDBが必要だったりと、
芋ずる式に新しいソフトが必要になって~~大変です~~、新しいことをたくさん学べます。



##設定変更関係
いろいろありますが、まずはこの２つの設定を推奨。
他は慣れてきたら順次変更していけばいいと思います。

***default_timezone***
タイムゾーンの設定で、デフォルトはUTC。

***catchup_by_default***
デフォルトのTrueだと、例えば過去のスケジュール実行日を設定すると今時点まで順次実行します。
つまり１年前の起動日の日次実行のジョブを設定すると365回実行されます。
デフォルトをFalseにして、個別のDAGというジョブスケジュール設定内で、```catchup = True```
とした方がわかりやすいと思います。
なぜこんなことするの？と初めは疑問でしたが、指定日付だけ処理するプログラムだった場合こちらの方が便利です。


```
[core]
default_timezone = system

[scheduler]
catchup_by_default = False
```

#まとめ

ユーザよりのソフトではなく、尖った感じのソフトです。
自分の目的のために特化していて、それ以外は自分でやってといったスタイルのソフトです。
ユーザ登録もコマンドですし、ログ削除もデフォルトではなく、自分で用意する必要があります。
ただ逆に使っていくとソフト作成者の思考やわかったり、周辺技術を学べるのでおもしろいソフトです。

コミュニケーションが活発なので使ってみましたが、それもうなずけるソフトです。
jsで26進数を処理する（Excelのカラム表記変換処理）


Excelのカラムの表記（26進数）と10進数をjsで相互変換するレアな要求があったのでその対応。

手動実装はしんどいなと思っていたところ、ライブラリがあるみたいなので試す。
とりあえずテストも書かれている[base26](https://github.com/jameslaneconkling/base26)というのを触ってみる。[他にもある](https://github.com/alexfeseto/hexavigesimal)みたい。


## インストール

```bash
npm install --save base26
```

## 実装

とりあえずindex.jsってファイルを作って記述。

```js:index.js
//10進数を26進数に変換して大文字表示
console.log(base26.to(10));
console.log(base26.to(100));

//26進数を10進数に変換
console.log(base26.from('j'));
console.log(base26.from('cv'));
```

## 実行と確認

まあ、動きます。

```bash
node index.js

j
cv
10
100
```

大文字にしたければtoUpperCase()などを使えば良い。

## 自力でto, fromを行う

いちおう自力で計算する方法も。

[ASCIIコード](http://www3.nit.ac.jp/~tamura/ex2/ascii.html)を利用する。

```js
//toBase26
//0とかだとおかしくなる
function to(num) {
    const mod = num % 26;
    let pow = num / 26 | 0;
    const out = mod ? String.fromCharCode(64 + mod) : (--pow, 'Z');

    return pow ? to(pow) + out : out;
}

//toBase1
//手抜きなので大文字じゃないとだめ
function from(str){
    let out = 0;
    const len = str.length;
    let pos = len;
    while(--pos > -1){
        out += (str.charCodeAt(pos) - 64) * Math.pow(26, len - 1 - pos); 
    }
    
    return out;
}

//利用
console.log(to(1));
console.log(from('A'));
```
dagger.androidでActivityからModuleへ値を渡す

## はじめに

dagger.androidを使用すると、

```kotlin
AndroidInjection.inject(this)
```

というようにActivity側は簡潔な記述になりますが、古いDaggerの実装で

```kotlin
(application as MyApplication).getAppComponent()
            .mainActivityBuilder(MainActivityModule("hoge"))
            .build()
            .inject(this)
```

このようにActivityからModuleに何かしらの値を渡していると、dagger.androidに移行するときに同じような書き方ができなくて辛いです。
しかし、どうしてもActivityからModuleへ値を渡す必要がある、そんな状況に陥ってしまったので色々調べながら実装しました。

## どうやるか

[公式サイト](https://google.github.io/dagger/android)の`Injecting Activity objects`を参考にMainActivity用のSubcomponentを作成します。
１箇所だけ公式と違う実装があります。

```kotlin:MainActivitySubcomponent.kt
@Subcomponent(modules = [MainActivityModule::class])
interface MainActivitySubcomponent: AndroidInjector<MainActivity> {

    @Subcomponent.Builder
    abstract class Builder : AndroidInjector.Builder<MainActivity>() {

        abstract fun mainActivityModule(module: MainActivityModule): Builder

        override fun seedInstance(instance: MainActivity?) {
            mainActivityModule(MainActivityModule(instance!!.prefix))
        }
    }
}
```

作成したSubcomponentをActivityModuleに紐付けます。

```kotlin:ActivityModule.kt
@Module(subcomponents = [MainActivitySubcomponent::class])
interface ActivityModule {

    @Binds
    @IntoMap
    @ClassKey(MainActivity::class)
    fun bindMainActivity(builder: MainActivitySubcomponent.Builder): AndroidInjector.Factory<*>
}
```

AcitivityModuleはAppComponentのmodulesに定義します。

```kotlin:AppComponent.kt
@Component(modules = [AndroidInjectionModule::class, AppModule::class, ActivityModule::class])
interface AppComponent {

    fun inject(app: App)
}
```

特筆すべきはMainActivitySubcomponentのSubcomponent.Builder内にあるseedInstanceメソッドです。
seedInstanceメソッドはMainActivityを引数に持っているので、MainActivityのpublicなメンバ変数やメソッドを準備してあげれば参照できます。
MainActivity側は下記のようになっています。

```kotlin:MainActivity.kt
class MainActivity : AppCompatActivity() {

    @Inject
    lateinit var injectionClassA: InjectionClassA

    @Inject
    lateinit var injectionClassB: InjectionClassB

    public val prefix = "Android"

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val textView = findViewById<TextView>(R.id.text_view)
        textView.setText("${injectionClassA.getHello()} ${injectionClassB.getDagger()} !")
    }
}
```

今回は、prefixというメンバ変数を準備してseedInstanceメソッド内でModuleに渡しています。
注意点として、`AndroidInjection.inject(this)` より前に渡す値を定義してあげないといけないです。

## 所感

MainActivityがModuleのことを知らなくてよくなったと思ったら、ModuleがMainActivityのメンバ変数を知ってる状態に変わっただけというオチですね。
一時回避策としてはありかもしれませんが、最終的にはModuleへ値を渡す必要がないようにModule内でnewするクラスのコンストラクタを見直したほうがよいかと思いました。
コードが一部だけだとわかりづらいので[GitHub](https://github.com/kseito/DaggerAndroidActivityInjectionSample)にあげます。
brew install yarn --without-node してもnodeがインストールされる。


##　追記(2019/2/19)
@ys-0-sy さんからコメントいただきました。
>yarn公式のインストレーションガイドによると，node.jsをインストールした状態で

```
$brew install yarn --ignore-dependencies
```

>とすれば良いようです．

今回の状況(node.jsのバージョン管理ツールで既にnode.jsを使用できる)ですと
こちらの方法がよいかと思われます。
コメントありがとうございました！

---

##　背景
nodebrewとyarnをHomebrewで入れる際に
yarnに付随してnodeがインストールされてnodebrewでのバージョン管理がうまくいかなくなる。
と小耳に挟んだので、これを回避するために

```terminal:ターミナル
brew install yarn --without-node
```

を実行したがnodeもインストールされていた。

##　調査
インストール中のメッセージを読み進めていくと

```terminal:ターミナル
Warning: yarn: this formula has no --without-node option so it will be ignored!
```
「yarnに--without-nodeってoptionはないので、無視しますよ〜。」
そうですか…

ググって、下記にたどり着く
https://github.com/yarnpkg/yarn/issues/6946

どうやら最近のHomebrewのアップデートで--without-nodeは使えなくなったらしい。

##　対策
```terminal:ターミナル
brew install yarn
brew uninstall --ignore-dependencies node
```
yarnをインストールした後にnodeをアンインストールした。
`--ignore-dependencies`をつけないと
yarnがnodeに依存しているので実行できませんでした。と言われます。

```terminal:ターミナル
❯ brew uninstall node
Error: Refusing to uninstall /usr/local/Cellar/node/11.7.0
because it is required by yarn, which is currently installed.
You can override this and force removal with:
  brew uninstall --ignore-dependencies node
```
##　最後に
初心者&独学なので間違いなどあるかもしれません。
他にも方法がありましたら、コメントに残していただけると幸いです。

##　参考
- https://github.com/yarnpkg/yarn/issues/6946
- https://github.com/Homebrew/homebrew-core/issues/31510
- https://webman-japan.com/memo/homebrew-update-no-used-node/
- https://qiita.com/tonpoo/items/950815630ac5766eb859
On/Off-Policyって結局なんやねん（SARSA／Q学習の方策改善についてのメモ）

# 初Qiita

方策反復（方策改善と方策評価）についてちょっと理解が進んだので備忘録とMarkdown練習を兼ねてメモ．


## 方策ってなんぞや

方策 $\pi(a|s)$ は確率分布なので，今いる状態 $s$ と 今とれる行動 $a$ を投げると
その行動 $a$ が選ばれる確率を返してくれる関数だと思っとけば具合が良い気がする．

* 強化学習の目的
    * どの状態でも最適な行動を提示してくれる，万能の最適方策 $\pi^*(a|s)$ を見つけること．
* __方策反復__ は，その目的に対する手段
    * 方策評価と方策改善を繰り返して，方策 $\pi(a|s)$ を最適方策に近づけていく．

## 方策反復

* __方策評価__：方策を用いた再帰反復計算で価値関数を求めること．
    * Q. なんで価値関数求めることが方策の評価になるんや？  
    A. そういうものだと得心せよ
* __方策改善__：価値関数をもとに新たな方策を得る．
    * ε-greedyとかSoftmaxとかの手法で，価値関数を方策に変換するイメージ





## SARSAの流れ

1. 今いる状態 $s_t$ を取得
2. ε-greedyやSoftmaxなどの手法を用いて，価値関数をもとに新たな方策 $\pi(a|s)$ を得る（__方策改善__）
3. 方策 $\pi(a|s)$ に今いる状態 $s_t$ を投げると取るべき行動 $a_t$ がわかる
4. 行動 $a_t$ を取ると，状態が $s_t$ から $s_{t+1}$ に遷移し，即時報酬 $r$ が発生する
5. SARSAの式にはもう一個先の行動 $a_{t+1}$ も必要なので，今度は方策 $\pi(a|s)$ に遷移先の状態 $s_{t+1}$ を投げて $a_{t+1}$ を得る
6. $s_t, a_t, r, s_{t+1}, a_{t+1}$ がそろったので，下のSARSAの更新式で行動価値関数 $Q(s_t,a_t)$ を求める（__方策評価__）

    ```math
    {
        Q(s_t,a_t) \leftarrow Q(s_t,a_t) + α\{ r + \gamma Q(s_{t+1}, a_{t+1}) - Q(s_t,a_t) \}
    }
    ```

7. 1.に戻る


## Q学習の流れ

4.まではSARSAとおんなじ

1. 今いる状態 $s_t$ を取得
2. ε-greedyやSoftmaxなどの手法を用いて，価値関数をもとに新たな方策 $\pi(a|s)$ を得る（__方策改善__）
3. 方策 $\pi(a|s)$ に今いる状態 $s_t$ を投げると取るべき行動 $a_t$ がわかる
4. 行動 $a_t$ を取ると，状態が $s_t$ から $s_{t+1}$ に遷移し，即時報酬 $r$ が発生する
5. Q学習では $a_{t+1}$ は必要なく， $s_t, a_t, r, s_{t+1}$ がそろってるので，下のQ学習の更新式で行動価値関数 $Q(s_t,a_t)$ を求める（__方策評価（？）__）

    ```math
    {
        Q(s_t,a_t) \leftarrow Q(s_t,a_t) + α\{ r + \gamma \max_{a_i} Q(s_{t+1}, a_i) - Q(s_t,a_t) \}
    }
    ```
6. 1.に戻る


## 何が違ったっけ

方策評価とは，__方策を用いた__ 再帰反復計算で価値関数を求めることなのだった．

「SARSAの流れ」の 6. の方策評価では，$Q(s_t,a_t)$ を求めるために $a_{t+1}$ が必要だったので，
方策 $\pi(a|s)$ を使って $a_{t+1}$ を求めた．
要するに，価値関数を求めるために __方策を用いた(On-policy)__ ので，方策評価が行われたことになる．

* SARSAでは，未来の行動は現在の方策に則って選ばれると仮定している．



対して，
「Q学習の流れ」の 5. の方策評価（？）では， $a_t$ を求める必要がなかった．
すなわち，価値関数を求めるために __方策を用いていない(Off-policy)__ ので， __方策評価は行われていない__ ことになる．

* Q学習では，未来の行動は最善のものが選ばれると仮定している．




<!-- ## 方策を2種類に分けれるとかいう話

* __Behavior policy__：行動を選ぶための方策 $\pi(a|s)$
* __Target policy__：評価して，最適方策に近づけていく方策 $\pi(a|s)$

-->

## 参考ページ
https://qiita.com/ABmushi/items/83a639506fcbc4050ce8
https://teratail.com/questions/126990

<!-- 知恵袋（teratailだけど）鵜呑みマンかよ，と突っ込まれるとぐうの音も出ない． -->
指紋認証のアプリ組み込み時の懸念点

##①内容
指紋認証をアプリに組み込む際に懸念していることをつらつらと書いてみました
（あくまで個人的な考えです）

##②アプリへの実装方式

1. Androidの場合
Android Marshmallow (Android 6.0.0)以上の場合はFingerPrint、
Android Pie (Android 9.0.0)以上の場合はBiometricPromptを使うかと思います
上記以外は指紋認証センサー(Nexus Imprintセンサー)がないので諦める

2. iOSの場合
iPhone 5s以降でiOS 8.0 以上のiPhoneの場合はLocalAuthenticationを使ってTouch IDを呼び出す
上記以外のバージョンはtouch IDが無いので諦める
iPhone X・iPhone XS・iPhone XRの場合もtouch IDが無いので諦めるかFace IDで対応する

3. ハイブリッドの場合
Cordova(Monaca)で想定しています。
cordova-plugin-keychain-touch-idをインストールして、使用する。
なお、サードパーティ製APIなので、Proプランへの登録が必要
(サードパーティ製なので、問題なく開発時に受け入れられるかという点も考慮する）
この場合も当然ですが、端末に機能が無ければ無理なので、注意する

##③設計時の考慮
社内で展開して同じ端末しか使わない、修理は正規の業者に依頼する場合には不要の観点です。
特定の端末は動作対象外としてアプリを開発・登録する、別方法の認証を用意するなどで回避する必要があると思います

1. 端末のバージョンにより指紋認証ができない場合を考慮する
②に書いた通り、端末が対応していなければお話にならない

2. 端末に不具合が生じて指紋認証ができない場合を考慮する
例えば、非正規の店で画面修理をした場合です。
iPhoneやiPadではiOSのアップデートやバックアップ復元時に他の部品が正規のものであるかチェックして、非正規以外の物があればブート時にエラー53と出て、Touch IDが利用できなくなります。
（ちなみに私の実例です。。。）

#④まとめ
アプリを開発する時には対象OS・バージョンなどを考慮する必要があるのは当然ですが、ユーザの不手際により一部機能が使用できなくなった時のことも考える必要があると思いました。

最近アプリ開発を始めてみましたが、バージョンの考慮が本当に大変ですね。。。
固定IPルーティング設定でハマった時の回避策

環境は、Google Cloud Platform上のDebian GNU/Linux9 (stretch)です。NetworkManagerとかは導入していません。

ネットで調べる限りでは、

```:/etc/network/interfaces
auto eth0
iface eth0 inet dhcp
    # mainテーブルよりも高い(=小さい)優先度を設定
    up ip rule add from 10.8.0.0/24 priority 100 table vpn
    up ip route add default via 172.16.0.1 protocol static table vpn
    # デバッグ用
    up ip route show table vpn 2>&1 > /tmp/log
```

で設定できるはずなのですが、上手くいきませんでした。詳しい状況としては、ruleは反映されている一方で、routeが反映されていませんでした。デバッグ用に取った、`/tmp/log`を見る限りでは上手くいっているので、実はこの後に一度リセットが入るとかのトラップ(バグ)が有るのでしょうか？

さらには、

```shell
systemctl restart networking
```

もしくは

```shell
ifdown eth0
ifup eth0
```

を実行すると正しく設定されるので、もう意味不明です。googleの独自設定の影響かな？

調べて見ると、ifupdown2とかifupdown-extraとかを使えば可能性はありそうでしたが、面倒なので諦めました。

通常の方法が使えないため、別の方法として、DHCPのhookを作ってそのなかでルーティングを行うことにしました。

```:/etc/dhcp/dhclient-exit-hooks.d/vpn-routes
if [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
    ip rule add from 10.8.0.0/24 priority 100 table vpn
    ip route add default via 172.16.0.2 protocol static table vpn
fi
```

こちらは上手く動作しています。

原因がわかる方はコメントを残していただけると幸いです。

# 追記

systemdを使って、以下のようにルーティングの設定をしようとしましたが、やはり同じように失敗しました。

デフォルトのサービスファイルをコピーします。この方法は、デフォルトの設定を変えたい時に行います。

```shell
cp /lib/systemd/system/networking.service /etc/systemd/system
```

以下の内容を追加します。

```:/etc/systemd/system/networking.service
[Service]
Type=oneshot
...
ExecStartPost=/opt/bin/my-route-up # 追加
ExecStart=/sbin/ifup -a --read-environment
...
ExecStop=/opt/bin/my-route-down # 追加
ExecStop=/sbin/ifdown -a --read-environment --exclude=lo # この上に追加
...
```

```sh:/opt/bin/my-route-up
#!/bin/bash
ip rule add from 10.8.0.0/24 priority 100 table vpn
ip route add default via 172.16.0.1 table vpn
```

```sh:/opt/bin/my-route-down
#!/bin/bash
ip route flush table vpn
ip rule delete table vpn
```

これで、networkingサービスが起動した後に、`/opt/bin/my-route-up`を実行してくれます。また、終了する前には、`/opt/bin/my-route-down`を実行してくれます。Typeがoneshotなので、`ifup -a --read-environment`の実行が終了した時に、サービスの起動が完了したとみなされます。

> the service manager will consider the unit started after the main process exits.
(https://www.freedesktop.org/software/systemd/man/systemd.service.html より引用)

ExecStopPreは実装されていないそうなので、ExecStopで対応します。そのため、ExecStopの順番が大切です。

この方法が、全く同じように失敗する(ruleの追加はされている)ので、おそらくifupdown自体の問題ではないのだと思います。

ちなみに、networkingサービスが起動した後に起動するサービスは、

```shell
systemctl list-units --before networking
```

で確認できます。この中に、ルーティングテーブルをいじっているサービスがあるのでしょうか。
goとUNIXドメインソケットでpub/subっぽいことができるコマンドをつくる

UNIXのパイプの延長で、

- 書き込み側プロセスはひとつ
- 読み込み側プロセスは複数
- 書き込み側プロセスで行を書き込むと、読み込み側プロセス全て書き込んだ行が出力される
- 読み込み側プロセスは任意のタイミングで読み込みを開始できる（読み込みを開始した以降に書き込みされた行を読み込む）

という挙動のものがほしい。
（pub/subとはちょっと違うかもしれない）

これは`tail -f -n 0`で達成できますが、何らかの方法でファイルをときどき消すなどしてやらないとファイルが無限にでかくなっていきます。

UNIXドメインソケットを使うと良いかもと思ったのですが、UNIXドメインソケットを読み書きできるいい感じのコマンドがなかったのでgoで実装してみました。

# コード

## pub

```go:pub.go
package main

import (
	"bufio"
	"io"
	"log"
	"net"
	"os"
)

var connections = make(map[net.Conn]bool)

func main() {
	go acceptConnections()

	stdin := bufio.NewReader(os.Stdin)
	for {
		b, err := stdin.ReadByte()
		if err == io.EOF {
			break
		}
		for conn := range connections {
			_, err := conn.Write([]byte{b})
			if err != nil {
				log.Println("socket write error:", err)
				conn.Close()
				delete(connections, conn)
				log.Println("connections count: ", len(connections))
			}
		}
		//log.Println("wrote:", b)
	}
}

func acceptConnections() {
	listener, err := net.Listen("unix", "./sock")
	if err != nil {
		log.Println("Listen error: ", err)
		return
	}
	defer listener.Close()

	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Println("Accept error: ", err)
			continue
		}
		log.Println("Accepted")
		connections[conn] = true
		log.Println("connections count: ", len(connections))
	}
}
```

## sub

```go:sub.go
package main

import (
	"fmt"
	"net"
)

func main() {
	conn, err := net.Dial("unix", "./sock")
	if err != nil {
		fmt.Printf("Dial error: %s\n", err)
		return
	}
	defer conn.Close()

	buf := make([]byte, 1024)
	for {
		n, err := conn.Read(buf)
		if n == 0 {
			break
		}
		if err != nil {
			fmt.Printf("Read error: %s\n", err)
		}
		fmt.Print(string(buf[:n]))
	}
}
```

# 使ってみる

ビルドします。

```shell-session:ビルド
$ go build pub.go
$ go build sub.go
```

書き込み側プロセスを起動します。
1秒ごとに時刻を出力するワンライナーの出力をパイプでつないでみます。

```shell-session:送信側
$ while :; do date; sleep 1; done | ./pub
```

読み込み側のプロセスを起動すると、`date`の結果がずらずらと流れてきます。

```shell-session:受信側
$ ./sub
2019年 1月27日 日曜日 05時47分16秒 JST
2019年 1月27日 日曜日 05時47分17秒 JST
2019年 1月27日 日曜日 05時47分19秒 JST
2019年 1月27日 日曜日 05時47分20秒 JST
```

別のターミナルを起動してもうひとつ`./sub`をたちあげると、起動したタイミング以降に書き込まれた`date`の結果がずらずらと流れてきます。

# ToDo

- 終了処理をちゃんとやる
- UNIXドメインソケットのパスを引数で指定できるようにする
- 入出力が逆バージョンもつくったら便利なのでは、複数のセンサの値を読んでひとつのログに書き出したりとかに使えそう
- コマンド名はやはりpub/subではない気がするし、なんか考える