OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerを使うならVSCodeが結構便利

# Dockerを使うけどなんかコマンドとかめんどい。。。

イメージの管理とかコンテナ管理とかなんか難しくないです？
そんなとき、VSCodeのDockerプラグインはかなり便利。

> Dockerプラグインのリポジトリ
> https://github.com/microsoft/vscode-docker

* コンテナを止めたり
* イメージを削除したり

コマンド打たなくてもいいから便利。
Dockerfileを作るときも便利。
開発するときも便利。
開発してるときなんかはディレクトリ共有したいから`docker-compose`使うけど。

---

# Python勉強会やってるのね

勉強会のときノートパソコン持って行くのしんどいし、環境別だし、書いたドキュメントとかとっておきたい。
サーバーに環境作ってiPadにキーボードつけて勉強会に参加したら楽だ。
ということでまず仮想環境作って見ようということにした。

## Dockerfile を書く

Dockerfile書くの初めてなのね。
だもんで勉強した。
以下の環境を整えたい。

* 作業環境は Jupyterlab にしたい
* せっかくのJupyterlabだし、TensorFlowも入れたい
* PHPとかJSとかも書きたいのでExtensionも使えるようにしたい（おいおいね）

**参考にさせて頂いた記事**
> DockerでJupyterLabを構築する
> https://qiita.com/muk-ai/items/a147cfd2cafc57420b15

上の記事のDockerfileを少しいじってみる
今回は貧弱なサーバーに乗せることも考えてるのでCPU版のTensorflowにしておいた。

``` Dockerfile:Dockerfile
FROM jupyter/datascience-notebook
# Jupyterが用意している物があるのでそれを利用する。
# これを利用する場合、jovyan というユーザーでUIDが500に設定されるようだ。

LABEL maintainer Ayumu Suzuki

# labをインストール
RUN pip install jupyterlab
# CPU版を使うならこっち
RUN pip --no-cache-dir install -I -U tensorflow
# GPU版ならこっち
# RUN pip --no-cache-dir install -I -U tensorflow-gpu
# 起動コマンド
RUN jupyter serverextension enable --py jupyterlab
```

docker-composeのためのYamlを書く。
ポートフォワーディングは必要ないので削除した。

``` yaml:docker-compose.yml
version: "2"
services:
  jupyterlab:
    build:
      context: .
    user: root
    volumes:
      - "./work:/home/jovyan/work"
    environment:
      NB_UID: 500
      GRANT_SUDO: "yes"
    command: start.sh jupyter lab
```

ビルド

``` shell
$ docker-compose build
```

実行

```
$ docker-compose up
```

一旦ここまで
Zabbix のインストール

必要になりそうだったので調べたメモ。
手順書が充実してたから基本そのまま。

（注意）使用するポートを開けていないとログインできてもそのあとで警告が出ますので、適宜ポートを開けてください

# 手順
1. リポジトリを登録する

    ```
    # rpm -i https://repo.zabbix.com/zabbix/4.0/rhel/7/x86_64/zabbix-release-4.0-1.el7.noarch.rpm
    ```

2. インストールする

    ```
    # yum -y install zabbix-server-pgsql zabbix-web-pgsql zabbix-agent
    ```

3. 日本語でレポートを出す場合は日本語パッケージをインストールする ([Index of /zabbix/4.0/rhel/7/x86_64/](http://repo.zabbix.com/zabbix/4.0/rhel/7/x86_64/))

    ```
    # yum -y install vlgothic-p-fonts
    # rpm -ivh http://repo.zabbix.com/zabbix/4.0/rhel/7/x86_64/zabbix-web-japanese-4.0.0-2.el7.noarch.rpm
    ```

4. PostgreSQL データベースを作成する

    ```
    # sudo -u postgres createuser --pwprompt zabbix
    # sudo -u postgres createdb -O zabbix zabbix
    ```

5. 次のコマンドを実行してスキーマをインポートする

    ```
    # zcat /usr/share/doc/zabbix-server-pgsql*/create.sql.gz | sudo -u zabbix psql zabbix
    ```
6. `/etc/zabbix/zabbix_server.conf` を編集してパスワードを設定する

    ```
    # vi /etc/zabbix/zabbix_server.conf
    ```
    ```sh:zabbix_server.conf
    DBPassword=<任意のパスワード>
    ```

7. `/etc/httpd/conf.d/zabbix.conf` を編集して正しいタイムゾーンを設定する(今回は東京で設定)

    ```
    # vi /etc/httpd/conf.d/zabbix.conf
    ```
    ```sh:zabbix.conf
    php_value date.timezone Asia/Tokyo
    ```

8. Zabbix と関連するサービスを再起動する

    ```
    # systemctl restart zabbix-server zabbix-agent httpd
    ```

9. Zabbix と関連するサービスの自動起動を設定する

    ```
    # systemctl enable zabbix-server zabbix-agent httpd
    ```

10. Zabbix にブラウザからアクセスする

    ```
    http://<ZabbixサーバのIPアドレスもしくはホスト名>/zabbix
    ```

11. DB の情報などを設定する
12. ログイン画面が出たら Zabbix の Superuser の情報でログインする
![Zabbixログイン画面.png](https://qiita-image-store.s3.amazonaws.com/0/34297/0f60902c-598d-1500-7b2f-400d32365e94.png)


    |項目名|設定値|
    |:-------|:----------|
    |ユーザ名|Admin|
    |パスワード|zabbix|

13. ログインできると次の画面が表示される
![image.png](https://qiita-image-store.s3.amazonaws.com/0/34297/71e7c596-d335-d9f2-9071-e19d5f568077.png)

# 参考
- [Download Zabbix](https://www.zabbix.com/jp/download?zabbix=4.0&os_distribution=centos&os_version=7&db=PostgreSQL)
- [公式ドキュメント - 1 Red Hat Enterprise Linux/CentOS](https://www.zabbix.com/documentation/current/manual/installation/install_from_packages/rhel_centos)
- [公式ドキュメント - Installing frontend](https://www.zabbix.com/documentation/4.0/manual/installation/install#installing_frontend)
- [公式ドキュメント - 1 Login and configuring user](https://www.zabbix.com/documentation/4.0/manual/quickstart/login)
[.NET] 特定ロケールのみで発生する例外の不思議

## はじめに
ポーランドの友から、謹製ソフトウェアが処理途中でクラッシュするという報告を受けた。
しかしながら、自分の環境では一向に問題が再現しない。
原因を探っていくとなかなか面白い問題であったので、本記事で共有する。

## 例外が発生するコード
例外を再現できる最低限のコードが、下記である。
このコードは、日本や中国、アメリカなど多くの端末で成功するが、一部地域の端末では例外を吐く。

```c#:C#
var num = float.Parse("0.25");
```

## なぜか？
一部の地域では、小数点を `.` ではなく `,` で表現する。(e.g. `0,25`)
したがって、`0.25` という文字列はfloatとしてパースできず、`FormatException` を発生してしまう。 

## 解決法
[`Parse` メソッド](https://docs.microsoft.com/en-us/dotnet/api/system.single.parse?view=netframework-4.7.2)の第二引数には、 `IFormatProvider` として `CultureInfo` インスタンスを渡すことができる。
この引数がない場合、プログラムが実行されている端末のロケールがデフォルトで利用されるようだ。
これでは環境依存のバグにつながる。

問題を回避するため、この引数に適切なロケールを渡してやれば良い。
多くの場合、`CultureInfo.InvariantCulture` が有効だろう。

```C#:IFormatProviderに渡す
float.Parse("0.25", CultureInfo.InvariantCulture);
```

あるいは、`CurrentCulture` を適切なロケールに書き換えてしまうのも有効と思われる。

```C#:CurrentCultureの書き換え
System.Globalization.CultureInfo.CurrentCulture = new CultureInfo("en-us");
```

シリアライズされたテキストを読み込むようなときは、上記のようにロケールを固定して問題ないだろう。

## 無理やり問題を再現させるには
[Locale Emulator](https://github.com/xupefei/Locale-Emulator) なるものがあるらしい。
これで再現環境でのロケールを設定すれば、自分の端末でも問題を容易に再現できるはずだ。
（しかしながら、今回のソフトウェアではエミュレータがうまく機能しなかった……）

## 終わりに
こういったバグはなかなか予見しづらいが、原因の存在を知っていることは重要である。
さすれば報告を受けたときに、迅速な対応が可能になるだろう。
ラズパイのフロントエンドでマイコン制御するライブラリのラッパーを書いてみた

#Chirimen for raspberry Pi とは
ライブラリを読み込むことで、navigator にrequestI2CAccessやrequestGPIOAccessを拡張する、ラズパイのIoT支援ライブラリとでも言いましょうか？
#本題であるラッパー
[chirimeneck](https://github.com/johnny-shaman/chirimeneck)と言います。
それほど難しいことはしていません。
chirimen上でのrequest...Accessは二重の呼び出しができないので、別の定数に返却されるオブジェクトを閉じ込めただけです。
chirimenenck上の関数呼び出しだけで、chirimen上の構文をそのまま使えます。

~~~html
  <script src="../../polyfill/polyfill.js"></script>
  <!-- load driver  as you like -->
    <script src="../../drivers/i2c-ADT7410.js"></script>
  <!-- load driver  as you like -->
  <script src="../../chirimeneck/gpio.js"></script>
  <script src="../../chirimeneck/i2c.js"></script>
~~~
~~~javascript

//GPIO

(async function () {
  const gpio5 = await GPIO(5, "in");
  const gpio26 = await GPIO(26, "out");
  let v = 0
  gpio5.onchange = function (e) {
    v ^= v
    await gpio26.write(v);
  };
})();

///I2C

(async function () {
  const adt7410 = await i2cLoadDriver(ADT7410, 0x48);
  while (true) {
    let value = await adt7410.read();
    // do somthing
    await sleep(1000);
  }
})();

(async function () {
  const groveLight = await i2cLoadDriver(GROVELIGHT, 0x29);
  while (true) {
    try {
      var value = await groveLight.read();
      // console.log('value:', value);
      head.innerHTML = value ? value : head.innerHTML;
      await sleep(200);
    } catch (error) {
      console.log(" Error : ", error);
    }
  }
})();
~~~

#ネジのような部品
プログラミングで最も必要なものは、大きな大枠の問題を解決するための、小さな部品です。しかし、絆創膏的なコードを書くという意味ではありません。
問題となる具象を包み込んで、いかなる抽象化を施すかで、ソースコードの質は抜群に上がります。
今回は、自分の勉強のためにも書いてみたようなものですが、皆様のためにもなればと思います。
【備忘録】面情報に「//」がない.objファイルに//を挿入するvscodeの正規表現置き換え

さっきユタ・ティーポットの3Dモデルを自作の.objファイルローダで読み込もうとしたときに、`f 1/2/3`のような構文ではなく`f 1`だけしかなかったので、これを`f 1//`にする方法を書き残しておく。
いつもは少し長めの記事を書くのになんでいきなり備忘録かというと、Qiitaで話題になっている[この記事](https://qiita.com/HiromuMasuda0228/items/a71dea7ef4d77a30b118)を見て、「ちょっとしたことでも、もしかしたら他の人がみたら役に立つかもしれない情報を残しておこう」と思ったからである。

ユタ・ティーポットのデータは[こちら](http://inst.eecs.berkeley.edu/~cs184/sp09/assignments/teapot.obj)で配布されている。
見ていただけるとわかるだろうが、

```object:obj(一部抜粋)
f 2402 2410 2222
f 1694 1806 2208
f 2208 2222 1694
f 3092 3072 3078
f 3078 3116 3092
```

面情報は上のような記法で統一されている。これを

```object:obj
f 2402// 2410// 2222//
f 1694// 1806// 2208//
f 2208// 2222// 1694//
f 3092// 3072// 3078//
f 3078// 3116// 3092//
```

のようにBlenderで出力したような結果にするのが今回の目的である。

#結論
まず、vscodeで`teapot.obj`を開く。そして`Ctrl+f`で検索をかけるのだが、ここで正規表現を使う。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/86191/f7e7eb59-414b-6e10-0293-f0e172ea0c80.png)

```
検索文字列: f (\d+) (\d+) (\d+)
置換文字列: f $1// $2// $3//
```

上のような結果を入れ、すべてを置換することで
![image.png](https://qiita-image-store.s3.amazonaws.com/0/86191/cae034bc-745c-5b9a-f9c7-d099702ce7f3.png)
から
![image.png](https://qiita-image-store.s3.amazonaws.com/0/86191/a55ae100-f206-6a9c-b2c4-c7693019a42c.png)
こうなる

#最後に
最後まで見てくださり、ありがとうございます。
今後はこのような「いいねはたくさんもらえないと思うけど、自分が役に立ったので共有しておいて、万が一ほかの人が役に立ったらうれしいな」というような記事が多くなるかもしれないです。
そしてあわよくば、いいねを押してくれると嬉しいです。
【Swift】配列（Array）と辞書（Dictionary）の理解

※実行環境
Swift version 4.1.2

こんにちは。

配列と辞書はswift独自の考え方ではありませんが、初心者は使い分けを理解するのに苦しむポイントなのではないかと思います。（僕がそうであったように）

今日はこの二つについて書いていきます。

# 配列（Array）と辞書（Dictionary）の理解
Appleの公式ドキュメントにはそれぞれこのような記載があります。

[Array](https://developer.apple.com/documentation/swift/array)
>
* アプリ内のデータを体系化する事が可能である
* 一つの型に固定して保存していく事が可能である
>

[Dictionary](https://developer.apple.com/documentation/swift/dictionary)
>
* Dictionaryはハッシュテーブルの型である。
    * 全体のコンテンツに素早くアクセス出来る
* ハッシュテーブルにはそれぞれに当てられたKeyによってアクセス出来る
>

二つを比較すると分かりやすいと思います。

![配列と辞書.001.jpeg](https://qiita-image-store.s3.amazonaws.com/0/263722/217a5a0b-78ef-80dc-e7bb-6331555b0bfa.jpeg)

簡単に言えば、

__配列は、番号が振られた箱の中にデータが格納されているもの__

__辞書は、自分でタイトルを指定した箱の中にデータが格納されているもの__

という違いがあります。

特にこの番号とタイトルの違いが大きく異なると思います。
後で話しますが、これによって使い分けも決まります。

コードで見ていきましょう。

```swift:arrayPractice.playground

import UIKit

// 配列の初期化

var list : [String] = []

// 配列に値を追加

list.append = ["月","火","水","木"]

/*
初期値が予め決まっている場合は以下の方法で配列を宣言出来る。

var list : [String] = ["月","火","水","木"]

また、appendの代わりに演算子を用いて値を追加する事も可能。ただし、追加できるデータは一つまで。

list += ("金")

*/

// 配列の中身の個数を出力

print(list.count) // 6

// 配列の中身のデータを全て出力 ２パターン

print(list)

for i in list {
    print(i)
}

// 上記二つ全て以下の結果
// 月,火,水,木

// 配列の特定の値を出力

print(list[1],list[2]) // 月,火

```

```swift:dicPractice.playground

import UIKit

// 辞書の宣言
var dic = ["mon" : "月",
           "tue" : "火",
           "wed" : "水",
           "thu" : "木",
           "fri" : "金",
           "sat" : "土"]

// 辞書内のデータにアクセス

print(dic["mon"]) // Optional("月")

// 辞書は普通に出力するとOptional型として出力するため、アンラップする必要がある。

print(dic["tue"]!) // 火

// 辞書にデータを追加
// 辞書変数に代入

dic["sun"] = "日"


//辞書内のデータを削除
// key値を指定し、nilを代入

dic["mon"] = nil

```

## 配列と辞書の使い分け

配列も辞書も複数データを保存し、自由に出し入れ出来るという点では同じですが、__データ数に応じて使い分けた方が良いです。__

先の画像とコードを見て分かるように、配列のデータにアクセスするためには配列が保存されている順番の数値（例えば火曜だったら"list[1]"）を使わなければいけません。

配列の中身が増えていけば、何番目に何のデータが入っているか覚えるのは難しくなるでしょう。
小規模、シンプルなアプリ制作においては問題ないかもしれませんが、大規模なアプリをつくりたかったり、複数人でアプリを制作する場面においては__法則性のないデータは開発に支障を与えかねません。__

いちいち配列の中身を確認していく作業は時間もかかるし、ミスも起こりやすいからです。

そこで辞書の出番です。

辞書なら、key値（添字）を自分で設定できるため、法則性を持たせる事が出来ます。
上の例で言えば、"mon","thu"を見ればどんなデータがそこに入っているか分かりやすいという事です。

説明の都合上、変数名を"dic"としましたが、これを"day"や、いっそ"曜日"にしてしまうのもありでしょう。（日本語をkey値にするのはあまり聞いた事ありませんが）

### ※おまけ 多次元配列について

配列は入れ子にする事が可能で、似たような種類のデータをまとめる事も出来ます。
とは言え、いずれにしてもデータ数が増えてきた場合は辞書を使う事をお勧めします。

```swift:arrays.playground
import UIKit

// 多次元配列の宣言と初期化

var days : [[String]] =
[["3月1日","3月2日","3月3日","3月4日"],
["4月1日","4月2日","4月3日"]]

// [配列の指定][配列のデータの指定]によって値を取り出す。

print(days[0][1],days[1][2]) // 3月2日 4月3日

```
PythonでUnderscore.jsのような配列操作

JavaScriptで書いてると、Underscore.jsがとても便利でしてな(´・ω・｀)

Pythonで配列操作やろうとした時に迷うことが多いので、自分用に対応表を作っておくことにしました。いいやり方見つけるたびにアップデートしていこうと思います。

基本的な配列操作(append/insert/pop/extend/+/*/スライス)は省略。

## 対応表
| Underscore.js | Python | 結果(Python) | 動作 |
|:---|:---|:---|:---|
| _.indexOf([1, 2, 3], 2) | [1, 2, 3].index(2) | 1 | 配列のどこにあるかインデックスを返す。なければ-1 |
| _.lastIndexOf([1, 2, 3, 2], 2) | (lambda array, val: len(array)-1 - array[::-1].index(val))([1, 2, 3, 2], 2) | 3 | 配列の後ろから検索してindexを返す。なければ-1。Python版は逆順配列を新たに作るので巨大な配列には使用しない |
| _.find([1, 2, 3], (val)=>{ return val == 2; }) | next((val for val in [1, 2, 3] if val == 2), None) | 2 | 配列の中に条件の合う値が存在すればそれを返す。無ければundefined/None | 
| _.contains([1, 2, 3], 2) | 2 in [1, 2, 3] | True | 配列に含まれるかどうかbooleanで返す |
| _.every([1, 2, 3], (val)=>{ return val < 10; }) | all(val < 10 for val in [1, 2, 3]) | True | 配列の内容が全て条件に当てはまるか |
| _.some([1, 2, 3], (val)=>{ return val < 2; }) | any(val < 2 for val in [1, 2, 3]) | True | 配列の内容が１つでも条件に当てはまるか |
| _.filter([1, 2, 3], (val)=>{ return val%2 != 0; }) | [val for val in [1, 2, 3] if val%2 != 0] | [1, 3] | 条件に一致した値だけ抜き出す |
| _.map([1, 2, 3], (val)=>{ return val+1; }) | [val+1 for val in [1, 2, 3]] | [2, 3, 4] | 配列の値を加工した新たな配列を作る |
| _.uniq([1, 2, 3, 2, 1]) | list(set([1, 2, 3, 2, 1])) | [1, 2, 3] | 重複を取り除く(※Pythonは順不同) |
| _.difference([1, 2, 3, 4, 5], [5, 2, 10]) | [val for val in [1, 2, 3, 4, 5] if val not in list(set([5, 2, 10]))] | [1, 3, 4] | 別の配列に存在しない値だけを返す |
| _.zip([1, 2], ["a", "b"], [true, false]) | list(zip([1, 2], ["a", "b"], [True, False])) | [(1, 'a', True), (2, 'b', False)] | 各配列の先頭要素から順番にグルーピングして１つの配列に |
| _.unzip([[1, 'a', true], [2, 'b', false]]) | list(zip(*[[1, 'a', True], [2, 'b', False]])) | [(1, 2), ('a', 'b'), (True, False)] | zipの逆動作。配列をバラして各グループでzipしなおす |
今更使うJSON Server

# [JSON Server](https://github.com/typicode/json-server)とは？
REST APIのモック。
コーディング無しで30秒もかからずに作れます（マジで）
>Get a full fake REST API with zero coding in less than 30 seconds (seriously)


# インストールから起動まで
Node.jsが導入されていることが前提です。

起動までならたった３ステップ。
## 1. json-serverのインストール
`npm install -g json-server`

## 2. db.jsonの作成
用意したディレクトリへ、*db.json*ファイルを作成。

```json:db.json
{
  "posts": [
    { "id": 1, "title": "json-server", "author": "typicode" }
  ],
  "comments": [
    { "id": 1, "body": "some comment", "postId": 1 }
  ],
  "profile": { "name": "typicode" }
}
```
※ルート直下のkey項目がそのままResource urlとなります

## 3.json-serverの起動
`json-server --watch db.json`

## 起動確認
テンション高めな顔文字が表示されたら起動成功です。

```
  \{^_^}/ hi!

  Loading db.json
  Done

  Resources
  http://localhost:3000/posts
  http://localhost:3000/comments
  http://localhost:3000/profile

  Home
  http://localhost:3000

  Type s + enter at any time to create a snapshot of the database
  Watching...
```

*http://localhost:3000*へブラウザからアクセスすると、
JSON Serverのホーム画面が表示されます。
![スクリーンショット 2018-10-20 15.35.02.png](https://qiita-image-store.s3.amazonaws.com/0/30704/bfe73ce7-5648-7643-8bf0-165eaf1c6c34.png)

あとはResourceに対してAPIcallしまくりましょう。
# 注意
Resourcesに対し、GET/POST/PUT/DELETE（取得/更新/挿入/削除）をすると、
***db.jsonが命令によって書き換わります。***
「せっかく作ったdb.jsonを、DELETEしてテスト不可能に……」なんてことにならないよう注意してください。
backupは、コンソールへ`s + enter`を入力すると取得できます。適宜使用しましょう。

# JSON Serverをカスタマイズする
## POSTでGETの内容が返却されるように
json-serverで用意されている、middlewareモジュールを利用します。
まずはmiddleware.jsを作成します。

```javascript:middleware.js
module.exports = function (req, res, next) {
  if (req.method === 'POST') {
    // Converts POST to GET and move payload to query params
    // This way it will make JSON Server that it's GET request
    req.method = 'GET'
    req.query = req.body
  }
  // Continue to JSON Server router
  next()
}
```
次に、起動時の引数で、middleware.jsを指定しましょう。
`json-server --watch db.json -m middleware.js`

## db.jsonを複数ファイルに分けたい
[json-serverでエンドポイント毎にjsonファイルを分割する - Qiita](https://qiita.com/nouka/items/47f26eecfd40712875e1)



# 参考
- [JSON Server使いこなし 第1回 モックサーバーの起動とリソース処理](https://app.codegrid.net/entry/2017-json-server-1)
- [Is it possible to 'get' data using POST with json-server? #453](https://github.com/typicode/json-server/issues/453)
jqだけ含むコンテナの作成

お勉強のため、jqコマンドだけを含むイメージを作成し、そのイメージをCLIとして使ってみる。作業はMacローカルで実施。

## jqコンテナ

### FROM alpine

こちらは以下の本で紹介されている内容です。

https://amzn.to/2Oc5y8w

Dockfileを作成する。

```dockerfile:Dockerfile
FROM alpine:3.7

RUN apk add --no-cache --virtual=build-deps wget && \
  wget https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 && \
  mv jq-linux64 /usr/local/bin/jq && \
  chmod +x /usr/local/bin/jq && \
  apk del build-deps
ENTRYPOINT ["/usr/local/bin/jq", "-C"]
CMD [""]
```

- jqに`-C`（`--color-output`）オプションをつけてターミナル以外に出力する場合もカラーリングを強制
- `--virtual`で仮の名前をつけておいて後で削除

イメージをビルドする。

```
docker image build -t sotoiwa540/jq-alpine:1.0 .
```

試す。パイプして使うので`-t`オプションはつけない。

```
echo '{"message": "hello"}' | docker container run --rm -i sotoiwa540/jq-alpine:1.0 .
```

（実行例）

```shell-session
$ echo '{"message": "hello"}' | docker container run --rm -i sotoiwa540/jq-alpine:1.0 .
{
  "message": "hello"
}
$
```

エイリアスを設定する。

```
alias jq-apline='docker run --rm -i sotoiwa540/jq-alpine:1.0'
```

エイリアスで実行。

```
echo '{"message": "hello"}' | jq-apline .
```

（実行例）

```shell-session
$ echo '{"message": "hello"}' | jq-apline .
{
  "message": "hello"
}
$
```

### FROM scratch

jqバイナリをダウンロードする。

```
curl -Lo jq https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64
```

実行権限をつけておく必要がある。

```
chmod +x jq
```

Dockerfileの作成。

```dockerfile:Dockerfile
FROM scratch

COPY jq /
ENTRYPOINT ["/jq", "-C"]
CMD [""]
```

ビルド。

```
docker image build -t sotoiwa540/jq-scratch:1.0 .
```

試す。

```
echo '{"message": "hello"}' | docker container run --rm -i sotoiwa540/jq-scratch:1.0 .
```

（実行例）

```shell-session
$ echo '{"message": "hello"}' | docker container run --rm -i sotoiwa540/jq-scratch:1.0 .
{
  "message": "hello"
}
$
```

イメージサイズを確認。

```shell-session
$ docker image ls | grep sotoiwa540/jq- | grep 1.0
sotoiwa540/jq-scratch                      1.0                 03a5a3445b84        6 minutes ago       3.03MB
sotoiwa540/jq-alpine                       1.0                 1ceb11c3b68e        40 minutes ago      7.26MB
$
```

もともとダウンロードしたjqのサイズを確認。

```
$ ls -l -h jq
-rwxr-xr-x  1 sotoiwa  staff   2.9M 10 20 15:44 jq
$
```
WebComponentsとPolymerをかんたんにさわってみた

## WebComponentsとは？

HTMLで使える独自のタグを定義していつでも呼び出せるようにする技術。
フレームワークに依存しないため、再利用性が高い。

ライブラリやフレームワークが不要。
HTML/CSS/JavaScriptだけで構築することができる。

4つの仕様で構成される。

- Custom Elements
- Shadow DOM
- HTML Imports
- HTML Template


## Webcomponentsを使ってみる

サンプルプログラムで表示してみる。

```html:html
<html>
<head>

<style>
span {
  color: white;
  background-color: black;
}
</style>

<template id="hello">
  <style>
    .colored {
      color: red;
    }
  </style>

  <div class="colored">
    Hello, <span><content></content></span>!
  </div>
</template>

<script>
class HelloDiv extends HTMLElement {
  constructor() {
    super();
    const template = document.querySelector('#hello');
    const node = document.importNode(template.content, true);

    this.createShadowRoot();
    this.shadowRoot.appendChild(node);
  }
}
customElements.define('hello-tag', HelloDiv);
</script>

</head>
<body>

<div><span>fugafuga</span></div>
<hello-tag>World</hello-tag>
<div><span>hogehoge</span></div>
<hello-tag>WebComponents</hello-tag>

</body>
</html>
```

例えば

```
<hello-tag>World</hello-tag>
```
こう書くと

```
<template id="hello">
  <style>
    .colored {
      color: red;
    }
  </style>

  <div class="colored">
    Hello, <span><content></content></span>!
  </div>
</template>
```

<content></content>の中にタグで囲まれた部分、今回だとWorldが入ってきて、

Hello, World

と赤字で表示されます。


## ブラウザで参照してみる

Firefoxから参照したとき

![スクリーンショット 2018-10-20 16.43.50.png](https://qiita-image-store.s3.amazonaws.com/0/117147/27172aac-f7cd-a744-dbb1-d26c395c1c96.png)


Chromeから参照したとき
![スクリーンショット 2018-10-20 16.43.55.png](https://qiita-image-store.s3.amazonaws.com/0/117147/407e8bad-a279-42df-0f4e-d44076d8fd7a.png)



Chrome以外は対応していないモジュールが多いらしい、ブラウザごとの実装に差異が結構ある。

→Polymerを使えばOK！


## Polymerの特徴

- WebComponentsの機能を利用できるOSSライブラリ。


## WebComponentsをやってみる
Polymer-CLIのインストール

```
npm install -g polymer-cli
mkdir polymer-sample
cd polymer-sample
```

起動する

```
polymer-init
```

スターターキットを選択する

```
? Which starter template would you like to use?
polymer-3-starter-kit
```

Polymer serveを実行

```
polymer serve

info: [cli.command.serve]    Files in this directory are available under the following URLs
      applications: http://127.0.0.1:8001
      reusable components: http://127.0.0.1:8001/components/polymer-starter-kit/

```

## Netlifyへデプロイ

https://www.netlify.com/

![スクリーンショット 2018-10-20 16.58.45.png](https://qiita-image-store.s3.amazonaws.com/0/117147/8427fc60-13fd-6780-aa4a-7cc990ec6983.png)

GithubやGitLabのリポジトリと連携してホスティングできるサービス。無料。便利。

## 実際にデプロイしたもの

https://nervous-cray-8b5aa1.netlify.com/

## まとめ

全体の流れはこんな感じ。
部品化できるので便利っぽい。
WebComponentsをもっとさわる必要あり。
systemd環境におけるハードウェアクロック調整を自動でやらせる

[systemd環境におけるハードウェアクロック調整](https://qiita.com/slug/items/4f902f45c5796f69309c)を自動化しましょう。
それも、cronを使わずに！~~と言っても、まーcronの方が短くて楽ですね。~~
なお、今回使用した環境は前回のopenSUSE TumbleweedではなくGentooです。

#TL;DR

以下の2ファイルを書きます。

```systemd.unit:/etc/systemd/system/hwclock.service
[Unit]
Description=hardware clock adjustment if NTP synchronized
Wants=time-sync.target

[Service]
Type=oneshot
User=root
Group=root
StandardOutput=journal
StandardError=journal
ExecStart=/sbin/hwclock --utc --update-drift --systohc --verbose
```

```systemd.unit:/etc/systemd/system/hwclock.timer
[Unit]
Description=adjust hardware clock monthly

[Timer]
OnCalendar=monthly

[Install]
WantedBy=timers.target
```

そしたら`# systemctl enable --now hwclock.timer`すれば毎月1日に調整してくれます。
マメな人であればその後`$ journalctl -u hwclock.service`でログを確認して、頻度を調整すれば完璧でしょう。

## 補足

サービスファイルのExecStart行の最後にある`--verbose`ですが、util-linuxのバージョンに依存して`--debug`じゃないと動かない可能性がありますので、サービスファイルに書く前に一度は手動で実行して出力を確認することをオススメします。~~Gentooでは7月の2.30.2から2.32.4へのアップデートでverboseにしないとログを吐いてくれなくなったために一回分記録がパーになりました。~~

# ログは実際どんな感じになる？
手元のサーバでこのタイマーを数ヶ月走らせた結果を貼りたいのですが、何日かお待ちください。
cognitoの2種類のフェデレーションについてメモ

AWSのCognitoには名前にフェデレーションとつくリソースが二つある

- Cognito フェデレーテッドアイデンティティ
    - [Amazon Cognito ID プール (フェデレーティッドアイデンティティ) - Amazon Cognito](https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/cognito-identity.html)
- Cognito UserPool サードパーティー (フェデレーション) 経由のサインイン
    - [サードパーティー経由のユーザープールへのサインインの追加 - Amazon Cognito](https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/cognito-user-pools-identity-federation.html)


公式ドキュメントで明示的に違うものだと注記がつく(程度には紛らわしい)

> 注記
> サードパーティー (フェデレーション) 経由のサインインは、Amazon Cognito のユーザープールで使用できます。この機能は、Amazon Cognito ID プール (フェデレーティッドアイデンティティ) 経由のフェデレーションとは別のものです。


## Cognito フェデレーテッドアイデンティティ

Cognito IDプールのこと

> 外部のIDプロバイダーで認証し、AWSでの一時的なID(STS)を作成できる。このIDを利用して、Cognito Sync とデータを同期したり、他のAWSサービスにアクセスできる。

- Cognitoの古いほうの機能
- 例えば、Facebookなどでログインさせて一時的にAWSの権限を付与することが出来る
- AWSサービスの認可に使えるが、認証は出来ないのでどこの誰だかはわからない
- APIGateway,Dynamodb,S3へのアクセスを制御、とかはこれだけで出来る
- ID**プール**とプールという言葉がついているが永続的なID管理をしてくれるわけではない


## Cognito UserPool のフェデレーション

Cognito Userプールの一機能

> ユーザーディレクトリを作成、管理し、モバイルアプリやウェブアプリケーションにサインアップとサインインを追加できる。

- Cognito UserPoolはCognitoの新しいほうの機能 (とても便利になったと評判)
    - UserプールはアプリのUserテーブル的なところawsがやってくれるサービス
    - 認証/パスワード再発行/MFAなどの機能が利用できる
- このUserテーブルに、Facebookでログインしたユーザを登録できるのがUserPoolのフェデレーション


### 連携

紛らわしい概念同士を連携させることが出来る

CognitoIDプールのIDプロバイダ(Facebook, Google)の一つとして
CognitoUserプールを使うことが出来る


## 参考

- [AWSとフェデレーション – サーバーワークスエンジニアブログ](http://blog.serverworks.co.jp/tech/2017/07/19/aws-federation/)
- [Amazon Cognito と仲良くなるために歴史と機能を整理したし、 Cognito User Pools と API Gateway の連携も試した ｜ DevelopersIO](https://dev.classmethod.jp/server-side/serverless/amazon-cognito-api-gateway-idtoken/)
はじめてのyukicoder vol.1

今回からyukicoderの問題をどんどん解いていきまーす

最初は【初めての方へ】で紹介されている問題を解いていきたいと思います

まずはNo.9000『文字を出力』ですよー<br>

##No.9000

```9000.f90
implicit none
character n*9
read(*,*)n
if ("n"=="Hello World!") then
    write(*,*)"Hello World!"
else
    write(*,*)"Hello World!"
end if
end

```
特にいうことなし！・・・と言いたい。

文字列の入力と判別に関しては初めてかいたんですよね・・・

"<font color=#FFCC00>character</font>"とか使って"n"は文字列ですよーとかしてますが、

他にもやり方あったんじゃ？と思うこの頃。

<br><br>

次はNo.480『数値計算』ですよー<br>
##No.480

```480.f90
integer a,n
read(*,*)n
a=0
do i=1,n
   a=a+i
end do
write(*,*) a
end
```
これに関しても特にいうことないですネ

ただ、yukicoderの仕様で"a"を整数型にしないと弾かれます

出力の書式形式を気にしなくても良い分、忘れがちなんですよねー

<br><br>

最後はNo.9002『FizzBuzz』<br>
##No.9002

```9002.f90
implicit none
integer i,j

read(*,*) j
 do i=1,j
  if (mod(i,15)==0) then
      write(*,*)"FizzBuzz"
  else if (mod(i,3)==0) then
      write(*,*)"Fizz"
  else if (mod(i,5)==0) then
      write(*,*)"Buzz"
  else
      write(*,*) i
  end if
 end do
end
```
コ　ピ　ペ

#####ああ＾〜たまらねえぜ

第二項辺りに載せてるものを書き換えただけです

今回は以上！
ssd_kerasを試してみる

## 環境
Mac
Anaconda 5.3
python 3.6.6
keras2
tensorflow 1.11.0
## ssd_kerasを取得
```
$ git clone https://github.com/rykov8/ssd_keras.git
```
## 必要な物をinstall
opencv

```
$ conda install -c conda-forge opencv
```
あたりまえだけど、keras

```
$ conda install keras
```
## 動かしてみる
準備が整い、SSD.ipynbを上から順に実行していくと、下記の部分でエラーがでた。

```python
input_shape=(300, 300, 3)
model = SSD300(input_shape, num_classes=NUM_CLASSES)
model.load_weights('weights_SSD300.hdf5', by_name=True)
bbox_util = BBoxUtility(NUM_CLASSES)
```

```py
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-dd64fe36fa33> in <module>
      1 input_shape=(300, 300, 3)
----> 2 model = SSD300(input_shape, num_classes=NUM_CLASSES)
      3 model.load_weights('weights_SSD300.hdf5', by_name=True)
      4 bbox_util = BBoxUtility(NUM_CLASSES)

~/github/ssd_keras/ssd.py in SSD300(input_shape, num_classes)
    256                              net['conv8_2_mbox_loc_flat'],
    257                              net['pool6_mbox_loc_flat']],
--> 258                             mode='concat', concat_axis=1, name='mbox_loc')
    259     net['mbox_conf'] = merge([net['conv4_3_norm_mbox_conf_flat'],
    260                               net['fc7_mbox_conf_flat'],

TypeError: 'module' object is not callable
```

## Keras2に対応する
Kerasのversionが合っていないらしい。
Pull requestにKeras2に対応してくれている方がいたので、使わせて頂く。

```
$ git fetch origin pull/141/head:api_update_to_keras2
```

```
$ git branch -a
  api_update_to_keras2
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
```

```
$ git checkout api_update_to_keras2
```

## もう一度動かしてみる
notebookを起動しなおして再実行してみると、今度は問題なし。
SSD.ipynbもいろいろ書き換わっていて問題なく動いた。
これを参考にしながら自分なりに何か作ってみたい。

![ダウンロード.png](https://qiita-image-store.s3.amazonaws.com/0/109158/6543b716-b9a2-5fb3-5078-6452758b9864.png)
ApacheでActive Directory SSO

# 本記事の内容
CentOS/Apache上のリソースにアクセス制限を行い、Active Directoryで認証させる方法です。ADにログオンしているWindows端末からはKerberosでSSOできるようにします。

# 参考文献
これがわかりやすいです。
https://active-directory-wp.com/docs/Networking/Single_Sign_On/Kerberos_SSO_with_Apache_on_Linux.html

# Active Directoryの設定
- ドメインコントローラがなければセットアップします (本記事ではhishi.localドメインで、DCはdc1.hishi.localです)
- apacheユーザーをドメインユーザーとして作成します (Linuxからの接続に利用します)
- keytabファイルを生成します

```
C:\> ktpass.exe -princ HTTP/www.hishi.local@HISHI.LOCAL -mapuser apache@hishi.local -pass Password1 -crypto RC4-HMAC-NT -ptype KRB5_NT_PRINCIPAL -out .\kerberos.keytab
```
このコマンドの詳細は、[ここ](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/ktpass)を参照してください。

# CentOSでの設定
- Apacheが入ってなければ入れてください。 ``` # yum install -y httpd```
- Kerberos認証モジュールをインストールします ``` # yum install -y mod_auth_kerb```
- 確認用のコマンドをインストールします ``` # yum install -y krb5-workstation.x86_64```
- ADで生成したkeytabファイルを /etc にコピーし、パーミッションを設定します

```
# chown apache:apache kerberos.keytab
# chmod 400 kerberos.keytab
```

- /etc/krb5.conf を編集します。

```
[logging]
(省略)

[libdefaults]
(省略)
 default_realm = HISHI.LOCAL
(省略)

[realms]
HISHI.LOCAL = {
  kdc = dc1.hishi.local
  admin_server = dc1.hishi.local
  default_domain = hishi.local
}

[domain_realm]
.hishi.local = HISHI.LOCAL
hishi.local = HISHI.LOCAL

```
- dc1.hishi.local を解決できるようhostsなりresolve.confなり修正します
- httpd.confを編集します

```
<Directory "/var/www/html/sso">
    AuthType Kerberos
    AuthName "Kerberos Auth"
    KrbAuthRealms HISHI.LOCAL
    KrbServiceName HTTP/www.hishi.local
    Krb5Keytab /etc/kerberos.keytab
    KrbMethodNegotiate On
    KrbMethodK5Passwd On
    require valid-user
</Directory>
```
- 試しにticketをとってみます ```kinit -p apache@HISHI.LOCAL```

# Internet Explorerから接続
すべての設定が完了ましたので、Windows端末でInternet Explorerで接続します。ドメインにログオンした端末からはSSOできますし、そうでない端末はドメインのuser/passwordでログインできます。
この際、Apacheがイントラネットゾーン（正確にはゾーンの設定ではなくセキュリティの設定ですが）として認識しないとSSOできませんので、必要に応じてインターネットオプションを設定します。
神戸・関西のRuby関連イベント

私なりにリサーチしているイベントの一覧です！一覧にないものがあればコメント下さい〜
もし、私に会った時はどうぞよろしくお願いします。

## 神戸のRuby関連イベント

* [Kobe.rb (Doorkeeper)](https://koberb.doorkeeper.jp/)
* [Rails Follow-up Kobe (Doorkeeper)](https://rails-follow-up-kobe.doorkeeper.jp/events/81789)
* [Ruby関西 (Doorkeeper)](https://rubykansai.doorkeeper.jp/)

## 関西

* [関西 Ruby コミュニティー 紹介](https://rubykansai.github.io/kansai-ruby-community/)

### もっと広くイベントを探すなら？

Googleで検索して、こんな記事をQiitaでこんな記事がありました！

* [関西のIT関連の勉強会・コミュニティ一覧](https://qiita.com/todogzm/items/c26aab6caa59d081d4f4)

以下のような人気のあるイベント運営サイトで地域とキーワードを入力して、検索してみるのも手です。

* [Doorkeeper](https://www.doorkeeper.jp/)
* [Meetup.com](https://www.meetup.com/)
主要SNSアプリ内ブラウザのuserAgent比較

## モチベーション
iOS、Line内のブラウザとデフォルトブラウザのSafariで挙動が違う処理があるので、その判別をする必要があった。

## 実験方法

```
navigator.userAgent.toLowerCase()
```

の出力結果の比較

## (今の所の)結論
TwitterブラウザとSafariの区別がつかない



## 結果

### Safari

```
mozilla/5.0 (iphone; cpu iphone os 12_0 like mac os x) applewebkit/605.1.15 (khtml, like gecko) version/12.0 mobile/15e148 safari/604.1
```

### Line

```
mozilla/5.0 (iphone; cpu iphone os 12_0 like mac os x) applewebkit/605.1.15 (khtml, like gecko) mobile/16a366 safari line/8.14.5
```

### Facebook

```
Mozilla/5.0 (iphone; cpu iphone os 12_0 like mac os x) applewebkit/605.1.15 (khtml, like gecko) mobile/16a366 [fban/fbios;fbav/192.0.0.61.85;fbbv/126707849;fbdv/iphone10,3;fbmd/iphone;fbsn/ios;fbsv/12.0;fbss/3;fbcr/&#12489-&#12467-&#12514-;fbid/phone;fblc/en_us;fbop/5;fbrv/127817253]
```

### Twitter(Safariと変わらない)

```
mozilla/5.0 (iphone; cpu iphone os 12_0 like mac os x) applewebkit/605.1.15 (khtml, like gecko) version/12.0 mobile/15e148 safari/604.1
```


## おまけ
アプリ、OS、デバイス環境を判別する正規表現

```javascript
      var ua = navigator.userAgent.toLowerCase();
      var isIOS = /ip(hone|od|ad)/.test(ua);
      var isAndroid = /android/.test(ua);
      var isMobile = isIOS || isAndroid;

      var isLine = /line/.test(ua);
      var isFacebook = /fb/.test(ua);
      var isSafari = /safari/.test(ua);
      var isChrome = /chrome/.test(ua);
      var isOpera = /opera/.test(ua);
```
シーケンス図

![スクリーンショット 2018-10-20 15.48.36.png](https://qiita-image-store.s3.amazonaws.com/0/286971/fe938c69-a08e-56c5-9a91-8f79910e6b25.png)

## 開始タグ閉じタグ

```
@startuml

　ここに記述していく

@enduml
```

## タイトル

```
・式
title
  タイトル
end title

例）

@startuml{plantuml_seq_title.png}

title 簡単なシーケンス図の例

Alice -> Bob: 認証要求
Bob --> Alice: 認証応答

@enduml


```

## アクションの流れ

```
・動き
->
<-

・ラベル

Alice -> Bob :同期メッセージ
Alice <- Bob :戻りメッセージ

```

## スペース  |||

```
@startuml{plantuml_seq_space.png}

Alice -> Bob: message 1
Bob --> Alice: ok
|||
Alice -> Bob: message 2
Bob --> Alice: ok
||45||
Alice -> Bob: message 3
Bob --> Alice: ok

@enduml

```

## 外部とのやりとり
```
[-> A: DoWork

A ->] : Request
A<--]

[<- A: Done
```

### ボックス

```
式）
box [ラベル] [色]
  participant または actor による定義
end box


例）
@startuml{plantuml_seq_box.png}
box "社内" #LightBlue
	actor エンジニア
	participant サポート
end box
participant 顧客

顧客 -> サポート : 問い合わせ
サポート -> エンジニア : 問い合わせ

エンジニア --> サポート : 回答
サポート --> 顧客 : 回答

@enduml

```



## メッセージのノート

```
 ・方程式
note 位置 [色] 
  コメント
end note

例）
@startuml{plantuml_seq_notes.png}
'この行は PlantUML のコメントで無視されます。
Alice->Bob : hello
note left : 最初のメッセージに対するノート

Bob->Alice : ok
note right #aqua : 次のメッセージに対するノート

Bob->Bob : I am thinking
note left #FFAAAA
	ブロックを使って定義した
	複数行の長いノート
end note

@enduml

```


```

## 実行

ctr potion  p

## 参考

http://yohshiy.blog.fc2.com/blog-entry-153.html
直列キューに非同期でタスクを追加するという意味

#背景

以下のコードの意味がずっと分からなかった。

```swift
DispatchQueue.main.async {
    print("Hello, World")
}
```

mainキューは直列処理（同期処理）を実行したい時に使用すると耳にした。
それでは、なぜ DispatchQueue.main.**sync** ではなく、DispatchQueue.main.**async** なのか。

僕はこれまで、以下のコードと実行結果を見て、
「処理が順番に実行されている！！　よし、同期処理成功だ！！」と喜んでいた。

```swift
for i in 0...10 {
    DispatchQueue.main.async {
        print("Start: \(i)")
        sleep(1)
    }
}

/*実行結果

Start: 0
Start: 1
Start: 2
Start: 3
Start: 4
Start: 5
Start: 6
Start: 7
Start: 8
Start: 9
Start: 10
*/
```

でも、なぜasync？？ syncじゃないの？？と思い、DispatchQueue.main.**sync**にした途端、xcodeからお叱りを受ける。意味がわからなかった。


#僕の勘違い

僕は、「ここでの直列処理と非同期処理の**実行主体は同じである**」という勘違いをしていた。

つまり、`DispatchQueue.main.async`は、
「mainキューが直列処理かつ非同期処理を行なうこと」を意味していると思っていた。


##ここでの直列処理と非同期処理の実行主体は異なる
以下のコードを実行してみて初めて理解ができた。

```swift
for i in 0...10 {
    DispatchQueue.main.async {
        sleep(1)
        print("Start: \(i)")
    }
}

print("End")
```

＜僕の予想した実行結果＞

```
Start: 0
Start: 1
Start: 2
Start: 3
Start: 4
Start: 5
Start: 6
Start: 7
Start: 8
Start: 9
Start: 10
End
```
＜実際の実行結果＞

```
End
Start: 0
Start: 1
Start: 2
Start: 3
Start: 4
Start: 5
Start: 6
Start: 7
Start: 8
Start: 9
Start: 10
```
---
？？？　
mainキューは直列処理（同期処理）を実行してくれるものじゃないの？

だとすると、これも

```swift
for i in 0...10 {
    DispatchQueue.main.async {
        sleep(1)
        print("Start: \(i)")
    }
}
```
これも

```swift
print("End")
```
mainスレッドで実行されるのなら、上から順番に実行されるんじゃないの？？

##非同期処理と直列処理の意味
そう、ここでのasync（非同期）の意味は、
**「タスクをキューに追加した後、そのタスクの処理完了を待たずに次の行に移行する」**であり、

mainキューの処理の特性であるSerial(直列)とは
**「キューに追加されたタスクを、追加された順番に、かつ前タスク処理が終わるのを待ってから処理側へ渡す」**
という意味。（ということを理解するのにすごく時間がかかりました。。。）

#まとめ
直列キューに非同期でタスクを追加するというのは、

「タスクをキューに追加した後、そのタスクの処理完了を待たずに次の行に移行し（**非同期**）、
キューは追加されたタスクを、前タスク処理が終わるのを待ってから処理側へ渡す（**直列**）。」
という意味。

つまり`DispatchQueue.main.async`メソッドにおいて、
同期・非同期というのは、**タスクを依頼した人（スレッド）**の動作に関わることで、
直列・並列というのは、**タスクを依頼された人（キュー）**の動作に関わること。


あー、やっと理解できたー。


#動作環境
- swift 4.2
- xcode 10.0



#参考リンク

- [Swift GCD入門](https://qiita.com/ShoichiKuraoka/items/bb2a280688d29de3ff18#%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%87%E3%82%A3%E3%82%B9%E3%83%91%E3%83%83%E3%83%81%E3%82%AD%E3%83%A5%E3%83%BC)
- [[Swift 3] Swift 3時代のGCDの基本的な使い方](https://dev.classmethod.jp/smartphone/iphone/swift-3-how-to-use-gcd-api-1/)
Clibor は Explorer のショートカットよりも優先順位が高いんですね

Clibor というクリップボード管理アプリがとても便利で、ずっと使っています。
https://www.vector.co.jp/soft/winnt/util/se472890.html

最近、エクスプローラーで `ctrl-shift-N` が聞かないぞ。と思ったら、
Clibor の定型文にショートカットを追加していたことが原因でした。
flutter upgradeで最新版にならない

現在flutter 0.9.4を使用しているのですが、GitHubのリリースタブにv0.10.1のタグがあったので、`flutter upgrade` を実行してみました。
しかし `flutter --version`の結果はかわらず、0.9.4のままです。

これはflutterがチャンネル毎に使用できるバージョンを管理しているためです。

`flutter channel`を実行してみると次のようになっていました。

```
Flutter channels:
* beta
  dev
  master
```

現在はbetaチャンネルでした。

[ここ](https://flutter.io/sdk-archive/#macos) でチャンネル毎に使用できるバージョンの確認ができます。
betaチャンネルは0.9.4が最新だったので、flutter upgradeをしてもバージョンが上がらなかったのですね。

現時点ではbetaの使用が推奨されているようですが、どうしても最新版を使いたい場合は `flutter channel dev`などとチャンネルを変更することでアップグレードできるようです。

# 2018/12/16追記
Flutter 1.0リリースに伴ってstableチャネルができました。
今後はこれを使えば基本的に問題なさそう。

```
Flutter channels:
* beta
  dev
  master
  stable
```
【書評】猫と森羅と日本語とRuby

# 技術書典5で買った本の書評

技術書典5で購入した本の書評を書いていこうと思います。

- 1. 猫と森羅と日本語とRuby  
https://qiita.com/drafts/ba919346367266414f99/
- 2. 秒速DEEP LEARNING
- 3. 色んなところでKubernetesを動かす本
- 4. Kubernetesの単語帳
- 5. 応用編 Kubernetes

## 1. 猫と森羅と日本語とRuby

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/f33294d7-be1c-dc1c-75b0-4b957832673b.png)


COMIC　ZIN　通信販売/商品詳細 猫と森羅と日本語とRuby
https://shop.comiczin.jp/products/detail.php?product_id=38068

猫と森羅と日本語とRuby - youchan - BOOTH（同人誌通販・ダウンロード）
https://youchan.booth.pm/items/1041946

あまりにも可愛い表紙に買おうかどうか迷ったのですが、技術書典5の会場を2回ぐらいぐるっと回って、Rubyに関する本が少なかったので思いきって買ってみました(Railsの本はあった)。

機械学習やディープラーニングをやろうとしていて、知識だけは付けてきましたが、どうもPythonに慣れずにTensorFlowを眺める日々を送っていました。なぜ、Rubyで書けないのか、Rubyで書ければいいのにとRuby脳に汚染されているのでJupyterでRubyが動くと聞けば試してみたりしていました。

そうこうしていると、Red Data Toolなるものがあると知っていました。
Red Data Tools - Rubyでデータ処理！
https://red-data-tools.github.io/ja/

しかし、今回この本を買う時には、そのようなものが出てくるとは全く想像しておらず「はじめに」を読んでビックリしました。まさしく、Red Data Tools のRed Chainer について書かれていたからです。（正確にいうと買う前に見本をパラパラッと見せてもらって多層パーセプトロンの図とかがでてきていたのでそういう本だとは思っていました）

この本は、日本語の自然言語処理とディープラーニングのRuby本です。
形態素解析から深層学習、word2vec、LTSM、RNNの話まで全編Rubyで突きとおしています。

かつ `分かりやすい文体` と `分かりやすい Rubyのソースコード` で書かれているので初学者の方にもお勧めの一冊だと思います(これで全部分かる分けじゃないのは当然ですので注意してください)。

特に Ruby脳に汚染された人には、とてもいいのではないかと思います。
Red Chainer入門書と言うにはちょっと大げさですね。どういうものかを理解するための紹介書と言った方がよいでしょう。

個々の章は、GitHubのソースコードを見ながら読むといいですね。

総じて面白い内容で無味乾燥な機械学習の本を読むよりも断然ライブ感がありました(コミットログを見るとさらに)。
（薄い本は個人の体験を元に書かれているので、その他の本でも同様のライブ感を感じました）

残念ながら著者の「森羅:Wikipedia構造化プロジェクト2018」へのチャレンジは今年間に合わなかったようですが、継続してチャレンジするということですし、続編も期待して待ちたいと思います。

残念な点としては、本の題名がなかなかポエティックなので、技術書典に来られた方は手に取りにくかったのではないかと思います(私もまさかそんなハードな本とは思いませんでした)。書店に並ぶ本ならオビを着けたいところですね。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/701a9b19-e2af-1f54-3435-0efdbe3e02c6.png)

ShinraSetsumeikai20180424.pptx - Google ドライブ
https://drive.google.com/file/d/1UhTGxPlZEkMdDnpSgJjlBYH2Rg0OlRc_/view
Google Home端末の初期設定ではまったメモ

#はじめに
Google Home Miniを買いました。
Bicカメラで5000円以上の買い物をすると半額の3000円になりますよ、といういつものキャンペーンによって。
この記事はGoogle Home端末の初期設定ではまってしまったので、その解決方法を書きます。

#何が起こったのか
Google Home端末の設定手順は大雑把にいって以下のとおりです。

1. スマホまたはタブレットに「Google Home」アプリをインストールする。
2. Google Home端末を電源に接続する。
3. 「Google Home」アプリからGoogle Home端末を追加する。

以上です。
この3番のGoogle Home端末の追加の作業で2つの問題が起きました。

- 「Google Home」アプリからGoogle Home端末を見つけられない
- Google Home端末を自宅Wifiへ接続できない。「ネットワーク上にGoogle Home Miniが見つかりません」と表示される。

#どうしたのか

1. Google Home Miniをリセットしました。リセット方法は裏側のリセットボタンを長押しです。
2. 無線Lanルーターを再起動しました。

これによって、Google Home端末を自宅Wifiに接続する処理は何事もなく完了し、我が家でGoogle Home Miniが無事に稼働を始めました。

とりあえず初期化・再起動は鉄板だなと改めて思いました。

#今後の課題
Google Home Miniの購入をどう妻に説明したらよいのか、検討しなければなりません。
Alexaさんもいるのに。
eslintの個人的な設定メモ

### ESLintの設定をしました。個人メモです。
とある小さなプロジェクトに参加することになり、.eslintrcの設定を書いてみました。
本来はチーフエンジニア的な人が、チームのコーディング規約を定めてそれに沿ってlintの設定を書くのが正だと思います。
今回はそれほど厳密にやる必要がないものなので、勉強ついでに書いてみました。
公式に沿って記述していくだけです。

### extendsプロパティ
.eslintrcのextendsプロパティに以下の記述すると、嬉しい。

```json:.eslintrc.json
"eslint:recommended"
```
これを書いていれば、eslintの推奨チェック項目が適用される。
あとは、これをベースに変更していく。

### 実際にどんな項目がチェックされているか？
[eslintの公式のルール一覧](https://eslint.org/docs/rules/)
↑これの左にチェックが入っている項目が、推奨の項目である。

### コーディング規約に沿って、ルールに変更を加えていく
あとは、コーディング規約とか、あのプロジェクトのあの設定は助けられたな。
みたいなものでルールを追加していきます。

### 参考
- [ESLintの公式](https://eslint.org/docs/user-guide/configuring)
- [公式のルール](https://eslint.org/docs/rules/)
- [eslint-plugin-react](https://github.com/yannickcr/eslint-plugin-react)
deviseを日本語表記にする。

#手順
deviseを入れた後、
ログイン時やログアウト時に出てくる文字を日本語にしたい。あとフォームに入力したエラーメッセージとか。

##gemのインストール

```
gem 'devise-i18n'
gem 'devise-i18n-views'
```

```$bundle install```

###読み込む用の日本語対応のymlファイルを作成
```$rails g devise:views:locale ja```

##日本語で反映されるようにconfig/application.rbに追記
config/application.rbファイル内の
class Applicationの中に
```config.i18n.default_locale = :ja```を記入。

***これで一旦完成です。***

###自分用にymlファイルを修正する
空欄で入力した時に表示される、
```「○○ cant be blank」```の部分を日本語にしたい。
***階層を作って***、修正する。

###修正前

```devise.views.ja.yml
ja:
  activerecord:
    attributes:
      user:
        current_password: "現在のパスワード"
        email: "メールアドレス"
        password: "パスワード"
        password_confirmation: "確認用パスワード"
        remember_me: "ログインを記憶"
    models:
      user: "ユーザ"
  devise:
    confirmations:
      new:
        resend_confirmation_instructions: "アカウント確認メール再送"
以下省略

```

###修正後

```devise.views.ja.yml
ja:
  activerecord:
    errors:
      models:
        user:
          attributes:
            email:
              blank: "が入力されていません。"
            password:
              blank: "が入力されていません。"
        message:　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　←これは自分で作ったmodel
          attributes:
            title:　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　←自分で作ったカラム名
              blank: "が入力されていません。"
            content:　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　←自分で作ったカラム名
              blank: "が入力されていません。"
    attributes:
      user:
        current_password: "現在のパスワード"
        email: "メールアドレス"
        password: "パスワード"
        password_confirmation: "確認用パスワード"
        remember_me: "ログインを記憶"
    models:
      user: "ユーザ"
  devise:
    confirmations:
      new:
        resend_confirmation_instructions: "アカウント確認メール再送"
以下省略
```

カラム名の日本語化は別途で
`config/locales/models.ja.yml`を作成


```config/locales/models.ja.yml
ja:
  activerecord:
    attributes:
      post: #これがmodel
        question_title: 質問
        answer: 回答
```

参考：
https://qiita.com/shizuma/items/a52fd0ef5b60d61fa330
http://31webcreation.hatenablog.com/entry/translate-devise-to-japanese
Askpassが無いだって？

**追記：不具合だったそうでアップデートで直りました。**

**※この対処法が合っているか正直に言って分かってません。**



##使用ソフトについて
[Sourcetree](https://ja.atlassian.com/software/sourcetree)




#経緯
数日前にSourcetreeの更新をしましてバージョンが3.0.6に変わりました、たぶん。
そんなことは気にせずいつも通りにコミットしてプッシュしたらエラーが出ました。
３，４行に渡ってエラーメッセージが出ましたか要約すると**「Askpass.exeが存在しない」**ということでした。
まっさかぁと思い指定されていたディレクトリを覗いたらあら、本当にありませんでした。



#対策
いたって簡単。
エラーにて指定されたディレクトリは更新した際に出来た**「app-3.0.6」**の階層下でした。
その隣にはアプデ前に使っていたバージョンが残っていました。
古い方にはちゃんと**Askpass**に関するdllやexeが残っていました。
なのでそれをコピーして新しい方に移しました。

それだけです。以上です。



#お詫び
冒頭でも申し上げましたがこれが本当に正しいのか分かっていません。
ちゃんとした対策がありましたら教えていただけると幸いです。
Railsでパフォーマンスチューニングする前準備

パフォーマンスについて全然わからなかったので、測定の仕方から調べた。
現状のパフォーマンスの把握 => 改善ポイント出し => 改善のプロセスの中で、現状のパフォーマンスの把握についてまとめた。

## パフォーマンスの把握
### rack-mini-profilerで測定する
簡単なパフォーマンス測定ができるgem `rack-mini-profiler` が便利（プロファイリングツールというらしい）
[rack-mini-profiler](https://github.com/miniprofiler/rack-mini-profiler)
ViewのレンダリングやActiveRecordの問い合わせにかかる時間などを計測してくれる

```ruby
gem 'rack-mini-profiler', require: false
```
チーム開発であれば、デフォルトfalseにしておいたほうがいいとか..
その場合は、config/initializers以下に下記のファイルを作る

```ruby:config/initializers/rack_profiler.rb
if Rails.env == 'development'
  require 'rack-mini-profiler'
  Rack::MiniProfilerRails.initialize!(Rails.application)
end
```

bundle installして、プロセスの再起動を行う

するとページの左上に `xx.ms` という数字が現れる
数字をクリックすると、ページとアクションごとにどのくらいの時間がかかっているか、sqlが発行されているかがわかるようになっている
<img width="557" alt="スクリーンショット 2018-10-20 14.40.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/302494/b4ef8ab0-8f9b-d1dc-7080-6d0d762d3292.png">
左下の `share`　をクリックするとさらに詳しい情報がわかる

<img width="979" alt="スクリーンショット 2018-10-20 14.47.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/302494/1397dca1-7e67-2dab-5d2b-f1be80075be7.png">
※サンプルデータは処理が少ないので↑のような形だが、無駄なクエリが走っていないか、などページとアクションごとに可視化される

### googleの検証ツールも優秀
検証ツールの中の `Newwork` タブでレンダリング速度など測定可能
<img width="736" alt="スクリーンショット 2018-10-20 14.51.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/302494/630ad279-c32b-b386-029a-32f6d16e53d7.png">

一番下に全体の表示速度を表示してくれる
<img width="743" alt="スクリーンショット 2018-10-20 14.54.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/302494/08020a3c-1899-38ac-613d-da52ed8dff2b.png">

TTFB(Time To First Byte)も参考になる
最初の1バイトでリクエストを投げてから返ってくるまでの速度らしい
Googleはこの部分が `200ms` までで返ってくることを推奨している模様
<img width="728" alt="スクリーンショット 2018-10-20 14.51.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/302494/5773e5f0-181d-dfab-f86a-e11e2b00711d.png">

###　おまけ
[google PageSpeed Insights]
(https://developers.google.com/speed/pagespeed/insights/)

* PageSpeed InsightsはURLを入力するだけで、モバイルとPCそれぞれの速度計測と課題を提示してくれる


## これから調べること
- [ ] 他のプロファイルツール
- [ ] 実際の速度改善の施策、できること
PythonでサクッとCLIツールを作る

# はじめに
業務でちょっとツールが必要という時はPythonを使いましょうという話。
お仕事でSEOやコンテンツマーケティングをしていると、ページをスクレイピングしたりするためにちょっとしたツールが必要になることがある。Pythonはこのようなタスクを片付けるのにちょうどいい。



# この記事でやらないこと
argparseやclickみたいな、コマンドライン用のパースライブラリは使用しない。ヘルプメッセージも出さない。目的を達成するための最低限の実装さえあればよい、という状況を想定しています。



# 想定するファイル構成
シンプルなツールを想定しているので、ファイルは2つだけ。

```
oreore-project
+ app.py
+ setup.py
```



# 実装手順
## setup.pyを書く
`install_requires`に必要なパッケージを書き、`entry_points`に`console_scripts`を定義する。
setup.pyについては以前まとめたので、詳細が気になる人は読んで欲しい。([pythonのsetup.pyについてまとめる](https://qiita.com/Tadahiro_Yamamura/items/2cbcd272a96bb3761cc8))

```python:setup.py
from setuptools import setup

setup(
    install_requires=["requests","beautifulsoup4"],
    entry_points={
        "console_scripts": [
            "oreore = app:main"
        ]
    }
)
```

## 処理を実装する
```python:app.py
import requests
import sys
from bs4 import BeautifulSoup

def main():
    # 引数の受け取り
    url = sys.argv[1]

    # 適当に処理を実装
    soup = BeautifulSoup(requests.get(url).text, "html.parser")
    print(soup.title.string)
```

## 必要なパッケージをインストールする
プロジェクトディレクトリに移動して次のコマンドを実行。

```bash:
$ pip install -e .
```


# 実行方法
コンソールを開き、コマンドを実行する。

```
$ oreore https://www.google.co.jp
Google
```
Vue.js で大きなオブジェクトをv-modelでやりとりするコンポーネントを作る

# はじめに

インプット要素を使いまわしたいなあと思っていたところ、ひらめいたので実装したらうまくったので紹介します。

# 目的

`v-model='hugeObject'` ができるカスタムコンポーネントを作る

# 方法

Reduxの考え方に影響を受けています。

## インプットエレメントをラップした「インプットコンポーネント」を作る

以下のように、インプットエレメントをラップします。

```vue:FormText.vue
<template>
  <label class="FormText" :for="name">
    <span>{{ label }}</span>
    <input type="text" :id="id" :name="name" v-model="text">
  </label>
</template>

<script>
export default {
  name: 'FoundationFormText',
  props: {
    id: String, // input要素のid
    label: String, // フォームのラベルに表示するテキスト
    name: String,  // input要素のname
    value: String, // input要素のvalue
  },

  computed: {
    text: {
      get() { return this.value },
      set(text) { this.$emit('input', text) },
    },
  },
}
</script>
```

このようにすることで、インプットエレメントをラップしたインプットコンポーネントを作成することができます。

## 「インプットコンポーネント」を複数所有するコンポーネントを作る

次に、上記で作成したコンポーネントたちを組み合わせたコンポーネントを作成します。

次い、 `lastName` と `firstName` を処理するコンポーネントを作ります。

```vue:CustomerForm.vue
<template>
  <div>
    <FormText v-model="lastName" id="last" name="last" label="姓" />
    <FormText v-model="firstName" id="first" name="first" label="名" />
  </div>
</template>

<script>
import FormText from './FormText.vue'

export default {
  name: 'CustomerForm',
  components: { FormText },
  
  props: {
    value: {
      type: Object,
      validator: customer => {
        if (typeof customer.lastName !== 'string') return false
        if (typeof customer.firstName !== 'string') return false
        return true
      },
    },
  },

  computed: {
    lastName: {
      get() { return this.value.lastName },
      set(lastName) { this.$emit('input', { ...this.value, ...{ lastName }}),
    },

    firstName: {
      get() { return this.value.firstName },
      set(firstName) { this.$emit('input', { ...this.value, ...{ firstName }}),
    },
  },
}
```

子コンポーネントに渡したいデータごとにcomputed propertyを作成します。
また、上記の例では 親コンポーネントから `value` propへ渡される値（Customer型）は、 `lastName` と `firstName` 以外のデータを受け取っても問題ないです。


このように定義したコンポーネントを使います。

```vue:RegisterForm.vue
<template>
  <div>
    <CustomerForm v-model="customer" />
    <OtherForm v-model="customer.otherObject" />
  </div>
</template>

<script>
import CustomerForm from './CustomerForm.vue'
import OtherForm from './OtherForm.vue'

export default {
  name: 'RegisterForm',
  components: { CustomerForm, OtherForm },
  
  data() {
    return {
      customer: {
        lastName: '',
        firstName: '',
        otherObject: {},
      },
    },
  },
}
</script>
```

# まとめ
`v-model`にコミュニケーションをまとめることで、再利用性の高いコンポーネントを作成できたと言えます。
react-popover で React 上でポップオーバーを手早く実装する

React でのポップオーバーの表示に最近取り組んでいたのですが、なかなか参考情報が見つけられませんでした。

色々調べた中で一番扱いやすそうだった <a href="https://github.com/littlebits/react-popover" target="_blank" rel="nofollow noopener">littlebits/react-popover</a> について紹介しようと思います。

## react-popover とは

<a href="https://github.com/littlebits/react-popover" target="_blank" rel="nofollow noopener">littlebits/react-popover</a>

React でシンプルにポップオーバーを実装できるライブラリです。

ポップオーバーにおける必要最低限のアニメーションが実装されており、ポップオーバーで表示できるコンテンツをカスタマイズできます。

また React の props を使って、ポップオーバーの挙動の調整もできます。

どんな形でポップオーバーが表示されるかは、<a href="https://littlebits.github.io/react-popover" target="_blank" rel="nofollow noopener">公式のStorybook</a> があるので、そちらからざっくり確認できます。

## インストール方法

yarn でパッケージ管理している場合は、下記でインストールできます。

```
$ yarn add react-popover
```

## サンプルコード

ボタンでポップオーバーを出し分ける、簡単なサンプルコードを書いてみました。

```jsx
import React from "react";
import ReactDOM from "react-dom";
import Popover from "react-popover";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isOpen: false };
  }

  togglePopover = () => {
    this.setState({ isOpen: !this.state.isOpen });
  };

  render() {
    return (
      <div className="App">
        <Popover
          isOpen={this.state.isOpen}
          body={<div className="Balloon">Popover Content</div>}
        >
          <button onClick={this.togglePopover}>Toggle Popover</button>
        </Popover>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```

Popover の `isOpen` props を切り替えることで、ポップオーバーの表示を制御するイメージです。

ボタン押下時に、`body` props に定義した jsx をポップオーバーとして表示しています。

こちらを実際に動かすと、以下のような感じになります。

https://codesandbox.io/embed/1421poyyn4

![Oct-19-2018 15-40-29.gif](https://qiita-image-store.s3.amazonaws.com/0/222030/4219f08e-c62d-3199-6aad-4c7686669a56.gif)

現状、ポップオーバーに何もスタイルをあてていないため、最低限の表示になっていますが、こちらに対してスタイルを適用していく形になります。

## react-popover の props について

ポップオーバーを制御する props は <a href="https://github.com/littlebits/react-popover" target="_blank" rel="nofollow noopener">README</a> にまとまっていますが、最低限以下をおさえていれば使えると思います。

prop | 内容
:--|:--
isOpen| ポップオーバーの表示・非表示を制御
body| ポップオーバーで表示させる Content
place| ポップオーバーを上下左右どの方向から表示させるか(`above`/`right`/`below`/`left`)
onOuterAction| ポップオーバー外のエレメントで `mousedown` か `touchstart` イベントを発生させたときのアクション

## 所感

react-popover は、bootstrap といったCSSフレームワークは使わないが、ポップオーバーだけ React で簡単に実装したい、という場合に使えそうだなと思いました。

ただ、README が必要最低限の使い方の説明しかされていないので、実際にサンプルコードを動かしながら動きを掴んでいったほうが良さそうです。