OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerではコンテナのlocaleの再確認を

# 動機

Pythonの例を出していますが、Python に限らないDocker一般論です。
普通によく利用されるDockerオフィシャルのコンテナでの話です。

Dockerコンテナ内で、PythonのUnicodeEncodeError、UnicodeDecodeErrorで悩まされたことがありました。

ベースになるイメージで```ja_JP.UTF-8``` の locale が用意されていないのに、ついうっかりDockerfile内で

```ENV LANG ja_JP.UTF-8```

とかやって、localeに```ja_JP.UTF-8```を指定してしまっていたのが原因でした。

私が気付いたときは Python を使っていたので UnicodeEncodeError という形で問題が現れたのですが、案件によっては原因不明の文字化けといった現象になるかもしれません。

知っていればどうということはないのですが、知らないとなかなか原因にたどり着けないのでここでメモしておきます。

# 再現テスト

例えば Python 使いの人なら、次のようにすれば問題を再現できます。

オフィシャルの python のコンテナイメージ（latest）を pull します

```
$ docker pull python
```

Dockerコンテナを起動し、シェルを立ち上げます

```
$ docker exec -it python /bin/bash
```

コンテナ内のシェルで、環境変数LANGを設定します。

```
# export LANG=ja_JP.UTF-8
```

エラー再現用のPythonスクリプトを作成・実行します。

```
# echo "print(\"ほげ\")" > test.py
# python test.py
```

実行結果は以下のようになります。

```
Traceback (most recent call last):
  File "test.py", line 1, in <module>
    print("\u307b\u3052")
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
```

ここで

```
# export PYTHONENCODING=utf-8
```

とかやっても状況は改善しません。

オフィシャルのコンテナに```ja_JP.UTF-8``` locale がインストールされていないのが原因なのですから。

確認のためにシェル上で

```
# locale -a
```

を実行すると

```
C
C.UTF-8
POSIX
```

の3つしか表示されません。

この問題、原因が分かっても解決するのは簡単ではありません。

# 対策

## STEP1 現在のlocaleの確認

まずはコンテナの locale を確認します。

pullしてきたコンテナ内で

```
# echo $LANG
```

を実行してみます。
ここで、

```
C.UTF-8
```

が表示されて、

```
# locales -a
```

の表示に

```
C.UTF-8
```

が含まれていて、現状取り組んでいる案件で```ja_JP.UTF-8```を使う必要がないのであれば、環境変数を変更せず、```LANG=C.UTF-8```の状態にしておくのが無難です。

参考: [LANGやPYTHONIOENCODINGを設定してもUnicodeDecodeErrorが出る時の更なる確認ポイント](https://qiita.com/mokemokechicken/items/55fe1cc83f93299ac4dd)

## STEP2 ベースイメージの確認

どうしても```ja_JP.UTF-8```を使う必要がある場合は、localeの生成から始める必要があります。
これは、ディストリビューション、バージョンによってやり方が違うので、コンテナのベースになっているディストリビューションが何なのかを調べるところから始める必要があります。

例えばオフィシャルの python の場合、https://hub.docker.com/_/python/ を参照すると、2018年2月13日現在、デフォルトの python:latest は、 Debian jessie がベースになっていることがわかります。

## STEP3 ja_JP.UTF-8 localeのインストール

オフィシャルの python:latest イメージには、locales パッケージが入っていませんので、そのインストールから始める必要があります。

```
# apt-get update
# apt-get install locales
# echo "ja_JP UTF-8" > /etc/locale.gen
# locale-gen
```

debianのまともな解説を読んでいると、```/etc/locale.genのja_JP.UTF-8のコメントを解除する```などと書いてああります。

参考: [Debian/Ubuntuのデフォルトロケールを変更する](https://qiita.com/tailak/items/77b90a4df07e4f6a1fc2)

ですが、そのためにテキストエディタを起動していては処理を自動化できません。どうせコンテナの中では必要最低限の1プロセスしか動かさないので、少々強引ですがここでは

```
# echo "ja_JP UTF-8" > /etc/locale.gen
```

という処理をしています。これなら後で自動化したいときに、Dockerfile の RUN コマンドの中に含めてしまうことができますね。

これで、先のスクリプトが動くようになりました。

```
# python test.py 
ほげ
```

ベースイメージが Alpine、 Ubuntu、CentOS などの場合は、それぞれのディトリビューションの流儀に従って locale を生成する必要があります。

# まとめ

レンタルサーバーやVPS、VirtualBoxの仮想環境などでしたら、OSインストールの際に locale の生成までやってしまうのでついつい見落としてしまうのですが、Dockerコンテナの場合、オフィシャルのイメージではそこまで面倒をみてくれていないことが普通にあります。

使う前にlocaleがどのような状態になっているのか確認するようにしましょう。
'NSLog' is unavailable: Variadic function is unavailable

Swift のエラーで, しばらく意味が分からなかったのでメモ.

'NSLog' is unavailable: Variadic function is unavailable

「可変長引数の関数が無効」？？？

いや, 他の箇所では引数沢山あっても通ってるのに？？？

...と, 色々試したところ, 引数の数は関係なく, 問題はどうやら引数の「型」の模様.
Swift の NSLog() にはどんな型でも渡せるわけではなく, 直接渡せない型があるようだ.

* enum
* Any, AnyObject など
* プロトコルだけの型

などを渡そうとしたときに, 上のエラーが出るようだ. (他にもありそう)

このため例えば Swift ではプロトコルである Error は直接渡せないので, 変数名を error とするならば error.localizedDescription() して渡すと上手くいった.
カジュアルにサーバーログをチェックするならLogglyが簡単だった

サーバーのログを色々とチェックしてみたいけど、自前でツールをセットアップしたりするの面倒だし、
何かないかなぁと思って探したら発見し、サクッと試すことが出来たので簡単にご紹介。

# Loggly

https://www.loggly.com/
所謂クラウドのログ管理サービス、という感じでしょうか。

# セットアップ
① アカウント登録をします。
https://www.loggly.com/signup/
最初はトライアルアカウントで登録され、30日間は制限無しで機能が使えるようです。  
  
② ソースを追加
対象となるログの設定を行います。
![source_map.png](https://qiita-image-store.s3.amazonaws.com/0/995/646cfd72-6859-e612-dd58-ec92eb206d6d.png)  
今回は Linux File Monitoring を選択。
すると↓のような表示が出てきまして、コピペして実行するだけでセットアップが完了するという親切設計になっております。

![e3b835b9f478d911f00f4fba095d2750.png](https://qiita-image-store.s3.amazonaws.com/0/995/ae0e6069-350f-37c4-8516-d2793beb7151.png)  
サーバーで実行すると、Logglyのパスワードが求められるのでそれを入力。
基本的には以上でセットアップが完了します。簡単！  

※↓から対応しているツールやFWが確認出来ます。
結構対応している模様でいいですね。
https://www.loggly.com/docs-index/log-sources/

# 使ってみる
実際の画面はこのような感じで、自動的にログを解析してチャートが表示されます。
![bfbbb0ee8d56bcee9c20b440981cb8a6.png](https://qiita-image-store.s3.amazonaws.com/0/995/29ec27b0-cb15-20fb-7490-cb6ecf784cfb.png)

各種フィルターも付いており、データの絞り込みもすぐ出来て便利。
![64379eb6c310ac240415d459fafcfb71.png](https://qiita-image-store.s3.amazonaws.com/0/995/dffa60a6-3662-97fc-6e74-c5212a32c3c7.png)

チャートやグラフ作成機能もあり、それをまとめるダッシュボードもあります。
![61325de5bd75c1750b0b198f7ce8810c.png](https://qiita-image-store.s3.amazonaws.com/0/995/a1410e56-a686-d2ac-e058-378e226df780.png)

![5cbfcea2f71db8b954e7f335bae3af2f.png](https://qiita-image-store.s3.amazonaws.com/0/995/d9f65b3f-e500-fd0d-9cab-a82fe7611cdc.png)

# まとめ
・簡単にですがLogglyを紹介しました。
・サクッと試すことが出来るので、とりあえずログをチェックしてみたいという人には便利だと思いました。
Python100本ノック(5/100)

## はじめに
Pythonを行き当たりばったりで触ってきたので
何処までPythonできているのかを見つめ直すために、[自然言語処理100本ノック](http://www.cl.ecei.tohoku.ac.jp/nlp100
)していきます。
python2ばっかり使っていましたので、慣れるためにpython3でやっていきます。

---
### **00. 文字列の逆順**
```python
    text = u'stressed'
    print(text[::-1])
```

    desserts


### **01. [パタトクカシーー]**
```python
text = u'パタトクカシーー'
print(text[::2])
```

    パトカー


### **02. [パトカー]+[タクシー]=[パタトクカシーー]**
```python
a = u'パトカー'
b = u'タクシー'
text = u''
for i, j in zip(a, b):
    text += i + j
print(text)
```

    パタトクカシーー


forにしてしまったけど、joinと内包表記使った方がよかったらしい。
print(''.join([i + j for i, j in zip(a, b)]))
内包表記は多様しますが、さらに関数に渡すことはあまりしてこなかったのでこの発想にいたりませんでした。

### **03. 円周率**
```python
text = u'Now I need a drink, alcoholic of course, after the heavy lectures inbolving quantum mechanics.'
words = [sorted(w.strip(',.'), key=lambda x: w.count(x), reverse=True)
         for w in text.split()]
print(words)
```

    [['N', 'o', 'w'], ['I'], ['e', 'e', 'n', 'd'], ['a'], ['d', 'r', 'i', 'n', 'k'], ['l', 'c', 'o', 'o', 'l', 'c', 'a', 'h', 'i'], ['o', 'f'], ['c', 'o', 'u', 'r', 's', 'e'], ['a', 'f', 't', 'e', 'r'], ['t', 'h', 'e'], ['h', 'e', 'a', 'v', 'y'], ['e', 'e', 'l', 'c', 't', 'u', 'r', 's'], ['i', 'n', 'i', 'n', 'b', 'o', 'l', 'v', 'g'], ['u', 'u', 'q', 'a', 'n', 't', 'm'], ['c', 'c', 'm', 'e', 'h', 'a', 'n', 'i', 's']]

splitとstripで英文を単語に分解しました。
その後、悩みましたが、sortedで並び変えを行いました。
そして、他の人の解答を見て問題を読み違えていることに気がつきました!
lenでええやん……
しかも、単語の出現数順にソートしているつもりだったんですが、できてない。

lenにしました。

```python
text = u'Now I need a drink, alcoholic of course, after the heavy lectures inbolving quantum mechanics.'
words = [len(w.strip(',.')) for w in text.split()]
print(words)
```

    [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9]

### **04. 元素記号**
```python
text = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."
words = [w.strip(',.') for w in text.split()]
# print(words)
one = [1, 5, 6, 7, 8, 9, 15, 16, 19]
word_dict = {w[0] if words.index(w) + 1 in one else w[:2]: words.index(w)
            for w in words}
print(word_dict)
```

    {'H': 0, 'He': 1, 'Li': 2, 'Be': 3, 'B': 4, 'C': 5, 'N': 6, 'O': 7, 'F': 8, 'Ne': 9, 'Na': 10, 'Mi': 11, 'Al': 12, 'Si': 13, 'P': 14, 'S': 15, 'Cl': 16, 'Ar': 17, 'K': 18, 'Ca': 19}

04と同じく分解しました。
その後、内包表記で辞書を作りました。
辞書に入れる順番が0になっているのは、問題がちゃんと読めていないためです。


一日何問解いていけるかなっという感じでしたが、単語にも疎いため時間がかかりそうです。
次のn-gramってなんだ…？

---
風呂でのプログラムは、誘惑が少くていい感じです!
問題は湯が冷めてきたら、どうしたらいいかわかんない所。
風呂蓋で多少マシになった気がする。
Nodeモジュールを手元でビルドして使用する方法(Vuetify)



VueのコンポーネントライブラリであるVuetifyですが、ちょっと前に`1.0.0`がリリースされました。
しかし、`npm i vuetify`でインストールできるバージョンはメジャーリリース前の`0.17.6`となっています。

https://www.npmjs.com/package/vuetify

そこで、現時点(2018/02/02)で最新版を手元で使用する方法を備忘録として残しておきます。

# `npm`でGitHubからインストール(失敗)

`npm`は以下のコマンドで直接GitHubからインストールすることができます。

```
npm install {user名}/{repository名}#{ブランチ名}
```

実際に実行したコマンド

```
$ npm i -D vuetifyjs/vuetify#dev
```

結果、Vuetifyの`package.json`に書かれている依存で必要なものはインストールされましたが、
ビルドに必要なディレクトリやファイル(`/build`等)がもってこれませんでした :cry: 
![image.png](https://qiita-image-store.s3.amazonaws.com/0/97227/aa2972b2-8a7d-ef9d-abf4-585e7fee350a.png)

原因や仕組みは調査中。知っている方がいたらコメントください。

# 別のディレクトリにクローンしてローカルモジュールとして扱う(成功)

ざっくり言うと`npm install`でインストールできないなら、直接クローンしてビルドしてローカルモジュールにしてしまえばいいじゃないということです :smirk:

## クローンしてビルド

`local_modules`というディレクトリを作成して、そこにクローンしました。

```
$ mkdir local_modules
$ cd local_modules
$ git clone https://github.com/vuetifyjs/vuetify.git
$ cd vuetify
```

クローンしただけなので当たり前ですが、ビルドに必要なファイルもそろっています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/97227/c65ee043-6fb3-a940-70fe-ca55bec525d6.png)

`package.json`を参考に必要なものをインストールしてビルドします。

```
$ npm install
$ npm run build
```

ビルドが完了すると`dist`と`es5`というディレクトリが作成されると思います。
これでVuetifyのビルドが完了したので、Vuetifyを使う側でインストールします。

## ローカルモジュールのインストール

ローカルモジュールのインストールは通常のモジュールのインストールとほとんど一緒で、モジュールのパスを渡すだけです。

```
$ npm i -D local_modules/vuetify
```

すると`package.json`には以下のように追加されるはず。

```json:package.json
{
  "devDependencies": {
    "vuetify": "file:local_modules/vuetify",
  }
}
```

あとはいつも通り開発するだけです :sunglasses: 

# 参考にした記事

http://efcl.info/2014/10/04/npm2-local-module/
https://qiita.com/nyamogera/items/9f40ed2aa2767d351fce
https://qiita.com/DQNEO/items/d166e25449124a3f2b4d
Project Euler 26「逆数の循環節 その1」

いい加減python3に慣れておいた方がよいかと思ったので今回からpython3。
今のところ「xrangeなくなったんやなー」とか「printに'()'つけるんやなー」くらいしか変化を感じてないけども。

## Problem 26 「逆数の循環節 その1」
単位分数とは分子が1の分数である. 分母が2から10の単位分数を10進数で表記すると次のようになる.

1/2 = 0.5
1/3 = 0.(3)
1/4 = 0.25
1/5 = 0.2
1/6 = 0.1(6)
1/7 = 0.(142857)
1/8 = 0.125
1/9 = 0.(1)
1/10 = 0.1

0.1(6)は 0.166666... という数字であり, 1桁の循環節を持つ. 1/7 の循環節は6桁ある.
d < 1000 なる 1/d の中で小数部の循環節が最も長くなるような d を求めよ.

```python
def hoge(num):
    ans = 0
    for d in range(2, num):
        # 2、5で割れる数字が分母なら循環小数にはならない（たぶん）
        if d % 2 == 0 or d % 5 == 0:
            continue
        (i, remainder) = (1, 10)
        lst_remainder = []
        while True:
            remainder = remainder % d
            # 過去に同値の余りが出現していたらループを抜ける
            if remainder in lst_remainder:
                break
            # 余りをリストに貯めていく
            lst_remainder.append(remainder)
            (i, remainder) = (i + 1, remainder * 10)
        # リストのインデックスを利用し循環節の長さを計算
        cycle_length = i - (lst_remainder.index(remainder) + 1)
        if ans < cycle_length:
            ans = d
    return ans

print (hoge(1000))
```

変数名とかもちゃんとしていこうと思う今日この頃。
Cloud Datalabに大きなデータをアップロードする方法

Cloud Datalab[^1]は、ブラウザでpythonが実行できる便利な環境ですが、大きなデータをアップロードできない問題があります。
検証用の大きなデータをアップロードしようとしても無反応で、裏側で何が起きているのかわかりません。
アップロードする方法はいくつかあるようですが、今回は `gcloud` コマンドを使用する方法について。

# 前提

* すでにローカルで動作する jupyter のプロジェクトがある  
→ BigQueryやCloud Storageからデータを取得するコードに書き換えるのは手間……
* DatalabのWebコンソールではアップロードできない大きなファイルがある

# 方法

`gcloud` コマンド の `scp` を使用し、Datalabインスタンスに直接投げます。
（これが良い方法かどうかは不明です、Datalabのドキュメントにはこのような方法は書いていなかった。気がする。）

## アップロードするファイルの準備

ファイル単体であれば問題ありませんが、複数のファイルやディレクトリをアップロードする場合は、事前に`tar`などでアーカイブを作成しておくと良いです。

## gcloud コマンドの設定

まずは、Datalabを使用しているプロジェクトにスイッチします。

```
gcloud projects list
gcloud config set core/project プロジェクトID
```

## アップロードと展開

Datalabのディレクトリは、インスタンスにマウントされていて、直接scpではアップロードできないようです。
そのため、一旦、自分のディレクトリにアップロードした後、インスタンス内で移動させます。

```
gcloud compute scp --zone [zone_name] ~/my_local_directory/data.tar my_account@instance_name:/home/my_account
```

コマンドラインか、ブラウザのコンソールからインスタンスに入ります。

```
gcloud compute --project "project_name" ssh --zone "zone_name" "instance_name"
```

移動して展開します。移動先が大事です。
Datalabのデータはどうやら、`/mnt/disks/datalab-pd/content/datalab/`にマウントされているようです。

```
cd ~
sudo mv data.tar /mnt/disks/datalab-pd/content/datalab/
cd /mnt/disks/datalab-pd/content/datalab/
sudo tar xzvf data.tar
```

以上！あってるのかわからないけど、これでできました。

---

[^1]: Datalabは、GCPで提供されている クラウド jupyter 環境。pythonのインタラクティブな実行が、ブラウザで、しかもクラウドで出来るのが特徴で、GCPの各サービスとの連携も良い感じらしいです。
Laravel でRestfullなコントローラーとモデルを作成する

公式ドキュメントに書いてある通りにやって見た
```
$ php artisan make:controller HogesController -r -m=Hoge
```

公式ドキュメント通りにやってできなかったのですが、出来なかったのですが、以下で出来ました。

```
$ php artisan make:controller HogesController -r --model=Hoge
```
workspaceを作らずにSwiftLintをCocoaPodsで管理する

リポジトリの`swiftlint`のバージョンを固定したい時に。

Carthageはバイナリの配布をサポートしていないのでCocoaPodsで管理する。
が、他のライブラリをCarthageで管理している場合、バイナリを利用するためだけに`xcworkspace`を使うのは気持ちよくないのでオプションを探してみた。


## [CocoaPods/CocoaPods](https://github.com/CocoaPods/CocoaPods)

ドキュメントには`xcworkspace`を作らないようにするオプションについての記述が見当たらなかったため、ソースコードを読むことにした。(見落としていただけかも)

https://github.com/CocoaPods/CocoaPods/blob/64ec0edd705978f99afda85d2e9e592dd6f1f145/lib/cocoapods/installer.rb#L120

https://github.com/CocoaPods/CocoaPods/blob/7bef87f95b85ee31ce6ad04e7d14645965ab86bf/lib/cocoapods/installer/user_project_integrator.rb#L62


どうやら、`integrate_targets`を`false`にすれば`create_workspace`が実行されないようだ。
試しに以下の`Podfile`で試したところ、`Pods`ディレクトリ**のみ**が作成された。`xcworkspace`の無い綺麗な世界の完成 :raised_hands:


```ruby:Podfile
platform :ios, '11.0'

install! 'cocoapods', :integrate_targets => false
target 'App' do
  pod 'SwiftLint'
end
```

## 注意点

`integrate_targets`を`false`にすると、`$PODS_ROOT`などの環境変数は使えなくなる。
そのため、`$PODS_ROOT` を `${SRC_ROOT}/Pods`に置き換える必要がある。
IFTTT × Hue

**注.これはN高 5,6限LT用の説明用ドキュメントです。**
この記事は、LTと**同時に**聞かないと、**理解不能**な内容になっていると思うので、もし一般の方でこちらにいらっしゃった方は申し訳ありません。こちらで**ブラウザバック**をしていただけると幸いです。

#🤔Hueって何？

![hue_White_and_ColorAmbianc_house_light.jpg](https://qiita-image-store.s3.amazonaws.com/0/185109/8bc1a4f8-86b5-d43e-f32a-3964dccd44be.jpeg)

HueはPHILIPS社が販売している、簡単に言うと「ネットに繋がる照明」です。

普通にスイッチでコントロールすればよくね？って思った貴方、🤫ｼー

[なーんとなくわかってもらえそうな動画](https://www.youtube.com/watch?v=p_YIGK3b97E)

###🙄何が凄いの？

先程も言った通りに、この電球は一つ一つがネットに繋がっています。そして、プログラミングで照明の制御が出来ます。

例えば、外出先から防犯目的に家にいなくても照明をコントロールしてみたり
例えばゲームや音に合わせた照明の色にしてみたり
例えば、時間や天気を検知して電気の雰囲気を変えてみたり
例えば、etc

可能性は**無限大**なんです。

ではここからは、実際にそのHueを使って、照明をコントロールする簡単なプログラミングをしてみましょう。
プログラミングと言ってもとても簡単な物です。安心してください。🤔


##🕺Hueを使ってみよう

本当はここでアカウントを作るのですが、今回はN高専用のアカウントを既に制作しているので、そのアカウントにログインして下さい。

###📲アプリのインストール
iPhone: [ココ](https://itunes.apple.com/us/app/philips-hue-gen-2/id1055281310?ls=1&mt=8)
Android: [ココ](https://play.google.com/store/apps/details?id=com.philips.lighting.hue2)

アカウントのIDとPasswordは当日、Slackに投稿します。
(おそらくLTを受ける人全員が同時にログインをすると、Botだと勘違いされてBanされる可能性が高いので、今回は1班一人にします。)

ログインが完了すると、既に設定済みの照明が出てきます。自由にコントロールしてみて下さい。



#🤔IFTTTって何？

**IF** = if
**T** = this
**T** = then
**T** = **T** hat 

もし◯◯が、◯◯であれば、◯◯を、◯◯する。
丸の部分にアプリ、またはサービスを入れる事によって出来る、とても簡単なプログラミングです。
例(もし「時間」が「12時になっ」たら、「通知」を「送信」する。)

例えばコレをSwift(iPhoneのアプリを作る時に使う言語)で書こうとすると、


こんな感じになります。


コレをIFTTTと言うツールは簡単にタップだけで作る事が出来てしまうのです。


#👨‍💻実際に作ってみよう

###📲IFTTTのインストール

iPhone: [ココ](https://itunes.apple.com/jp/app/ifttt/id660944635?mt=8)
Android: [ココ](https://play.google.com/store/apps/details?id=com.ifttt.ifttt&hl=ja)

###⛏登録

Googleの連携使えば秒で終わります。

![許可画面](https://www.evernote.com/l/AkTXB5mSqfJPRr5ivqLaM2oxQ7PLwDQQglYB/image.jpg)

![成功!](https://www.evernote.com/l/AkQV6keGlEJDYZ7-0JpY2S5zxDH_El6SNE4B/image.jpg)

###👏こんな画面が出れば成功



###💻プロジェクトの作成
      

**詳しいことは当日説明します**
---

右下にある 「My Applets」 の右上にある＋ボタンを押して、新しいプロジェクトを作成します。
青色の「This」を選択して、動作を選択します。

今回はButtonを選択します。
![IMG_A06AADAB98D4-1_2.jpg](https://qiita-image-store.s3.amazonaws.com/0/185109/0c766697-f671-0697-63ed-a559d23df7de.jpeg)

選択が終わったら「Then」の部分にLINEを選択します。メッセージ内容等は自由に作ることが出来ます。

<img width="375" alt="IMG_5852.png" src="https://qiita-image-store.s3.amazonaws.com/0/185109/4797efc4-3db5-3f3f-dbe6-36a144acf599.png">

ここから更に授業では発展したアプリを作っていきます。

###😅おしまい。



なんとなく〜でもいいので分かってもらえたら…
プログラミングは自分で物を作る楽しさだったり、物凄く**奥が深い**本当になんでも出来てしまうので、是非少しでも興味を持ってもらえると嬉しいです。


###🌚宣伝
[Life is Tech!](https://life-is-tech.com)
[春キャンTop!](https://life-is-tech.com/camp)
Cloud9でウェブサイトを作成後、Herokuで公開する

同じことをやって挫折したので以下メモ。。

参考
<a href="https://qiita.com/NaokiIshimura/items/378839914919f74e29f4">Cloud9で作成したWEBサイトをHerokuで公開する手順</a>
Capybara+headless-chrome でフルサイズのスクリーンショットを撮る

#Capybaraでスクリーンショットを撮る

```ruby
page.save_screenshot "ss.png"
```

ただし、上の書き方だと画面の一部分しか撮ってくれません...

# Capybaraでフルサイズのスクリーンショットを撮る
フルサイズのスクリーンショットの撮り方を調べると`full: true`オプションを発見したので付けてスクリーンショットを撮ってみます。

```ruby
page.save_screenshot "ss.png", full: true
```

しかし、headless-chromeだとフルサイズに撮れませんでした...

他の方法がないか調べると以下のサイトを発見。
https://testingrepository.com/full-page-screenshot-with-selenium/

`take_full_page_screenshot`メソッドを適当な場所に定義して、`page.save_screenshot`を`take_full_page_screenshot`に置き換えてみます。

```ruby:spec_helper.rb
def take_full_page_screenshot(path)
  width  = Capybara.page.execute_script("return Math.max(document.body.scrollWidth, document.body.offsetWidth, document.documentElement.clientWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth);")
  height = Capybara.page.execute_script("return Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);")

  window = Capybara.current_session.driver.browser.manage.window
  window.resize_to(width+100, height+100)

  page.save_screenshot path
end
```

今度はフルサイズで撮ることができました！
[備忘録]bundle で指定したrailsのバージョンでアプリを作成

# bundle で指定したrailsのバージョンでアプリを作成
## 適当なアプリのディレクトリを作成
```
mkdir test_app && cd test_app
```

## rbenv でrubyのバージョン指定
```
rbenv local 2.4.x
```

## bundle でGemfileを設定
```
bundle init
vi Gemfile
```

下記のように好みのバージョンで指定する。

```
gem 'rails', '4.1.7'
```

gemのインストールをする

```
bundle install --path vendor/bundle
```


## rails 構築
```
bundle exec rails new --skip-bundle .
```

# 他の方法

rails new する際にバージョンを指定

```
 rails _4.1.7_ new test_app
```
Fluentdでそのままログ（生ログ）を転送する

# 概要

Fluentdで生ログを転送するための設定を残したいと思います。
source側の`format none`だけでいけると思っていたが、それだけではfluentdの標準的なメッセージフォーマットで出力されてしまい、望んでいた出力結果にはならなかった。なので、結論から言いますと、file出力側で`format single_value`を指定することで送信元のログのまま出力されます。

# 転送元の設定

例）転送するログ

```text:apache.log
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
```

```xml:td-agent.conf
<source>
  @type tail
  <parse>
    @type none
  </parse>
  path /var/log/apache.log
</source>
<match **>
  @type forward
  send_timeout 60s
  <server>
    host xxx.xxx.xxx.xxx
    port 24224
  </server>
</match>
```

# 受信側の設定（ログ出力側）

```xml:td-agent.conf

<source>
  @type forward
  port 24224
  bind 0.0.0.0
</source>
<match **>
  @type file
  <format>
    @type single_value
  </format>
  append true
  # 受信したデータを出力ファイル
  path /var/log/apache-copy.log
  # 日単位に出力
  time_slice_format %Y-%m-%d
  <buffer>
    # バッファタイプはファイル
    @type file
    # バッファファイルの出力先
    path /var/log_buffer/apache-buffer
    flush_mode interval
    # 60sごとにファイルに書き出す
    flush_interval 60s
  </buffer>
</match>
```

# ポイント

送信側の`@type tail`の`format none` にすること

ファイル出力側で`format none`だけでは、以下のような標準的なfluentdのメッセージフォーマットで出力されます

```text:apache-copy.log
datetime tag {"massage": "127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] \"GET /apache_pb.gif HTTP/1.0\" 200 2326"}

```

受信側の`@type file`の`format single_value`にすること
これで転送元のログのままになります

```text:apache-copy.log
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
```
[Mac/ubuntu]最新Python実行環境構築手順

# 目的
任意のバージョンのpythonを選べるようにし、常に最新のバージョンを利用できるようにする。
実行環境ごとに依存ライブラリが分離された環境を準備する。
システムワイドに環境を汚染せず、ユーザごとに任意のPythonを実行可能とする。

# anyenv+anyenv-updateインストール

ndenvツールの導入を容易にしたり、envツールのアップデートを容易にするためにanyenvから入れていく。

```bash
$ git clone https://github.com/riywo/anyenv ~/.anyenv
```
環境設定

## Macの場合
```bash
$ echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(anyenv init -)"' >> ~/.bash_profile
$ exec $SHELL -l
$ git clone https://github.com/znz/anyenv-update.git ~/.anyenv/plugins/anyenv-update
```

## Ubuntuの場合
```bash
$ echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.profile
$ echo 'eval "$(anyenv init -)"' >> ~/.profile
$ exec $SHELL -l
$ git clone https://github.com/znz/anyenv-update.git ~/.anyenv/plugins/anyenv-update
```
# pyenv+pyenv-virtualenvインストール

開発環境ごとに依存関係を分離するため、pyenv-virtualenvをあわせて導入。

```bash
$ anyenv install pyenv
$ exec $SHELL -l
$ git clone https://github.com/yyuu/pyenv-virtualenv ~/.anyenv/envs/pyenv/plugins/pyenv-virtualenv
```

# 任意のバージョンのpythonをインストール
## ubuntuの場合の関連パッケージ導入
```bash
$ sudo apt install build-essential zlib1g-dev libffi-dev libssl-dev libbz2-dev libreadline-dev libsqlite3-dev
```

```bash
$ pyenv install 3.x.x
```

## 最近、MojaveにアップグレードしたMacでインストールに失敗する場合

```
zipimport.ZipImportError: can't decompress data; zlib not available
make: *** [install] Error 1
```
上記のようなエラーが出てインストールに失敗する場合は下記のコマンドを試す

```bash
$ sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /
```

上記のコマンドを実行しても下記のようなエラーがでる場合

```
installer: Error - the package path specified was invalid: '/Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg'.
```

Command Line Tools (macOS 10.14) for Xcode 10パッケージを下記のURLからダウンロードしてくる
https://developer.apple.com/download/more/

# Macでopensslが入っているにも関わらず3.7.0以上がインストールできない場合
下記のようなエラーが出る場合

```
ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?
```
下記の対応で、openssl1.1.1を使用

```bash
$ brew install 'openssl@1.1'
$ CONFIGURE_OPTS="--with-openssl=$(brew --prefix openssl@1.1)" pyenv install 3.7.0
```


# インストール可能なバージョンの一覧を見たい場合
```bash
$ pyenv install --list
```

# 最新のバージョンのpythonがインストールできない場合
```bash
$ anyenv update
```

# 切り離された実行環境をカレントディレクトリに作成
```bash
$ pyenv virtualenv 3.x.x my-develop-environment
$ pyenv local my-develop-environment
```
Python 勉強開始

pythonプログラミング初心者がわかりやすいと思った記事や、まとめておきたい情報を載せていきます。

同期に教えてもらった「progate」というサイトは、初心者が学ぶにはわかりやすいとおもいます。
URL: https://prog-8.com/
環境構築する必要もなく、解説がイラスト付きでわかりやすい、学んだことがその場で演習できていいです。
一通り学習しようと思います。

それと同時進行で、自宅PCにデバックできる環境を構築してコマンドを試す
公式リファレンスや、ドットインストールで学んでいく予定です。
nmbd (メモ)

小規模なWindows系のネットワークでの名前解決は、NetBIOS over TCP/IPを使って、ブロードキャストを使った名前解決を行っている事が多い。

sambaサーバを構築して、ホスト名でサーバーにアクセスしたいときは、NetBIOSによる名前解決プロトコルに対応しなければならない。

そのためのデーモンが「nmbd」

ホスト名の設定は、/etc/samba/smb.confに

[global]
netbios name = host_name

この設定をnmbdが読み込み、host_nameの名前解決パケットが走ったら、返答するようになる。

んーCentOS6だと、この二つのデーモンを起動しないといけないみたい。

nmdbデーモンを起動しておけば、ブラウザからでもホスト名でそのサーバーにアクセスできるようになるので、社内サイトとか置いておくとき楽しいかも。
Ubuntu で暗号通貨お手軽CPUマイニング(Bitzeny 編

余ったCPUを利用してマイニング
CPU でもマイニングしやすいと噂の Bitzey をマイニングします。

# 環境

Ubuntu

# コード

送り先は良しなに書き換えてください。

```sh
git clone https://github.com/fumiya-kume/bitzenyStartup.git
cd bitzenyStartup
sh ./start.sh
```
https://github.com/fumiya-kume/bitzenyStartup
Rails5でチャット機能（Action Cable) 試してみるメモまとめ

チャットアプリを作ってみるにあたって、環境構築に特に苦労したのでメモ

# 作業環境
- AWS EC2 Red Hat Enterprise Linux 7.4(HVM)
- Ruby 2.3.1
- Rails 5.0
- MySQL 5.7

#　参考URL
- [サンプルコードで学ぶRuby on Rails 5実践入門](https://codezine.jp/article/corner/681)
- [世界一丁寧なAWS解説。](https://qiita.com/naoki_mochizuki/items/814e0979217b1a25aa3e)
- [rails環境構築（CentOS + ruby on rails）](https://qiita.com/shinyashikis@github/items/3501c5f7f71a8e345c3d)
- [CentOS7.3にMySQL5.7をインストールした時のメモ](https://qiita.com/prgseek/items/7c77d4b14d0afbf84f5c)
- [【AWS EC2 エラー】ssh port 22 Operation timed out](https://qiita.com/yokoto/items/338bd80262d9eefb152e)
- [RAILS5+PUMA+NGINXで本番環境を構築してみる](https://www.gakusmemo.com/?p=608)
- [CentOS 7 (5, 6) で "安定版 (最新版)" のNginxをインストールする方法](https://qiita.com/noraworld/items/1aae57dcbe428089c7d5)



MariaDBではなくMySQL
MySQL関連ではハマりまくったので上記メモに助けられた

#ffiのインストールで失敗した時
ライブラリがないようなので
- sudo yum install libffi-devel
Androidアプリケーション技術者認定試験ベーシックの試験範囲の知識をまとめた(17)

# おまけ

## 用語集

忘れそうな用語をいくつか抜粋してまとめました。

|用語|内容|
|---|---|
|Apache Licence 2.0|Androidのソースのほとんどが適用されているライセンス|
|GPL|AndroidのLinuxカーネルで定義されているライセンス|
|LGPL|AndroidではWebkitのコア部分で適用されている|
|ADT|Eclipseのプラグイン|
|Android SDK Manager|Android SDK をインストールするためのマネージャ|
|AVD Manager|Android Virtual Deviceの作成編集削除をするためのマネージャ|
|adb|Androidアプリケーションの実行環境へのアクセスを可能とする|
|DDMS|Androidアプリケーションをデバッグするための各種機能を提供する|
|Hierarchy Viewer|Androidアプリケーションに含まれるViewの階層を表示する|
|Pixcel Perfect|Androidアプリケーションの画面を拡大表示し、画面の設計や構築支援を行う|
|ProGurard|ソースコードの最適化（リバースエンジニアリング対策）を行う|
|TraceView|Androidアプリケーションの実行ログを取得する|
|layoutopt|レイアウトのXMLで無駄な定義がないかチェックするツール|
|Draw 9-patch|PNG形式の画像に拡大領域(左上）コンテンツ領域（右下）を指定できる|
|aapt|コンパイルしたコードをapkにまとめるツール aapt d[ump]で内容表示|
|AIDL|IPC通信をするためのインターフェースを定義するツール|
|sqlite3|SQLiteを利用するためのコマンドラインツール|
|dx|dexファイルを作るためのツール|
|zipalign|apkファイルを最適化するツール4バイト境界に合わせる|
|SL4A|Scripting Layer for Android|
|ASE|Android Scripting Environment|


## 最後に

これで終わりです。知識の整理には良いですね。
Androidアプリケーション技術者認定試験ベーシックの試験範囲の知識をまとめた(16)

# アプリケーション配布

## 署名

### 署名が必要な理由

署名されていないアプリケーションは端末にインストールできない

1. アプリケーション製作者を識別する
1. 異なるアプリケーション間の信頼関係を確約する

署名とは、事前に作成したプライベートキーをアプリケーションに登録(署名)するといいう事。
プライベートキーの生成には、認証局の証明は不要。

#### エミュレータへのインストールにも署名は必要！？

署名は必要。ただしEclipseがADTで自動的にデバック用の署名をしているため意識することはない。

### 署名の手順

Eclipseでウィザードを使って署名する方法と、コマンドラインから実行する方法がある。
コマンドラインから実行するには、まずEclipseで署名なしのアプリケーションを作成し、
その後JDK付属のjarsignerを利用して署名をつける

### Eclipseから署名する

1. Eclipseからウィザードを起動する(プロジェクトを右クリックして、Androidツール→Export Signed Aplication Packageを選択)
1. 対象プロジェクトを確認する
1. プライベートキーファイルを指定し、キーファイル生成時のパスワードを入力する
1. キーエイリアス（キーの別名）を選択し、パスワードを入力する
1. 出力するアプリケーションファイルを指定する（拡張子apk)

---

## アップデート

### アップデートの準備

アプリケーションをアップデートする際には、マニフェストファイルを更新する必要がある。

アップデート時に更新が必要な属性

|属性名|更新内容|
|---|---|
|android:versionCode|アプリケーションのバージョンを表す整数値。アップデート時は前回より大きな数値に変える必要がある|
|android:versionName|アプリケーションのバージョンを表す文字列。1.0.0のように記述するのが一般的。ユーザーにはこの文字列がバージョンとして認識される|

### アップデート時の注意点

アップデートするためにはアップデートする前に署名したプライベートキーと同一のキーファイルを使う必要がある。

- アップデート前のプライベートキーファイルを保存しておくこと
- プライベートキーのパスワードを忘れないこと
Android 4.4以下でReact NativeのSwitchが動かない場合の対処

React nativeのAndroid特有のトラブルシューティングについてのお話です。Android 4.4でこういうのが出ました。

![device-2018-02-13-040940.png](https://qiita-image-store.s3.amazonaws.com/0/2276/a53da9d9-8dea-8512-86e5-ede278ba3898.png)

> This app has been build with an incorrect configuration. Please configure your build for VectorDrawableCompat.

スタックトレースから原因を推測してみる
----------

JSのスタックトレース的には

* ReactSwitchManager.java
* SwitchCompat.java

あたりを通っているので、どうやら `<Switch>` コンポーネントがやらかしているらしいことまでは分かります。今回のケースでもSwitchを使っていましたし、Switchをコメントアウトしたらエラーが出なくなりました。

> JSのスタックトレース的には

JSじゃないですねそうですね

Android開発の経験則から原因を推測してみる
----------

実はスタックトレースを追わなくても、Android開発に慣れ親しんだエンジニアであれば次の２つのキーワードで察しが付いたりします。

* Android 4.4（5.0未満）
* VectorDrawableCompat

VectorDrawableはAndroidでSVGライクなベクターイメージを扱うための機能なのですが、導入されたのはAndroid 5.0からです。それ以下のバージョン向けにはSupport Library（JSでいうPolyfill）が用意されていますが、これもオプトイン方式なので、デフォルトでは有効になっていません。

このSupport Library版VectorDrawableがVectorDrawableCompatです。これを有効にすることで、エラーが解消されます。

そんなわけで、この問題は完全にJava側の方法論でしか解決できないやつでした。Android StudioでLogCatを見てみると、もう少し詳しいスタックトレースが見れます。

![スクリーンショット 2018-02-13 4.17.07.png](https://qiita-image-store.s3.amazonaws.com/0/2276/971ac275-c499-f623-5cb9-183382d053e1.png)

直し方
----------

それでは直し方です。できたらAndroid Studioをご用意ください。無ければVS Codeとかでもいいです。

### 1. build.gradleに設定を追記

app内のbuild.gradleに `vectorDrawables.useSupportLibrary = true` を書いてください。VectorDrawableCompatが使えるようになります。

```groovy:android/app/build.gradle
android {
    // 省略
    defaultConfig {
        // 省略
        vectorDrawables.useSupportLibrary = true
    }
```

### 2. 魔法のフラグをオンにする

VectorDrawableCompatを使う場合、本来であれば適切に [`app:srcCompat`や
 `ImageView#setImageResource` を利用するなどの措置](https://medium.com/@chrisbanes/appcompat-v23-2-age-of-the-vectors-91cbafa87c88)が必要になりますが、今回のように公式提供のNative Componentsが相手ではそうもいきません。

そんなときのために、少しパフォーマンスを犠牲にするものの、VectorDrawableCompatに関する問題を雑に解決するためのフラグがあります。

```java:android/app/src/main/java/com.yourapp.MainActivity

public class MainActivity extends ReactActivity {

    static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }
```

上記のように、staticブロックで　`AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);` を実行しておくと、このstaticが生存している間は全ての画像読み込みが「VectorDrawableの可能性あり」と判断されて、様々な判定の対象となります（なのでパフォーマンスが犠牲になるのです）。

### 3. 解決

私の手元ではこれで無事にSwitchが表示されるようになりました。

もうちょっと正統派の解決策も見つけられそうな気がしなくもないですが、ひとまずこれが手っ取り早いと思います。

最後に
----------

こういうJSer殺しな罠があるのはどうかと思う・・・・

追記：2018.3.29
----------

再発した・・・機種依存の可能性ありますね・・・・
β^t Aβ公式証明[機械学習]線形回帰

# β^t Aβ公式証明[機械学習]線形回帰

```math
証明する公式:
\frac{\partial({}^t \boldsymbol{\beta A \beta})}{\partial(\boldsymbol{\beta})} = (\boldsymbol{A} + {}^t \boldsymbol{A}) \boldsymbol{\beta} \\
\\
\boldsymbol{A} \in \boldsymbol{R}^{(1+p) \times (1+p)}, \boldsymbol{\beta} \in \boldsymbol{R}^{(1+p)}
```

>コメントで指摘を受けました通り、機械学習で実際に多く目にするのは以下のような形のものです。

>```math
\frac{\partial \left( {}^t \boldsymbol{\beta A \beta} \right) }{\partial \boldsymbol{\beta}}
= 2 \boldsymbol{ A \beta}
\tag{ただし、Aは対称行列}
```

>対称行列は転置行列が自身と同じ行列なのでこの形がすぐ導かれます。

## 登場シーン
線形回帰問題の最小２乗法などの導出時

```math
\boldsymbol{y} = \boldsymbol{X} \boldsymbol{\beta} + \boldsymbol{\epsilon}
\\
\boldsymbol{X} \in \boldsymbol{R}^{(1+p) \times (1+p)}, \beta \in \boldsymbol{R}^{(1+p)}
```

```math
\left[
\begin{array}{c}
y_1\\
\vdots\\
y_N
\end{array}
\right]
=
\left[
\begin{array}{c}
1 & x_{1,1} & \cdots & x_{1,p}\\
\vdots\\
1 & x_{N,1} & \cdots & x_{N,p}\\
\end{array}
\right]

\left[
\begin{array}{c}
\beta_0\\
\vdots\\
\beta_p
\end{array}
\right]
+
\left[
\begin{array}{c}
\epsilon_1\\
\vdots\\
\epsilon_N
\end{array}
\right]
```

## 証明

```math
\begin{align}
\frac{\partial({}^t \boldsymbol{\beta A \beta})}{\partial(\boldsymbol{\beta})}

&= 
\left[
\begin{array}{c}
\frac{\partial({}^t \boldsymbol{\beta A \beta})}{\partial(\beta_1)}\\
\vdots \\
\frac{\partial({}^t \boldsymbol{\beta A \beta})}{\partial(\beta_i)} \\
\vdots \\
\frac{\partial({}^t \boldsymbol{\beta A \beta})}{\partial(\beta_{(1+p)})}
\end{array}
\right] 
\\

&=
\left[
\frac{\partial({}^t \boldsymbol{\beta A \beta})}{\partial(\beta_i)} 
\right]_i 
\tag{略記}

\end{align}

```

```math
\begin{align}
\left[
\frac{\partial \left(
{}^t \boldsymbol{\beta A \beta}
\right)}{\partial(\beta_i)} 
\right]_i 

&=
\left[
\frac{\partial \left(
\sum_{j=0}^{1+p} {}^t \boldsymbol{\beta} \boldsymbol{a}^{(j)} \beta_j
\right)}{\partial(\beta_i)} 
\right]_i 
\left(
\boldsymbol{a}^{(j)}は行列\boldsymbol{A}のj列目ベクトル
\right)
\\

&=
\left[
\frac{\partial \left(
\sum_{j=0}^{1+p} \left(
\sum_{k=0}^{1+p} \beta_{k} a_{k, j}
\right) \ \beta_j
\right)}{\partial(\beta_i)} 
\right]_i
\\

&=
\left[
\left(
\sum_{j=0}^{1+p} a_{i, j} \ \beta_j
\right)
+
\left(
\sum_{k=0}^{1+p} \beta_{k} a_{k, i}
\right)
\right]_i
\\

&=
\left[
\left(
\boldsymbol{a}_{(i)} \ \boldsymbol{\beta}
\right)
+
\left(
{}^t \boldsymbol{a}^{(i)} \boldsymbol{\beta}
\right)
\right]_i
\left(
\boldsymbol{a}_{(i)}は行列\boldsymbol{A}のi行目ベクトル
\right)
\\

&=
\left(
\boldsymbol{A} + {}^t \boldsymbol{A}
\right) \ \boldsymbol{\beta}
\tag{証明終}

\end{align}

```
Oracle Certified Java Programmer, Silver SE 8 をとるよ。

#書く目的
- 取得宣言（自分へのプレッシャーをかける）
- 数年先の自分へのメモ（何かしらのよい影響を与えるため）

#資格を取ろうと思ったきっかけ
- ここ数年は要件定義や基本設計に携わることが多く、Java 8をきっちり使っていない
- プロのエンジニアだけど、エンジニアらしい資格を持っていない
- 会社から資格支援金が出る

#資格を取る目的
- Java 8の知識習得
- エンジニアとしてのステータス
- 趣味（勉強たのしい♪）

#Oracle Certified Java Programmer, Silver SE 8とは
- (正直細かい話はどうでもいいですが)Oracleが認定するJava開発初心者向けの資格
- Javaでプログラミングができれば取得できるってわけではない点がオモシロイ
- Javaの言語仕様をおさせているという点が大事

#想定受験時期
2018/05頃

#勉強方法
- 利用書籍
    - 紫本（山本道子 著）
    - 黒本（志賀澄人 著）
- 通勤
    - 紫本の読み込み
- 会社
    - 動きがよくわからない言語仕様について、手を動かして動作確認
- 自宅
    - 黒本を章ごとに消化
    - 1回目、N回目で理解度を把握、弱い部分の理解を深める

#状況@2018/03/19
紫本の各章を一通り読んで、黒本の各章を解いた。結果、けっこうイケてる感がある。
が、初歩的な部分がけっこう知らない、イレギュラーな構文をされるとどんな振る舞いになるのかあやしい、
オブジェクト指向な部分で未知の知だったりと、まだまだ強化が必要な所感( ･`ω･´)
Rubyで残り日数の計算

Rubyで残り日数を表示しようとした時、不思議な動きをしたのでメモ代わりにまとめます

まず、思いついたままやってみました

```ruby:remaining_day.rb
require 'date'
today = Date.new(2018, 2, 13)   
future = Date.new(2018, 2, 23)

remainingDay = future -today

puts remainingDay  # => 10/1
```
なんか分数の形なるし、

```ruby:remaining_day.rb
puts remainingDay.class # => Rational
```
[Rational](https://docs.ruby-lang.org/ja/latest/class/Rational.html)クラスというのがあるらしいです
ドキュメントにはこんな感じで書いてました、へーって感じです

>要約
有理数を扱うクラスです。
「1/3」のような有理数を扱う事ができます



メソッドを探したら、分子のみを返すメソッドがありました

```ruby:remaining_day.rb
puts remainingDay.numerator # => 10
puts remaininDay.class      # => Integer
```
無事残り日数が取得できました

なんですけど、こっちでもいけました

```ruby:remaining_day.rb
puts remainingDay.to_i # => 10
puts remaininDay.class # => Integer
```
[Integer](https://docs.ruby-lang.org/ja/latest/class/Integer.html)は整数クラスやから、
`.to_i`使えば、整数に変換できるから、必然的に分子のみになる

難しいこと考えんでも、簡単でした

読んでいただきありがとうございます。
メモ: multiprocessingでグリッドサーチ


```python3
import itertools
from multiprocessing import Pool

def worker(x, y, z):
    return x ** 3 + y ** 2 * z

grid = itertools.product([1, 2, 3], [4, 5], [3, 4, 5])
p = Pool()
p.starmap(worker, grid)
```
並列処理も3行でかけてお得館がある。
starmapは複数変数を使って関数をマップするもの。キーワード引数に対応したものはないっぽくもしやりたいなら


```python3
def worker(x, y, z):
    return x ** 3 + y ** 2 * z

def worker_wrapper(kwargs):
    return worker(**kwargs)

p = Pool()
p.map(worker_wrapper, kwargs_list)
```
のようにラップしなければならない模様。
ちなみに上ぐらいの処理だと手元の環境(仮想4コア)むしろオーバーヘッドが大きくなってしまうことが多そうだった。
lambda 式ではだめな様子で

```
Can't pickle <function <lambda> at 0x************>: attribute lookup <lambda> on __main__ failed
```

みたいな感じになりだめだった。
Kioskアプリと端末の作り方　～DroidKaigi2018発表内容の要約＋α～

# はじめに

光栄なことに「Kioskアプリと端末の作り方」というテーマで DroidKaigi 2018 に登壇させて頂きました。
セッションにお越し頂いた方々、ありがとうございました！

本記事は発表内容の要約＋オフィスアワーでのお話し、です。

# 本記事の対象者

本記事の対象者は下記の通りです。

* セッションに参加したが、その後のオフィスアワーでどのような話があったのか気になる
* セッションは不参加だが、要点だけをざっくり確認したい

# 発表動画

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

# 発表資料

GIFアニメ無し
https://speakerdeck.com/tomoya0x00/kioskapuritoduan-mo-falsezuo-rifang …

GIFアニメ有り（環境によってはちょっとレイアウト崩れるかも）
https://docs.google.com/presentation/d/1K9-Tn13yRAyOmN480DhchDTchVANaUDMn5y4gvRpoLc/edit?usp=sharing …

サンプルソース
https://goo.gl/ryz8mX

# 発表内容の要約

## Kiosk端末とは？

* 特定用途に特化した情報端末
* 回転寿司屋や居酒屋に設置してあるタッチパネルなど

## Kiosk端末の実現方法

* DeviceOwnerをうまく活用する
    * 端末に様々な制約を課すことが出来る特別な管理者
    * Android 5.0から追加された
    * 基本的に端末の初期化が必要
* Lock task mode
    * 特定アプリ以外への遷移を制限できる
    * DeviceOwnerで許可されたアプリだけが開始できる
* 強制的にホームアプリ化
    * DevicePolicyManager#addPersistentPreferredActivity でできる
    * DeviceOwner権限が必要
* DeviceOwner指定時の注意点
    * 端末のファクトリーリセット後、極力初期設定をスキップすること
    * WiFiやアカウント設定してしまうと、DeviceOwnerの指定に失敗することがある
        * 挙動は端末依存

## 活用事例紹介

実際のサービスで活用しているDeviceOwnerの機能紹介

* サイレントインストール
* ワイプ
* USBデバッグOFF
* スクリーンショットOFF

## Kiosk端末開発のノウハウ

* バッテリー残量と電波強度が表示されない
  * Lock task modeではステータスバーが表示されない
  * APIで取得してアプリ内で表示
* ホームアプリ化すると再起動後にロック画面が表示される
    * 設定でロック画面無しにする
* Kioskアプリが落ちると他画面に遷移できてしまう
    * 例外処理を横取りして自分自身を再起動させる
* 端末起動直後のアップデート確認処理が毎回失敗する
    * 端末起動直後はネットワーク接続確立されてないので注意
    * リトライ回数や間隔を増やしましょう
* ホームアプリ化が解除されない
    * DeviceOwner権限削除前にホームアプリ化解除
or
セキュリティ->端末管理アプリからチェック外してadb uninstall
* デバッグメニューが欲しい
    * Activityの邪魔にならない箇所にデバッグメニュー表示ボタンを置いておく

# オフィスアワーでのお話し

※公開するとマズイお話しがある場合、ご連絡ください。

* セーフモードではKioskアプリの起動を回避できてしまうのでは？
    * いいえ。回避は出来ず、Kioskアプリが起動します。
    * この回答は自分では無く、 DroidKaigi 2018 サポーター [アイキューブドシステムズ](http://www.i3-systems.com/) 所属のエンジニア様が答えてくださいました！ありがとうございます。
* ユーザー様側でKiosk端末化をお願いすることはできそうか？
    * NFCを使えばワンタッチでKiosk化できるみたいですが、試せていません。
    * 弊社では端末セットアップ手順書を作成し、キッティング作業を専用の会社様に委託しています。
* Kioskアプリ自体をサイレントインストールでアップデートできるか？
    * 今回のサンプルソースでは試せていませんが、できると思います。
* オフィスアワーで電源ボタン無効化の話題があったが、電源ボタンの長押しを onWindowFocuschanged() で検出（電源オフするか確認のダイアログが表示されるので）し、自分自身を起動することで回避できる。
    * [株式会社東京](https://www.tokyo-inc.com/) のエンジニア様に教えていただきました！ありがとうございます！

# 最後に

発表準備は大変（公の場での発表はこれまで5分LTだけだったので）でしたが、
皆様からのフィードバックを頂き「発表して良かった！」という気持ちが強いです。
（特にKiosk化の苦労を分かち合えたのが嬉しい）

また、逆に開発ノウハウを教えて頂く事もあり、「情報を発信すると情報が集まってくる」を実感いたしました。

次はもっとうまく発表できるように頑張ります！
【メモ】PHPで複数の複数の文字で文字列を分割する

```php
<?php
//3語以上で分割する場合
function ex_explode($word_array, $str) {
    $return = array();

    //文字列を配列に入れる
    $array = array($str);

    //分割文字ごとにforeach
    foreach ($word_array as $value1){

        //文字列の配列を分割
        foreach ($array as $key => $value2) {
            $return = array_merge($return, explode($value1, $value2));

            //配列の最後になったら初期化
            if(count($array) - 1 === $key) {
                $array = $return;
                $return = array();
            }
        }
    }
    return $array;
}

//使う時

$word = 'タグ1,タグ2　タグ3 タグ4、タグ5';

ex_explode([' ',',','、','　',],$word);

```

(参考)https://q-az.net/explode-php-extension/
【Rでデータハンドリング】解析前に行う基本的なハンドリングの紹介１

解析前には研究データを解析出来るように加工する機会が多くあります。
その中でも最低限使えると助かる技術を紹介します。

以下紹介するハンドリング技術は主にrmsパッケージを使用していますので、
**ご覧頂く前にrmsパッケージをインストールして`library(rms)`まで実行を済ませてください。**

#このページで紹介するハンドリング
・変数名を変える(rename)
・変数ラベルを付与する(label)
・変数をデータフレームに残す(keep)
・変数をデータフレームから削除する(drop)
・データを並べ替える(sort)
・グループの最初/最後の行を取得する(first/last)

「文字列操作」、「2つのデータの結合」、「縦→横、横→縦変換」については別ページで紹介します。

#データについて
今回は次のようなデータを取り扱うことにします。

|id|arm|age|sex_c|sex_n|bmi|ha1c0|sbp0|asa0|
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|1|コントロール|  79|  男性|1| 26.12|  11.0|  134|    1|
|2|       介入|  61|  男性|1| 39.48|  10.8|  188|    1|
|3|コントロール|  64|  女性|0| 26.11|  14.1|  141|    0|
|4|コントロール|  47|  男性|1| 31.17|   8.0|  136|    0|
|5|コントロール|  47|  男性|1| 27.61|   8.1|  164|    0|

このデータを読み込むためのサンプルコードはこちらになります。
詳しくは、こちらを参照ください。
【Rでデータハンドリング】RコードでDropboxのCSVファイルを直接読み込む
https://qiita.com/ishihara_airport/private/907b1fb9ae118ddacfb0

```r
library(dplyr)
data <-
  "https://www.dropbox.com/s/rc1j53415f2l06r/DMRCT180_sum.csv?raw=1" %>%
  url %>%
  read.csv(na.strings = c("", "#VALUE!")) 
```

#upData関数の基本
`upData`関数の基本ですが、第一引数には操作するデータ名を記載します。
いまは、`data`というデータを操作して、`newdata`という新しいデータを作ります。
第二引数以降は、データの操作を記載していきます。データの操作は、「,(カンマ)」で区切って複数書くことができます。

```r
newdata = upData(data,…
              #第二引数以降はデータの操作を記載)
```
この基本を押さえた上でデータハンドリングを身につけましょう。

#変数名を変える(rename)
`rms`の`upData`関数を使います。

```r
newdata = upData(data,
              rename=list(id  ="ID",　#元の名前=新たな名前
                          sex_c  = "gender_c"))
```


#変数ラベルを付与する(label)
sex_nにラベルをつけたsex_lという変数を作ります。

```r
newdata = upData(data,
              sex_l = factor(sex_n,levels=c("0", "1"), labels=c("女", "男"))
)
```
`levels=`には元の変数のカテゴリを、`labels=`にはつけるラベルを順に記載します。

#変数をデータフレームに残す(keep)
この操作では、`upData`関数は使わず、`subset`関数を使います。

```r
newdata = subset(data, select = c(id,age,sex_n,ha1c0))
```
`select =`の後に残したい変数を書きましょう。

#変数をデータフレームから削除する(drop)
```r
newdata = upData(data,drop = c("sbp0"))
```
`upData`内で`drop =`の後に削除したい変数を書きましょう。

#データを並べ替える(sort)
`dplyr`パッケージを使う方法が簡潔で応用も効かせやすいので、こちらを紹介します。

```r
library(dplyr)
newdata =
  data %>%
  arrange(arm,id)
```
`arrenge`の中に並べ替えたい順に記載します。
`arm,id`の順で記載すると、まず、`arm`で並び替えた中で`id`順に並び替えてくれます。

#グループの最初/最後の行を取得する(first/last)
`dplyr`パッケージを使います。
今回グループは`arm`として、その中で最初の行を取得します。

また最初や最後の行を取得するときには、並び替え(sort)も同時に行うということをクセ付けるようにしましょう。

```r
library(dplyr)
newdata =
  data %>%
  arrange(arm,id) %>%
  group_by(arm) %>%
  filter(row_number()==1)
```
まずは並び替えるために`arrange`を使って`arm`内を`id`順に並び替えます。
次に今回のグループは`arm`ですので、`group_by`で`arm`のグループ指定をします。

この2つの処理をした後に、`filter(row_number()==1)`で最初の行に絞り込みます。`row_number()==`はグループ内で連番をつけてくれているとイメージしましょう。これを覚えておくと、2番目をとってくることもできますし、最後の行のコードもイメージしやすくなります。

グループ内の最後の行を取得するコードは下記になります。

```r
library(dplyr)
newdata =
  data %>%
  group_by(arm) %>%
  arrange(arm,id) %>%
  filter(row_number()==n())
```
`row_number()==n()`という部分が変化しただけです。

以上。
Shaderで表示するプロパティーをToggleでOn,Offする[Unity]


![check.gif](https://qiita-image-store.s3.amazonaws.com/0/113504/bcb27787-c1e7-bd6e-8a51-a97eb9e85386.gif "check.gif")



# プロパティー
表示したいプロパティーには名前の頭に"_SubTex"とつけます．

```csharp
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
...
        // SubTexture
        [Toggle(USE_SUB_TEXTURE)] _UseSubTexture ("Use SubTexture", Float) = 0
        _SubTex("Sub Texture", 2D) = "white"{}
        [Header(Blend)]
        [KeywordEnum(Add, Mix)]
         _SubTexBlend("Blend", Float) = 0
         _SubTexBlendIntensity("Intensity", Range(0,1)) = 1
    }

```

# Editor

```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEditor;

public class TSpritesEffectEditor : ShaderGUI {

	public override void OnGUI (MaterialEditor materialEditor, MaterialProperty[] properties)
	{
		var subTexToggle = ShaderGUI.FindProperty ("_UseSubTexture", properties);
		TShaderGUIUtils.DrawProperties (subTexToggle, "_SubTex", materialEditor, properties);
	}
}
```

### ポイント
- ShaderGUIを継承(MaterialEditorではない)
- Toggleを取得
- DrawPropertiesを呼ぶ



# Util

```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Linq;

public static class TShaderGUIUtils {
	/// <summary>
	/// Toggleで表示するUIを切り替える
	/// </summary>
	public static void DrawProperties(MaterialProperty toggle, string keyword, MaterialEditor materialEditor, MaterialProperty[] properties){
		
		materialEditor.ShaderProperty (toggle, toggle.displayName);

		if (toggle.floatValue == 1f) {
			var subTexProps = properties
				.Where (x => x.name.Contains (keyword))
				.Where (x => x.name != toggle.name);

			foreach (var prop in subTexProps) {
				materialEditor.ShaderProperty (prop, prop.displayName);
			}
		}
	}

}

```

プロパティーから対象のUIを検索して表示しています．


# 参考

https://www.alanzucconi.com/2016/11/07/shadergui-custom-material-inspectors-unity-5/

MaterialEditorはOldみたいです．
Virtualbox上のUbuntuにSteamを入れた覚書

# 動機
archlinuxに移行しようとしたらsteamが*公式ではArch Linuxはサポートされていません*とか*Steam クライアントは32ビットアプリケーションなので、64ビット環境で動かすには multilib リポジトリを有効にする必要があります。また、重要な multilib ライブラリを取得するために multilib-devel のインストールをしてください*とか[言われて](https://wiki.archlinux.jp/index.php/Steam)面倒になったので「ならvirtualbox上のubuntuに入れればええやん。そんなハイスペを要求するゲームしないし」となった。

# 環境

CPU: Core i5-4460
メモリ: 16GB
ホストOS: ubuntu16.04.3
ゲストOS: ubuntu16.04.3
virtualbox: 5.2.6 r120293 (Qt5.6.1)
ゲーム: Sakura Spirit

まだホストOSにubuntuを使っていますが、そのうちarch linuxにします。

# 準備

virtualboxのインストール、ubuntuのisoファイルのダウンロードは割愛

# インストール

## 仮想マシン作成

virtualbox上に仮想マシンを作っていきます。
メモリは**多め(4GB)**、ハードディスクはVDI、ストレージは**固定サイズ**、ストレージサイズも**多め(20GB)**で動作確認しました。ストレージは固定サイズにしないとSteam起動前に「容量が足りない」と言われ失敗します。
これより少ないリソースで動くかは未検証。この辺はゲームによっても違いそうです。

今気づいたのですが、プロセッサー数1でも動きましたが設定でシステムのプロセッサー数を増やした方が良いと思います。

## Steam導入

何はともあれアップグレードをかけます

```
$ sudo apt update
$ sudo apt upgrate
$ sudo apt install -y gdebi
```

私だけかもしれませんが、`Ubuntuソフトウェア`でdebファイルからインストールしようとすると上手くいかないので`gdebi`を使ってインストールします。

steamの公式サイトからdebファイルをダウンロードします。

![Screenshot from 2018-02-13 00-18-46.png](https://qiita-image-store.s3.amazonaws.com/0/49469/6395736b-a530-f155-af41-dbdcb05db163.png)

保存されたdebファイルをGDebiパッケージインストーラーで開き、インストール。
インストール後、steamを起動しようとすると依存解決が行われるので表示に従います。

依存解決後、ターミナルから`steam`を起動しようとすると、

```
STEAM_RUNTIME is enabled automatically
Installing breakpad exception handler for appid(steam)/version(1437790054)
libGL error: unable to load driver: r600_dri.so
libGL error: driver pointer missing
libGL error: failed to load driver: r600
libGL error: unable to load driver: swrast_dri.so
libGL error: failed to load driver: swrast
```

と言われ失敗します。(アイコンから起動するとsteamが無言で落ちてる)

失敗を確認した後、以下のコマンドを打ちます。

```
$ rm ~/.local/share/Steam/ubuntu12_32/steam-runtime/i386/usr/lib/i386-linux-gnu/libstdc++.so.6
$ rm ~/.local/share/Steam/ubuntu12_32/steam-runtime/i386/lib/i386-linux-gnu/libgcc_s.so.1
```

steamの起動に失敗しないとファイルが作られていないので注意してください。

>参考: [Steam doesn't start\. LibGL error \- Ask Ubuntu](https://askubuntu.com/questions/654566/steam-doesnt-start-libgl-error)

## 起動
あとは普通に起動してログインすればOKです。

![Screenshot from 2018-02-13 00-28-16.png](https://qiita-image-store.s3.amazonaws.com/0/49469/8f18a22d-5f99-f6e3-46ad-c5f6babc4056.png)

![Screenshot from 2018-02-13 00-30-47.png](https://qiita-image-store.s3.amazonaws.com/0/49469/f07b8777-310f-179b-3e94-f898b8201333.png)

ゲーム起動時に「パフォーマンスが足りない」というメッセージが表示されますがノベルゲームぐらいであれば問題なくプレイできました。

# 所感
「virtualboxならパフォーマンス悪いけど簡単に入るだろう」という見通しでいったら意外と手こずりました。
~~arch linux上にsteamをインストールした方が楽だったのでは説 is ある~~(ない)

今後はarch linuxにsteamを入れる方法を確立したいと思います。もし確立できなければ今回の方法でvirtualbox上のubuntuにsteamを入れてプレイします。
辞書をpandasのデータフレームに変換できない

なかなか欲しい情報がヒットせず、やっと見つけた。
python3では辞書をリストに変えなければならなかった。

https://stackoverflow.com/questions/18837262/convert-python-dict-into-a-dataframe/32344037

Pass the items of the dictionary to the DataFrame constructor, and give the column names. After that parse the Date column to get Timestamp values.

Note the difference between python 2.x and 3.x:

In python 2.x:

df = pd.DataFrame(data.items(), columns=['Date', 'DateValue'])
df['Date'] = pd.to_datetime(df['Date'])

In Python 3.x: (requiring an additional 'list')

df = pd.DataFrame(list(data.items()), columns=['Date', 'DateValue'])
df['Date'] = pd.to_datetime(df['Date'])
【GAS】当日が指定日に含まれるか判定する関数

## 背景

休日や祝日、夏季休暇中などにGASを実行したくないという要望は、
わりとよくあることではないかと思います。

休日・祝日の判定方法は[こちらの記事](https://qiita.com/jz4o/items/d4e978f9085129155ca6)に記載しましたが、
上記では、夏季休暇や年末年始などに対応できないため、判定する関数を作成しました。

## 当日が指定日に含まれるか判定する関数

```js
// 当日が指定範囲に含まれている場合 `true` を返す.
function todayIsBetweenTo(fromDateString, toDateString){
  var today = new Date();
  
  var fromDate = new Date(fromDateString);
  var toDate   = new Date(toDateString);
  toDate.setHours(23, 59, 59, 999);
  
  return fromDate <= today && today <= toDate;
}
```

## 利用例

```js
function example(){
  // 8/13～8/15は夏季休暇のため、スクリプトを動かさない
  var toyear = new Date().getYear();
  var startSummerVacationDate = toyear + '/08/13';
  var endSummerVacationDate   = toyear + '/08/15';
  if(todayIsBetweenTo(startSummerVacationDate, endSummerVacationDate)){
    return;
  }
}
```
最低限firewalldを操作するためのチートシート

# firewalld

## 概要

通信が入力される際、パケットフィルタを設定している入力には**ゾーン**（Zone）という単位があり、ゾーンは**サービス**（Service）という単位で構成され、サービスはポート番号と名前で定義される**XMLファイル**で構成される。

firewalldを操作するには `firewall-cmd`というコマンドを使う。
`--permanent`オプションを付けると再起動後も保持される。付けないまま実行した場合、設定は揮発する（再起動後は消える。）。

## 動作を確認する
`# firewall-cmd --state`

```:echo
running
```

## サービス定義ファイルを作る
`/usr/lib/firewalld/services/*.xml` が実体である。
パスはディストリビューションによって異なるかも知れない（CentOS7+, openSUSE Tumbleweedでは同じパスだった）

### 例:SSH
`# cat /usr/lib/firewalld/services/ssh.xml`
で、内容は

```
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>SSH</short>
  <description>Secure Shell (SSH) is a protocol for logging into and executing commands on remote machines. It provides secure encrypted communications. If you plan on accessing your machine remotely via SSH over a firewalled interface, enable this option. You need the openssh-server package installed for this option to be useful.</description>
  <port protocol="tcp" port="22"/>
</service>
```
のようになっている。このファイルに倣って書けば良い。ファイルのオーナーは`root:root`であり、パーミッションは**644**であるようだ。

## サービス定義ファイルのリロードを行う
ファイルは追加しただけでは認識されない。
`# firewall-cmd --reload`

```:echo
success
```

## サービスをゾーンに追加する
https(443/TCP)を通信許可するフィルタに追加する場合
`# firewall-cmd --zone=public --permanent --add-service=https`

```:echo
Success
```

## ポート番号を追加する
TCPの2222ポートを通信許可するフィルタに追加したい
`# firewall-cmd --zone=public --permanent --add-port=2222/tcp`

```:echo
Success
```

## その他

### 設定中のポート一覧
現在設定されているポート一覧
`# firewall-cmd --zone=public --permanent --list-ports`

```:echo
2222/tcp
```

### 設定中のサービス一覧
現在設定されているサービス一覧
`# firewall-cmd --zone=public --permanent --list-services`

```:echo
dhcpv6-client ssh ore-ssh
```

### 追加可能なサービス一覧
`# firewall-cmd --get-services`

```:echo
# firewall-cmd --get-services
RH-Satellite-6 amanda-client amanda-k5-client bacula bacula-client bgp bitcoin bitcoin-rpc bitcoin-testnet bitcoin-testnet-rpc ceph ceph-mon cfengine condor-collector ctdb dhcp dhcpv6 dhcpv6-client dns docker-registry docker-swarm dropbox-lansync elasticsearch freeipa-ldap freeipa-ldaps freeipa-replication freeipa-trust ftp ganglia-client ganglia-master git high-availability http https imap imaps ipp ipp-client ipsec irc ircs iscsi-target kadmin kerberos kibana klogin kpasswd kprop kshell ldap ldaps libvirt libvirt-tls managesieve mdns minidlna mosh mountd ms-wbt mssql murmur mysql nfs nfs3 nrpe ntp openvpn ore-ssh ovirt-imageio ovirt-storageconsole ovirt-vmconsole pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy proxy-dhcp ptp pulseaudio puppetmaster quassel radius redis rpc-bind rsh rsyncd samba samba-client sane sip sips smtp smtp-submission smtps snmp snmptrap spideroak-lansync squid ssh synergy syslog syslog-tls telnet tftp tftp-client tinc tor-socks transmission-client vdsm vnc-server wbem-https xmpp-bosh xmpp-client xmpp-local xmpp-server zabbix-agent zabbix-server
```

### Firewalldのフィルタ確認

iptablesへ設定が書き込まれるので、 `iptables -L`などして状態の確認を行う（が、見づらい）。

# 参考
- [firewalld Documentation](http://www.firewalld.org/documentation/)
- [How To Set Up a Firewall Using FirewallD on CentOS 7](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-using-firewalld-on-centos-7)
MacにAnacondaをインストールし、Jupyter環境の構築


## Anaconda のインストール
1. 以下 URL から、Python 3.6 version の Mac版Anaconda をダウンロード
    - https://www.anaconda.com/download/#macos
2. ダウンロードしたパッケージを実行
3. 画面にしたがいインストールを完了
4. Anaconda-Navigator を起動

## 新規Environment の作成
1. Environmentメニューを選択
2. 下メニューから、「Create」 を押下
3. 名前を付けて Python 3.6 を選択し、「Create」ボタンを押下

## Jupyter のインストール
1. Homeメニューを選択し、作成した Environment名をセレクトボックスから選択
2. Jupyter の 「Install」ボタンを押下
3. インストールが完了すると 「Launch」ボタンに変わるので

## Anaconda からターミナルを起動した場合のエラー対応
- 起動シェルを zsh にしている場合、Anaconda からターミナルを起動すると以下のようなエラーが表示される

```
$ /Users/username/.anaconda/navigator/a.tool ; exit;
/Users/username/.anaconda/navigator/a.tool: line 1: syntax error near unexpected token `('
/Users/username/.anaconda/navigator/a.tool: line 1: `bash --init-file <(echo "source activate /Users/username/anaconda3/envs/morph;")'

[プロセスが完了しました]
```

- 起動シェルを zsh から bash に切り替えて、再度、Anaconda からターミナルを起動
    - 参考: https://groups.google.com/a/continuum.io/forum/#!msg/anaconda/q3Y_lABnzIc/vcQ1KIm9AQAJ

```
# 起動シェルを確認
echo $SHELL

# シェル一覧
cat /etc/shells

# 起動シェルの変更
chsh -s /bin/bash
```