OmniAICreator/Qiita-1.07M huggingface dataset:
エンジニア組織LOBにおける英語化に向けて

# はじめに
こんにちは！LOBの @kshibayama です。
**この記事は** [株式会社 LOB Advent Calendar 2018](https://qiita.com/advent-calendar/2018/lob-inc) **8日目の記事です。**

今回、技術そのものからは少し離れますが、僕の勤務先で開発を進めるにあたって直面している英語化という課題について、記録がてら書こうと思います。
※Qiita内の他の記事にもエンジニア組織論的なものがあったので、怒られないはず。

# そもそも何をやっているの
LOBは、Web広告領域における開発を生業としているのですが、最近二子玉川にグローバル本社を構える一部上場企業に買収され、そのグループ傘下に収まりました。

我々が掲げているミッションは下記の通りで、特に市場を限定していないのは、上記買収の先に、日本に閉じないプロダクト開発に関わることが念頭にあったからなのでした。
> [**「流通のケタを変える広告プラットフォームを創る」**](https://lob-inc.com/)

そして今現在、このミッションの旗印のもと、プロダクト開発に勤しむ日々を過ごしています。

# 何が課題なの
大まかな状況としては、買収されてまだ日が浅いため、いわゆる買収後統合（PMI: Post Merger Integration）のプロセスが裏で進行するなかで、開発を進めています。その中で、少なくとも僕がこれまで経験してきた職場と違う大きな点があります。

それは、 **プロダクト開発において日本国外に拠点を置くチームと協業する前提があること** です。

LOBが買収されることになった大きな理由の一つに、いわゆるアドテクという技術領域における開発力があります。しかし、英語でのコミュニケーションを前提にした開発に対して社内の誰もが真剣に捉えられていたかというと、正直そうではなかったというのが実情です。

ところが、開発開始してから数ヶ月間がたった今、明らかになったのは、 **海外メンバーとの意思疎通不全、開発を共同して進めるのに困らない程度の英語力の必要性** でした。

そもそもグループの様々なビジネスで利用してもらえるような広告プラットフォームを作るためには、各地域ごとのビジネス状況、それに連なる要件の把握が必須であり、開発を進める上で日本に閉じずにそうした要件を考慮していかなければならないわけです。しかし、少なくともLOB内部で開発の優先度をつけるためにも、積極的に情報を取りに行くことが必要で、組織として **公用語としての英語** に適応していかなければならないなと考えています。

# 英語化してどうするの
これはもう端的に、日本国内だけでも3兆円以上の取引額を誇るECを中心とした事業群を、下支えする広告プラットフォームを作っていきます。それに尽きます。

日本国内だけで相当な額の取引があるのだから、別に英語化する必要ないじゃないか、という反論もありうると思いますが、マクロで捉えたときに縮小しつつある日本市場に閉じるのは好手ではない、ということになると思います。

以下のような証言もあるので、組織としての英語化もサクッとこなし、着実にミッションを遂行していきたい、という次第です。
> 「英語を学んだおかげで海外のエンジニアとコミュニケーションがとれるようになってきました。（中略）サービスに対する高いマインドは、海外のエンジニアたちに負ける気はしませんでした。したがって、これから重要になるのは、楽天グループ内の海外エンジニアたちにも、その高いマインドを知ってもらうこと。そのためにも英語が必要だと思っています。」
>> 三木谷浩史「たかが英語！」第4章; とあるエンジニアの証言より抜粋

---
株式会社 LOB では「流通のケタを変える、広告プラットフォームを創る」仲間を募集しています。
https://lob-inc.com/recruit/
CloudFront + WordPress (4.9.8以降?) で WP REST API 403 rest_cookie_invalid_nonce が出たときの対応方法 

CloudFront + WordPressでサイトを公開していて WordPress 4.9.8 で表題のエラーが発生し、記事の投稿がエラーになっていました。
その際の対応方法を備忘録としてまとめます。

# 環境

CloudFront -> EC2 (WordPress) -> RDS

WordPress は 4.9.8 で不具合を確認して、対応したあと 5.0 にアップデートしてから投稿できることを確認しています。

# 参考・前提

CloudFront + WordPress で環境を構築するのは以下が大変参考になるかと思います。
丁寧にまとめてくださってありがとうございます！

[WordPressサイトをCloudFrontで配信する - Qiita](https://qiita.com/Ichiro_Tsuji/items/38592e737257cb45ca13)
[CloudFrontの下でWordpressを実行する時に色々ハマった話 前編 - Qiita](https://qiita.com/kunitaya/items/1a78cd2d4d2971394e0d)
[CloudFrontの下でWordpressを実行する時に色々ハマった話 後編 - Qiita](https://qiita.com/kunitaya/items/876a12cc803c5d495f43)

上記に関する内容はこの時期では省略します。

# 投稿画面でエラー

新規投稿画面を開くと 403 エラーが発生します。

![スクリーンショット 2018-12-08 16.43.46.png](https://qiita-image-store.s3.amazonaws.com/0/16339/2769cc67-8afd-937c-5fc8-57d0803f246b.png)

レスポンスの内容はこんな感じです。

```
{code: "rest_cookie_invalid_nonce", message: "Cookie nonce が不正です", data: {status: 403}}
```

WordPressのいつのバージョンから発生するかは正確にはわかりませんが、Gutenberg の新エディタの状態でページで開いたときに非同期で投稿者のユーザ情報やカテゴリ情報を取得しているようです。

このエラーが発生している状態で内容を入力して公開しようとすると公開に失敗します。

![投稿の編集_WordPress.jpg](https://qiita-image-store.s3.amazonaws.com/0/16339/25019301-61df-de50-01e7-9139dda942a9.jpeg)

# エラーの原因

403 エラーになったリクエストは WP REST API にアクセスしています。
投稿者のユーザ情報は認証無しで取得できてしまうと問題なので、何かしらの認証情報を付与してAPIを呼び出していると推測しました。

検索したところAPI呼び出しは `_wpnonce` の値を設定して GET / POST で取得するか、HTTP Header に `X-WP-Nonce` を付与するかのいずれかでした。

参照 > https://v2.wp-api.org/guide/authentication/

Gutenberg の新エディタでは `X-WP-Nonce` のHTTPヘッダーを付与してアクセスしようとしているのですが、CloudFrontで該当のHTTPヘッダーを許可していないのでオリジンに届いていないことが原因です。

# 対応

CloudFront の Behavior で WP REST API のアクセスに該当のHTTPヘッダーをオリジンに渡すよう設定します。
AWSコンソールの CloudFront ページで対象の Distribution を選択し "Create Behavior" から以下のように設定・作成します。

![cloudfront_settins_01.jpg](https://qiita-image-store.s3.amazonaws.com/0/16339/8686c8cb-dc1d-bdf2-09ed-3dc3931ba8e2.jpeg)

要点だけ

- Path Pattern : `/wp-json/`
- Cache Based on Selected Request Headeres : `Whitelist` を選択
    - `X-WP-Nonce` を入力して「Add Custom」ボタンを押下して追加

![cloudfront_settins_02.jpg](https://qiita-image-store.s3.amazonaws.com/0/16339/41574795-a5bb-ab43-d655-8a98b89f1a61.jpeg)

- Forward Cookies : All
- Query String Forward and Caching : Forward all, cache based on all

# 結果

![投稿の編集_WordPress_after.jpg](https://qiita-image-store.s3.amazonaws.com/0/16339/39f51c44-d59b-d85f-3c6f-01ddbaa7e2d6.jpeg)

投稿できることを確認しました。
Kubernetes構築はkubesprayがおすすめ！

# はじめに
* この記事はKubernetesの構築ツールである「[kubespray](https://github.com/kubernetes-sigs/kubespray)」の宣伝記事です。
* 以前[kubeadmでの構築方法](https://qiita.com/ozota/items/027befd3fa77a826ea62)を書きましたが、実は私は普段kubesprayを使っています

# kubesprayのここがすごい！！
## 各ノードにいちいちログインしてコマンドコピペしなくていい！
* kubeadmで構築する場合、全てのノードにsshしてコマンドを打つ作業が必要です
* 一方kubesprayはAnsible製のツールであり、設定ファイルを編集してansibleコマンドを打つだけで、全ノードの設定を行ってくれます

## プロキシ設定箇所に困らない！！！
* DockerやKubernetesを使っていると、「プロキシ設定を書いたはずが反映されてない(;ω;)」なんて経験ありませんか？
* 設定ファイルに次の3行を書くだけで、Node, Docker, Kubernetesの各設定箇所に必要な設定を入れてくれます

```yaml
http_proxy: "<proxy>"
https_proxy: "<proxy>"
additional_no_proxy: "<private registry等、no_proxy設定したいものを列挙>"
```

## master冗長構成もたったの1行！！！
* インベントリのmasterを複数台指定するだけで、ロードバランサ等もろもろ含めてよしなにやってくれます

```yaml
[kube-master]
node1
node2
```

## 最新のKubernetesに追従！[^1]
* ツールによってはなかなか最新バージョンサポートしてくれないな。。なんてこともありますが、kubesprayはサポートしてくれます

## オンプレからクラウドまで幅広いサポート！[^2]
* README.mdに`AWS, GCE, Azure, OpenStack, vSphere, Oracle Cloud Infrastructure (Experimental), or Baremetal`と書かれているように、幅広いサポートです

## 構築だけでなく運用もサポート！[^3]
* [ノード追加・削除等の作業をサポートします](https://github.com/kubernetes-sigs/kubespray/blob/d30dbdde23df204e156fe054c13783438e38bfc3/docs/getting-started.md)
* [アップグレードもできます](https://github.com/kubernetes-sigs/kubespray/blob/master/docs/upgrades.md)

## IaC実現！[^4]
* 既存のAnsibleリポジトリと組み合わせることもできます: [kubespray in own ansible playbooks repo](https://github.com/kubernetes-sigs/kubespray/blob/master/docs/integration.md)

# さあKubesprayを始めよう！
* 本記事は宣伝記事なので実際の手順は紹介しません
  * 基本的な使い方は[CentOS7 kubespray で kubernetes(1.9) cluster を作る - その1 -](https://qiita.com/ainamori/items/cf24466c6c0f4cec16d5) にまとまっています 

# 免責事項
[^1]: サポートにはタイムラグが発生します。2週間〰2カ月程度かかる場合があります
[^2]: 筆者はBaremetal（オンプレ）のみ使用しており、クラウドへ構築したことはありません。
[^3]: 全ての運用作業がサポートされる訳ではありません。
[^4]: IaC導入による効果は組織差があります
Backlog API(v2) wrapperの実装者に送る、サポートAPIリストの作成ヘルパー

今私は[Backlog APIのPythonラッパー](https://github.com/hassaku63/backlog_util)を作っているところなのですが、サポートするAPIの一覧と、現在対応しているAPIの対応表が欲しくなりました。

本家サイトにその手の表はないようでした。ないなら自分で作ろうと思い立ち、Seleniumを利用したちょっとしたスクリプトを書いてみました。CC0なのでお好きにご利用ください。

Gist: https://gist.github.com/hassaku63/e986a7123ed3dc00034b0435aae08e76

なお、2018年12月時点で成立しているスクリプトなので、リファレンスサイトのUI変更などで容易に破綻することはご容赦ください...。
オフラインリアルタイムどう書く E29 の実装例( racc )

問題の名前 : アンエスケープ
問題 : http://nabetani.sakura.ne.jp/hena/orde29unes/
実装リンク集 : https://qiita.com/Nabetani/items/f2db9b916c0a301b744f

次回のイベントは  2/2
see https://yhpg.doorkeeper.jp/events/84247 。

で。

当日、スタート直前に書き上がった、racc による実装。

```text:racc
class E29Parser
rule
  result : BOL entries EOL { @ents = val[1] }
  entries : entry { result = [val.join] }
          | entries SLASH entry { result = val[0] + [val[2]]}
  entry : entry_unit  { result = val.join }
        | entry entry_unit { result = val.join }
  entry_unit : ALNUM { result = val[0] }
             | SLASH_PAIR { result = "/" }
             | dq_unit
             | sq_unit

  dq_unit : DQ in_dq DQ { result = val[1] }
          | DQ DQ { result = "" }
  in_dq : in_dq_atom { result = val.join }
        | in_dq in_dq_atom { result = val.join }
  in_dq_atom : SLASH_PAIR { result = val[0] }
             | ALNUM { result = val[0] }
             | SLASH { result = val[0] }
             | SQ { result = val[0] }

  sq_unit : SQ in_sq SQ { result = val[1] }
          | SQ SQ { result = "" }
  in_sq : in_sq_atom { result = val.join }
        | in_sq in_sq_atom { result = val.join }
  in_sq_atom : SLASH_PAIR { result = val[0] }
             | ALNUM { result = val[0] }
             | SLASH { result = val[0] }
             | DQ { result = val[0] }
end

---- inner
def parse( src )
  @q = [[:BOL, nil]] + src.scan( %r!\w+|\"|\'|//|/! ).to_a.map{ |t|
    type = case t
    when /\w+/; :ALNUM
    when '"'; :DQ
    when "'"; :SQ
    when "//"; :SLASH_PAIR
    when "/"; :SLASH
    else; raise "unexpected"
    end
    [ type, t ]
  } + [[:EOL,nil]]
  do_parse
  @ents
end

def next_token
  @q.shift
end

---- footer
require "json"

def solve( src )
  begin
    parser = E29Parser.new
    ents = parser.parse( src )
    ents.any?(&:empty?) ? "-" : ents.join(",")
  rescue Racc::ParseError => e
    return "-"
  end
end

def test( src, expected )
  actual =  solve( src )
  okay = actual == expected
  puts [
    ( okay ? "ok" : "**NG**" ),
    src, actual, expected
  ].join(" ")
end


if __FILE__ == $0
  data = JSON.parse( File.open( "data.json" ){ |f| f.read } )
  data["test_data"].each do |e|
    test( e["src"], e["expected"] )
  end
end
```

racc はシンタックスハイライトが効かないのがちょっと残念。
VSCode で書いたんだけど、VSCode でも白黒だった。そういうものか。

テストデータは上記の問題文ページの末尾にある `data.json` 。

実行方法は、上記の内容を `e29.y` として、

```shell
racc -g e29.y -o e29.rb && ruby e29.rb 
```

こんな感じ。

生まれて初めて racc 書いたのでちょっと大変だったけど、1時間前後だと思う。
もちろん自分が回答者だったら本番では選ばない選択だけど。

実装にあたっては、
https://qiita.com/lnznt/items/ecbc16cae8ab9c641391
を大いに参考にした。ありがとうございます。

不満は

* dq_unit と sq_unit は大差ないのに両方ベタで書いてしまった
* レキサ(`scan`)で、 `//` を `/` と別のトークンにしたところ

の二点。

両方とも、rule の書き方がわかってないということだと思う。
もうちょっとあがいてみようと思うけれど、今日のところはこれぐらいで。
Ubuntu 18.04 で Kindle Fire HD をサブディスプレイとして使う方法

# 概要

ホストに仮想スクリーンを作成します。
ホストの仮想スクリーンをKindle Fire HD に合わせて設定します。
KindleからホストへVNCをつかって接続します。

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

- Ubuntu 18.04 LST (ThinkPad E580)
- Kindle Fire HD 8 inch (2018)

# 仮想スクリーンを追加する

参考文献に従って次の通り作成しました。

`/usr/share/X11/xorg.conf.d/` に設定を追加します。

```sh
sudo vi /usr/share/X11/xorg.conf.d/20-intel.conf
```

このファイルに次の内容を記述します。
`VirtualHeads` に指定する数は任意です。
ここでは２つの仮想スクリーンを作成します。

```
Section "Device"
    Identifier "intelgpu0"
    Driver "intel"
    Option "VirtualHeads" "2"
EndSection
```

ログインし直すと、VIRTUAL1およびVIRTUAL2スクリーンが追加されています。

```
$ xrandr -q

... （ディスプレイの設定一覧が表示されます）
VIRTUAL1 disconnected (normal left inverted right x axis y axis)
VIRTUAL2 disconnected (normal left inverted right x axis y axis)
```

もし、設定がうまくいかずログインできなくなってしまった場合は、ログイン画面からWaylandでログインし、修正作業をしてください。

# gtf で設定値を計算する

Kindle Fire HD 8inchの解像度は 1280*800です。
ただし、このままの解像度を使ってしまうと、スクリーン下部のナビゲーションバーと干渉してしまうので、本稿では1280 * 700ピクセルの解像度を使用します。

はじめに `gtf` コマンドで今後使用する設定値を算出します。

```shell-session
# gtf x軸の解像度 y軸の解像度 リフレッシュレート
$ gtf 1280 700 60
```

次のような値が得られるので、 Modeline より右をクリップボードにコピーします。

```
# 1280x700 @ 60.00 Hz (GTF) hsync: 43.50 kHz; pclk: 72.38 MHz
Modeline "1280x700_60.00"  72.38  1280 1336 1472 1664  700 701 704 725  -HSync +Vsync
```

# Xrandrで仮想スクリーンを設定する

次のコマンドを入力してください。
`xrandr --newmode`のオプションは、先の工程でクリップボードにコピーした値です。


```sh
$ xrandr --newmode "1280x700_60.00"  72.38  1280 1336 1472 1664  700 701 704 725  -HSync +Vsync
$ xrandr --addmode VIRTUAL1 1280x700_60.00
$ xrandr --output VIRTUAL1 --mode 1280x700_60.00 --left-of eDP1
```

VIRTUAL1 は追加された仮想スクリーン名です。
eDP1はホストの内蔵ディスプレイです。環境に応じて修正してください。


# ホストにVNCサーバをインストールする

```sh
$ sudo apt install tightvncserver
```

# x11vncをインストールし起動する
```
$ sudo apt install x11vnc
$ x11vnc
```

# Kindle Fire HDからVNCで接続する

Kindle Fire HDにVNCクライアントをインストールし、ホストへ接続します。



# 参考文献
- https://www.hitbits.net/2016/02/26/use-an-android-tablet-as-a-second-monitor-for-linux-pc/
- https://askubuntu.com/questions/453109/add-fake-display-when-no-monitor-is-plugged-in
メンテナンス用に、Kubernetesのコンテナ内のポートにkubectlでアクセスする（ポートフォワード）

Kubernetes上でRedisやPostgreSQL等のDBを構築した場合など、中のDBに直接アクセスしてメンテナンスを行いたい場合がある。Kubernetes内に、phpMyAdmin等のDB管理ツールを立てる場合もあるが、逐一そのようにするのは面倒が大きい。

kubectlが実行可能であれば、ローカルのポートをPodにつなぐポートフォワードができる。

```
kubectl port-forward pods/redis-master-765d459796-258hz 6379
```

この状態でローカルの6379ポートにアクセスすると、コンテナの6379にアクセスできる。ポートを変更する場合は`ローカルポート:Podポート`のように指定する。

リファレンス先: https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/
Laravelでviewに値を渡すベストプラクティスはこれだと思うの

#Laravelでviewに値を渡すやり方
タイトルの通りですけど、Laravelではコントローラーからビューに値を渡すのに複数のやり方があって、結局どれ使うのがいいのよっていうのがあんまりない気がするんで、考えてみました。
ちなみにlaravel5.6時点の想定で書いてます。
#早速それぞれの渡し方をみてみる
っていうことで、早速どんな渡し方があるか見てみる。
###1, with関数を使う

```php5:TekitouController
public function doSomething()
{
    $value1 = 'value 1';
    $value2 = 'value 2';
    $value3 = 'value 3';

    return view('/home')->with('value1', $value1)->with('value2', $value2)->with('value3', $value3);
}
```
いやー、前はなんとなくこれを使ってたんだけど、これ面倒くさいなあ笑
渡す値が一つくらいなら読みやすいですが、多くなると->with()を続けて書いていくことになって可読性も下がる気がする。
書く側も見る側も辛いんじゃないでしょうか？？
はい、次。

###2, [ ]を使う

```php5:TekitouController
public function doSomething()
{
    $value1 = 'value 1';
    $value2 = 'value 2';
    $value3 = 'value 3';

    return view('/home' , [
        'value1'=> $value1,
        'value2'=> $value2,
        'value3'=> $value3,
    ]);
}
```
おおっ！！さっきと比べてだいぶ読みやすいし書きやすい！！
with関数を使うよりシンプルに配列で渡してあげるほうが全然いい気がする！！２馬身差くらいで！！
最後いこう。

###3, compact関数を使う

```php5:TekitouController
public function doSomething()
{
    $value1 = 'value 1';
    $value2 = 'value 2';
    $value3 = 'value 3';

    return view('/home' , compact('value1','value2','value3'));
}
```
うおおおおっ！！すっごいスッキリした！
このcompact関数を使うと、すでに定義した変数と同じ名前のstringをドット区切りで渡してあげるだけでいいらしいっす。
ビューに渡す値って、だいたいは変数名と同じ名前になることが多いからいちいちそれを書かなくていいのはすごくいいんじゃないでしょうか！？

#結論：compact関数が素敵
・・・ということで、個人的にベストプラクティスはcompact関数で渡すことだと思うのですがどうでしょう？
ちなみに、速度等のベンチマークは一切行っていないので、異論は大いに認めます。笑
むしろ他にもこんなのどうとかあったら教えて！えろい人！
Eclipseの読みづらいイタリック体（斜体）の表示変更

Eclipseでコーディングをしていて、エディタの設定によっては一部の文字がイタリック（斜体）になっていて読みづらい事がありますよね？:point_down:みたいなのが上から下までダーッと表示されていると発狂したくなります。個人的には。
![first.png](https://qiita-image-store.s3.amazonaws.com/0/295858/a1aa6c0d-14f5-0848-5c0e-6f80a60c0546.png)
以下の設定変更で解消が可能です。

設定変更
--
設定の中にある**構文の色指定**の斜体の:ballot_box_with_check:チェックを外す事で変更が可能です。画面の例はHTMLですが、Javaなど各種言語でも同様の設定で変更ができます。
![設定.png](https://qiita-image-store.s3.amazonaws.com/0/295858/6123337f-5df8-9752-7d8d-c73ca075fe1c.png)

結果
--
![before.png](https://qiita-image-store.s3.amazonaws.com/0/295858/92069056-3c9b-026f-cf2f-19dc7a4344fb.png)
パストレーシングを実装するときの流派

パストレーシングを実装する上でどちらの流派をとるかというのがあります.
レンダラによって異なるので複数のレンダラの実装を参考するときは注意が必要です.

## BSDF f のふるまい

o OSL testrender : BSDF f に cos を入れる
o PBRT-v3 : integrator で cos で割る派

cos を f に入れる場合の利点は Hair BSCDF など BSDF でないものとインターフェイスを合わせることができる. 欠点は光積分式とは食い違いが出る

## BSDF を計算するときの空間

ローカル, ワールド, etc. 

## 環境マップの座標空間

Y up か, Z up か.


## Fresnel 項

* OSL(e.g. Blender cycles) : Fresnel は closure(BSDF)の外で計算して, mix shader で対応
* PBRT とか. Fresnel 減衰を f に含める. Disney Principled BSDF など uber shader 系を扱いやすい.


## 光線方向

wi と wo がどれに対応するか?

たとえば,

wi : サンプルされた方向, 光源方向
wo : 入射方向, レイの方向


## 面の下かどうかの判定

Ns(shading normal) を使うか, Ng(geometric normal) を使うか

## shadow ray のオフセット

normal 方向に押し出すか, 光源方向に押し出すか
AWS DeepRacer について調べてみた

こんにちは、ナレコム繁松です。

今日は、AWS DeepRacerについて書いていきます。
この記事は株式会社ナレッジコミュニケーションが運営する[Amazon AI by ナレコム Advent Calendar 2018](https://qiita.com/advent-calendar/2018/knowcom-amazonai) の8日目の記事になります。

## DeepRacerとは
![deepracer01.jpg](https://qiita-image-store.s3.amazonaws.com/0/147666/37a9ee02-1b23-0064-bf91-6ca2b786a070.jpeg)


DeepRacerは自律的な1/18スケールのレースカーで、強化学習（RL：Reinforcement learning）と呼ばれる機械学習技術を、開発者がハンズオンで学習でき、実践的に体験できます。
また、Amazon Sagemakerで作成したモデルをクラウドベースの3Dレーシングシミュレータでトレーニングすることができます。

簡単に説明すると、、**AIで自動運転するラジコン！**です。
ただ、自動運転が目的ではなくSageMakerなどを使用して強化学習について学ぶエンジニアを増やすことが目的みたいですね。

発売日は2019年3月6日で、定価399ドルですが現在は249ドルで[販売](https://www.amazon.com/dp/B07JMHRKQG)されてます。
**※日本での販売は未定です。**

写真を見るとカメラが付いている方が後ろに見えますが、、、
![deepracer05.jpg](https://qiita-image-store.s3.amazonaws.com/0/147666/ac34e404-1ccb-6cb5-08e1-b27c50f84759.jpeg)
になります！

以下YouTubeのリンクです。（画像クリック）
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/lRGSHtHtcrk/0.jpg)](http://www.youtube.com/watch?v=lRGSHtHtcrk)
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/jD0Z9D9Y0Sc/0.jpg)](http://www.youtube.com/watch?v=jD0Z9D9Y0Sc)

## 実機
![deepracer03.jpg](https://qiita-image-store.s3.amazonaws.com/0/147666/16d12680-1ce3-b655-7e62-2e41815e6f4a.jpeg)


実機にもかなり力を入れていますね！

| | |
|-----|-----|
|本体|モンスタートラックシャシーを搭載した 1/18 scale 4WD|
|CPU|Intel Atom™プロセッサ|
|メモリ|4GB RAM|
|ストレージ|32GB（拡張可能）|
|WI-FI|802.11ac|
|カメラ|MP4カメラ MJPEG|
|ソフトウェア|Ubuntu OS 16.04.3 LTS, Intel® OpenVINO™ toolkit, ROS Kinetic|
|バッテリー|7.4V / 1100mAh(リチウムポリマー)|
|COMPUTE BATTERY|13600mAh USB-C PD|
|ポート|USB-A x4、USB-C x1、マイクロUSB x1、HDMI x1|
|センサ|モーションセンサ、ジャイロスコープ|

## シミュレータ解説
![deepracer06.jpg](https://qiita-image-store.s3.amazonaws.com/0/147666/10ed1e98-25aa-305e-5c79-78a1afa10af5.jpeg)

Amazon SageMakerでモデルを作成し、AWS DeepRacerコンソールと3Dレーシングシミュレータのトラック上で簡単にトレーニング、テストの繰り返しを実行できます。
ソフトウェア環境、トレーニング環境、シミュレータなどの設定は必要なく、AWS Cloudでホストされている統合シミュレーション環境と強化学習プラットフォームを使用できます。
モデルを構築するには、基本的なPythonプログラミングスキルが必須です。
シミュレーターでモデルのトライ＆エラーを強化学習で行い、正確な運転を学習させリーグへの出場を目指していきたいですね。

## リーグ
![deepracer04.jpg](https://qiita-image-store.s3.amazonaws.com/0/147666/8b4703c0-7731-85d0-68d1-fdf625884a3c.jpeg)


re:Invent2018 でAmazon DeepRacerを使った初の大会**AWS DeepRacer League 2018 Season**が開催されました。
内容は機械学習を利用してコース上に設置された点線をトレースし、スピードを競うタイムアタックです。
優勝者には賞金も出てます！

2019年からはリーグも開催され、結果を残せばre:Invent2019 で行われるチャンピオンシップに進出することができます。
リーグは、ロンドン、東京、シドニー、シンガポール、ニューヨークなど世界各地のAWSサミットで行われるそうです。
予選はシミュレーションで行い、上位10位が実機を使用したレースに参加できます。

## 感想
はやく実機を触ってみたいです。日本での発売が楽しみですね。
re:Invent2018に参加した人はすでに実機を入手している人もいるみたいですね。
リーグ勝ち残りチャンピオンシップ出場を目標に、DeepRacerを触っていきたいと思います。

明日の記事もお楽しみに！
ESP32を省電力で使いたい

今回は[情報通信システム工学科 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/ics2018)の9日目です。8日目はdaiさん(@dainbe)がラズパイについて書いたので、今回はラズパイに対抗してESP_WROOM_32(以下ESP32)についてです。

#まえがき
ESP32はWiFiやBluetoothが使え、ESP IDF以外にもArduino IDEやPythonで書けて便利です。しかし高機能であるため消費電力も他のマイコンの比にならないくらい多いです。定点観測カメラなどバッテリー駆動で動かしたい場合は一定周期で起動し、必要な処理を終えたら低消費電力のSleepモードに移行するのが賢明です。
//ESP32にはESP_WROOM_32やらESP_WROOM_32DやらESP_WROVER_32やらのバージョンがありますが基本的には同様の動作をするはずです。

#データシート
　まずは[データシート](http://akizukidenshi.com/download/ds/espressifsystems/esp_wroom_32_datasheet_en.pdf)を確認します。
Table5より、5つの動作モードがあることが分かります。
・Active mode
・Modem-sleep mode
・Light-sleep mode
・Deep-sleep mode
・Hibernation mode

通常起動ではModem-sleep、コード上でWifi.begin()とかするとActiveに、sleep()とかするとLight-sleepに入ると思います。この3つのモードはメインのCPUが動作している状態なので消費電力が比較的大きいです。
Deep-sleepに入るとメインのCPUは停止するのでプログラム自体が終了しますが、コプロセッサからリセットをかけることは可能なようです。コプロセッサも停止させるとHibernationになります。
**コプロセッサはアセンブラで書かなければならないらしいので今回はパスします。**

#機材
ESP32_Core_board_V2
Arduino IDE
[不燃性酸化金属皮膜抵抗 0.1Ω 3W](http://akizukidenshi.com/catalog/g/gR-11011/)
[HX711使用　ロードセル用ADコンバータ　モジュール基板](http://akizukidenshi.com/catalog/g/gK-12370/)

#実験
//実際に消費電流を測定します。
//詳しい結果が出たら追記します。

今回はESP32のボードを電池駆動させることを主眼に置く為、core boardのmicroUSB端子を通過する電流を測定します。
データシート上ではActive modeでWi-Fi Tx packet 13dBm~21dBmのときに160~260mAとなっています。

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/318382/2ee080c2-dd1b-b555-4d97-1435970a873f.png)
今回は実験装置としてこのような回路を考えます。
右側のUSBコネクタにESP32測定対象をUSBケーブルで接続し、A点とB点の電位差を測定し抵抗値で割ることで通過した電流を求める事ができます。
この回路では500mAが流れた時に0.5*0.1=0.05Vの電圧降下が生じることになりますが、ボード上の3端子レギュレータの動作範囲を割ることは無いので恐らく大丈夫でしょう。それよりも重要なのは測定装置の分解能です。データシート上の最低電流はHibernation modeの5μAです。これを測定するためには並のテスターの分解能では測定できません。今回は24bitADCを使うことでギリギリ測定範囲内に収めることにしました。

#参考
https://trac.switch-science.com/wiki/esp32_tips
https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/ulp.html

#おわりに
ESP32はラズパイには劣りますがPICやArduinoよりも高機能です。
setupにWiFi.begin()を書いた後にPOSTしてやればラズパイよりも簡単にWiFiのログイン認証を通せそうな気がします。
次は大木君(@2357gi)の機械学習にバトンタッチします。ところでESP32は安価なので大量に並列化して機械学習用のスパコンにできたりしないですかね？
シェル芸人を目指して

私は業務でシェルスクリプトを書く機会が多いのですが、書籍やサイトで学習してみると、意外とまだまだ知らないテクニックや、非推奨の書き方を使っていたりすることが多いです。シェル芸人を極める道を歩む上で、知っておいたほうがよさそうなことをいくつかまとめてみました。

## 前置き
本記事のシェルスクリプトは全て**bash**か**zsh**を想定しています。
FreeBSD系やSolaris系の場合は動作しない/使えないテクニックがあるので、移植する可能性がある場合はご注意ください。

## ShellCheck
[ShellCheck](https://www.shellcheck.net/)
ShellScriptを書く上で欠かせない、Linterツールです。

macならhomebrewで、Debian系ならaptでインストール可能です。

## if文での算術式

bashで数値を比較するif文では、通常下記のように**double bracket**(testコマンドと等価なbracketの拡張)を使うかと思います。

```bash
a=1
if [[ $a -gt 0 ]]; then
    echo "a is positive."
fi
```

bashでは以下の算術式がif文の条件式としても使えます。
こちらのほうが可読性が高い場合もあるかと思います。

```bash
a=1
if (( a >= 0 )); then
    echo "a is positive."
fi
```

## .コマンドとsourceコマンドの違い
別のshellscriptを読み込む方法には.(ドットコマンド)とsourceコマンドがあります。

```bash
# .profileファイルを読み込む
. "$HOME/.profile"
source "$HOME/.profile"
```

実はこの2つのコマンドに機能的な差異はありません。
~~sourceコマンドはcsh由来なのでFreeBSD系やSolaris系では動作しないという点が異なります。~~
使用できる環境に関しては現在確認中...(2018/12/10)

個人的には`.`はディレクトリパスや正規表現でも多様するので、`source`コマンドのほうが可読性がよいかと思います。

## execコマンドの使いどころ
execコマンドは新しいプロセスを作らずにコマンドを実行します。
ラッパースクリプトなどでshellとjava等の2つのプロセスが残ってしまうケースに利用したほうがよさそうです。

# setコマンドとシバン(1行目の`#!/bin/bash`)
シバンとはUNIXのスクリプトの`#!`から始まる1行目のことです。
`#!/bin/bash`と指定した場合はファイルを`./test.sh`のように実行した場合、このシバンで指定されたコマンドでファイルが実行されます。

bashの`-x`オプション(デバッグ表示)や`-e`オプション(エラー時にスクリプト終了)等もシバンに指定できるので、使い分けたいところ。

## setコマンド
setは上記でも述べたbashのオプションをスクリプト中から指定するコマンドです。
(位置パラメータもセット可能です)
スクリプトの冒頭で`set -e`と宣言すれば、コマンドが偽の終了ステータスで終了した場合、コマンドを終了します。

## 未定義参照をエラーにする
シェルスクリプトでは未定義の変数を参照しても、空文字列が返ります。
デバッグの妨げになることがしばしばあります。
`-u`オプションを使用すると、未定義の変数にアクセスした場合、エラーとすることができます

```bash
 $ set -u
 $ echo $a
zsh: a: parameter not set
```

## コマンド置換`$()`
コマンド中に別のコマンドの標準出力を利用する、コマンド置換があります。

```bash
basename "$(pwd)"
# reireias
```

上記は`pwd`の結果が`/home/reireias`であるので、`basename /home/reireias`が実行され、`reireias`という出力を得ます。

もちろん、スクリプト中では変数に代入して渡すということも可能なのですが、ワンライナーで書く際にも重宝します。

また、バッククォートで囲んでいました。(今でもこの書式でもかけます)
ですが、エスケープ処理の面で`$()`のほうが優れているため、バッククォートはshellcheckでも非推奨となっているようです。

## ブレース展開
複数の文字列の組み合わせから、文字列を展開する**ブレース展開**という機能があります。
こちらは、スクリプトよりもワンライナーや普段のターミナル操作でよく使用します。

```bash
# 列挙した値の展開
$ echo /home/{a,b,c}
/home/a /home/b /home/c
# 連続での展開
$ for i in {1..3}; do echo $i; done
1
2
3
# いくつかのバージョンのディレクトリの削除
$ rm -r /path/to/{1.0,1.2,2.5}/hoge
```

## exprより`$(())`を使う
数値を計算するコマンドとして、`expr`がありますが、bashの場合は`$(())`という**算術式展開**の利用が推奨されます。

算術式展開に関しては、[こちらの記事](https://qiita.com/akinomyoga/items/2dd3f341cf15dd9c330b)に詳しく紹介されているので、一読をおすすめします。

## if文の代わりに、`&&`や`||`を使う
`&&`は前のコマンドの終了コードが真の場合、後ろのコマンドが実行されます。また、`||`は前のコマンドが偽の場合、後ろのコマンドが実行されます。(所謂and, or演算)
これは多用しすぎると可読性を損なう可能性がありますが、簡潔に記述できるテクニックだと思います。

```bash
a=1
# if文の場合
if [[ a -eq 1 ]]; then
  echo "equal"
fi
# &&の場合
[[ a -eq 1 ]] && echo "equal"
```

## 参考文献
- [シェルスクリプト 基本リファレンス #!/bin/shで、ここまでできる](https://www.amazon.co.jp/%E6%94%B9%E8%A8%82%E7%AC%AC3%E7%89%88-%E3%82%B7%E3%82%A7%E3%83%AB%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E5%9F%BA%E6%9C%AC%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9-sh%E3%81%A7%E3%80%81%E3%81%93%E3%81%93%E3%81%BE%E3%81%A7%E3%81%A7%E3%81%8D%E3%82%8B-PRESS-plus/dp/4774186945)
Goole Cloud Platform の Cloud Text-to-SpeechとPHPで音声データを作成する

# 1.はじめに
[Google Cloud Platform](https://cloud.google.com/)の[Cloud Text-to-Speech](https://cloud.google.com/text-to-speech/)とPHPを使って音声データを作成します。

# 2.準備
* GCPのAPI Key  
(GCPのコンソール＞APIとサービス>認証情報から生成できます)  
* PHPが動作する環境  
（当方ではphp7.1で動作を確認）

# 3.開発

```php:create_voice.php
<?php
$google_api_key = '*****'; //ここに自分のAPI key情報をセット
$google_tts_api_url = 'https://texttospeech.googleapis.com/v1/text:synthesize?key='.$google_api_key;
$output_file_name = 'voice.mp3'; //書き出しファイル名

$request_data = [
    'audioConfig' => [
        'audioEncoding' => 'MP3', //出力フォーマット
        'pitch' => 0, //読み上げピッチ調整
        'speakingRate' => 1 //読み上げスピード倍率
    ],
    'input' => [
        'text' => 'this is a pen.', //読み上げたい文字列
    ],
    'voice' => [
        'languageCode' => 'en-US', //言語コード
        'name' => 'en-US-Wavenet-C' //ボイス対象
    ]
];

//apiリクエスト
$ch = curl_init();
$result_json = null;
curl_setopt($ch, CURLOPT_URL, $google_tts_api_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($request_data));
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result_json = curl_exec($ch);
curl_close($ch);

//出力
$result_data = json_decode($result_json, true);
file_put_contents($output_file_name, base64_decode($result_data['audioContent']));
exit;
```  


これでphpファイルと同じ階層に音声データが生成されます。

# 4.まとめ
今回は英語音声を作成しましたが、言語コードを変えれば日本語の読み上げも対応しています。 
また、細かな調整やDeepMindによる、より自然な音声データの生成が可能です。

100万文字/月までは無料(2018-12-08時点)なのでちょっとした音声データの生成であればこれで済ますこともできるでしょう。

# 5.参考リンク
[Cloud Text-To-Speech 公式](https://cloud.google.com/text-to-speech/)
php-master-changes 2018-12-07

今日は 7.3 リリース作業に伴うドキュメントの修正、ext/sqlite3 の若干のリファクタリング、コンパイラ内で引数経由で引き回す値を減らす最適化の修正があった！

# 2018-12-07
## cmb69: [ci skip] Fix NEWS wrt. ChangeLog conversion
- https://github.com/php/php-src/commit/327e2d015342ea35ba3274bef9ff05e221940ecc
- [7.3~]
- ChangeLog の生成用に NEWS を整形

## cmb69: Stable releases also should be on frontpage
- https://github.com/php/php-src/commit/8b275b52493f4be5458cb73da818687e157be0a7
- [7.3~]
- README.RELEASE_PROCESS で、安定版リリースのニュースエントリをトップページにも出すよう記述を修正

## cjbj: Sync with test files
- https://github.com/php/php-src/commit/91776f7264dccf252e97e88d1634dc26bede21f2
- [7.3~]
- ext/oci8 で、PECL 用の package.xml の内容を実際のテストファイル内容にあわせて修正

## cjbj: Simplify based on feedback from nikic
- https://github.com/php/php-src/commit/b797818e09d3d2f7b81ca4c8c4e4bb874f623c87
- [7.2~]
- ext/oci8 で、参照カウントの操作処理を単純化
- 7.3 以降で追加されたマクロ GC_ADDREF / GC_DELREF を使ってる部分で、7.2 以下のバージョンで PECL から入れる場合は自前で定義することで条件コンパイルをなくしてる感じ
- フィードバックというのがどのフィードバックかは見つけられず

## nikic: Drop unnecessary HASH_OF uses in ext/oci8
- https://github.com/php/php-src/commit/e3946534a47afc6678eccaf5217632221ed297df
- [7.2~]
- ext/oci8 で、[10 月の修正](https://qiita.com/sj-i/items/287aa832fbfc1307830e#nikic-drop-unnecessary-hash_of-uses-in-extoci8)を 7.2 系へバックポート

## cmb69: MD5 checksums are history
- https://github.com/php/php-src/commit/257696a0c2f83ffa0e91fe5465939cff69c835bb
- README.RELEASE_PROCESS で、リリース時に MD5 チェックサムを出していたのは[過去の話になった](https://wiki.php.net/rfc/release-md5-deprecation)ため、記載を削除

## cmb69: Remove outdated note regarding Windows
- https://github.com/php/php-src/commit/ec027d5f3a9a1b8f6e296030c32ae605bc06c8fc
- README.RELEASE_PROCESS で、Windows ビルド専用キー（5.3 から存在しない）についての記載があったのを削除

## cmb69: Add note that release manager karma is required
- https://github.com/php/php-src/commit/1a2577093b87201d9ca5f96a221d1fdd349e85ac
- README.RELEASE_PROCESS で、main/php_version.h の編集をリリースブランチで行うにはリリースマネージャのカルマが必要であるむねを付記

## cmb69: Note additional RM tasks
- https://github.com/php/php-src/commit/c4e9f6fc331316bb08c6cd377f02510b002a6483
- README.RELEASE_PROCESS で、リリースマネージャのタスクについて追記
- 安定版リリースの前にマイグレーションガイド用意するのは[必要ですね ＞＜](https://externals.io/message/103562#103569)

## cmb69: ZEND_VERSION should be in sync with PHP_VERSION and friends
- https://github.com/php/php-src/commit/8f46f6dd6f3c3dcab1dbc4d8e56bf8b509901389
- README.RELEASE_PROCESS で、ZEND_VERSION を PHP_VERSION 等とあわせて更新するよう追記

## bohwaz: SQLite3: Separating parameters binding in a function
- https://github.com/php/php-src/commit/abd9f0875283e55b803613da2dd09ea164665640
- ext/sqlite3 で、パラメータのバインド処理を別関数へ分離
- [PR:3702](https://github.com/php/php-src/pull/3702) の奴、[PR:3669](https://github.com/php/php-src/pull/3669) でとりあえず分けねえすかとなってた奴

## dstogov: Stop passing CG(active_op_array) between internal compiler functions.
- https://github.com/php/php-src/commit/be4c67a40abf9c88317e57ab862ffab56da0dce1
- コンパイラ内部の関数間で CG(active_op_array) を引数経由で引き回すのをやめた
- コピーが減らせる分速くなるのかな
KubernetesのPodのmanifestを図示するツールを作った

# これは何？

Kubernetesのマニフェストはすべてyamlで記載します。
慣れればyamlを見ただけで、どんなマニフェストかがすぐにわかるのですが、慣れないうちは何が何だかわかりません。
そこで、マニフェストを少しでも読みやすくするためのツールを作ってみました。

# マニフェストの例

複雑なPodのmanifestとして https://kubernetes.io/docs/concepts/storage/volumes/#using-subpath で紹介されているsubpathの例を示します。

慣れた人が見るとコンテナが2つあり、ボリュームが1つ、それぞれのコンテナがマウントしているようだな、ということがわかります。
しかし、いきなりこのマニフェストを見せられると、面食らってしまう人もいるでしょう。

```pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-lamp-site
spec:
    containers:
    - name: mysql
      image: mysql
      env:
      - name: MYSQL_ROOT_PASSWORD
        value: "rootpasswd"
      volumeMounts:
      - mountPath: /var/lib/mysql
        name: site-data
        subPath: mysql
    - name: php
      image: php:7.0-apache
      volumeMounts:
      - mountPath: /var/www/html
        name: site-data
        subPath: html
    volumes:
    - name: site-data
      persistentVolumeClaim:
        claimName: my-lamp-site-data
```

# 可視化の例

今回作成したツールで先ほどのマニフェストを可視化してみます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/100375/1fe760d1-9995-1663-2927-4dd788a72daa.png)

どうでしょう？
2つコンテナがあり、ボリュームを共有していることが一目瞭然ではないでしょうか？
このように、マニフェストから図をパッと生成できるツールを作りました。

## 利用技術

すべてブラウザで上のJavaScriptで動作しています。

- mermaid.js
    - https://mermaidjs.github.io/
    - JavaScriptで書かれたフローチャートを書くためのDSLとその描画ライブラリ
- js-yaml
    - http://nodeca.github.io/js-yaml/
    - JavaScriptで書かれたyamlパーサ

あとはいい感じにyamlから要素を取り出してフローチャートを記述するだけです。
mermaid.jsのフローチャートを書くためのDSLで無理やりPodを図示しています。
`initContainers`, `containers`, `volumes`をmermaid.jsのsubgraphで表現し、その中の要素をフローチャートのタスクとして記述しています。
yamlではパッと理解しづらいVolumesとvolumeMountの関係を矢印で表現できるようにしました。

## 試してみたい！と思った方へ

https://inajob.github.io/pod-manifest-visualizer/ で公開しているのでいろいろ試してみてください！

# まとめ

今回作成したPodの可視化ツールで、少しでもマニフェストが読みやすくなれば幸いです。
ソースコードも公開しているので、ぜひいろいろカスタマイズしてみてください。
CloudWatch Logs Insightsの簡単なまとめ

今年のre:Inventでは多くの新サービス/新機能が発表されましたがその中の一つ[CloudWatch Logs Insights](https://aws.amazon.com/jp/blogs/news/new-amazon-cloudwatch-logs-insights-fast-interactive-log-analytics/)について(備忘録も兼ねて)簡単にまとめます。

## CloudWatch Logs Insightsとは
- CloudWatch Logsのログデータを簡単に検索したり分析できる
- クエリ言語を使ってログを操作
- 料金
    - スキャンされたデータ 1 GB あたり 0.0076 USD
    - [参考](https://aws.amazon.com/jp/cloudwatch/pricing/)

## Log Fields
以下の3つのログフィールドはログの種類にかかわらず自動で生成されます
`@message`: ログのメッセージ本文
`@timestamp`: タイムスタンプ
`@logStream`: ログストリーム名

また、ログの種類によっては、そのほかのフィールドが自動で検知されCloudWatchコンソールの右下に`検出されたフィールド`として表示されます
例えばLambdaの実行ログにクエリを発行したい場合`@requestId`, `@duration`, `@billedDuration`, `@type`, `@maxMemoryUsed`, `@memorySize`などが利用できます

そのほかログの種類によって利用できるフィールドの一覧は[ドキュメント](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/CWL_AnalyzeLogData-discoverable-fields.html)にあります

## Command
以下6つのコマンドを実行できます

- `fields`: フィールドを取得してくることができます,また後述する関数と組み合わせることで取得したフィールドに加工を加えることもできます
- `filter`: フィールドを絞り込みます
- `stats`: 後述する関数と組み合わせることで様々な集計計算ができます
- `sort`: 降順、昇順で結果をソートできます
- `limit`: クエリの実行結果数を制限できます
- `parse`: ログフィールドからデータを取り出すことができます

parseについてはもう少し追記しておくと, 例えばログメッセージの中から例外が発生したメッセージの内容だけ取り出したいときに

```
fields @message
| filter @message like /Exception/
| parse "*:*" as errorCode, errorMessage 
```

のように使うイメージです

## Functions
クエリ内では以下の関数を使うこともできます
### General Functions
- `ispresent`: フィールドが存在するか真偽値を返す
- `coalesce`: リストの中から最初のnullでない値を返す

### String Functions
- `isempty`: フィールドが存在しないもしくは空の時trueを返す
- `concat`: 文字列を連結する
- `trim`: 文字列をトリムする
- `strlen`: 文字列の長さを返す

など

### Aggregation Functions in the Stats Command
`stats`コマンド内で使える集計関数もあります

- `avg`, `count`, `sum`など

そのほかいくつか利用可能なオペレーションや関数がありますので詳しくは[ドキュメント](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/CWL_QuerySyntax.html)を参照してください。

## 試してみる
例えば,`logger.error()`などで出力したエラーログのうち最新20件の発生箇所と該当コードだけ抜き出してみたいときは以下のようにクエリを書くことで簡単に参照できるかと思います。

```
filter @type = 'ERROR'
| parse @message "*:*:*" as message, place, code
| fields place, code
| sort @timestamp desc
| limit 20
```

## まとめ
ドキュメント読めばわかるようなことをつらつら書いていてアレですが日本語ドキュメントがまだないようなので書きました。

上で紹介した機能以外にも集計結果をグラフ化したりクエリの結果をCloudWatchダッシュボードにエクスポートしたりクエリの履歴を参照することもできとても便利な機能が揃っています。
CloudWatchでのログの取り扱いに困っている方は一度試してみてください。
CryptZombiesレッスン4(チャプター1~5)の自分なりのまとめ

# はじめに
この記事は私がCryptZombiesを進めていく上で自分なりにまとめたものです。
**前回の記事**
https://qiita.com/daichi77/items/aaee82cc59973b367734
**参考にしたサイト**
サイト名: イーサリアム上のDApp開発をゲームを作って学びましょう
URL: 　https://cryptozombies.io/jp/　
**この記事の問題文と答えについては上の参考にしたサイトから引用しています。**
# チャプター１ Payable関数
## 要点
今までの修飾子の復習は省略
**Payable関数**
Etherを受け取ることができる特別なタイプの関数を作るときに記述する。
イーサリアムではお金(Ether)、データ(トランザクションの内容)、コントラクト・コード自体が全てイーサリアム上にあるので、ファンクション・コール及びお金の支払いが同時に処理できる。
**例**

```
 function 関数名() external payable {
 }
```
## 今回したこと(テスト)
1. levelUpFeeに0.001 etherを格納
2. levelUp関数の定義(externalかつpayable)
3. msg.valueがlevelUpFee(0.001 ether)であるかrequireでチェック
4. ゾンビのレベルを＋１する。
Payable関数を使うことで0.00１etherでゾンビをレベルアップさせることができるようになった。

# チャプター２　Withdraws関数
## 要点

```
contract contract名 is Ownable {
  function withdraw() external onlyOwner {
    owner.transfer(this.balance);
  }
}
```
このように書くことでetherをコントラクトから引き出すことができる。
(ownable.solがimportされている前提)
transferを使えばetherを違うアドレスに送ることもできる。
## 今回したこと(テスト)
1. Etherをコントラクトから引き出す関数の作成
2. ownerがlevelUpFeeを設定することができるようにsetLevelUpFeeという名の関数を作成

# チャプター3 ゾンビ・バトル
importやcontractの定義のみなので省略
# チャプター４ 乱数
## 要点
keccakは不誠実なノードの攻撃に対して脆弱である。しかし大金がかかっていないとユーザーが攻撃するメリットはないので今回のチュートリアルでは気にしなくてもOK。後々oraclesという方法で乱数を生成する。
## 今回したこと(テスト)
1. randNonceに０を設定
2. randMod関数の作成
3. 関数内でrandNonceに+１する。
4. keccak256とか使って乱数作成

# チャプター５
## 要点
バトルの流れの説明のみなので割愛
## 今回したこと(テスト)
1. attackVictoryProbabilityに70を代入
2. attack関数の作成

# 次の記事
https://qiita.com/daichi77/items/a0e893706ff9419c66e1
UIViewのframeとboundsとcenter

![049.png](https://qiita-image-store.s3.amazonaws.com/0/302540/ce54da0f-e517-69ec-5a56-23e414e97775.png)
#frame 

親View（SuperView）からみて、現在のViewのサイズと位置を保持するプロパティ。上記図では、親Viewからみて、(40,40)の位置に現在Viewの開始地点があり、現在Viewは高さ=380,横幅=240という情報を保持している。

#bounds

現在のViewからみて、現在のViewのサイズと位置を保持するプロパティ。上記図では、開始地点は(0,0)で、高さ=380,横幅=240という情報を保持する。

#center
親View（SuperView）からみた、現在のViewの中央位置を保持する。上記図では、現在Viewの中央位置は、親Viewの(160,230)のポイントにあるという情報を保持する。!
オフラインリアルタイムどう書く E29 の問題

オフラインでリアルタイムに「どう書く」をやるイベント( https://yhpg.doorkeeper.jp/events/82699 )を行っています。

問題は「アンエスケープ」という名前で、詳細は
http://nabetani.sakura.ne.jp/hena/orde29unes/
です。

実装ができた方はこちらのコメント欄からリンクを張っていただくと見つけやすくて助かります。

似たような問題をもっと解きたいという方は、https://nabetani.hatenadiary.com/entry/yhpg_list
に過去問リンク集がありますので、そちらをご覧になると良いと思います。

次回は E30 は 2/2(土) です。
see https://yhpg.doorkeeper.jp/events/84247
iPhone　スクリーンサイズ取得方法　メモ


iPhoneのスクリーンサイズ取得方法

| Left align       |       Right align |    Center align    |
|:-----------------|------------------:|:------------------:|
| iPhone 2G, 3G, 3GS           |     320 |        480        |
| iPhone 4, 4s          |             320　 |       480       |
| iPhone 5, 5s, 5c, SE           |              320 |        568        |
| iPhone 6, 6s, 7, 8               |                375 |        667         |
| iPhone 6+, 6s+, 7+, 8+          |             414 |       736       |
| iPhone X          |           　375 |      812       |



```swift

let boundSize: CGSize = UIScreen.main.bounds.size//スクリーン全体を取得　
let width = boundSize.width//横スクリーン取得
let height = boundSize.height//縦スクリーン取得
ReactNativeを利用したOTAの仕組みについて

※ [Retty Advent Calendar 2018](https://qiita.com/advent-calendar/2018/retty) 8日目の記事です。

はじめまして。本日は@PONTA-N がお送りします。
最近は[スクラムについて話したり](https://employment.en-japan.com/engineerhub/entry/2018/11/16/110000)、[Kotlinの勉強会と称して脱いでいたり](https://togetter.com/li/1293397)していますが、本業はエンジニアであり開発もしているんだぞという事をお話をさせていただきます。

## RettyのiOSアプリについて
実はRettyのiOS版アプリでは一部の画面でReactNatvieを利用しています。
主にここ半年の間に新しく実装されたリコメンド機能で使われています。


<img width="395" alt="スクリーンショット 2018-12-08 14.45.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/51557/6fd3db03-5c08-2cd1-17ce-b0d98050d64b.png">



### なぜReactNativeを使っているのか？
新しい施策の場合、ユーザーのリアクションを見てボタンの色や文言など簡単なものは今すぐにでも改善しユーザーの元へ届けたいというお気持ちがあります。
しかしiOSアプリの場合はAppleに申請を行い、審査を待ってリリースするという手順を踏む必要がある為、実装してからユーザーの手元に届くまでに数日のラグがあります。
細かい変更の為に高頻度で申請していくのは時間が掛かりすぎてしまいあまり現実的ではありません。
そこでOTA(OverTheAir)の仕組みを取り入れるためにReactNativeを利用する事にしました。


### OTAの仕組み
<img width="1123" alt="スクリーンショット 2018-12-08 15.59.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/51557/2b18b005-d64d-683c-9202-3516973a1129.png">


AWS S3にjsbundle及びメタデータをアップロードをしており、それをクライアント側で取得する事で実現しました。

メタデータはアプリのバージョンやビルドバージョンなどが記述されています。
クライアント側では起動時にメタデータの中身を比較して最新のものだった場合にjsbundleをダウンロードして更新するようにしています。

## 導入した事で発生した問題
###後方互換の問題
ReactNative側のコードは常に最新のものにアップデートされる為、過去のアプリバージョンではネイティブ側にメソッドが存在しなかったり、ネイティブ側からコンポーネントに渡しているプロパティに齟齬があった場合はクラッシュするなどのバグが発生していました。

##対応方法
### ネイティブのメソッドを利用する時にはguardする
新しいバージョンで実装したネイティブ側のメソッドをReactNative側で呼び出す実装を行った場合、過去のアプリバージョンにてReactNative側のコードがアップデートされてしまった時に、ネイティブ側にメソッドが存在しない為TypeErrorが発生してしまいます。
なので基本的にネイティブ側のメソッドを使う場合は、存在チェックを行い早期リターンをするなどしてメソッドが存在しなくても動く実装にしました。

### バージョン毎に分岐するコードを入れる
基本的には上記の実装にて対応をしていますが、それだけではどうしても対応できない場合はアプリバージョンを比較してコードを出し分けるようにしました。
これを多用してしまうとコードが巨大化してしまう為あまり使わないようにしています。

### 後方互換は2バージョンまでにする
上記の対応で後方互換対応ができましたが、アップデートを重ねる度に考慮しなければいけない事が増えていきます。
そこでS3側に最新のjsbundleがアップロードされていても、2バージョン以上離れている場合には更新しない対応をいれました。

2バージョン分であれば対応する範囲が狭まりますし、人の手で最終チェックができる量となりました。
2DレーザーのみでGoogle Cartographer rosを動かして地図を作る（デプスカメラでも可)

二次元のCartographer_rosをレーザのみで動かし、地図を作りました。

Cartographer_rosはgoogleが公開しているオープンソースのSLAMパッケージのrosラッパーです。

レーザー用のSLAMでループクロージャーができてるパッケージは貴重で、有名なgmappingは明示的にループが閉じないので屋外などの大規模環境で地図がずれるって人は使ってみたらよいと思います。
2DではIMU・オドメトリが不要なのもポイント高いです。ただし、3DはIMUが必須です。
ちなみに[depthimage_to_laserscan](http://wiki.ros.org/depthimage_to_laserscan)を使えば，デプスカメラでもできます．
### ビルド時の注意
チュートリ通りに既存のcatkin_wsでビルドするとビルドできなかった時の対処が非常に面倒くさいので，google_wsと言った名前のcartographer専用のワークスペースを作ったほうがよいと思います．
### 編集したところ 

#### 1.レーザースキャンの型の設定
デフォルトではMultiEchoLaserScan型を読み込む設定なので、使用機器にあったLaserScan型に変更しました。ちなみにPointCloud2型も設定かえれば読み込めます。

```:cartographer_ros/cartographer_ros/configuration_files/backpack_2d.lua

options = {
・・・
num_laser_scans = 1,-- <--default:0
num_multi_echo_laser_scans = 0,-- <--default:1
num_subdivisions_per_laser_scan = 10,
num_point_clouds = 0,--<--if pc2 is used,set 1
・・・
}

```

#### 2.IMUの設定
デフォルトではimuの入力が必要だったので、imuの設定を切りました。

```:cartographer/configuration_files/trajectory_builder_2d.lua

TRAJECTORY_BUILDER_2D = {
use_imu_data = false,-- <--default:true
・・・

}
```
### launch起動時の注意
パラメータを設定したら、またビルドしないとパラメータが反映されないので注意して下さい．

### 実行
scanデータをpubishするノードとcartographerのbackpack_2d.launchを立ち上げ


#### できた地図
![20181206032203.png](https://qiita-image-store.s3.amazonaws.com/0/229952/842d13b1-9afb-52b0-57f6-05188e2d7f78.png)
map_serverのmap_saverで地図をpgm形式で保存もできます。 


### 結果
簡単に地図ができる！
DecodableでkeyDecodingStrategyとCodingKeyを併用するさいに気をつけるべきこと

##はじめに
SwiftでJSONのパースを行う際はCodableが非常に便利です。
サーバとの通信のレスポンスではSnake Caseが使用されることが多く、 iOSアプリ内ではCamel Caseが使用されることが多いです。それらの相互の変換がJSONDecoderのkeyDecodingStrategyを使用すると簡単に行えますが、 CodingKeyと併用した際に少しはまったポイントがあったため共有します。

なお、keyDecodingStrategyに関しましては別記事に記載していますので、[そちら](https://qiita.com/iganin/items/6c6a588dd73731097698)をご確認ください。

##検証環境
以下の環境を使用しています。

* macOS Mojave Version 10.14
* Xcode Version 10.0.0

##発生事象例

以下のように、サーバからの通信では姓に該当する名称がfamily_nameで返ってきますが、アプリ内ではlastNameとして使用したいとします。この場合、key名が異なっているため基本的にはCodingKeyを使用してKeyの対応関係をつけるかと思います。

```Swift
import Foundation

let jsonData = """
{
    "first_name": "Taro",
    "family_name": "Tanaka"
}
""".data(using: .utf8)!

struct User: Decodable {
    let firstName: String
    let lastName: String
    
    enum CodingKeys: String, CodingKey {
        case firstName
        case lastName = "family_name"
    }
}

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
    let user = try decoder.decode(User.self, from: jsonData)
    print("first name: \(user.firstName), last name: \(user.lastName)")
} catch let error {
    print(error)
}
```

一見うまくいきそうですが、このコードを実行すると以下のエラーが表示されます。
family_nameに該当する keyがないというエラーです。

```
出力結果
keyNotFound(CodingKeys(stringValue: "family_name", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"family_name\", intValue: nil) (\"family_name\").", underlyingError: nil))
```

##原因と対応
原因はJSONDecoderのkeyDecodingStrategyとして.convertFromSnakeCaseを使用しながら、 CodingKeyでの対応関係にSnake Caseを使用していることです。具体的には下記の箇所です。

```Swift
struct User: Decodable {
    let firstName: String
    let lastName: String
    
    enum CodingKeys: String, CodingKey {
        case firstName
         // .convertFromSnakeCaseを使用しながら、
         //  Codingkeyでの対応づけにSnake Caseをそのまま使用している
        case lastName = "family_name"
    }
}
```

元のSwiftのソースコードをまだ追えていないので、　なぜこの挙動になるかの把握ができていませんが、 keyDecodingStrategyで.convertFromSnakeCaseを使用する際は、CodingKeyでの対応づけではJSONのkey名をSnake Caseのまま書くのではなく、Camel Caseにしなければいけないようです。以下のコードにしたところ正常にパースできました。

```Swift
import Foundation

let jsonData = """
{
    "first_name": "Taro",
    "family_name": "Tanaka"
}
""".data(using: .utf8)!

struct User: Decodable {
    let firstName: String
    let lastName: String
    
    enum CodingKeys: String, CodingKey {
        case firstName
        case lastName = "familyName" // CodingKeyの対応付けをCamelCaseで行う
    }
}

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
    let user = try decoder.decode(User.self, from: jsonData)
    print("first name: \(user.firstName), last name: \(user.lastName)")
} catch let error {
    print(error)
}
```

```
出力結果
first name: Taro, last name: Tanaka
```

##まとめ
JSONのデコードを通信クラスないで共通して行なっている場合など、デコード処理が隠蔽されているような場合に気づきにくいところかなと思いました。keyDecodingStrategyとCodingKeyを併用する際は気をつける必要がありそうです。
なお、サンプルコードは以下にあげていますのでよければご参照ください。
https://github.com/HironobuIga/Samples/tree/master/01_iOS/20181208/CodingKey_keyDecodingStrategy_sample.playground
便利なLinuxコマンド

#はじめに

こんにちは。
初めてのQiita記事を書いてみたいと思います。

今回はできれば開発に携わってる皆さんにも、トクになるようなお話を書きたいと思い、
Linux上で扱うと便利なコマンドを紹介・調査をしました。

よろしくお願いいたします。

#便利なコマンド

##ls -lahコマンド

ファイルのサイズを知りたいときに、便利なコマンドです。
「-h」オプションを付けることで、ファイルサイズを適切な単位に表示させてくれます。
![lsこまんど.PNG](https://qiita-image-store.s3.amazonaws.com/0/314234/fed29ed8-b74a-ce48-c2ed-399f4cf8e017.png)



ちなみに、メモリのサイズを表示する「free」コマンド、
ディスクのサイズを表示する「df」コマンドも「-h」オプションをつけることで、
同様に適切な単位にサイズを表示させてくれます。
![freeとdf.PNG](https://qiita-image-store.s3.amazonaws.com/0/314234/79ff06af-2189-d56d-2c6a-b8cd3c51b43c.png)


#findコマンド

自分が探してるファイルを探すときに便利なコマンドです。

find /-name　○○○
○○○に自分の探したいファイル名を入れます。
![find.PNG](https://qiita-image-store.s3.amazonaws.com/0/314234/ac3eb407-1fd9-7846-99a3-2379c1cc380c.png)


find / -maxdepth △　-name ○○○ 
ディレクトリ階層を指定することで、検索する範囲を絞ることもできます。
![find.2 PNG.PNG](https://qiita-image-store.s3.amazonaws.com/0/314234/334f4f2f-8970-6d31-86bd-05048fa02ec0.png)


##grep -rlコマンド

中身に自分が探したい文字列が含まれてるファイルを探すコマンドです。

例えば、「GATEWAY」が含まれてるファイルを探す場合は、
下記のようなコマンドを実行します。
![grep.PNG](https://qiita-image-store.s3.amazonaws.com/0/314234/17771cd3-e90f-29cc-1f1e-fbdb748d966e.png)



##ip aコマンド
自分のIPアドレスを表示させるコマンドです。
ip addrコマンドの「addr」オプションを省略した形となります。

![ip a.PNG](https://qiita-image-store.s3.amazonaws.com/0/314234/62dcb06d-0dcd-ec7b-d273-f3b9bbf06b9e.png)


ifconfigコマンドでもIPアドレスを表示させることができますが、
こちらの方が入力する文字数が少ないので、私はこのコマンドを愛用しております。

##grep -n "×××" ○○○.txt
○○○はテキストデータの名前、×××は自分が探してる文字列を入れます。

grep -nコマンドを使うことで、
テキストの中身において、自分が探してる文字列が何行目に含まれてるのか表示してくれます。

例えば、下記のようなaaa.txtを作成します。
![aaaテキスト.PNG](https://qiita-image-store.s3.amazonaws.com/0/314234/852ad60c-051b-335a-b481-420446c973e0.png)


「yamada」さんは3行目に存在することがわかります。
![grep n.PNG](https://qiita-image-store.s3.amazonaws.com/0/314234/2fd40675-0170-f2db-08d3-9c1b7c7d4705.png)


##awkコマンド

テキストデータやコマンドの実行結果から必要な情報を抜き出すことができるコマンドです。
cutコマンドと同じ働きがあります。

例えば、先ほどのaaa.txtを使って、2列目の名前だけを取り出す場合は、
下記のようにコマンド実行します。
![awk①.PNG](https://qiita-image-store.s3.amazonaws.com/0/314234/a75ebae1-2438-7890-8197-4cfbc0ce50f2.png)



print $2で2行目のみを表示するということです。

また、次のコマンドで3列目の合計を求めることもできます。


awk '{sum+=$3} END {print sum}'
![awk②.PNG](https://qiita-image-store.s3.amazonaws.com/0/314234/c80d02e4-6d12-46ae-dded-4c6326d27246.png)


##pushdコマンド、popdコマンド

pushdコマンドで、カレントディレクトリ(現在、自分が存在するディレクトリ)を一時的にスタッククに保存し、別のディレクトリに移ります。
popdコマンドを使うことで、スタックに」保存しておいたカレントディレクトリに戻ることができます。

![pushとpop.PNG](https://qiita-image-store.s3.amazonaws.com/0/314234/1ca4dc6b-d8b7-ed03-1cbb-818c5921174c.png)




#まとめ
今回は個人的に便利だと思った、Linuxコマンドをご紹介させて頂いたきました。
上記のコマンドを扱うことで、業務の効率が向上できれば、幸いです。
yum - Not using downloaded ius/repomd.xml because it is older than what we have: ...

# 経緯

CentOS 7 で最新の Git を入れるために IUS リポジトリを追加したら発生。
別に問題になるわけではないが、 yum-cron の hourly cron で毎時メールが飛んできてうざいので、何とかしたい。

# 原因

1. IUS のミラーサイトのうち、およそ半数のミラーサイトの反映が遅い。 [ミラーリスト](https://mirrors.iuscommunity.org/mirrorlist?repo=ius-centos7&arch=x86_64&protocol=http)
2. yum-plugin-fastestmirror によって、利用するミラーが定期的に変わる。
3. 最新版が反映されているミラーサイトを利用した後、反映が遅いミラーサイトに変わると、件名のようなメッセージが出力される。

# 対処

ようするに反映が遅いミラーサイトを利用しないようにしたい。が……

## 対処 A. ミラーサイトをそもそも使わないようにする。

**非推奨**。確実だが、配布側、利用側、どちらのためにも出来るだけミラーサイトを利用したい。
どうしようもないときに。

`/etc/yum.repos.d/{name}.repo` を編集する。

- `mirrorlist` をコメントアウト。
- `baseurl` をアンコメント。

## 対処 B. 反映が遅いミラーサイトを調べ、利用しないように設定する。

**ちょっとはマシ**。調べるのが面倒だが……。

`/etc/yum/pluginconf.d/fastestmirror.conf` で、除外したいミラーサイトのドメインを
`exclude=mirror1.example.com, mirror2.example.com` のように設定する。

## 対処 C. 利用するミラーサイトを固定する。

**同じくらい、ちょっとはマシ**。やはり、どのミラーサイトの反映が早いかを一度調べる必要がある。

`/etc/yum/pluginconf.d/fastestmirror.conf` で、利用するミラーサイトのドメインを
`prefer=mirror.example.com` と設定する。

なお、 prefer に複数のドメインを設定することはできない。

## 対処 D. それ以外

現状なさそう。

# 結果

結局、対処 C (利用するミラーサイトを固定する) で対処した。
IUS リポジトリのミラーリストに `mirrors.kernel.org` が含まれていたので、それを `prefer` に設定した。

なお、設定後、

```sh
# リポジトリのメタ情報を削除。
sudo yum clean metadata

# yum-plugin-fastestmirror のキャッシュを削除。
sudo rm -f /var/cache/yum/x86_64/7/timedhosts
```

を実行する必要がある。
【プログラミングいろは】足したり引いたり(計算&結果表示)

[K3Tunnel](https://k3tunnel.com)を使ってプログラミングのいろはを書いています。

K3Tunnelのはじめかたはこちら⇒[【プログラミングいろは】はじめるのはカンタンです](https://qiita.com/drrn/items/96a86e8fa83dc48741cf)

今回は計算…たし算、ひき算、かけ算、わり算をしてみます。

# 足したり引いたり

たし算するには、画面左の「計算」のなかにある「1+1」というブロックを使います。
2つの数字をタップすれば書き換えらるので、好きな数字に変えましょう。2+3とか100+20とか計算できます。

ひき算(-)、かけ算(×)、わり算(÷)、べき算(^)もできます。"+"のところをタップして選びます。

# 計算結果を書く

K3Tunnelの画面の下の方に「計算結果」というところがあります。ここの「表」に計算結果を書こうと思います。

画面左の「表」に、そのためのブロックがあります。「"~"に~を表示する」ブロックを使って書けます。

# プログラミング

ブロックを並べましょう。
こんな感じ。
![Screenshot_20181208-133843.png](https://qiita-image-store.s3.amazonaws.com/0/297642/c14856a0-dc68-3e8c-fa28-21019a80e0aa.png)

# 実行する
実行してみます。計算出来ました。

![Screenshot_20181208-133904.png](https://qiita-image-store.s3.amazonaws.com/0/297642/1fd0cf23-f25f-f5a4-0883-59e8be5f3b2d.png)
__slots__を定義する場合の継承に関する注意点



通常、`class`文によって定義されたクラスのインスタンスは自由にデータメンバを追加することができ、属性の値は`__dict__`メンバ変数に保存されていますが、クラスに`__slots__`を定義し、明示的にデータメンバを列挙すると、そのクラスのインスタンスは、`__dict__`を持たなくなり、列挙されていないデータメンバを持てなくなります。
`__dict__`を持たない分、メモリが節約でき、またデータメンバへのアクセスも若干早くなります。
ただ、`__slots__`を定義する際、いくつか注意点があります。
(参考: https://docs.python.org/3/reference/datamodel.html#slots)


**1. クラスに`__slots__`を定義する場合、その基底クラスは全て`__slots__`を持つ必要がある。**

次の例のように、基底クラスに`__slots__`が定義されていないと、`__dict__`が生成されてデータメンバが追加可能になり、`__slots__`を定義した意味が無くなります。

```py

class A:
    pass

class B(A):
    __slots__ = ('foo',)
```

```py
>>> b = B()

>>> b.bar = 3     # __slots__を定義しているにも関わらず属性が定義できてしまう

>>> b.__dict__    # __dict__が生成されてしまっている
{'bar': 3}
```
基底クラスに`__slots__`を定義すると、この問題は解決します。

```py

class A:
    __slots__ = ()    # 空の__slots__を定義する

class B(A):
    __slots__ = ('foo',)
```

```py

>>> b = B()

>>> b.bar = 3     
AttributeError: 'B' object has no attribute 'bar'

>>> b.__dict__   
AttributeError: 'B' object has no attribute '__dict__'
```
**2. 基底クラスの`__slots__`に同名の変数の定義があると、重複してデータメンバが確保されていまう。**
無駄なアクセスできない変数が生成されてまいます。将来的にはエラーとなるようチェックをかけるかもしれないということですが、Python 3.7時点ではエラーにはなりません。

```py
class A:
    __slots__ = ('foo',)
    
class B(A):
    __slots__ = ('foo',)
```
```py
>>> import sys

>>> a = A()

>>> b = B()

>>> sys.getsizeof(a)
48

>>> sys.getsizeof(b)
56
```
**3. 多重継承により、空でない`__slots__`を持つ複数の基底クラスは持てない。**
この制約はエラーになるのですぐにわかりますが、下記のコードを実行すると`TypeError: multiple bases have instance lay-out conflict`となります。

```py
class A:
    __slots__ = ('foo',)
    
class B:
    __slots__ = ('bar',)
    
class C(A, B):
    __slots__ = ('baz',)
```
次のように、どちらか一方は空の`__slots__`となるようにクラスの設計を考え直す必要があります。

```py
class A:
    __slots__ = ()

class B:
    __slots__ = ('foo', 'bar')
    
class C(A, B):
    __slots__ = ('baz',)
```

参考: https://stackoverflow.com/questions/472000/usage-of-slots
CentOS7でXWindowが起動しない際に、multi-user.targetモードに切り替える方法

# 困ったこと（記事を書くきっかけ）
XWinodowの設定等をいじったあとに、graphical.targetモードで起動しようとしたところ、画面真っ暗となり、OSログインができなくなってしまいました。
シングルユーザモードで起動して、

```bash
systemctl set-default multi-user.target
```
と実行しても、設定ファイルがシングルユーザモードでは書き換えできないため（read-only）multi-user.targetに切り替えられませんでした。そこで、備忘録的に対処内容をまとめました。

# 対処法
参考サイト：[CentOSのEmergency Modeでの起動方法](https://www.thegeekdiary.com/rhel-centos-7-how-to-set-default-target-replaced-runlevel/)
(1) Bootup画面で起動するカーネル選択し、e押下
(2)linux16 lineのパラメータで以下を指定（参照サイトはsystemd.unit=emergency.targetとなっている箇所）

```bash:
systemd.unit=multi-user.target
```

(3)Ctl+xで起動
(4)OSから起動モードを切り替える

```bash
systemctl set-default multi-user.target
```
keras モデルファイルのバージョンを確認する

### keras モデルファイルのバージョンを確認する

### はじめに
***
kerasで現在利用しているバージョンと、モデルファイルのバージョンが違っていると
ファイルを読めないことがあります。
以下でモデルファイルのバージョンを確認できます。

```py

# coding:utf-8
import h5py

with h5py.File("model.hdf5", "r") as fp:
    print(fp.attrs.get("keras_version"))

```
私はGoogle Colaboratoryで、別の環境で作成したファイルが読めず原因を探していて
この問題に行き着きました。
（2.1.6で作成したファイルが2.2.4で読めなかった）

現在の環境のkerasのバージョンは以下で確認できます。

```py
import keras
print(keras.__version__)
```

Google Colaboratoryでkerasをバージョン指定してインストールするのは以下でできます。

```py
! pip install keras==2.1.6
```