OmniAICreator/Qiita-1.07M huggingface dataset:
管理者権限の無いWindowsにフォントをインストールする

MSゴシックって目が疲れませんか？
でも標準だと等幅フォントはMSゴシックくらいなんですよね・・・

ClearTypeフォントに慣れてしまっていると目も疲れるし、ストレスがハンパ無いので変えてしまおうというお話し。

管理者権限が無いWindows向けの操作方法ではあるけど、許可された範囲が異なると動かないかもしれません。そこはあしからず。

# 設定概要
通常`C:\Windows\Fonts`にフォントをインストールしますが、`\Windows`は書き込み権限が無いのでユーザーフォルダに保存します。
そこへリンク飛ばす感じ。

よく紹介される一時インストールとは異なり、再起動しても消えません。

# フォントを配置する
`%HomePath%\conf\font\`等、適当なディレクトリを作ってフォントを置く。

# フォントを登録する
1. コントロールパネルからフォントの設定を開く
1. サイドバーの`フォント設定`から`ショートカットを使用したフォントのインストールを許可する`をチェック
1. ユーザーフォルダに置いたフォントをドラッグ＆ドロップで登録する

# コンソールで使えるようにする
フォントをインストールしただけでは、コマンドプロンプトやPowerShellからは認識されない。なのでレジストリを登録します。

```bat:reg-font.bat
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont" /v 932.1 /t REG_SZ /d "MeiryoKe_Console"
```
MeiryoKe_Consoleはインストールするフォント名に読み替えてください。

# 完了！！
これで快適にエディタやコンソールが使えます。
会社に入ってから、システムの隙を突くような環境整備ばかりしてる気がする・・・

# ちなみに・・・
FHD程度のディスプレイに文字を小さくして、低解像度で表示させるなら[MeiryoKe_Console](http://www.geocities.jp/meir000/meiryoKe/)が見やすいと思う。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/233978/15c535d8-07f1-d7f3-7dc3-a06f78b6cd26.png)
Qiita 100本ノック w/ Python

最近暇なので Qiita APIを pythonから叩くプログラムを100コ作って公開するよ。どうせ100コも作れないから興味があるのがあればコメントしてくれたら作成順位を引き上げるよ。こんなの作って欲しいというリクエストも歓迎。 __2018年1月いっぱいは意見出しのため本記事の内容はころころかわるかも__

想定読者: python 3.5+ on linux, プログラミング中級者

役立ちそうなプログラム

- [トークンの取得と基本APIの発行](https://qiita.com/_____/items/d8fd99b1854f3b8e6bd6#%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E5%8F%96%E5%BE%97%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF)  
-   [全投稿のダンプ](https://qiita.com/_____/items/d8fd99b1854f3b8e6bd6#%E5%85%A8%E6%8A%95%E7%A8%BF%E8%A8%98%E4%BA%8B%E3%81%AE%E3%83%80%E3%83%B3%E3%83%97)
- [直近10投稿の統計情報](https://qiita.com/_____/items/d8fd99b1854f3b8e6bd6#%E6%9C%80%E8%BF%91%E3%81%AE%E6%8A%95%E7%A8%BF%E3%81%AE%E7%B5%B1%E8%A8%88%E3%82%92%E7%9B%A3%E8%A6%96)
- [Like、コメント、いいねしてくれた人全員をフォロー] (https://qiita.com/_____/items/9a1e5d7ed18f731e6710)
- 記事のスケジュール投稿 
- 投稿記事の一覧化
- 全投稿記事限定共有化、もしくは公開化
- フォロワーをContributionが多い順にソート
- フォロワーの所属組織を一覧化
- イベントが発生したら discord に通知

Qiita関連サイト習作

- https://qiita.com/takeharu/items/bb154a4bc198fb102ff3 
- http://qrank.wbsrv.net/
- 他なんかある？

Qiitaストーキング

- Qiitaのアクティブユーザ数、投稿数の推定
- Qiita ユーザ偏差値プログラミング
- ヘビーライカーな企業の行動を可視化する
- 100いいね以上の投稿のみで構成された「良質」なQiita記事紹介サイト作成

# 重要: トークンの取得とAPIの発行について

QiitaのWeb APIを利用するためにはトークンが必要。以下のように全てのリクエストに`Authorization`ヘッダを付ける必要がある。トークンの取得についての詳細は、 https://qiita.com/_____/items/d8fd99b1854f3b8e6bd6#%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E5%8F%96%E5%BE%97%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF に記載した。

```python
import urllib, urllib.parse, urllib.request
import json

token = 'XXXXXXXXXXXX'
myname = '_____'

opener = urllib.request.build_opener()
opener.addheaders = [('Authorization', 'Bearer {}'.format(token)),]
urllib.request.install_opener(opener)

def api_authcheck():
  url = "https://qiita.com/api/v2/authenticated_user"
  data = (json.load(urllib.request.urlopen(url)))
  assert (data['id'] == myname )

if __name__ == '__main__':
  api_authcheck()
```
IEではoptionタグに対してdisplayが効かないバグ

optionタグを`display: none;`したくてもIEではできません。
2018/01/27追記：iPhoneのSafariとかChromeでもこの現象が発生してました。

# 検証用コード(IEでは動かないバージョン)

本来であれば、連動して日本を選択したら日本の地域だけで絞られるんですが、IEではそうならないです。

<p data-height="265" data-theme-id="0" data-slug-hash="mpNoyx" data-default-tab="html,result" data-user="momosetkn" data-embed-version="2" data-pen-title="単一選択プルダウンの連動(IEでは動かないバージョン)" class="codepen">See the Pen <a href="https://codepen.io/momosetkn/pen/mpNoyx/">単一選択プルダウンの連動(IEでは動かないバージョン)</a> by momosetkn (<a href="https://codepen.io/momosetkn">@momosetkn</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

# 解決策

要素を削除するやり方にする

<p data-height="265" data-theme-id="0" data-slug-hash="JMQKKM" data-default-tab="html,result" data-user="momosetkn" data-embed-version="2" data-pen-title="単一選択プルダウンの連動" class="codepen">See the Pen <a href="https://codepen.io/momosetkn/pen/JMQKKM/">単一選択プルダウンの連動</a> by momosetkn (<a href="https://codepen.io/momosetkn">@momosetkn</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
nginxとrails(Puma)の接続をSELinuxに阻まれた話

# まとめ
* nginxとrailsは同じサーバー上で動かしていて
* nginxの80ポートで受けたリクエストをrailsの3000ポートに流そうとしたら
* `connect() to 127.0.0.1:3000 failed (13: Permission denied)`と言われ接続できず
* 原因はSELinuxでしたというお話

# 概要
* vagrant上のCent OS 6
* nginxは80番ポート, 443番ポートで動かす（443はSSLラッパも）
* RailsアプリはPumaで3000番ポートで動かす

# nginxの設定
```
server{
    listen 80;
    server_name rails.example.com;

    location / {
        proxy_pass    http://localhost:3000;
    }
}
server{
    listen 443 ssl;
    ssl_certificate /etc/nginx/server.crt;
    ssl_certificate_key /etc/nginx/server.key;

    server_name rails.example.com;

    location / {
        proxy_pass    http://localhost:3000;
    }
}
```

# Railsの設定
* rails newしただけ。
* `bundle exec rails s Puma -b 0.0.0.0`

# アクセス確認
* http://rails.example.com:3000 にアクセス
    * 繋がった！
* http://rails.example.com にアクセス
    * nginxのBad Gateway 502でアクセスできず
    * ログを見ると `connect() failed (111: Connection refused) while connecting to upstream`と出ている

# 解決
* [nginxでホームディレクトリを公開ディレクトリに設定する](https://qiita.com/kieaiaarh/items/3455040597ee34c8c49e) の記事を参考に
* `$ setenforce 0`でselinuxを一時停止  
  →アクセスできた

# あとがき
* ローカルの検証環境なのでここで終わらせたが、本番環境でやるのであればselinuxの設定をしっかりしてやるべき
* 何かの記事でnginxの実行ユーザーとrailsの実行ユーザーが違うからだというミスリードをしてしまい、頑張ってrootでrailsを動かしてみたけど、ダメでした。。。
Raspberry Pi で ADコンバータを使う

12bit 8ch ＡＤコンバータ の MCP3208 の使い方です。
SPI 通信です。ライブラリーは、gpiozero　です。

プログラム

```py3:mcp3208_read.py
#! /usr/bin/python3
#  -*- coding: utf-8 -*-
#
#	mcp3208_read.py
#
#					Jan/26/2018
#
# --------------------------------------------------------------------
import sys
from gpiozero import MCP3208
from time import sleep
# --------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
ports = []
for it in range(8):
	ports.append(MCP3208 (channel=it))
#
imax = 4096
try:
	while True:
		for it in range(8):
			iv = int(imax * ports[it].value)
			print (it,iv)
#
		print()
		sleep(3)
#
except KeyboardInterrupt:
	print('interrupted!')
	for it in range(8):
		ports[it].close()
	sys.exit
#
sys.stderr.write("*** 終了 ***\n")
# --------------------------------------------------------------------
```

実行の様子です。
![mcp3208_jan26.png](https://qiita-image-store.s3.amazonaws.com/0/179446/cd046a3f-8d31-fd74-ae3e-7db02192b2c8.png)
High SierraにしたらESP^WROOM-02(ESP8266)にプログラムが転送できなくなった

# 現象
High SierraにしたらESP^WROOM-02(ESP8266)にプログラムが転送できなくなった
## ビルドはできるが転送が出来ず
下記のようになる

```
Uploading 243008 bytes from to flash at 0x00000000
warning: espcomm_send_command: didn't receive command response
warning: espcomm_send_command(FLASH_DOWNLOAD_DATA) failed
warning: espcomm_send_command: wrong direction/command: 0x01 0x03, expected 0x01 0x04
error: espcomm_upload_mem failed
error: espcomm_upload_mem failed
```

# 対処
「ツール - Upoad Speed」を「115200」だったのを「230400」に変更したらできるようになった
VMWare上にCentOSを最小構成でインストールし、ネットワーク接続まで。

#ユーザ作成
##ユーザの追加
- `useradd workUser`で、作業用ユーザ(workUser)を作成する。
- `passwd workUser`で、作業用ユーザのパスワードを設定する。

##sudo権限付与
- `visudo`で、sudo設定ファイルを編集する。
- 以下の内容を設定する。

```
   workUser   ALL = (ALL) ALL
```
|項目      |説明                          |
|:---------|:-----------------------------|
|workUser  |sudoを許可するユーザ名。        |
|ALL=      |ホストに対する許可(通常ALL)。   |
|(ALL)     |sudoされるユーザ名。           |
|ALL       |利用できるコマンドの制限。      |

#ネットワーク接続
##ネットワークディバイス確認
- `nmcli device show`でネットワークディバイスの確認をする。

##固定IP設定
- 以下のコマンドで固定IPを設定する。

```
nmcli con mod [デバイス名] ipv4.method "manual" connection.autoconnect "yes" ipv4.addresses "192.168.147.11/24" ipv4.gateway "192.168.147.2" ipv4.dns "192.168.147.2"
```

- `nmcli con down [デバイス名]`で対象のネットワークを切断、`nmcli con up [デバイス名]`で対象のネットワークを接続することで、上記で設定した固定IPの設定が有効になる。
[Python]2次元配列の要素の和を求める

2次元配列の要素の和を求めたくなった。
ただし、numpyが使えない環境で。

## 参考: numpyを使う場合
```python3
import numpy as np

# [0, 1]の100×100の配列 
twod_array = np.random.randint(0, 2, (100, 100))

result = twod_array.sum()

print(result)
```

## 2重ループ
あまりこんなことはしないと思うが……

```python3
import random

# [0, 1]の100×100の配列 
twod_array = [[random.randint(0, 1) for _ in range(100)] for _ in range(100)]

result = 0
for row in twod_array:
    for element in row:
        result += element

print(result)
```

## sum関数
for文は残るけど。

```python3
import random

# [0, 1]の100×100の配列 
twod_array = [[random.randint(0, 1) for _ in range(100)] for _ in range(100)]

result = 0
for row in twod_array:
    result += sum(row)

print(result)
```

## mapとsum関数
for文を使わずワンライナーでもかける。

```python3
import random

# [0, 1]の100×100の配列 
twod_array = [[random.randint(0, 1) for _ in range(100)] for _ in range(100)]

result = sum(map(sum, twod_array))

print(result)
```

## 結論
- 実行速度は numpy < (sum+map) = (sum+for) < (for*2) みたいな感じだった。
- numpyが使えるならnumpyを使おう。
80ポートが使えない！（時の原因と対処方法）

開発で久々に80ポートを使用しようとして、
既にSystemに占拠されてて右往左往した時の備忘録。

あるWeb画面を立ち上げようとしたところ、
80番ポートが使用済みのため起動できず、
「何か別のWebサーバー立ち上げてたかな?」と調査開始。
以下のコマンドで使用済みポートの一覧を確認。

```batch
netstat -nao
```

こうすると、ローカルアドレスの一覧が表示される。
一覧から「0.0.0.0:80」を探し、PIDを確認。
ここまではいつもの手順。
あとは、タスクマネージャーの「詳細」タブから、
該当するPID（初期表示されていなかったかも、、）を確認し、
プロセスを終了するだけ、、、、のはずだったが、
確認すると「System」が使っていて停止できない！

調査したところ、
IISが実行されているとSystemとして表記されるらしい。。
[【Apacheが起動しない】System(PID:4)にてポート番号80を使用/Windows10](http://lovee7.blog.fc2.com/blog-entry-35.html)

紛らわしい。
ちなみに筆者の環境だと、Visual Studioをインストールしたのが原因。
大して使っていないのに、常にIIS Expressが起動している状態に。

対処方法としては、サービスの一覧から
「World Wide Web Publishing Service」を
停止、手動起動に変更。

これで、ようやく開発が進められることに。。
Font Awesome 5の仕組みで自作のアイコンを表示する

新しくなったFont Awesome 5では、SVG+JavaScriptでアイコンを表示する仕組みが取られています。この枠組に乗っかれば、自分でアイコンを追加することもできるのではないか…と思って試してみました。

# おことわり

言うまでもないかもしれませんが、このような使い方はFont Awesomeの作者が本来想定したものではないので、きちんと動作することは**一切保証しません**。そして、従来の「Webフォントを使う」ようなやり方ではもちろんこの手は使えません。

# でも、やってみる

ここでは、試しにQiitaの「Q」をアイコン化してみることにしましょう。

## アイコンのデータ構造

作業に入る前に、アイコンのデータ構造を確認しておきましょう。`fontawesome.findIconDefinition`（[リファレンス](https://fontawesome.com/how-to-use/font-awesome-api#findicondefinition)）でアイコンを定義したハッシュが得られますが、以下のようになっています。

```json
{
  "prefix": "fas",
  "iconName": "user",
  "icon": [
    512,
    512,
    [],
    "f007",
    "M962…-112z"
  ]
}
```

それぞれの意味は、以下のようになっています。

* `prefix`…アイコンを分類するプレフィックス。仕組み上、組み込みの`fas`、`far`、`fal`（アイコンが定義されているのは有料版のみ）、`fab`のどれかでないといけません。
* `iconName`…アイコン名。このアイコンであれば、`fa-user`で参照される、という次第です。
* `icon[0]`・`icon[1]`…アイコンの幅・高さ。幅と高さは片方が512、もう片方も32の倍数、ということが多いようです。
* `icon[2]`…リガチャの指定。なければ空配列となっています。
* `icon[3]`…文字コード。Webフォント版のFont Awesomeでは、この文字コードでアイコンを呼び出します。
* `icon[4]`…SVGのパス。実際にはかなり長いです。

## SVGデータ（パス）を準備する
もちろん必要なのはパスだけなのですが、パス1本だけ操作するのは逆に難しいので、ある程度のところまではSVGとして処理します。

0. 元になるSVGデータを用意する…Qiitaの場合、左上のロゴがSVGだったので、これから抜き出して保存すればかんたんにファイルとして得られました。
1. 必要なデータをパス1本で用意する…保存したSVGをInkscapeなどSVGエディタで開いて、不要な部分の削除、パス以外のものはパスへの変換、複数あれば統合などを行って、必要な描画を1本のパスにまとめましょう。
2. サイズの調整…どうやら、FontAwesomeでは512pxが1つの基準になっているので、これに合わせてアイコンを拡大しましょう。Qの場合は512×512の正方形がちょうどよい感じでした。
3. 最適化…そのまま使ってもいいのですが、Inkscapeで編集したままだと「134.41882」のように細かい端数が付いています。アイコンで表示するのにそんな細かい精度は不要なので、[SVGOMG](https://jakearchibald.github.io/svgomg/)などを使って、端数を丸めておきましょう。

あとはテキストファイルでSVGを開けば、`<path d="....." />`の形でパスを得られます。

## アイコンとして登録する

パスが準備できればあとは一息です。上で書いたような形式に従って、オブジェクトを作りましょう。なお、既存のものとかぶらないようにすることが必要ですが、「文字コード」については、勝手に投入したものはコードが存在しないので、'xxxx'のようにコードとして認識しないものを適当に入れておく、ということで大丈夫そうでした。また、`i2svg`が動き出す`DOMContentLoaded`より前に仕掛けましょう。

`fontawesome.library.add`で登録すれば、あとは`<i class='fab fa-qiita'></i>`のように呼び出すなり、公式バインディングのある[React](https://github.com/FortAwesome/react-fontawesome)・[Vue](https://github.com/FortAwesome/vue-fontawesome)なり、それ以外でも自分でやってみた[Riot](https://qiita.com/jkr_2255/items/2631f9f889ddd9cebf01)や[picodom](https://qiita.com/jkr_2255/items/0514536c84302400ed45)対応もありますので、好きなように使うことができます。

[実際に表示させてみたjsFiddle](https://jsfiddle.net/nca7u5o2/)
Python3 + Numpy > 5列の要素を持つ二次元リストから3列だけ取出す > 思いつき実装 | より良い実装 | 内包表記

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 16.04 LTS desktop amd64
TensorFlow v1.2.1
cuDNN v5.1 for Linux
CUDA v8.0
Python 3.5.2
IPython 6.0.0 -- An enhanced Interactive Python.
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
scipy v0.19.1
geopandas v0.3.0
MATLAB R2017b (Home Edition)
ADDA v.1.3b6
```

### 処理概要

```py3
alist = [
	[3, 1, 4, 1, 5],
	[3, 1, 4, 1, 5],
	[3, 1, 4, 1, 5],	
]
alist = np.array(alist)
```

上記から[3, 1, 4]の３列だけを取出す。

### 思いつき code

思いついたのはtranspose()を使う方法。

```test_extract_array_180127.py
import numpy as np

# on Python 3.5.2

alist = [
	[3, 1, 4, 1, 5],
	[3, 1, 4, 1, 5],
	[3, 1, 4, 1, 5],	
]
alist = np.array(alist)

print(alist)

wrk = alist.transpose()[:3].transpose()
print(wrk)

```

```txt:run
$ python3 test_extract_array_180127.py 
[[3 1 4 1 5]
 [3 1 4 1 5]
 [3 1 4 1 5]]
[[3 1 4]
 [3 1 4]
 [3 1 4]]
```

### リンク

https://docs.scipy.org/doc/numpy/reference/routines.array-manipulation.html
の関数を使えばもっとスマートにできるかもしれない。

### より良いcode

@shiracamus さんの[コメント](https://qiita.com/7of9/items/5dcdfc295f942634b888/#comment-da26912a94144d893f9b)にてもっとシンプルな書き方を教えていただきました。
情報感謝です。

この書き方は過去に([TensorFlowにて](https://qiita.com/7of9/items/eff3930441aade94ed1b))使ったことがあるのですが、忘れていました。精進します。

```test_extract_array_180127.py
import numpy as np

# on Python 3.5.2

alist = [
    [3, 1, 4, 1, 5],
    [3, 1, 4, 1, 5],
    [3, 1, 4, 1, 5],    
]
alist = np.array(alist)

print(alist)

#wrk = alist.transpose()[:3].transpose()
wrk = alist[:, :3]
print(wrk)

```
Unityを使用する準備

# Unityを使用する準備
この記事ではUnityを使用する準備について解説します。
インストール、アカウント登録、起動までを通して行っていきます。

### 目次
- ダウンロードとインストール
 - ダウンロード
 - インストール
- アカウントの登録と認証
 - Unityアカウントとは
 - アカウントの登録
 - アカウントの認証
- さいごに

## ダウンロードとインストール
### ダウンロード
公式サイトのダウンロードページにアクセスします。
https://unity3d.com/jp/get-unity/download/archive

最新バージョンのUnityインストーラーを選択してダウンロードします。
![](https://qiita-image-store.s3.amazonaws.com/0/233956/23bf7bc0-450c-fe6e-c56e-c7ef20fd55e1.png)

### インストール
ダウンロードされたインストーラーを起動します。
![](https://qiita-image-store.s3.amazonaws.com/0/233956/1b1ba6cc-624e-5af9-fcdb-55a65a330607.png)

次へをクリック
![](https://qiita-image-store.s3.amazonaws.com/0/233956/57f4c6c1-1520-b901-6148-d1300a0fce5b.png)

利用規約に同意して次へ
![](https://qiita-image-store.s3.amazonaws.com/0/233956/03e7aaf5-c559-f52d-6860-5c80e7f16d7f.png)

インストールするコンポーネントを選択します。
Unity本体とスクリプトエディタは必須です。
必要であればAndroidビルドやiOSビルドのコンポーネントも選択しましょう。
インストール完了後でもインストーラーを再度開けば、後からコンポーネントを追加することも可能です。
![](https://qiita-image-store.s3.amazonaws.com/0/233956/0b4074d8-06f3-139d-ae1e-72f0726fe0e5.png)

インストール先のフォルダを選択します。
Unityはアップデートによる仕様変更などが頻繁なので、バージョンごとにフォルダを分けてインストールすることを推奨します。
![](https://qiita-image-store.s3.amazonaws.com/0/233956/5094c0bf-fe33-ba67-fba2-c79f88c03e30.png)

必要なコンポーネントのダウンロードが始まるのでしばらく待てばインストール完了になります。
この間にUnityアカウントの登録を行ってしまいましょう。
![](https://qiita-image-store.s3.amazonaws.com/0/233956/970d8a6f-4fea-909e-fb44-b2c5632e6549.png)

インストールが完了すると以下の画面が表示されます。
Launch Unityのチェックを入れた状態でFinishを押すと、Unityが起動します。
![](https://qiita-image-store.s3.amazonaws.com/0/233956/ba40b222-bced-11b6-4c6b-e86204832237.png)

## アカウント登録
### Unityアカウントとは
Unityはアカウントを登録すれば無料で使うことができます。
有料アカウント（月額￥4,200～）に切り替えると、アプリ起動時のロゴをUnityロゴではなくオリジナルや非表示に設定できるなどのサービスが受けられます。
開発時に使用できる機能については無料版と有料版で差異はありません。

### アカウントの登録
アカウントの登録ページにアクセスします。
https://id.unity.com/account/new

登録項目を埋めていきます。
ロボットによるアカウント自動取得を防ぐために、簡単なテストが用意されています。
太字で書かれている部分のアイコンをクリックして選択しましょう。
![](https://qiita-image-store.s3.amazonaws.com/0/233956/a0d5d479-8b49-4483-e8c1-48db9c6f5cf6.png)

確認のメールが送信された旨が表示されます。
![](https://qiita-image-store.s3.amazonaws.com/0/233956/31da141d-c4fc-59d5-4567-16f9989954b4.png)

メールボックスを確認すると以下のようなメールが届いているので、
"Link to confirm email"をクリックしてメールアドレスを認証します。!
![](https://qiita-image-store.s3.amazonaws.com/0/233956/c76ef1cd-57e0-d333-db87-c67df6108749.png)

サインインページが表示されるので、メールアドレスとパスワードを入力してサインインします。
サインインできることを確認したら、ブラウザでの操作は以上になります。
インストールも終わっていると思うのでUnityの方に戻りましょう。
![](https://qiita-image-store.s3.amazonaws.com/0/233956/527efd07-736b-028b-b664-f6eacb069411.png)

### アカウントの認証
Unityを初めて起動すると以下のような画面になるので、先程登録したメールアドレスとパスワードでサインインを行います。
![](https://qiita-image-store.s3.amazonaws.com/0/233956/277a5334-e807-8b1e-2c3b-1c76be0c0389.png)

以下のようなウィンドウが表示されれば成功です。
これでUnityを使う準備は整いました。
![](https://qiita-image-store.s3.amazonaws.com/0/233956/0acca16f-e407-da12-abab-aa2cacd3516f.png)

最後に、各種ボタンの機能も下図で示しておきます。
![](https://qiita-image-store.s3.amazonaws.com/0/233956/69314066-59e8-1577-014c-73f0e57a69b3.png)

## さいごに
いかがだったでしょうか。
不明な点やうまくいかない点などあれば、コメントにて受け付けています。

Unityを使用する準備ができましたら、
そこから先は公式のチュートリアルをおすすめします。
https://unity3d.com/jp/learn/tutorials

以上、お読み頂きありがとうございました。
.bash_profileや.bashrcの変更が反映されない問題を解決する

# .bash_profile / .bashrc とは

.bash_profile
`ログインしたときに読み込まれる設定ファイル`

.bashrc
`bashを起動したときに読み込まれる設定ファイル`

# 前提
.bash_profileや.bashrcのファイル内を変更済。

# 原因
変更内容が反映されていない(PATHが通っていない)為。

# 解決方法

.bash_profileや.bashrcの変更を反映する(PATHを通す)為、下記コマンドを実行。

```terminal:terminal
$ source ~/.bash_profile
$ source ~/.bashrc
```

忘れがちなので気をつけましょう。


以上
Unityのディレクトリ構成と.gitignoreを自動で作るWindows PowerShellスクリプト

#どんなの
Unityで開発するときにAssets以下のテンプレディレクトリ構成と、Unity用の.gitignoreを作ってくれるPowerShell用スクリプトです。
UnityのプロジェクトフォルダをD&Dすると勝手に用意してくれます。
作ってる途中で[Unityで開発するときにフォルダ構成と.gitignoreを作る便利スクリプト](https://qiita.com/takish/items/1604b9dcb053d116b43b#_reference-e231f722b9a63ab68998)を見つけて、あーかぶってしまったと思いましたが、あちらは.shだったので、こちらはWindows向けということで。(Windowsでも.shを使うぞという方はあちらをぜひ)
[Githubの方に](https://github.com/knasa21/UnityDirectorySetting)公開していますので、そこからクローンなり.zipでダウンロードなりしてもらえればすぐ使えます。

#まずはバッチファイル(.bat)
PowerShellじゃないん......
PowerShellスクリプトにD&Dできなかった＋この方が楽という罠(参考:[Powershellを楽に実行してもらうには](https://qiita.com/tomoko523/items/df8e384d32a377381ef9))

```bat:Project&nbsp;folder&nbsp;D&nbsp;and&nbsp;D&nbsp;in&nbsp;this&nbsp;file.bat
@echo off
echo make dir......
powershell -NoProfile -ExecutionPolicy Unrestricted %~dp0UnityDirectorySetting.ps1 "'%~dp0' '%1' '%~n1'"
echo finished!

#pause > nul
exit
```
自身のいるディレクトリのパスとD＆Dされたプロジェクトフォルダのパスと名前をPower Shellスクリプトの方に渡します。
自分の場所は渡さなくてもいいよねっていう意見はごもっともだと思います。

#そしてPowerShellスクリプト(.ps1)
```ps1:UnityDirectorySetting.ps1
$settingPath = $Args[0]
$projectPath = $Args[1]
$projectName = $Args[2]

echo $settingPath
echo $projectPath
echo $projectName

$file = (Get-Content "$settingPath\setting/directory.txt") -as [string[]]
$i = 1
foreach($f in $file) {
	New-Item ("$projectPath\Assets/$projectName/$f") -itemType Directory
	$i++
}

Invoke-WebRequest -Uri https://raw.githubusercontent.com/github/gitignore/master/Unity.gitignore -OutFile ("$projectPath\.gitignore")
```
　　　　　　　　　　　　　
バッチファイルから受け取ったパス(プロジェクトフォルダのパス)以下Assets/[プロジェクト名]/の下にテンプレディレクトリを作っていきます。
そしてプロジェクトフォルダ直下に.gitignoreを作ります。
.gitignoreは[githubの提供してるもの](https://github.com/github/gitignore/blob/master/Unity.gitignore)をもらってくるようにしています。

#テンプレディレクトリ構成
先ほどの@takishさんの[エントリ](https://qiita.com/takish/items/8608ba9070755da3ae6d)を参考にディレクトリ構成を作りました(Shadersを追加したくらい)
これを.batと.ps1同じディレクトリにsettingディレクトリを作って、その下に入れてください。

```text:directory.txt
Scenes
Preafabs
Scripts
Animations
Materials
Shaders
Physics Materials
Fonts
Textures
Audio
Resources
Editor
Plugins
```
ここに書いてあるものを作成するので好みに合わせて書き換えてください。
Scenes/Stage1 のように書けばちゃんと子ディレクトリも作られます。

#ディレクトリ構成
こんな感じで置いてもらえれば大丈夫です。
>hoge/
├Project folder D and D in this file.bat
├UnityDirectorySetting.ps1
└setting/
&emsp;&emsp;└directory.txt

#使い方
1. Unityの新規プロジェクトを作成
1. Edit->Project Settings->EditorでVersion ControlをVisible Meta Filesに変更 +(多分平気)Asset SerializationをForce Textに変更
1. Unityプロジェクトのフォルダ(Assetsの親)を"Project folder D and D in this file.bat"にドラッグ＆ドロップ

以上でAssets以下にプロジェクト名と同じディレクトリが作成され、その中にsetting/directory.txtに書かれたディレクトリが作成される+プロジェクトディレクトリ以下に.gitignoreが作成といった感じです。

#おわりに
前々から面倒だなぁ思ってたので、Power Shellスクリプトを試しがてら作ってみました。
Editor拡張と悩んだのですが、.unitypackageを入れるのとどっちが楽かなと考えてこっちにしました。
.unitypackage入れたりせずにEditor上でボタン一つでできると楽ですけどねー。できるのかな。
vsftpdが起動しなかった話



#起動したらこんなエラー


```shell-session:起動した結果
# systemctl start vsftpd
Job for vsftpd.service failed because the control process exited with error code.  
See "systemctl status vsftpd.service" and "journalctl -xe" for details.
```

#設定ファイルの文法が違うっぽい

* ~~ =YES のあとに空白文字がある
* 誤字脱字

などはありがちなミス


#文法に問題がないかチェックしてもらう

```shell-session:文法の確認
#/usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf
```

#問題があれば指摘してくれる
逆になければ、そのまま起動するので注意
Max/MSPノート

noteにMax/MSPの記事を書き始めてみました。

https://note.mu/onigiri2/m/md19a44482b73

具体的なパッチの解説というよりは日々の実験動画や見つけた面白い動画などをひたすら貼り付けて行ってます。

もしご興味ありましたら見てみて下さい！
初心者にはこう説明してくれ!!coffeescriptのfs.readFileコールバック

#例えばこんなコード。

```CoffeeScript
loadCompletions: ->
    　　fs.readFile(
      　　path.resolve(__dirname, '..', 'completions.json'),
      　　(err, data) => @completions = JSON.parse(data) unless err?)
```

##初心者はここに違和感を感じる

```CoffeeScript
(err, data) => @completions = JSON.parse(data) unless err?
```

#こんな説明はヤダ。

ググればすぐ出てくるよ。⇒本当に？
これは非同期で読み込んで引数にコールバック関数を指定しているんだよ。⇒はぁ？ 
javaから学び、直したほうがいいよ。⇒知らないし・・。


#私ならこう説明されたい。

##ポイントは2つあって「非同期、コールバック」なんだけど、聞いたことある？

このreadFile関数は**非同期で実行されるように設計されている**んだ。
**例えば**重たいファイルがあって、それを全部読み取らないと、次の画面に行ってくれないアプリだったら、ユーザーはイライラしてしまうだろ？そーゆうのを避けるために、非同期っていう思想があるんだ。
全部読み取らなくても、次に進むってことね。それを可能にするためにコールバックっていう概念があるんだ。
さっきの例で言ったアプリの場合だと、全部読み取らないで次の画面を出したら、動いている処理は、二つあることになるよね。

1、ファイル読み取り中⇒読み取り終了に向かう処理
2、ユーザーに次の画面を見せる処理

じゃデータ読み込み中はユーザーに画面見せて、他の事してもらうことにしよう。
それも終わって次の画面出したいけど、次に行くにはどうしてもさっき読み込み中だったデータが必要ってときは**どうする？**

画面をまた前に戻す。なんてしてたら、マジ切れされちゃうよね。
そうじゃなくて読み込み中の処理が全部終わったら、読み込んだデータを、次の画面に送るような機能をつければいいよね。
そうやって、非同期で実行された処理が終了した時点で実行する処理の事をコールバックっていうんだ。
プログラムでいう**これがその部分だよ。**

>(err, data) => @completions = JSON.parse(data) unless err?

**今回は、unless err?でエラーがないかチェックして、JSON.parse(data)の結果を、loadCompletionsメソッドの外側にあるcompletions変数に格納しているよ。**

>(err, data)

このerrとdataはどこから来たか**も気になるよね。**
それはreadFile関数が、ファイルを読み取ったデータをdataに、エラーが出たらerrに入れてくれるんだよ。
まだ、あまり馴染みがない形かもしれないけど、関数自体が、結果を引数に入れて、さらにそれを引数である、コールバック関数に渡す形は、非同期処理によく出てくるから覚えておくといいよ。

あと、completionsの前についている「@」が、気になる？javaScriptのthisって言えばすぐわかるかな？
「->」じゃなくて「=>」なのが気になるなら、メソッド⇒関数⇒関数って構造が入れ子になっていくと、thisの状態も所々で変わってくるんだ。「=>」はそれを防ぐんだ。つまり前のthisを引き継いでいるって考えて。

#で結局どうしてほしいかって？
１、目的を伝えてほしい。
なぜそれが必要になるのか、どうしてその形にしているのか。理解すると人は応用できるようになる。

２、例えてほしい。
　　とても難しい概念でも、だいたいは身近なもので置き換えることができる。そうすれば人は容易に理解できるようになる。

３、実際に示してほしい。
コードのどの部分がそーゆう意味なのか、視覚に訴えて示してくれると、印象に残る。


４、それでもう一度詳しく説明してほしい。
そうすれば、要点が繰り返され、記憶に刻まれる。


５、察してほしい。
上級者は初心者がどんな分野でつまずくのか、知見があるはず。自分も初心者だったのだから。それを活かしてほしい。でも質問する側にも問題がある。自分がどこが分かっていないのかさえわからないようでは絶望的。でもどこがわからないのか親切に聞きだしてくれたら、初心者にとってはありがたい事に変わりはない。

６、考えさせる。
説明を受け身になっているだけだと、思考は停止する。本来人の思考速度はとても速いのだ。それを止めてはいけない。適切な質問をして考えを確認し、思考を導けば良い結果につながる。
Elm で Video Element や Audio Element の Media Event を扱う

Elm を初めて触ってみたのですが、 Video 要素などの扱いはどうなんだろうと、 [slack](https://elmlang.slack.com) で訊いてみたところ 「[custom dom event handler を作れ](https://robots.thoughtbot.com/building-custom-dom-event-handlers-in-elm)」と言われたので実装してみました。

![](https://i.gyazo.com/56a0e683cbd110699361f497d010ae65.png)

http://elm-lang.org/try にコピペすると現在シーク時刻とビデオ再生状態が取得できます。

```elm
import Html exposing (..)
import Html.Events exposing (..)
import Html.Attributes exposing (..)
import Json.Decode as Json

main =
  Html.program
    { init = init
    , view = view
    , update = update
    , subscriptions = subscriptions
    }


-- MODEL

type alias Model = { videoState : String
                   , currentTime : Float }

init : (Model, Cmd Msg)
init = (Model "loading" 0, Cmd.none)

-- UPDATE

type Msg = CurrentTime Float
         | Loading
         | Playing
         | Paused
         | Seeking

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    CurrentTime currentTime ->
      ({ model | currentTime = currentTime }, Cmd.none)
    Loading ->
      ({ model | videoState = "loading" }, Cmd.none)
    Paused ->
      ({ model | videoState = "paused" }, Cmd.none)
    Playing ->
      ({ model | videoState = "playing" }, Cmd.none)
    Seeking ->
      ({ model | videoState = "seeking" }, Cmd.none)

-- SUBSCRIPTIONS

subscriptions : Model -> Sub Msg
subscriptions model = Sub.none

-- VIEW

targetCurrentTime : Json.Decoder Float
targetCurrentTime = Json.at ["target", "currentTime"] Json.float

view : Model -> Html Msg
view model =
  div [] [
    video [ src "http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"
          , on "timeupdate" (Json.map CurrentTime targetCurrentTime)
          , on "seek" (Json.map CurrentTime targetCurrentTime)
          , on "seek" (Json.succeed Seeking)
          , on "seeking" (Json.succeed Seeking)
          , on "seekend" (Json.succeed Paused)
          , on "playing" (Json.succeed Playing)
          , on "play" (Json.succeed Playing)
          , on "pause" (Json.succeed Playing)
          , on "ended" (Json.succeed Paused)
          , on "loadedmetadata" (Json.succeed Paused)
          , controls True] [],
    div [] [text (toString model.currentTime)],
    div [] [text (toString model.videoState)]
  ]
```

## 所管

Elm は入出力が増えたら Msg が大変なことになりそうだと思いました（小学生並の感想

## 参考

* https://robots.thoughtbot.com/building-custom-dom-event-handlers-in-elm
* https://github.com/elm-lang/html/blob/2.0.0/src/Html/Events.elm#L251
* http://package.elm-lang.org/packages/elm-lang/html/2.0.0/Html-Events
* http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode
YouTubeの動画をスクショするブックマークレット

作りました！！

## ブックマークレット

```js
javascript:(()=>{const parseQueryString=(queryString)=>{const params={};queryString.split('&').forEach((str)=>{const[k,v]=str.split('=');params[k]=decodeURIComponent(v)});return params};const{v:videoId}=parseQueryString(location.search.substr(1));const videoElm=document.querySelector('video');const canvasElm=document.createElement('canvas');canvasElm.width=parseInt(videoElm.style.width);canvasElm.height=parseInt(videoElm.style.height);canvasElm.getContext('2d').drawImage(videoElm,0,0,canvasElm.width,canvasElm.height);const anchorElm=document.createElement('a');anchorElm.setAttribute('download',`${videoId}.png`);anchorElm.setAttribute('href',canvasElm.toDataURL("image/png").replace("image/png","image/octet-stream"));anchorElm.click()})();
```

## ソースコード
```js
(() => {
  const parseQueryString = (queryString) => {
    const params = {};
    queryString
      .split('&')
      .forEach((str) => {
        const [k, v] = str.split('=');
        params[k] = decodeURIComponent(v);
      });
      return params;
  };

  const { v: videoId } = parseQueryString(location.search.substr(1));
  const videoElm = document.querySelector('video');
  const canvasElm = document.createElement('canvas');
  canvasElm.width = parseInt(videoElm.style.width);
  canvasElm.height = parseInt(videoElm.style.height);
  canvasElm.getContext('2d').drawImage(videoElm, 0, 0, canvasElm.width, canvasElm.height);
  const anchorElm = document.createElement('a');
  anchorElm.setAttribute('download',`${videoId}.png`);
  anchorElm.setAttribute('href',canvasElm.toDataURL("image/png").replace("image/png","image/octet-stream"));
  anchorElm.click()
})();
```
MonoDevelop をビルドするまで on macOS

Visual Studio for Mac を更新すると、IME が動作しない（例:日本語が入力できない、IMEのON/OFFができない、など）ことが、まあまあ良くある。
↓
まあ元が OSS の MonoDevelop だし、日本語入力環境を使っているコントリビューターなんて稀なのでは？
↓
じゃあ、その辺直せるようになったらコントリビューターワンチャンあるで！
↓
まずは MonoDevelop を自力でビルドしてみよう！

というわけで。

## Steps

（かなり高い確率の）たぶんですが、先に Xcode Command Line Tools がインストールできていれば、 6. 〜 12. くらいまで全部 3. のスクリプトがやってくれると思いますお。

1. [Development - Getting Started | MonoDevelop](http://www.monodevelop.com/developers/articles/development-getting-started/) を見る
2. "If you’re on OS X you can also try @dvdsgl’s one step install: https://github.com/dvdsgl/monodevelop-build" をハケーン
3. 適当なディレクトリを作って Terminal で ``ruby -e "$(curl -fsSL bit.ly/1zCQCam)"`` を実行
4. 途中で macOS のパスワードを聞かれるので入力する
5. また待つ
6. 「**Error**: You must have `automake' installed to compile MonoDevelop.」 が出る
7. ``brew install automake`` を実行する
8. 「Error: Xcode alone is not sufficient on Sierra. Install the Command Line Tools: xcode-select --install」 が出る
9. ``xcode-select --install`` を実行する
10. なんかダイアログボックスが出てくるのでそれに従い Xcode Command Line Tools をインストールする
11. もう一度 ``brew install automake`` を実行する → 成功
12. ``monodevelop`` ディレクトリに移動して ``./configure --profile=mac`` を実行する([参照](http://www.monodevelop.com/developers/building-monodevelop/#macosx)) → 成功
13. ``make`` を実行する → 待つ → 待つ → 待つ → 成功
14. ``make run`` を実行する → MonoDevelop が起動する(↓ババーン)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/8227/a1a0165a-e8c0-c5e9-2f31-c09ab9ca14e6.png)

おーこれが素の MonoDevelop かー（初めて見たｗ）。
ソリューション作成はできたけど、実行したら IDE もろとも落ちたけど、これからこれから。

## おまけ

Visual Studio for Mac で ``monodevelop/main/Main.sln`` を開いて config を ``DebugMac`` にして実行したら、 MonoDevelop がビルドされて起動した。
django-admin-bootstrap を試してみる

Django管理者向けのサイドバーメニューを使用したレスポンシブなテーマ。
AWESOME DJANGO の ADMIN INTERFACE 部門で（アルファベット順ですが）2番目に紹介されてたので試してみることに。
ドキュメント に従って設定。

# 使用した環境
Windows10
Python 3.5.4
Django 1.11.8
django-admin-bootstrap 0.3.8

# インストール

```
> pip install bootstrap-admin
```

# 設定
## settings.py
INSTALLED_APPS に bootstrap_admin を追加。
django.contrib.admin の前に追加すること。

```py3
INSTALLED_APPS = [
    # TODO: for django-admin-bootstrap
    'bootstrap_admin',
    'django.contrib.admin',
    ...
]
```
これだけ。

# 管理サイトを起動
## デフォルトの管理サイト(Home)
比較のため django-admin-bootstrap 適用前のデフォルトの管理サイト

![通常_admin_.png](https://qiita-image-store.s3.amazonaws.com/0/112763/5707959c-6709-32f2-b9e7-997885d0d6f6.png)

## django-admin-bootstrap 適用後の管理サイト(Home)

![bootstrap-admin.png](https://qiita-image-store.s3.amazonaws.com/0/112763/73e546b9-89f6-7e07-b96c-5e6ee4c85103.png)

ログイン画面もカッコいい。
![bootstrap-login.png](https://qiita-image-store.s3.amazonaws.com/0/112763/eeb3803c-6794-ddd4-6ba7-205ff2406116.png)

スマホから。
<img src="https://qiita-image-store.s3.amazonaws.com/0/112763/31b08eac-4523-3804-27ae-49247eea8834.png" width=50%>

残念ながらスマホはログインユーザーの表示が少しかぶってる。

# 感想
スマホの件に目をつぶれば、いくつか試した管理インターフェイスでこれが１番カッコいい。
どこかで使いたい。

# ライセンス
BSD 3-clause 

ライセンスについてご参考。
- [たくさんあるオープンソースライセンスのそれぞれの特徴のまとめ](http://coliss.com/articles/build-websites/operation/work/choose-a-license-by-github.html)
- [商用利用できるオープンソースライセンスはけっきょくどれで何をすればいいのか？](https://qiita.com/0xfffffff7/items/efbb65521d7708f2db7d)
[Ruby]効率的なループ処理


どんな状況でも`each`でループ処理を書くことは可能だけど、
適したメソッドを使えば余分なコードを書かず本質的なコードのみにすることが出来る。

# 結論
・ループ処理の結果を配列で返して欲しい場合は`map`を使う
・ループ処理の結果をHashで返して欲しい場合は`each_with_object`を使う
・ループ処理の結果を集計したい場合は`reduce`を使う


各要素に加算を行い配列を返したい場合を例にする。

eachの場合

``` ruby
result = []
numbers = [4, 3, 9]
numbers.each do |number|
	result << number + 3
end

result
```

## Array#map
ブロックの戻り値を集めた配列を返す。

``` ruby
numbers = [4, 3, 9]
numbers.map do |number|
	number + 3
end
```

## Enumerable#each_with_object
繰り返しごとにブロック引数numberには各要素を、resultには引数objectで指定したオブジェクトを入れる。

``` ruby
numbers = [4, 3, 9]
numbers.each_with_object([]) do |number, result|
	result << number + 3
end
```

## Enumerable#reduce
ブロックを使って繰り返し計算を行うのに使う。

``` ruby
numbers = [4, 3, 9]
numbers.reduce([]) do |result, number |
	result << number + 3
	result
end
```

各要素の集計を出したい場合にreduceを使うと、とてもシンプルに書くことが出来る。
eachの場合

``` ruby
result = 0
numbers = [4, 3, 9]
numbers.each do |number|
	result = result + number
end

result
```
reduceの場合

``` ruby
numbers = [4, 3, 9]
puts numbers.inject(:+)
```
DeepLearningで画像中のモザイク箇所を検出する

以前に以下でOpenCVなどを駆使して力技でモザイク検知をしたが、今度は機械学習でやってみる。

- https://qiita.com/summer4an/items/306acc5d38169f880ba8
- https://github.com/summer4an/mosaic_detector

利用したコードは以下に。
- https://github.com/summer4an/mosaic_detector_with_DL

Deep Learning CNNのsemantic segmentationを使った。
semantic segmentationについては以下等参照。

- http://postd.cc/semantic-segmentation-deep-learning-review/
- https://www.slideshare.net/takmin/semantic-segmentation

FCNやDeepLab等いろいろなネットワークがあるが、TensorFlowでの実装があり動作させられた
SegNetのものを利用する。
SegNetの元論文はこれ。

- https://arxiv.org/abs/1511.00561

以下のコードを拝借。

- https://github.com/tkuanlun350/Tensorflow-SegNet

画像データはターゲットのモザイクを含むpngファイルと、
モザイクの位置を示す答えのpngファイルが必要。

答えのpngはsemantic segmentationでは一般的(？)な形式で、
ラベル部分(ラベルの順に#000000、#010101、#020202…)に塗り分けられたもの。

今回の場合、モザイクでない部分は#000000で、モザイク部分だけ#010101で塗って学習させてみたが、
うまく判別できず(開発途中だったためこれが原因ではないかも)。
背景は#010101、モザイク部分は#020202で塗ったところうまくいった。

手順。

- 元画像を用意。train、valid、test用にそれぞれ500枚程度。
- 001_mosaic_kakeru.shを使ってモザイクをかけたものと、かけた部分を表す答えのpngを作る。
- 100_list_maker.shでファイルリストを作成。
- 101_gakusyuu.shで学習。NVIDIA GTX 1060を使い、20000イテレーションで5時間程度。
- ログディレクトリにできた連番名付きのckptファイルを201_move_model.shで連番名無しに。
- 202_hantei.shでtest用のファイルを判定。元画像と同じディレクトリに生成される。

以下が実際に判別させたもの。
(画像は http://gahag.net/011032-cat-sunflower-smell/ より拝借)

![pic00001_generated_mosaic.png](https://qiita-image-store.s3.amazonaws.com/0/108313/0354110b-5995-d0a2-d244-68432829df05.png)

![pic00001_generated_mosaic_hanteikekka.png](https://qiita-image-store.s3.amazonaws.com/0/108313/e0b73087-4447-67c6-e454-9d3c8744f55b.png)

精度は完全とは言えないがまあまあか。
[Ruby]Comparableモジュールのメソッド

1年くらい前にRubyの勉強のためにComparableモジュールの便利メソッドをまとめたもの

参考
・https://docs.ruby-lang.org/ja/latest/class/Comparable.html

## 範囲内の値か判定する
between?
引数で指定した値の範囲内か判定する

``` ruby
num = 5
num.between?(1, 5) # => true

str = 'c'
str.between?('a', 'g') # => true
```

## 範囲内の値を返す
clamp
指定範囲内の値を返す。 
・指定範囲内であればレシーバを返す
・下限値より小さければ下限値を返す
・上限値より大きければ上限値を返す

``` ruby
min = 10
max = 30
     
5.clamp(min, max)  # => 10
70.clamp(min, max) # => 30
15.clamp(min, max) # => 15
```

clamp以前はこんな状態でわかりにくかったのでclampわかりやすい

``` ruby
min = 10
max = 30
 
[[5, min].max, max].min => 10
```
手探りVue.js入門記

書いておかないと忘れるのでおいて置きます。おそらく追記アリ。

## 始める前の自分
- Node.js サーバサイド開発経験
- 多少のHTML, CSS, JavaScriptの知識
- めんどくさいことは少しPythonにやってもらっている程度
- *フロントエンドフレームワークって何？*

とりあえず、リッチなフロントエンド開発を始めたいと思いVue.jsを選択。

## 使ってみて思ったこと
まずはメリット面から。

**DOM操作をしている自覚がなく、扱いやすかった。**
以前使ったjQueryとは違い、厄介なDOM操作をしている印象が皆無だった。特に、変数に何か代入した時点でページの内容が変わるので、流れが追いやすくデバッグが簡単だった。

**手軽である。**
Vue.jsはCDNにて管理されているので、HTMLに一行追加するだけで試すことができた。
これらのフレームワークは大規模なアプリケーションを作るのに選択されるイメージがあったが、小規模なアプリケーションでも使う価値があるように感じた。

**学習コストは低い**
JavaScriptと多少のHTML&CSSの知識でサーバとちゃんと連携するページを書くことが出来た。他所でも言われていたことだが、それなりに直感的に出来ていると感じる。

比較対象が無いのでデメリットは今のところ思いつかない。

## ハマったポイント
**JSの読み込み場所はBody内にしなければならなかった。**
Head内で読み込んでも全然適応されなくて困った。公式ページでは全然触れられていなかったので、Vue.jsを使っているページのソースを見て判明した。

**thisが一体何を指しているのかわからなかった。**
thisが指していたのはdataオブジェクト。よって、this.data.hogeと書いてもundefinedになってしまいアクセスすることが出来ない。

**methods内の無名関数はアロー関数を使用することができなかった。**
function()を使わずアロー演算子を使用したところ上手く動かなかった。
[この記事](https://qiita.com/_Keitaro_/items/d48733a19c10889e2365)がわかりやすく説明している。

## 成果物
2018-01-26 Node.jsからJSONを受け取り色を変更するスクリプト
やっていることは簡単なことではあるが、Vue.jsの特徴をつかめたと思う。
[GitHub](https://github.com/kznrluk/vuejs-colors)

![動画](https://camo.githubusercontent.com/03df8a49444985f22c3cf205f8b20a8e55013562/68747470733a2f2f692e6779617a6f2e636f6d2f65393131303136373466363236363862663166383537373230633132376261322e676966)
[Ruby]Threadについての紹介

1年くらい前にRubyの勉強のためにThreadクラスのメソッドや基礎をまとめたもの

参考
・https://docs.ruby-lang.org/ja/latest/class/Thread.html
・https://docs.ruby-lang.org/ja/latest/class/Thread=3a=3aMutex.html
・https://docs.ruby-lang.org/ja/latest/class/Fiber.html

スレッド基礎
・スレッド
　スレッドとはメモリ空間を共有して同時に実行される制御の流れのこと。　
　
・スレッドの変数の扱い
　同じプロセス上の他のスレッドとメモリを共有する。
　そのため他のスレッドと共有したくない値は、ブロックの仮引数として受け取る。ブロックローカル変数にすると他のスレッドと共有されなくなる。

スレッドの状態
・run		：実行or実行可能状態
・sleep		：停止状態
・aborting	：終了処理中
・dead		：終了状態

## スレッドの生成
Thread#fork
スレッドの生成してブロックの評価を開始する。

Thread#join
スレッドが終了するまで待つ

Thread#value
スレッドが終了するまで待ち、戻り値を得る

## スレッドの操作
Thread#wakeup
停止スレッドを実行可能状態にする

Thread#run
即座に処理をそのスレッドに切り替える

Thread#kill
生きている状態のスレッドの終了

Thread#pass
現在のスレッドから他のスレッドに実行を移す

Thread### スレッドの優先順位
優先順位の値が大きいほどスレッドの優先度が高くなる

Thread#priority
スレッドの優先度を確認する

## ThreadGroup
すべてのスレッドはどこかのスレッドグループに属しており、デフォルトはThreadGroup::Defaultに属している。

ThreadGroup#group
自身の所属グループを得る

ThreadGroup#add
グループにスレッドを追加する

ThreadGroup#list
グループのスレッド一覧


## Mutex
共有データを並行アクセスから保護するためにある。排他制御を行う。
Mutex#lock、Mutex#unlock、Mutex#locked?などのメソッドがある。

Mutex#try_lock
ロックをしようとしてロックが成功したらtrueを返す。失敗ならfalse。

## Fiber
ノンプリエンプティブな軽量スレッドを提供する。Threadと違い処理の流れを扱うことができる。例えば、処理を途中まで実行して、その後任意のタイミングで再開させることが出来る。

## Process
プロセスを管理するモジュール。デーモンプロセスを生成、操作できる。
スレッドと違いメモリを共有しない。
[Ruby]日付系クラス（Time, Date, TimeDate）のメソッド

1年くらい前にRubyの勉強のために日付系クラスの便利メソッドをまとめたもの


参考
・[パーフェクトRuby](https://www.amazon.co.jp/%E3%83%91%E3%83%BC%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88Ruby-PERFECT-6-Ruby%E3%82%B5%E3%83%9D%E3%83%BC%E3%82%BF%E3%83%BC%E3%82%BA/dp/4774158798/ref=sr_1_2?ie=UTF8&qid=1493615214&sr=8-2&keywords=%E3%83%91%E3%83%BC%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88Ruby)
・https://docs.ruby-lang.org/ja/latest/class/Time.html


## 文字列表現
Time#strftime
Time オブジェクトから日時を表す文字列を任意のフォーマットで得ることができる

``` ruby
time = Time.now
time.strftime('%Y/%m/%d %H:%M:%S') # => "2017/05/20 21:43:10"
```

## 閏年判定
Date#leap?
閏年かどうか判定する

``` ruby
require 'date'

Date.new(2000).leap? # => true
Date.new(2001).leap? # => false
```

時刻から曜日を返す
Time#wday
曜日を数値で取得する。(0が日曜日、6が土曜日）

``` ruby
wdays = %w[日 月 火 水 木 金 土]
day = Time.now # => 2017-05-22 00:03:47 +0900
wdays[day.wday] # => "月"
```
１行でintの配列を偶数と奇数に分ける

存在を忘れがちだがToLookup（またはGroupBy）を使うと１行でできる。

```csharp
var numbers = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var oddsAndEvens = numbers.ToLookup(n => n % 2 == 0);

// oddsAndEvens[true];
// == [1, 3, 5, 7, 9]
// oddsAndEvens[false];
// == [2, 4, 6, 8, 10]
```

その他、ありがちなケースとして、「エラーがあるオブジェクトとないオブジェクトを分ける」みたいな時にも使える

```csharp
var items = new[] 
{
	new {Name = "A", HasError = false },
	new {Name = "B", HasError = true },
	new {Name = "C", HasError = false },
	new {Name = "D", HasError = true }
};
	
var validOrInvalidItems = items.ToLookup(i => !i.HasError);

// 指定したキーのデータがなかった時は例外になるので注意
// validOrInvalidItems[false].Select(x => x.Name);
// == ["A", "C"]
// validOrInvalidItems[true].Select(x => x.Name);
// == ["B", "D"]
```

なお、ToLookupの中身を列挙する場合、今のところ追加した順番が維持されるようだが、保証されている訳ではないと思われるので、列挙する順番が重要な場合はOrderByしてから列挙した方がよさそう。
[関連するStackOverflowのQA](https://stackoverflow.com/questions/1189982/preserve-order-of-values-with-linq-and-tolookup)
[Ruby]Struct, OpenStructクラスのメソッド

1年くらい前にRubyの勉強のためにStruct, OpenStructクラスの便利メソッドをまとめたもの

参考
・[パーフェクトRuby](https://www.amazon.co.jp/%E3%83%91%E3%83%BC%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88Ruby-PERFECT-6-Ruby%E3%82%B5%E3%83%9D%E3%83%BC%E3%82%BF%E3%83%BC%E3%82%BA/dp/4774158798/ref=sr_1_2?ie=UTF8&qid=1493615214&sr=8-2&keywords=%E3%83%91%E3%83%BC%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88Ruby)
・https://docs.ruby-lang.org/ja/latest/class/Struct.html
・https://docs.ruby-lang.org/ja/latest/class/OpenStruct.html

# Struct
構造体クラス

## 基本的な使い方
Structのサブクラスを作って利用する。

``` ruby
point = Struct.new('Point', :x, :y) # => Struct::Point
item = point.new(10, 30) # => #<struct Struct::Point x=10, y=30>

p item.x # => 10
```

## メソッド定義
Struct.newにブロックを渡し、その中にインスタンスメソッドを定義する。

``` ruby
Human = Struct.new('Human', :age, :gender) do
  def teen?
    (13..19).include?(age)
  end
end

Human.new(17).teen? # => true
```

# OpenStruct
要素を動的に追加・削除できる手軽な構造体を提供するクラス

``` ruby
require 'ostruct'

Human = OpenStruct.new
Human.gender = 'male'

p Human.gender # => "male"
```
初期値にHashを使用することもできる。

``` ruby
require 'ostruct'

Son = OpenStruct.new({gender: :male})
p Son.gender # => :male
```
[Ruby]IO、File、Dirクラスのメソッド

1年くらい前にRubyの勉強のためにIO、File、Dirクラスの便利メソッドをまとめたもの

参考
・[パーフェクトRuby](https://www.amazon.co.jp/%E3%83%91%E3%83%BC%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88Ruby-PERFECT-6-Ruby%E3%82%B5%E3%83%9D%E3%83%BC%E3%82%BF%E3%83%BC%E3%82%BA/dp/4774158798/ref=sr_1_2?ie=UTF8&qid=1493615214&sr=8-2&keywords=%E3%83%91%E3%83%BC%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88Ruby)

## ファイルの読み込み
IO#open：ファイルを開く
IO#close：ファイルを閉じる
IO#read：ファイルの内容を末尾まで読み込む。読み込むバイト数の指定も可能
IO#gets：ファイルを１行ずつ読み込む


``` ruby
# 例：read
File.open('sample.txt') do |file|
	puts file.read	
end

# 例：gets
File.open('sample.txt') do |f|
	while line = f.gets
		puts line
	end
end

# each_lineを使いより自然な記述へ
File.open('sample.txt') do |f|
	f.each_line do |line|
		puts line
	end
end
```

## ファイルの書き込み
IO#write
文字列を書き込む

``` ruby
File.open('sample.txt') do |f|
	f.write 'Ruby' # ファイルに"Ruby"と書き込む
end
```

## アクセス位置の操作
IO#rewind
アクセス位置を先頭に戻す

IO#seek、IO#pos=
任意の位置に移動する


## ファイルのロック
File#flock
ファイルをロックしたりロックを開放するメソッド

## ファイルに関する情報の取得
File#atime：最後にアクセスした日時
File#ctime：最後に状態を変更した日時
File#mtime：最後に更新した日時
File#size：ファイルサイズ

## ファイル操作
File#rename：ファイル名の変更/移動
File#unlink：ファイルの削除
File#symlink：ファイルのシンボリックリンク作成
File#link：ファイルのハードリンク作成
File#symlink：ファイルのシンボリックリンク作成
File#chmod：ファイルモードの指定
File#chown：オーナー・グループの変更

## ファイルパス操作
File#dirname：ファイルのディレクトリパス
File#basename：ファイル名
File#extname：拡張子
File#join：ファイルパスの連結
File#split：dirnameとbasenameの配列
File#expend_path：相対パスから絶対パスを取得する

## ファイル一覧の取得
Dir#entries：ディレクトリに含まれるファイル一覧の取得

## ディレクトリ操作
Dir#mkdir：ディレクトリ作成
Dir#chdir：ディレクトリの移動
Dir#rmdir：ディレクトリの削除
Dir#exist?：ディレクトリの存在検査
[Ruby]Hashクラスのメソッド

1年くらい前にRubyの勉強のためにHashクラスの便利メソッドをまとめたもの

参考
・[パーフェクトRuby](https://www.amazon.co.jp/%E3%83%91%E3%83%BC%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88Ruby-PERFECT-6-Ruby%E3%82%B5%E3%83%9D%E3%83%BC%E3%82%BF%E3%83%BC%E3%82%BA/dp/4774158798/ref=sr_1_2?ie=UTF8&qid=1493615214&sr=8-2&keywords=%E3%83%91%E3%83%BC%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88Ruby)
・https://docs.ruby-lang.org/ja/latest/class/Hash.html

## 繰り返し
each_key
ハッシュのキーだけを繰り返す

each_value
ハッシュの値だけを繰り返す

``` ruby
hash = { ruby: 1, java: 2}

hash.each_key{ |key| puts key} # => "ruby" "java" と順番に出力
hash.each_value{ |val| puts val} # => "1" "2" と順番に出力
```

## マージ
2つのハッシュを１つにまとめる

``` ruby
a = { ruby: 1, java: 2}
b = { php: 3, ruby: 5}

a.merge(b) # => {:ruby=>5, :java=>2, :php=>3}
```

## キーと値の入れ替え
invert
キーと値を入れ替えた新しいハッシュを生成

``` ruby
hash = { ruby: 1, java: 2}
hash.invert # => {1=>:ruby, 2=>:java}
```

## キーや値の確認
has_key?
指定したキーが存在するか確認（値がnilか区別を付けるため）

``` ruby
hash = {hoge: nil}

hash[:unknown]	 # => nil
hash[:hoge]	 # => nil

hash.has_key?(:unknown)	# => false
hash.has_key?(:hoge) 		# => true
```
has_value?
指定した値を持つエントリが存在するか確認

``` ruby
hash = {ruby: 1}

hash.has_value?(1) # => true
hash.has_value?(2) # => false
```

## デフォルト値の設定
Hah.newの第一引数にデフォルト値を指定できる

``` ruby
hash = Hash.new('ruby')
hash[:a] # => "ruby"

hash = Hash.new { |v| 'java'}
hash[:b] # => "java"
```

fetch
指定したキーに値が存在しない場合の戻り値を指定

``` ruby
hash = {ruby: 1}

hash.fetch(:ruby, 5) # => 1
hash.fetch(:java, 5) # => 5
hash.fetch(:java) {|key| key} # => :java
```
[Ruby]Arrayクラスのメソッド

1年くらい前にRubyの勉強のためにArrayクラスの便利メソッドをまとめたもの

参考
・[パーフェクトRuby](https://www.amazon.co.jp/%E3%83%91%E3%83%BC%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88Ruby-PERFECT-6-Ruby%E3%82%B5%E3%83%9D%E3%83%BC%E3%82%BF%E3%83%BC%E3%82%BA/dp/4774158798/ref=sr_1_2?ie=UTF8&qid=1493615214&sr=8-2&keywords=%E3%83%91%E3%83%BC%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88Ruby)
・https://docs.ruby-lang.org/ja/latest/class/Array.html


## 要素の取得
values_at
複数の添字の要素を配列で返す

``` ruby
ary = [3, 4, 2, 8]
ary.values_at(0, 3, 4) # => [3, 8, nil]
```

sample
selfからランダムに要素を返す

``` ruby
ary = [3, 4, 2, 8]
ary.sample # => 2

# 引数を設定すると返す要素の個数を指定できる
array.sample(2) => [4, 2]
```

assoc
特定のキーを持つ要素を返す

``` ruby 
ary = [[:ruby, 5], [:java, 3], [:c, 1]]
ary.assoc(:ruby) # => [:ruby, 5]
```

dig
深い階層にある値を引っこ抜く。keyが見つからない場合はnilが返る。
ネストしたHashや配列へのアクセスがしやすくなる。 

``` ruby
# Hash
h = { foo: {bar: {baz: 1}}}
h.dig(:foo, :bar, :baz) # => 1
h.dig(:hoge)            # => nil
 
g = { foo: [10, 11, 12] }
g.dig(:foo, 1)          # => 11
 
# Array
a = [[4, [5, 6]]]
 
a.dig(0,1,0) # => 5
a.dig(0,1,1) # => 6
a.dig(0,1)   # => [5, 6]
a.dig(1)     # => nil
a.dig(0,0,0) # => TypeError: Integer does not have #dig method
```


## 配列の整形
compact
配列の要素からnilを取り除く

``` ruby 
array = [false, nil, 0, '', [0, nil], []]
array.compact # => [false, 0, "", [0, nil], []]
```

uniq
配列から重複要素を取り除く

``` ruby
array = ['ruby', 'ruby', 2, 2.0, 2]
array.uniq # => ["ruby", 2, 2.0]
```

flatten
配列の階層を完全にフラットにする

``` ruby
array = [1, 2, [3, 4], 5]
array.flatten # => [1, 2, 3, 4, 5]
```

transpose
配列を行列に見立てて行と列の入れ替えを行う

``` ruby
array = [[1, 2, 3], ['北海道', '青森', '秋田']]
array.transpose # => [[1, "北海道"], [2, "青森"], [3, "秋田"]]
```

## 二分探索
bsearch
二分探索する。

``` ruby
array = [1, 2, 3, 5, 8]

array.bsearch { |n| n > 4 } # => 5
array.bsearch { |n| n > 9 } # => nil
```

## 要素の連結
join
配列を連結する

``` ruby
array = [1, 2, [3, 4], 5]
array.join # => "12345"
# セパレータとなる文字列を引数に指定も可能
array.join(',') # => "1,2,3,4,5"

# Array#*メソッドでも同じことが可能だけど暗号っぽくなるので非推奨(StyleGuideより）
array.*(',') # => "1,2,3,4,5"
```
[Ruby]Stringクラスのメソッド

1年くらい前にRubyの勉強のためにStringクラスの便利メソッドをまとめたもの


参考
・[パーフェクトRuby](https://www.amazon.co.jp/%E3%83%91%E3%83%BC%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88Ruby-PERFECT-6-Ruby%E3%82%B5%E3%83%9D%E3%83%BC%E3%82%BF%E3%83%BC%E3%82%BA/dp/4774158798/ref=sr_1_2?ie=UTF8&qid=1493615214&sr=8-2&keywords=%E3%83%91%E3%83%BC%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88Ruby)
・https://docs.ruby-lang.org/ja/latest/class/String.html


## 部分文字列の取得
slice
指定した任意の文字列を取得する

``` ruby
str = 'Super Multiple Vitamin 12'

# 範囲で指定
str.slice(6..10) #=> "Multi"

# 正規表現で指定
str.slice(/[0-9]+/) #=> "12"
```

## 文字列の整形
strip
両端の余分な空白文字（半角スペースと\t\r\n\f\v）を取り除く。
※全角のスペースは取り除かれない

``` ruby
" hi \t".strip #=> "hi"
" hi　".strip  #=> "hi　"
```

chop
文字種に関わらず末尾の1文字を取り除く

``` ruby
"client\n".chop  #=> "client"
```


squeeze
同じ文字列が連続した場合に１つにまとめる

``` ruby
'Greeeen'.squeeze #=>Gren
# まとめる対象を指定することも可能
'aabbaacc'.squeeze('ab') #=> "abacc"
```


## 文字列の変換
downcase
すべてを小文字に変換
upcase
すべてを大文字に変換
swapcase
大文字と小文字を変換
capitalize
先頭の文字だけ大文字

``` ruby
'BIG'.downcase #=> "big"
'small'.upcase #=> "SMALL"
'BIG small'.swapcase #=> "big SMALL"
'aaa'.capitalize #=> "Aaa"
```

## 文字列の置換
sub
最初にマッチした文字列の置換
gsub
マッチした文字列すべてを置換

``` ruby
'静岡県 埼玉県'.sub('県', 'X') #=> "静岡X 埼玉県"
'静岡県 埼玉県'.gsub('県', 'X') #=> "静岡X 埼玉X"
# ブロックを渡すことも可能
'09-123-9'.gsub(/[0-9]/) {|str| str.to_i.succ} #=> '110-234-10"
```

## 配列への変換
指定した文字をセパレータとして分割した配列を返す

``` ruby
'hoge,fuga,piyo'.split(',') #=> ["hoge", "fuga", "piyo"]
# 第２引数で指定すれば分割する最大数を指定できる
'hoge,fuga,piyo'.split(',', 2) #=> ["hoge", "fuga,piyo"]

```

## 繰り返し処理
each_char
文字ごとの繰り返し
'たのし'.each_char {|c| print "#{c}ー"}  #=> たーのーしー

each_line
行ごとの繰り返し
"われわれは\nかしこいので\nかしこいので".each_line {|line| puts line}
 #=> 
われわれは
かしこいので
かしこいので

## 文字列の判定
include?
指定文字列が含まれているか判定する

``` ruby
'super'.include?('up') #=> true
```
start_with?
先頭が指定文字列と同じか判定する

end_with?
末尾が指定文字列と同じか判定する
``` ruby
'super'.start_with?('per') # => true
'super'.end_with?('su') # => true
'super'.start_with?("str", "ing") # => true
'super'.end_with?("str", "ing") # => true
```

## 寄せる
ljust
指定した長さの文字列にselfを左寄せした文字列を返す

``` ruby
'ab'.ljust(1) #=> "ab"
'ab'.ljust(4) #=> "ab  "
# 埋める文字を指定することも可能
'ab'.ljust(4, '*') #=> "ab**"
```

rjust
指定した長さの文字列にselfを左寄せした文字列を返す

``` ruby
'ab'.rjust(1) #=> "ab"
'ab'.rjust(4) #=> "  ab"
```

center
指定した長さの文字列にselfを中央寄せした文字列を返す

``` ruby
'ab'.center(4) #=> " ab "
```

## 文字列の左右逆転
reverse
文字列を文字単位で左右逆転

``` ruby
'abcde'.reverse #=> "edcba"
```
PHP でバージョン番号の比較方法と確認方法（各種）

PHP アプリを作成した際の外部ライブラリなど、**特定のバージョン以上で実行／稼働させたい場合のバージョン比較**や **PHP のバージョン確認の方法**です。

`version_compare()` 関数は PHP のバージョンに限らず**`xx.xx.xx` 形式のバージョン情報であれば比較することが可能**です。

## 比較
### スクリプト内で [`version_compare`関数](http://php.net/manual/ja/function.version-compare.php)で比較する

```php:アプリケーションのバージョン・チェック
<?php
$ver_app_current = $someapp->version(); // 現在のバージョン (6.0.15)
$ver_app_require = '6.1.10';            // 必要最低バージョン
$ver_operator    = '<';                 // より上

if (version_compare($ver_app_current, $ver_app_require, $ver_operator)) {
    echo "APP バージョンが低すぎます。" . PHP_EOL;
    echo "現在のバージョン: " . phpversion() . PHP_EOL;
    echo "必要なバージョン: ${ver_php_require} ${ver_operator}" . PHP_EOL;

    die();
}

// #結果
// APP バージョンが低すぎます。
// 現在のバージョン: 6.0.15-RC0
// 必要なバージョン: 6.1.10 <
```

もちろん PHP のバージョン・チェックにも使えます。

```php:PHPバージョン・チェック
<?php // version_compare() PHP >= 4.1.0
$ver_php_current = phpversion(); // 現在のバージョン (7.0.22)
$ver_php_require = '7.1.10';     // 必要最低バージョン
$ver_operator    = '<';          // より上

if (version_compare($ver_php_current, $ver_php_require, $ver_operator)) {
    echo "PHP バージョンが低すぎます。" . PHP_EOL;
    echo "現在のバージョン: " . phpversion() . PHP_EOL;
    echo "必要なバージョン: ${ver_php_require} ${ver_operator}" . PHP_EOL;

    die();
}

// #結果
// PHP バージョンが低すぎます。
// 現在のバージョン: 7.0.22-0ubuntu0.16.04.1
// 必要なバージョン: 7.1.10 <
```

### 比較オペレーター（比較演算子）の種類

`version_compare($a, $b, $operator)`の場合の比較オペレーター。小文字であること。

|オペレーター|概要|
|:--:|:---|
|`<`, `lt`|`$a`は`$b`より下|
|`<=`, `le`|`$a`は`$b`以下|
|`>`, `gt`|`$a`は`$b`より上|
|`>=`, `ge`|`$a`は`$b`以上|
|`==`, `=`, `eq` | `$a`は`$b`と同じ|
|`!=`, `<>`, `ne` | `$a`は`$b`と異なる|



## 確認

### スクリプト内で [`phpversion` 関数](http://php.net/manual/ja/function.phpversion.php)から確認する

```php
<?php // >= PHP 4.x.x

echo phpversion(); // 7.0.22-0ubuntu0.16.04.1
```

### スクリプト内で [PHP_VERSION 定数](http://php.net/manual/ja/reserved.constants.php#reserved.constants.core)から確認する

```php
<?php // >= PHP 5.2.7

echo PHP_VERSION . PHP_EOL;         // 7.0.22-0ubuntu0.16.04.1
echo PHP_MAJOR_VERSION . PHP_EOL;   // 7
echo PHP_MINOR_VERSION . PHP_EOL;   // 0
echo PHP_RELEASE_VERSION . PHP_EOL; // 22
echo PHP_EXTRA_VERSION . PHP_EOL;   // -0ubuntu0.16.04.1
echo PHP_VERSION_ID . PHP_EOL;      // 70022
```

### シェル/ターミナル/コマンドラインから確認する

#### シェル/ターミナル/コマンドラインでバージョンだけ確認する

```bash
$ php -v
PHP 7.1.8 (cli) (built: Aug  7 2017 15:02:45) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
```

#### シェル/ターミナル/コマンドラインで他の情報(phpinfoの内容)も確認する

```bash
$ php -r "phpinfo();"
phpinfo()
PHP Version => 7.1.8
//略
```

### Webから確認する

下記ファイルをブラウザから開く。コマンドラインで `$ php ./index.php` でもよい。

```index.php
<?php
phpinfo();
```