OmniAICreator/Qiita-1.07M huggingface dataset:
dex2jar を buildして、新しめのandroid のclasses.dex で利用する

# Overview

新しめのclasses.dexは.dex IRが変更になっているため？(Java8対応か?)dex2jar-2.1とかでは例外を吐いて動作しない。

しかし、数ヶ月前にdex2jarに対応commitが入ったので、buildして利用します。

# dex2jarの取得

https://github.com/pxb1988/dex2jar

```
$ cd ~/work
$ git clone https://github.com/pxb1988/dex2jar.git
```

もし、proxy環境下であれば、

```~/.gradle/gradle.properties
systemProp.http.proxyHost=proxy.hoge.com
systemProp.http.proxyPort=8080
systemProp.http.proxyUser=****
systemProp.http.proxyPassword=****
systemProp.https.proxyHost=proxy.hoge.com
systemProp.https.proxyPort=8080
systemProp.https.proxyUser=****
systemProp.https.proxyPassword=****
```

# build

なお、2017/11/1現在では、

```dx:23.0.0``` でエラーが出るので、削除してください ( ```//```行を削除 or ```//``` で comment out )

```~/work/dex2jar/dex-tools/build.gradle
mainClassName="com.googlecode.dex2jar.tools.BaseCmd"

dependencies {
  compile project(':dex-translator')
  compile project(':d2j-smali')
  compile project(':d2j-jasmin')
  compile project(':dex-writer')
  compile project(':d2j-base-cmd')
//  compile "com.google.android.tools:dx:23.0.0"
}
```

```
$ cd ~/work/dex2jar
$ gradle clean distZip
```

```~/work/dex2jar/dex-tools/build/distributions/dex-tools-2.1-SNAPSHOT``` みたいなところに、build結果が出ます。
読書の進捗管理するスニペット

ゼミ当日までにテクストを読むペースを計算するPythonの関数を作った．
読書家のみなさんのお役に立てたら嬉しい．

```py3:reading_plan.py
from datetime import date
import math

def reading_plan(title, total_number_of_pages, period):
    
    current_page = int(input("Current page?: "))
    deadline = (date(*period) - date.today()).days
    remaining_pages = total_number_of_pages - current_page
    
    print(title, period, "まで", math.ceil(remaining_pages / deadline) , "p/day 残り",
          remaining_pages, "p/", deadline, "days" )
```

例えば，『現象学の理念』という本で，ノルマが118ページ，2020年2月1日までに読む必要がある場合の引数の書き方．

```py3
reading_plan("『現象学の理念』", 118, (2020,2,1))
```

Current page?と聞かれるので現在のページ数を入力する

```shell-session
Current page?: 1
『現象学の理念』 (2020, 2, 1) まで 3 p/day 残り 117 p/ 57 days
```

すると，1日のノルマと，残りページ数と残り日数が計算される．
拙い技術力でコードを書いているので，より洗練された書き方等を教えていただけたら幸いです．
では，happy reading!! :books:
Metatrader4　酒田五法を使ったＥＡ

# 手法
* 酒田五法を使ってトレード。
* 時間足は5分でスキャ用。
* 通貨はなんでもよいが、ユーロ円とする。
* 利確・損切はトレールを利用。
* ロット数はとりあえず10枚に固定。

# バックテスト結果
* 今年1月から10月末までのバックテスト結果を以下に記す。
* トレールを利用しているため、利がのってるときは長期間保有する。短期間時間足スキャのわりにはトレード回数が222回と少ないのはこのため。
* PFは1.5でまぁまぁ。
* 異なる期間のバックテスト結果も似たようものなので、一応、優位性があるＥＡができた。

<img width="1010" alt="キャプチャ.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/189952/f11d375d-f8c6-7533-6b6c-780bd81fa1fb.jpeg">
MTクラウドでは通常のバックアップをリストアできない

Movable typeには標準でバックアップとリストアの機能がありますが、実はMTクラウドでは使えません。当てにしていると結構痛いです。

まず、バックアップは普通にできます。メニューの「ツール→バックアップ」から「バックアップを作成」ボタンを押すと、多少時間がかかりますが、バックアップのアーカイブがダウンロードできます。

![](https://qiita-image-store.s3.amazonaws.com/0/42710/3028d8cf-f6bc-525d-58c2-5399fee9e45f.png)

復元はシステムの「ツール→復元」から行います。

![](https://qiita-image-store.s3.amazonaws.com/0/42710/34b19609-707c-5fc9-e29e-75c1d70394c7.png)

バックアップファイルに先ほど取得したバックアップファイルを指定して「復元」ボタンを押すと……

![403 Request Entity Too Large | nginx](https://qiita-image-store.s3.amazonaws.com/0/42710/b695e4c5-0727-c6f7-4779-6732c66a05d9.png)

アアーッ！！


アップロードするファイルのサイズが大きすぎたようです。この403応答は一見nginxが出しているように見えて詰んだ感じがしますが、実はMovable Typeが出しています。Movable TypeにはCGIMaxUpload[^1]という最大アップロードサイズを指定する環境変数があり、これによって制限されています。ちなみに初期設定値は20480000です。

MTクラウドにはMT環境変数を変更できる機能があり、システムの「クラウドサービス→MT環境変数にあります。ということで設定してみましょう。

![CGIMaxUploadを変更することはできません](https://qiita-image-store.s3.amazonaws.com/0/42710/b52b298d-0201-66b3-41e7-917aa84ad940.png)

終わった……

ということでMTクラウドではバックアップはできてもリストアができないのでした。
CGIMaxUploadを変更することができないのは、むやみに大きな値にするとDoS攻撃に弱くなるからでしょう。

# 実はMTクラウド用のバックアップ・リストア機能があります

通常のリストア機能が使えないからなのか、MTクラウドには専用のバックアップ・リストア機能が用意されています。

> [バックアップと環境のリストアについて](https://www.sixapart.jp/movabletype/support/cloud/back-up-and-restore.html)
>
> Movable Type クラウド版では1日に1度、バックアップデータを自動的に保存しています。
> 
> バックアップデータは FTPS を使用してサーバー上の「backup」ディレクトリから取得することが可能です。 世代ごとにバックアップデータを保持されたい場合は、手動でのダウンロードを行ってください。任意に選択したバックアップデータをご自身のパソコンなどのハードディスクの保管しておくことで、そのバックアップデータを Movable Type クラウド版にリストアすることが可能です。
> ※取得したバックアップデータをソフトウェア版の Movable Type にリストアすることはできません。

バックアップは自動なので、サーバ移行などを行うのであれば、その時刻に合わせて作業する必要があります。

リストアはシステムの「クラウドサービス→環境のリストア」から行うことができます。

![capture5.png](https://qiita-image-store.s3.amazonaws.com/0/42710/2d767b8f-34f7-d95b-fe01-00ee808769ba.png)

通常のバックアップの復元機能では新たにブログが作られて記事が追加されるためIDが変わってしまいますが、この復元を行うと本当に完全にバックアップされた時の状態に戻ります。なので利用開始時のバックアップを取っておけば何回でも初期状態に戻すことができます。ためしに作ってみたけど最初からやり直したいという時に役立ちます。

ちなみに*.trials.jpで取得したバックアップを*.movabletype.bizに復元したら管理画面のSSL証明書すらバックアップの状態に戻ってしまいました。まさか、バックアップに証明書と秘密鍵が含まれている?

気になるのでバックアップのアーカイブの中身を見てみましょう。

- mt-static
- plugins
- search_templates
- static
- themes
- alt-tmpl
- backup
- data
    - conf
        - SSLCERT
- error
- import

SSLCERTファイルの中身が怪しいですね。

```text:SSLCEAR
trials.jp
```

なるほど。
どこかに証明書ファイル一式があって、バックアップ内の記述を元に使い分けるという感じになっているようです。

[^1]: [CGIMaxUpload - 環境変数リファレンス | CMSプラットフォーム Movable Type ドキュメントサイト](https://www.movabletype.jp/documentation/appendices/config-directives/cgimaxupload.html)
Docker(compose)初学者が困ったときに役立つコマンド集


前回の記事

* [今から始めるDocker初心者にお届けするDockerの始め方](https://qiita.com/ryurock/items/c0515a4a9dcb3dd44d3b)
 
でDockerを触り始めたらDockerfileや、docker-compose
周りをいじくり始めますのでいざやり始めた時に

**この時どうするの？**

のコマンド集を集めてみます。
尚、初学者なので指摘等ありましたらコメントお願いします。mm

## 参考にした記事

* [Dockerで\<none>なイメージを一括で削除するワンライナー](https://qiita.com/DQNEO/items/e3a03a14beb616630032)
* [Dockerに\<none>:\<none>なイメージが生まれてくる理由](https://suin.io/540)


## イメージのビルドでキャッシュを使用したくない場合

キャッシュなしでビルドが実行されます

```
docker-compose build --no-cache
```

## コンテナを一回削除する

なんかコンテナがうまく起動しないな。と思ったら

```
docker-compose rm
```

## コンテナがうまく起動しないのでエラーの箇所を確認したい

```
docker-compose logs
```

コンテナ名を指定してもいけます

```
docker-compose logs {コンテナ名}
```


## コンテナが起動しない！！！

まず正常に稼働している状態の ``` docker-compose ps ``` の状態です

```
$docker-compose ps
      Name                     Command               State           Ports
-----------------------------------------------------------------------------------
hoge_rails   bundle exec rails s -p 300 ...   Up      0.0.0.0:3001->3001/tcp
hoge_mysql       docker-entrypoint.sh mysqld      Up      0.0.0.0:3306->3306/tcp
```

Stateが ``` Up ``` であれば起動している状態です。
逆にStateが ``` Exit {数字} ```
だとエラーが発生して起動していない状態です。

その場合のエラー箇所は

```
docker-compose logs {Name}
```

でエラー内容を確認できます。
それでもコンテナが起動しない場合は

```
docker-compose stop
docker-compose rm --force
docker-compose build
docker images | awk '/<none/{print $3}' | xargs docker rmi
docker-compose up
```

と実行してみてください。
これでコンテナは最新になるはず。(です)


## docker images 叩いたら noneがいっぱい

imageをビルドし直すと\<none>:\<none>なイメージができます。

[Dockerにnone:noneなイメージが生まれてくる理由](https://suin.io/540)




こんな状態

```
$docker images 
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
hoge_rails    latest              96817ad65925        4 minutes ago       1.01GB
<none>                 <none>              a12f704e8d62        2 hours ago         1.01GB
<none>                 <none>              58054eb2f0a2        3 hours ago         1.01GB
<none>                 <none>              e11a08ad9320        4 hours ago         1.01GB
<none>                 <none>              7a72b5b89cfb        6 hours ago         1GB
hoge_mysql    latest              ebb10baa9a30        26 hours ago        348MB
ruby                   2.4.2               47fd5dc7df6e        6 days ago          684MB
ruby                   2.3.4-alpine        f1ca99f256aa        6 weeks ago         138MB
hoge_mysql   latest              a0f5d7301767        7 months ago        329MB
mysql                  5.6.35              a0f5d7301767        7 months ago        329MB
```


そうするとDisk容量が逼迫しますので一旦クリーンしましょう

```
docker images | awk '/<none/{print $3}' | xargs docker rmi
```

## 最後に

随時更新していこうかと思っております。
findでまとめてパーミッション変更

**注意**
投稿練習のため自身のweblogに投稿した内容（[findでまとめてパーミッション変更 \- hadacchi blog](https://www.hadacchi.com/wp_blog/?p=3407)）を転載したものです．

# 課題

sambaでファイルサーバを運用している時に，別ユーザでのアクセスが問題になることがまれによくある．
なのでディレクトリは755に，ファイルは644にしたい．

# find + chmod

```sh
# まとめてchmodに渡す．数が多いとコマンドの上限文字数を越える
$ find . -type d -exec chmod 755 {} +
# 1つずつchmodに渡す．数が多いとえらい時間がかかる
$ find . -type d -exec chmod 755 {} \;
```

# find + xargs + chmod

```sh
# まとめてchmodに渡す．数が多いとコマンドの上限文字数を越える
$ find . -type d -print0 | xargs -0 chmod 755
# 20ずつまとめてchmodに渡す．上3つと比べるとマシ
$ find . -type d -print0 | xargs -0 -n 20 chmod 755
```

ちなみに，こちらの記事（[ファイルやディレクトリのパーミッションを一括で置換したい \- Qiita](https://qiita.com/takeshi81/items/48ea62eae2fc7f1cb2f0)）のようにchmodだけでやる方法があるらしく，多分これが一番速い（試してないけど）
com.apple.dt.XcodeDeviceMonitorの警告

以下の警告がたびたび出るようになり、**Always Allow**を押してもおさまらなかった。
<img width="425" alt="Screen Shot 2017-11-01 at 21.26.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/141797/b6af66f4-5d2d-e54a-2373-4febf7cf5b68.png">
日本語
<img width="425" alt="Screen Shot 2017-11-01 at 21.17.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/141797/5e9affe0-eb50-1c53-7528-b8e07c3444b4.png">
Xcodeは、キーチェーンに含まれるキー"com.apple.dt.XcodeDeviceMonitor"へアクセスしようとしています。

以下の方法で解決した。
1. **keychain**を開く
2. **com.apple.dt.XcodeDeviceMonitor**を検索してダブルクリック
3. **access control**をクリック
4. １つ目の**Allow all applications to access this item**をクリック
5. 右下の**Save Changes**をおす。

どうやら、macOS Sierraで起こる問題らしい。
この他に、「keychain内のcom.apple.dt.XcodeDeviceMonitorをドラッグして、左の『システム』に移したら直った」というパターンもあるらしいので、うまくいかなかったらそっちも試すといいかもしれない。

#### 参考
https://stackoverflow.com/questions/40144668/repeated-popup-xcode-wants-to-access-key-com-apple-dt-xcodedevicemonitor-in-y
shellでカンマの入った値をCSV変換する(Jenkins内)

#例えば下記のような文言をカンマ区切りさせずに、CSV変換するShellScript
[田中、マルクス、闘莉王]

#普通のMysqlだったら
```
"田中、マルクス、闘莉王"
```
で一発解決するが、Jenkins内でShellScriptとして書くときに、エスケープ問題で結構ハマった。。。

#結論
```
"mysql .... -e'select .... when .. then \"\"\"田中、マルクス、闘莉王\"\"\" ... '"
```

性格的にエスケープ苦手
SQLAlchemy で MySQL の upsert を試す

## 概要

Python のデファクトスタンダード O/R マッパーである SQLAlchemy。最新のバージョン 1.2 から MySQL の upsert 機能である INSERT...ON DUPLICATE KEY UPDATE構文が使えるようになった。使えるようになるまでにいろいろはまったのでメモ。

## 環境

Python 3 を想定。

執筆時点での SQLAlchemy 最新版は 1.2.0b3 であった（[全バージョンはこちら]
(https://pypi.python.org/pypi/SQLAlchemy/))。ベータ版のせいか、バージョン指定しないと入らないので、

```
$ pip install SQLAlchemy==1.2.0b3
```
としてインストール。

```
$ pip install PyMySQL
```
も合わせて入れておく。

## サンプルコード

[こちら](https://qiita.com/zakuro9715/items/7e393ef1c80da8811027)からコードのひな形をお借りする。そして、MySQL に対応させるために、[こちらの記事](https://qiita.com/nskydiving/items/88377d57040db17281fe)を参考にさせていただいた。

あらかじめ MySQL の `test_db` データベース上で

```
create table menus(id int primary key, name varchar(100), kcal int);
```

と menus テーブルを作っておく。

```
insert into menus values(1, 'apple', 100);
```
として1件だけデータをいれておく。

[公式ドキュメント](http://docs.sqlalchemy.org/en/latest/dialects/mysql.html#insert-on-duplicate-key-update-upsert)を参考に次のようなコードを実行すると、

```py3
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String
from sqlalchemy.dialects.mysql import insert

url = 'mysql+pymysql://root:@localhost/test_db?charset=utf8'
engine = create_engine(url, echo=True)
metadata = MetaData()
metadata.bind = engine

# menuテーブルの定義
menus = Table(
  'menus', metadata,
  Column('id', Integer, primary_key=True),
  Column('name', String),
  Column('kcal', Integer)
)

insert_stmt = insert(menus).values([
    {'id': 1, 'name': 'apple2', 'kcal': 200},
    {'id': 2, 'name': 'orange', 'kcal': 300}]
)
on_duplicate_key_stmt = insert_stmt.on_duplicate_key_update(
    name=insert_stmt.inserted.name,
    kcal=insert_stmt.inserted.kcal
)

conn = engine.connect()
conn.execute(on_duplicate_key_stmt)

```


結果は以下の通り。

```
mysql> select * from menus;
+----+--------+------+
| id | name   | kcal |
+----+--------+------+
|  1 | apple2 |  200 |
|  2 | orange |  300 |
+----+--------+------+
2 rows in set (0.00 sec)
```

既存の id = 1 のレコードは更新され、一方で name == 'orange' な新しいレコードが挿入された。めでたしめでたし。
JRubyからJavaを呼び出す

##経緯
- [こっち参照](https://qiita.com/_-----------_/items/a75f41b0430f57a0bad1)

##やり方
（前提）JRubyを使える・javaをコンパイルできる
1. Javaのコードを書く（ファイル名を`JavaCallTest.java`とします）
2. `JavaCallTest.java`をコンパイルして`JavaCallTest.class`を用意
3. JRuby内で`require 'java'; java_import 'JavaCallTest'`
4. 適当に呼び出す

以下、具体例。

##Javaのコード
```JavaCallTest.java
public class JavaCallTest{
    public static String str1(){
        return "str1";
    }

    public String str2() {
        return "str2";
    }
}
```

##JRubyのコード
```java_call_test.rb
require 'java'
java_import 'JavaCallTest'

p JavaCallTest.str1
begin
  jct1 = JavaCallTest.new
  jct1.str1
rescue => e
  puts e.class
  puts e.message
  puts e.backtrace
end

jct2 = JavaCallTest.new
p jct2.str2
begin
  p JavaCallTest.str2
rescue => e
  puts e.class
  puts e.message
  puts e.backtrace
end
```

##結果
```
$ jruby CallJava1.rb 
"str1"
NoMethodError
undefined method `str1' for #<Java::Default::JavaCallTest:0x553a3d88>
Did you mean?  str2
CallJava1.rb:7:in `<main>'
"str2"
NoMethodError
undefined method `str2' for Java::Default::JavaCallTest:Class
Did you mean?  str1
org/jruby/RubyBasicObject.java:1657:in `method_missing'
CallJava1.rb:17:in `<main>'
```

##コメント
呼び方が以下のように対応するらしい

- JavaのstaticソッドがRubyのクラスメソッド
- Javaの非staticソッドがRubyのインスタンスメソッド

Javaの知識が0だったので大変でした
Linux コンピュータの検診コマンド[基本編]

最近Linuxを扱うようになったので、役にたったと感じたコマンドを書いていきます。

# whoコマンド
Linuxなどのマルチユーザーシステムで、誰か作業していないか確認したい時に使える。

```bash
$ who
```


# lsofコマンド
いろいろな切り口でプロセスを確認したい時に使える。
（補足：おそらく*list open files*の略。*open*している*file*のプロセスを*list*できるコマンド。）

### ポート番号を指定

```
$ lsof -i :<ポート番号>
```
例

```
$ lsof -i :8888
```

### プロセス名を指定

```
$ lsof -c <プロセス名>
```

例

```
$ lsof -c Python
```


### ユーザー名を指定

```
$ lsof -u <ユーザー名>
```

例

```
$ lsof -u hogeuser
```



### PIDを指定

```
$ lsof -p <PID>
```
例

```
$ lsof -p 12345
```
さくらのクラウドでサーバークローンをした際に外部から接続できず困った

## 今回のお題

さくらのクラウドで構築したサーバーをクローンした時に、
外部からなかなか接続することができずに冷や汗をかいてしまいました。
いつもの事ながら備忘録としての投稿です。

今回のOSはCentOS6.9です。
結論から言うと、2つの変更で解決しました。

### eth0を書き換え
クローン元と同じアドレスだったので編集し、新たなアドレスを設定します。
`vi /etc/sysconfig/network-scripts/ifcfg-eth0`

```ifcfg-eth0
DEVICE=eth0
NETMASK=XXX.XXX.XXX.0
IPADDR=YYY.YYY.YYY.YYY
```

IPADDRを書き換えます。

### デフォルトゲートウェイを書き換え
こちらもクローン元と同じでしたので、新たに設定します。
`vi /etc/sysconfig/network`

```network
NETWORKING=yes
HOSTNAME=host_name
NETWORKING_IPV6=yes
GATEWAY=YYY.YYY.YYY.Y
```

GATEWAYを書き換えます。

### 再起動
張り切って再起動を行いましょう。
`service network restart`

### 確認
ipconfigで設定が変わっていることを確認し、外部から接続できるかも確認しましょう。
` ifconfig -a`
Summpyを使ってみたらエラーが出たので

リクルートが公開している文章要約API、Summpy( https://github.com/recruit-tech/summpy )。LexRankなどのロジックを用いて、入力した文章から重要なセンテンスを抜き出してくれるというものです。ただいま文章生成についてトライしていて試してみた次第。

利用には様々なライブラリが必要ですが、

summpyを使って文章を要約してみる（今北産業）
http://kakushika.hatenablog.com/entry/2016/01/11/231727

などを参照させていただき簡単に完了しました。

文章を入力して試してみたのですが、なぜか3センテンス以上の文章を入力すると以下のエラー。

```error: add_edge() takes exactly 3 arguments (4 given)```

色々検索した結果

```pip install networkx==1.11
pip install multiqc==1.2```

MultiQCのバグだということで、上記を試すと正常に動作しました。文章生成は奥が深いので、もう少し試してみようと思います。
新人のためのMarkdown記法まとめてみた

##はじめに
Markdown記法は調べたらいくらでも出てきますが、自分のメモとしても残したいなと思い書きました。

##見出し
書き方
\#を先頭につけます

    # title  
    ## titile
    ### title
    #### title
    ##### title
    ###### title
    
**結果**     

# title
## title
### title
#### title
##### title
###### title

別の書き方もあります。

    title
    ==
    
    title
    --  
**結果**

title  
==

title
--


## 引用表現
書き方
\>を先頭に書く

    >初めまして。こんにちは

**結果**

>初めまして。こんにちは


##区切り線
書き方は3通りあります
ハイフン3つ
アスタリスク3つ
アンダーバー3つ

    ---
    ***
    ___
    
**結果**

---
***
___



##箇条書き

書き方は3通りあります

    - item
    * item
    + item 

**結果**

- item
* item
+ item

##連番付きリスト
書き方

    1. item1
    2. item2
    3. item3

**結果**

1. item1
2. item2
3. item3

最初の番号は全て1でも連番付きリストになります。


リンクの表現方法

    [ドットインストール](http://dotinstall.com)
    
**結果**

[ドットインストール](http://dotinstall.com)

リンクにタイトル属性をつける


    [ドットインストール](http://dotinstall.com "タイトルはドットインストール")
   
**結果**
３秒ほどカーソルを上にのせて見てください。

[ドットインストール](http://dotinstall.com "タイトルはドットインストール")
   

##コードを見やすくする
書き方
バッククオートでコードをはさむ


\`\`\`
function x() {
  return x;
}
\`\`\`

**結果**

```
function x() {
  return x;
}
```

##インラインでコード表現する場合
書き方
バッククオートを表現したいコードの間に入れる。


    この場合、`return x;`はどこに置くのでしょうか

**結果**

 この場合、`return x;`はどこに置くのでしょうか

##画像を表示する方法
書き方

    ![logo image](https://cdn.pixabay.com/photo/2017/10/30/01/10/dog-2901205__340.jpg)
    
**結果**

![logo image](https://cdn.pixabay.com/photo/2017/10/30/01/10/dog-2901205__340.jpg)


##  テーブルを表示させる
書き方

```
| Left align | Right align | Center align |
|:-----------|------------:|:------------:|
| This       |        This |     This     |
| column     |      column |    column    |
| will       |        will |     will     |
| be         |          be |      be      |
| left       |       right |    center    |
| aligned    |     aligned |   aligned    |
```
**結果**

| Left align | Right align | Center align |
|:-----------|------------:|:------------:|
| This       |        This |     This     |
| column     |      column |    column    |
| will       |        will |     will     |
| be         |          be |      be      |
| left       |       right |    center    |
| aligned    |     aligned |   aligned    |


##参考文献
ドットインストール
https://dotinstall.com/lessons/basic_markdown_v2
Xcode 8のプロジェクトをXcode 9に移行するときのメモ

今更ですがXcode 9に移行するときの作業メモ。

Xcode 9はこれまでのバージョンアップと比較して、比較的素直にコンパイルまで終わらせられそうです。
ただ、どういう理由で変更が必要かわからんのでざっくりと調べてみました。

## `@objc`ディレクティブの追加
Swift 4では、これまで暗黙的に付与されていた `@objc` ディレクティブを明示的に書くように変更されました。

```swift
// Swift 3
func closeDial() {
  // do something
}

// Swift 4
@objc
func closeDial() {
  // do something
}

```

この変更は、Xcode9でプロジェクト設定を自動更新する際に（ある程度）自動変換させることができます。
変換時に、"Minimize Interface"と"Match Swift 3 Behavior"のどちらかを選択できます。前者の"Minimize Interface"を選択した場合、自分で必要な箇所に `@objc` を追加する必要があります。後者の"Match Swift 3 Behavior"を選択すると、Swift 3で暗黙的に付与されていた時と同様に `@objc` を付与します。

後者を選択するとバイナリサイズが大きくなるので、基本的には前者を選択するのが良いでしょう。

## タプル型引数の呼び出し方が変わった
Swift 4では[SE-0110](https://github.com/apple/swift-evolution/blob/master/proposals/0110-distingish-single-tuple-arg.md)の変更に伴い、引数と戻り値の型の宣言をする際に `(Void) -> Void` と書く場合は `() -> Void` と宣言するよう変わりました。

この影響で、以下のように変更を加える必要が出ています。

```swift
// Swift 3
DispatchQueue.main.async { [weak self] _ in
  // Void型の引数なので、"_"をつけていてもコンパイルエラーにはならない
  // do something
}  

// Swift 4
DispatchQueue.main.async { [weak self] in
  // Void型の引数なので、"_"は必要ない
  // do something
}
```

## `NSAttributedStringKey` への変換 (Xcode9が自動変換)
`NSAttributedString`の仕様が変わりました。
これまでは `NSFontAttributeName` や `NSParagraphStyleAttributeName` のように定数が設定されていましたが、`NSAttributedStringKey.font` や `NSAttributedStringKey.paragraphStyle` のように、enumに変更されています。

この箇所はXcode 9が自動変換してくれる項目ですが、`NSAttributedStringKey.font.rawValue`のように変換してしまうので正直恰好悪い。
`NSAttributeStringKey`の型を使って書くほうがシンプルに書けます。

```Swift
//Swift 3
let textAttributes: [String : AnyObject] = [
    NSFontAttributeName: someAtttributeName,
    NSParagraphStyleAttributeName: paragraphStyle
]

//Swift 4 自動変換だとこうなる
let textAttributes: [String : AnyObject] = [
    NSAttributedStringKey.font.rawValue: someAtttributeName,
    NSAttributedStringKey.paragraphStyle.rawValue: paragraphStyle
]

//Swift 4 こう書くほうがベター
let textAttributes: [NSAttributedStringKey : AnyObject] = [
    .font: someAttributeName,
    .paragraphStyle: paragraphStyle
]
```
Rich Menu APIをブラウザから使えるWebサービス


<img width="800px" alt="util.png" src="https://qiita-image-store.s3.amazonaws.com/0/164153/77520def-b65f-8d6f-7b3a-84f0c8a054a4.png">

# 前置き
先日、LINE Messaging APIのRich　Menu APIの使い方をご紹介しました。

[LINE BotのRich Menu APIの使い方まとめ](https://qiita.com/stachibana/items/5dcb5ed3c6b3015601a7)

# 本題
作成したり削除したり紐付けたりはcurlで出来るので分かりやすいのですが、やや面倒だったので、ブラウザで直感的に作成できるWebサービスを作成してみました。

[Rich Menu API Util](http://richmenuapi-util.herokuapp.com/)

<img width="500px" alt="util.png" src="https://qiita-image-store.s3.amazonaws.com/0/164153/4cd6c9aa-420a-24b5-e12f-378618228ccd.png">

開くとこんな感じ。

<img width="500px" alt="util.png" src="https://qiita-image-store.s3.amazonaws.com/0/164153/c88fff2b-fbc0-e6bb-25c7-9594aee97b24.png">

結構複雑な設定が可能なのもRich Menu APIのウリの一つだと思うのですが、ドローソフトとか入ってないと座標調べるだけで嫌になります。というわけでドラッグでエリアの定義が可能にしてあります。

ドラッグするとエリアが作られてActionのタイプや値を入力できるフィールドが有効に。全部入力してexecuteすればAPI叩いてリッチメニューが作られ、IDが返却。あら簡単。これがメイン機能。

あとは普通に削除したり、紐付けしたり、リスト一覧を表示したり。

<img width="500px" alt="スクリーンショット 2017-11-01 19.22.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/164153/eb95299e-789c-dd23-b990-90f4d9dce999.png">

あとはリクエストとレスポンスが表示されるのもちょっと便利ですかね。一覧だして違うAPI叩いて比較とかも出来ます。

# 使ってみた

![beef_ss.png](https://qiita-image-store.s3.amazonaws.com/0/164153/04baa9c2-ef8d-93ee-f1f1-c731c0dba05a.png)

見るだけで作成したくなくなるようなこんな面倒くさいデザインのリッチメニューもサクサク作れました！

# まとめ

Rich Menu API使うと最高にいいUIになりそうなボットがたくさんあるので、是非検討してみて下さい。
[Watson] Retrieve and Rankのサービス終了について

- 2017年11月3日以降、Retrieve and Rankの新しいインスタンスは作成することが出来ません。
- 既存のインスタンスは2018年10月3日までサポートされます。
- 後継のサービスは[Discoveryサービス](https://console.bluemix.net/docs/services/discovery/index.html)となり、Retrieve and Rankからの移行も可能です。

公式情報は[こちら](https://console.bluemix.net/docs/services/retrieve-and-rank/index.html#overview)
欲しいものが無いからつくってみました。誰でも使えるオープンソースなネットワークアイコン集

# 概要

システム構成図などを作成しようとすると、ユーザーやサーバーの図形を使うことになりますが、ライセンスを気にせずに、タダで使えて、見た目がそれなりによくて、統一感があるものは、なかなか見つからないですよね。無いならつくるしかない、ということでつくってみました。

![sample.png](https://github.com/k-tamura/cocha-icons/raw/master/sample.png)

<!--
![sample.png](https://qiita-image-store.s3.amazonaws.com/0/43869/43c47758-33f8-fbe4-dd95-ef5909fdc17c.png)

![sample1.png](https://qiita-image-store.s3.amazonaws.com/0/43869/7aa07795-ef0e-1c2a-cda0-050dd6a146ac.png)
-->

この図をつくっているパーツを含むPowerPointも[GitHub](https://github.com/k-tamura/cocha-icons)に公開したので、ある意味オープンソースです。グループ化を解除すれば、各パーツに分解できます。

![div.png](https://qiita-image-store.s3.amazonaws.com/0/43869/1d671582-8ac8-9140-d295-20a153111217.png)

昨日から作り始めたので、まだ納得のいくものになっていませんが、これからクオリティを上げていきます。

ちなみにWindows 10のPowerPoint2013でつくっているので、LibreOfficeなどでは正常に表示されません。最初からMacかUbuntuで作図した方がもう少しマシなデザインになったと思いますが、職場はWindowsという人が多いと思うので、PowerPointにしました。

まだまだアイコンの数も少ないですが、今後どんどん追加していきます。リクエストがあれば、issueを登録して下さい。

![xx.png](https://qiita-image-store.s3.amazonaws.com/0/43869/2749b2a4-3634-8a61-dada-5cc143c023b2.png)

など、このページにコメントしていただいても構いません。

# 使い方

アイコンをグリッドの交点に配置して、矢印などで動線を付ければ、分かりやすい図になると思います。アイコンを追加したい場合などは、pptファイルを開いて直接編集して下さい。

[アイコンのトリセツ](https://qiita.com/tamura__246/items/4c7becfd0b4653c0af3e)もご一読下さい。

# ライセンス <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="クリエイティブ・コモンズ・ライセンス" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a>

このアイコン集は<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">クリエイティブ・コモンズ 表示 - 継承 4.0 国際 ライセンス</a>の下に提供されています(一応)。クリエイティブ・コモンズ・ライセンスを守る範囲であれば、自由に使うことができます。商用利用も可能です。クリエイティブ・コモンズ・ライセンスについては、[こちらのページ](https://creativecommons.jp/licenses/)を参照下さい。

気に入っていただけたら、GitHubへのスターもお願いします。

<!--
![enjoy.png](https://qiita-image-store.s3.amazonaws.com/0/43869/593730cf-35b8-f34e-6057-459e92b8a4e4.png)
-->
プログラミング初心者がkotlinでチャットアプリを作りたい話【０日目】


せっかくプログラミングを勉強するならば何か0からアプリケーションを作りたい！

どうせ作るなら趣味に関連したプログラムかWEBサービスを作りたいなと考えたプログラム初心者が言語の勉強をしつつ、モチベーション維持のために自分でQiitaで進捗と感想を書いていこうと言う連載です。
##自己紹介
月歌友梨という名前でTRPG、人狼などのゲームをやっているゲーマー
<dl>
<dt>やったことあるTRPG</dt>
<dd>ソード・ワールド2.0 (3年くらい、今年の夏以外全部夏サプリは持っている）</dd>
<dd>クトゥルフ神話TRPG（5〜10回ほどオンラインセッションをGM経験はなし）</dd>
<dd>ナイトウィザード、パラノイア、ダブルクロスetc...<dd>
<dt>やったことあるゲーム</dt>
<dd>minecraft(工業化Modとか詰んだりしてやってた、最近はバニラ（マルチ）も楽しいなと思い始めてるただし酔う）</dd>
<dd>Civ5 （みんな大好きciv5。そろそろ６もほしい、快適なプレイ環境もほしい）</dd>
<dd>カタンの開拓者たち(なかなか人が集まらない）</dd>
</dl>
<dl>
<dt><em>プログラミング歴</em></dt>
<dd>Ruby　3ヶ月（体系的に勉強を初めたのは先月）　</dd>
<dd>HTML、CSS、JS　そこそこかける。</dd>
<dd>Vagrantはそれなりに使ったことある。</dd>
</dl>

***
#作りたいアプリケーション

TRPGが趣味なので、チャットアプリが良いかなと思っている。特にサイコロ触れるチャットアプリって少ない気がする（特にPC,スマホ両方対応だと）
機能として
- チャット機能（自動で更新されるやつ）
- 2d6などの特定のコマンドを入力すると値が返る
- HP、MPなどのステータスを管理するタブ（ウィンドウ）
- PC、スマホ両方に対応【重要】

できたらキャラクターシートに反映できるような総合ツールみたいなのがあったら楽しそうだけど夢物語になりそう。。。
なので、上記の機能を最低限載せたアプリケーションを作る。

#開発期間と使用言語
開発には、「kotlin」を使おうかなと考えている。
スマホに対応するのでスマホ対応にしやすい言語かつ、響きが可愛いのでこの言語を勉強してみようかなとおもった。

データベースや、どこのVISなりAWS？に作るかは、ローカルである程度開発が終わってからにしようと考えようかなと思う。

期間としては2018年３月まで、使える時間は土日のどちらか２時間は使えるようにすることを目標に、週一回は更新、できたら毎日更新できるように頑張るぞい。

##セットアップ(次回までのタスクまとめ）
ローカル開発環境
Macbook airでVagrantを使ってboxはbento/centos-7.1を使用。ここは使い慣れているものを。
SDKMAN！を利用してkotlinはインストールしようかなと考えているところ。
log4cxx.properties の設定方法

log4cxx のコンセプト

## Logger (ログ実行)

* Logger とは? ログ記録に使うオブジェクト。com.foo や com.foo.Bar のような階層的な名前を持つ。
    * お薦めはログ対象のクラスと同じ名前をつける。
* 最上階の Logger を Root Logger と呼ぶ。
* 各 Logger は DEBUG, INFO 等の level を持てる。level を指定していない Logger の level は親 Logger と同じになる。
* Root Logger は必ず level を持つ。
* ログ要求は LOG4CXX_DEBUG(Logger, ...)  のようなマクロを使う。
    * ログ要求に指定された level が Logger の level 以上の時だけログが実行される。
    * つまり、Logger に記録する level を指定する。

## Appender (ログ出力)

* Appender とは? ログを出力するオブジェクト
* addAppender で Appender に Logger を追加する。
* additivity flag == true の時、子の Logger が送ったログは親の Logger の Appender にも送られる。
* additivity flag == false の時、子の Logger が送ったログは親の Logger の Appender に送られない。

## 設定

* logger4cxx::PropertyConfigurator::configure(設定ファイル名) を使うとファイルでログの設定が出来る。
* BasicConfigurator も PropertyConfigurator も無い場合
    * 環境変数 LOG4CXX_CONFIGURATION があればそのファイル名を設定ファイルとみなす。
    * なければ "log4cxx.xml", "log4cxx.properties", "log4j.xml" and "log4j.properties" を検索して設定ファイルとみなす。
    * なければログをしない。


ConversionPattern で出力フォーマットを指定出来る。

* `%-5p`: level を 5 文字左寄せ
* `%d{dd MMM yyyy HH:mm:ss,SSS}`: タイムスタンプ
* `%t`: スレッド名
* `%c`: Logger の名前
* `%F`: ファイル名
* `%L`: 行番号
* `%M`: メソッド
* `%m`: メッセージ
* `%n`: 改行 

設定例1

    log4j.appender.SmartDeviceLinkCoreLogFile.layout.ConversionPattern=%-5p [%d{dd MMM yyyy HH:mm:ss,SSS}][%t][%c] %F:%L %M: %m%n

出力例2

    TRACE [31 Oct 2017 18:54:29,905][0x7fe1fd6dc740][Utils] /home/tyamamiya/src/sdl_core/src/components/utils/src/threads/posix_thread.cc:160 Thread::start: Enter

設定例1

    log4j.appender.SmartDeviceLinkCoreLogFile.layout.ConversionPattern=%-5p [%d{HH:mm:ss}] %.32F:%L %m%n

出力例2

    TRACE [12:59:03] tion_manager/src/request_info.cc:178 Enter

Appender ごとにレベルを変えたい場合は Threshold を使う。

    log4j.appender.SmartDeviceLinkCoreLogFile.Threshold=DEBUG

参考: 
* [How to use log4cxx?](https://logging.apache.org/log4cxx/latest_stable/usage.html)
* [Short introduction to Apache log4cxx」への補足](http://hhsprings.pinoko.jp/personal_works/various_docs/log4cxxbasics/supplementary.html)
* [基本のAppdender](http://www.nurs.or.jp/~sug/soft/log4j/log4j4.htm)
《JavaScript》 jQueryなしで、ある要素集合に対しての要素のインデックスを調べる方法。


ある要素が所属する要素集合に対しての、インデックスを調べるスクリプトです。

html はこんな感じだと仮定します。

```html

<button class="js-btn">button</button>
<button class="js-btn">button</button>
<button class="js-btn">button</button>

```

## jQuery あるとき 🎊

クリックした要素のインデックスをアラートで表示します。

```js

let $buttons = $('.js-btn');

$buttons.on('click', (e) => {

  e.preventDefault();
  let index = $buttons.index(e.currentTarget);

  alert(index);

});

```

このように、 jQuery だと簡潔に書くことができていい感じですね。



## jQuery ないとき 🔨

```js

let buttons =  document.getElementsByClassName('js-btn');

[].forEach.call(buttons, (el) => {

  el.addEventListener('click', (e) => {

    e.preventDefault();
    let index = Array.prototype.indexOf.call(buttons, e.currentTarget);

    alert(index);

  });

});

```

長くなりましたね。


### 少し解説

集めたボタンを配列に格納して、操作します。
普通は `for` 文で書くようなところですが、 `forEach` を使った方が好みなので、こうしました。
パフォーマンスでいうと `for` 文の方がいいと思います。

```js

[].forEach.call(buttons, (el) => { ... })

```

`Array.prototype.indexOf` でインデックスを調べます。

```js

Array.prototype.indexOf.call(buttons, e.currentTarget);

```

少しずつ [You Dont Need jQuery](https://github.com/oneuijs/You-Dont-Need-jQuery) に近づいていきたいですが、同時にES6で綺麗にコードをまとめていくことを念頭にしたいです。

おわります。
EcmaScriptの個人的に気になる新機能提案

[tc39のリポジトリ](https://github.com/tc39)を中心に気になる提案をまとめます。

# do expressions(stage-1)
## リポジトリ
https://github.com/tc39/proposal-do-expressions

## 概要
関数型言語のようにifやtry、switchなどを式のように扱えるようにする為にdo式を追加しようという提案です。

## 例
```js
let b = true;
let x = do {
  if (b) {
    'hoge';
  } else {
    'foo';
  }
};
assert(x === 'hoge');
```

## その他
「doいらなくね？普通にifなどを式として扱おうぜ」みたいなissueがあがっています。
https://github.com/tc39/proposal-do-expressions/issues/9
何故これではダメなのかはよく分かりません。後方互換性的な問題があるのでしょうか？

# optional chaining(stage-1)
## リポジトリ
https://github.com/tc39/proposal-optional-chaining

## 概要
kotlinやangularのテンプレートなどで使える`?.`構文の提案です。

## 例
```js
let obj = null;
let a = obj?.x;
assert(a === null);
```

```js
let f = null;
let a = f?.();
assert(a === null);
```

# pipeline operator
## リポジトリ
https://github.com/tc39/proposal-pipeline-operator

## 概要
Elmなどにあるパイプライン演算子です。
これが追加されればプロトタイプ汚染をすることなく拡張メソッドのような事を出来ます。

## 例
```js
function f(str) {
  return str + str;
}
const x = 'x' |> f;
assert(x === 'xx');
```

awaitにも使えます。
async/await使ったことある方なら分かると思うんですが、あれ前置演算子なので括弧だらけになるんですよね。
それが改善されそうなので嬉しいです。

```js
const google = 'https://google.com' |> http.get |> await;
```

# bind operator
## リポジトリ
https://github.com/tc39/proposal-bind-operator

## 拡張メソッド的な使い方
### 概要
pipeline operatorみたいに拡張メソッドのような事のような事をできる機能です。
こっちの方がOOPっぽいですね。あっちはFPっぽいので。
pipeline operatorが追加されるならなくてもいいかなって感じです。await機能もないし…

### 例
上のpipeline operatorの例をbind operatorで書きなおした版。

```js
function f() {
  return this + this;
}
const x = 'x'::f();
assert(x === 'xx');
```

## メソッドにthisをバインド
### 概要
突然ですが、以下のJSを実行したらどうなるか分かりますか？

```js
class Hoge {
  constructor(name) {
    this.name = name;
  }

  log() {
    console.log(`name is ${this.name}`);
  }
}

const hoge = new Hoge();
const log = hoge.log;
log();
```

普段JSを書いている方なら分かると思います。
`Uncaught TypeError: Cannot read property 'name' of undefined`
とエラーが出ますよね？
これReactなどで凄く不便ですよね。それを解決するのがbind operatorです。

### 例
```js
//クラス定義省略
const hoge = new Hoge();
const log = ::hoge.log;
log();
```

### bindじゃ駄目なの？
これでも勿論動きます。

```js
//クラス定義省略
const hoge = new Hoge();
const log = hoge.log.bind(hoge);
log();
```

でもhogeって二回書くの面倒じゃないですか？
しかも、もし`a.b.c.d.e`の`f`を呼びだそうと思ったら

```js
const f = a.b.c.d.e.f.bind(a.b.c.d.e);
f();
```

と大変な事になってしまいます。
でもbind operatorなら

```js
const f = ::a.b.c.d.e.f;
f();
```

と書くだけです。楽ですよね？
# その他
* [パターンマッチ](https://github.com/tc39/proposal-pattern-matching)
* [JSのバイナリフォーマット](https://github.com/syg/ecmascript-binary-ast)
* [ジェネレーター関数でもasync使いたい](https://github.com/tc39/proposal-async-iteration)
* [TypeScriptのようなクラスフィールド](https://github.com/tc39/proposal-class-fields)
* [flatMap](https://github.com/tc39/proposal-flatMap)
* [正規表現でユニコード文字プロパティ(`[\p{Han}]`みたいな事が出来るようになる)](https://github.com/tc39/proposal-regexp-unicode-property-escapes)
* [throw式](https://github.com/tc39/proposal-throw-expressions)
[Unity]uGUIのDropdownでリストの描画順がおかしい時の対処法

##SortingLayer設定してるとこうなる
![dropdown.gif](https://qiita-image-store.s3.amazonaws.com/0/59989/5f326d49-3828-05e5-a445-49c50b4f28af.gif)


原因はDropdown自体は前面のレイヤーでも展開した時のリストはDefaultに表示されるから（なんでや！）

## 対応方法
ゴリ押し

``` DropdownSortingLayer.cs
using UnityEngine;

public class DropdownSortingLayer : MonoBehaviour
{
	public string SortingLayerName = "Front";
	void Awake()
	{
		Canvas canvas = GetComponent<Canvas>();
		if (canvas != null)
			canvas.sortingLayerName = SortingLayerName;
	}
}
```

## 結果
![dropdown2.gif](https://qiita-image-store.s3.amazonaws.com/0/59989/d31c980f-b37a-60d3-7639-2780c872a37f.gif)


## 参考
https://forum.unity.com/threads/dropdown-list-appears-behind-everything.356750/
C++ Builder XE4, 10.2 Tokyo > TPageControl > TButtonでのページの追加、削除

```txt:動作環境
C++ Builder XE4
RAD Studio 10.2 Tokyo Update 2 (追記: 2018/01/05)
```

TPageControlのページを動的に変更してみる。

参考: https://stackoverflow.com/questions/21970127/delete-tabs-from-a-page-control-at-run-time

```Unit1.h
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ComCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TPageControl *PageControl1;
	TButton *B_add;
	TButton *B_delete;
	void __fastcall B_addClick(TObject *Sender);
	void __fastcall B_deleteClick(TObject *Sender);
private:	// ユーザー宣言
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
```

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_addClick(TObject *Sender)
{
	int count = PageControl1->PageCount;

	TTabSheet *pPage = new TTabSheet(PageControl1);
	pPage->PageControl = PageControl1;
	pPage->Caption = L"Page" + IntToStr(count);
	pPage->Name = L"ts" + IntToStr(count);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_deleteClick(TObject *Sender)
{
	int count = PageControl1->PageCount;

	if (count == 0) {
        return;
	}

	delete PageControl1->Pages[count - 1];
}
//---------------------------------------------------------------------------
```

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/6932bcd4-3c90-fb84-a041-a6b3c35ac53e.png)
PHP if($var),empty($var),isset($var),is_null($var)

初学者（自分）がよくハマるアレ。

## まずは早見表で確認！
[PHP 型の比較表](http://php.net/manual/ja/types.comparisons.php)
[PHP isset, empty, is_null の違い早見表](https://qiita.com/shinichi-takii/items/00aed26f96cf6bb3fe62)

## 動作の整理
上記を整理すると、

1. `if($var)` と `!empty($var)`
1. `isset($var)` と `!is_null($var)`

が~~等価となっていることがわかりました。~~
【追記↓】
isset()とempty()は**未定義の変数**でエラーを吐かないので、正確には対にはなっていません。
※コメント参照
⇒[isset, empty, is_null の動作まとめ](https://qiita.com/mpyw/items/51bf42fe1ad8a7e535aa)
【↑ここまで】

そして、`if($var)` と `isset($var)` で違いが出るのが、

| $var |  | isset($var) | if($var) |
|:---:|:---:|:---:|:---:|
| "" | 空文字 | TRUE | FALSE |
| array() | 空の配列 | TRUE | FALSE |
| false | 真偽値の偽 | TRUE | FALSE |
| 0 | 数値のゼロ | TRUE | FALSE |
| "0" | 文字列のゼロ | TRUE | FALSE |

でした。

## 緩やかな比較で0は・・・
上述したPHPマニュアルの比較表を見ていると、
`==`による緩やかな比較は腑に落ちない動きをしますね。
　**if(0=="") ⇒ TRUE**
　**if("0"=="") ⇒ FALSE**
これはまだしも、
　**if(0=="hoge") ⇒ TRUE**
とは・・・？？

特に理由がないならば`===`を使うべき、と・・・。
ただ、[`switch`は緩やかな比較と聞いたことが・・・](http://php.net/manual/ja/control-structures.switch.php)。

## 0を判定するなら
0 または "0" については、[`is_numeric($val)`](http://php.net/manual/ja/function.is-numeric.php)なんですかね。

| $val | is_numeric($val) |
|:---:|:---:|
| 0 | TRUE |
| "0" | TRUE |
| "" | FALSE |
VMware vSAN環境のストレージ拡張

ハイパーコンバージドインフラ（HCI）の分野は個々最近盛り上がりを見せています。先行して導入した環境ではそろそろ容量を拡張したくなってきている頃かと思います。例に漏れず私が昨年構築した環境でもストレージ容量の拡張が必要になってきました。
本記事ではvSANストレージの拡張手順を記します。

はじめに言っておきます、**簡単です！！**

#前提
物理サーバー：Lenovo System x3650M5（本環境ではディスクは１本ずつRAID0で構成しています）
VMware：vSphere 6.0

#作業の流れ
すべてオンラインで作業可能です。

1. 物理サーバーにディスク追加
2. 物理サーバーのマネージメントモジュールからRAID0を構成
3. vCeter ServerからvSAN構成のディスク追加

以上。はい、簡単です！
やはりHCIだと管理が簡単ですね。

#実作業
もう少し詳細に手順を記載します。

1. 物理サーバーにディスク追加
    1.1. 物理サーバーのディスク用空きスロットに追加するディスクを差し込みます

2. 物理サーバーのマネージメントモジュールからRAID0構成
    2.1. IMM2にログインし、RAID Managerの画面に進みます
    2.2. ディスクはJBOD構成となっているため、対象ディスクを選択し、「Convert JBOD to Unconfigured Good」をクリックし、Unconfigured goodの状態に設定変更します
![raid1.png](https://qiita-image-store.s3.amazonaws.com/0/142407/a7c33c5f-0bf0-2938-615c-04c50a47a5f1.png)
 
    2.3. RAID0を構成します

3. vCenterのvSAN構成からディスク追加
    3.1. vSphere Web ClientでvCenterに接続し、vSANの構成画面を開きます
    3.2. 追加対象のディスクグループを選択し、追加ボタンをクリックします
![vsan1.png](https://qiita-image-store.s3.amazonaws.com/0/142407/e5ad2993-1abc-317b-215f-d98d6f9dd258.png)

    3.3. 対象ディスクを選択し、追加します
![vsan2.png](https://qiita-image-store.s3.amazonaws.com/0/142407/27c89dbd-7e88-ec4e-6952-0f34344cd860.png)

    以上でvSANデータストアが拡張されました。

#その他
vSAN環境は使用するディスクや構成に制約があるため、構成検討には注意が必要です。

#参考
[VMware Virtual SAN (VSAN) 構築ガイド ～ 32GB Enterprise Value USBメモリー・キー版](http://www.lenovojp-cms.com/cmscontents/gdfiles.php?md=82)
[ServeRAID Mシリーズ 導入・構成ガイド(ServeRAID M5210 編)](http://www.lenovojp-cms.com/cmscontents/gdfiles.php?md=85)
[VMware Docs: キャパシティ デバイスの追加](https://docs.vmware.com/jp/VMware-vSphere/6.5/com.vmware.vsphere.virtualsan.doc/GUID-F1A01098-B538-49F7-9DEF-45DF429DD8C2.html)
ubuntuでgcpを使えるようになるまでの最短ルート(python)

#はじめに
[Debian / Ubuntu 用のクイックスタート](https://cloud.google.com/sdk/docs/quickstart-debian-ubuntu)
に添って説明していく。(2017/10/30のバージョン)
この記事を書いている段階ではpython3系に対してないっぽいので、python2.7.13でやっています。
#gcpのアカウントを作成
スクショを撮り忘れてしまったので略

#Google Cloud SDK のインストール
bashrcに以下のものを追加

```sh
export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)"
```

以下の３つのコマンドを実行

```sh
echo "deb https://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt-get update && sudo apt-get install google-cloud-sdk
```

このとき```Problem executing scripts APT...```みたいなエラーを吐かれたら[ここ](https://forums.ubuntulinux.jp/viewtopic.php?id=19399)にかかれているコマンドを実行。

#初期設定
上のページのSDKの初期化に添って行う
Compute Engineは「asia-northeast1-a」を選択すれば良い。ちなみに「asia-northeast1-*」は東京にあるサーバー

これで、gcpの認証については終了。次はpythonのmoduleのインストールに移る。

#pythonの環境設定（speech apiとnatural language apiについてのみ）
##はじめに
上記のsdkは２系のpythonでしか動かないが、プログラムは３系でも動く。謎。
##speech api
サンプルコードはここ
https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/speech/cloud-client
###環境構築
```sh
git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
```
でgitをclone。 その後、上記のURLに当たるディレクトリ部分まで移動し、以下のコマンドを実行

```sh
pip install -r requirements.txt
```
###動作確認

```sh
python transcribe.py resources/audio.raw
```
蛇足だが、個人的には下のソースコードの方がわかりやすいので、自分でプログラムを組むときはこっちを参考に作った方がよさげ
https://cloud.google.com/speech/docs/reference/libraries?hl=ja#client-libraries-install-python

##natural language api
サンプルコードはここ
https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/language/cloud-client/v1

###環境構築
speech apiと同様に、該当のディレクトリに移動して以下のコマンドを実行

```sh
pip install -r requirements.txt
```
###動作確認
```sh
python quickstart.py
```
speech apiと同様に下記のコードの方がオススメ
https://cloud.google.com/natural-language/docs/reference/libraries?hl=ja
ajaxでファイルアップロードをしたいけど、任意のタイミングでアップロードしてほしい。

**はてブから転記**

ファイル選択した後、すぐにはアップロードを走らせたくない。ワンクッション挟みたい。そんな時の方法。
実はこのソース。今見るとよくわからないことが多い。

・したいこと
　　ボタンが押されたらファイルアップロードを走らせたい。
・解決策
　　addの中に、ボタンが押されたらsubmitするよって書く

```fileupload.js
$('#csvupload').fileupload({

  dataType: 'json',
  url: $.hoge.webroot + 'user_account/csv/import',
  // addを実行してからajaxが走る
  add: function(e,data) {
    data.context = $('.button_edit').click(function(){
      data.submit();
    });
　 },

  done: function (e, data) {
    if(data.result.length > 0) {
      var result = true;
      var done_msg = ''; 
      var fail_msg = '';
      for(var fi = 0; fi < data.result.length; fi++) {
        result = result && data.result[fi]['success'];
        if(data.result[fi]['success'] == true) {
          done_msg += "\n" + data.result[fi]['message'];
        } else {
          fail_msg += "\n" + data.result[fi]['message'];
        }
      }
      if(result) {
        alert("アップロード完了" + done_msg);
        location.href = $.seap.webroot + 'user_account/';
      } else {
        alert("一括登録に失敗しました。" + fail_msg.replace('\\n','\n'));
        $('.filename').text('');
      }
      $('.csv_drop_field .label').html('');
    }
  },

  fail: function (e, data) {
    alert("アップロードに失敗しました");
    $('.csv_drop_field .label').html('');
  },

  progressall: function (e, data) {
    var progress = parseInt(data.loaded / data.total * 100, 10);
    var progresshtml = "アップロード中 : " + progress + "%";
    $('.csv_drop_field .label').html(progresshtml);
  },
});
```
よくこんなに書いてたなぁ……しみじみ。
Javaで文字コードを正してURLから読み込む

##経緯
- JRubyの#openがWindows10環境だとエラーを吐く
- Java側で実装してみよう
- jisautodetect使うとutf-8の場合ダメだ
- 下のコードに至る

※特定のURLだけなので普通はこんな必要ないと思います

##入出力
- 引数
    - url(変数名 : link)
    - タイムアウトする時間(変数名 : time_limit)
- 戻り値
    - 成功時 : 正しい(?)ファイル文字列
    - 失敗時 : 空文字列

##コード
```JavaOpen.java
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class JavaOpen{
    public static String open(String link, int time_limit){
        String html = "";
        try {
            URL url = new URL(link);
            URLConnection con = url.openConnection();
            con.setConnectTimeout(time_limit*300);
            con.setReadTimeout(time_limit*700);
            try (InputStream is = con.getInputStream();){
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] byteChunk = new byte[8192];
                int n;

                while ( (n = is.read(byteChunk)) > 0 ) {
                    baos.write(byteChunk, 0, n);
                }
                byte[] bytes = baos.toByteArray();
                html = bytesToHtml(bytes);
            } catch (IOException e) {
                e.printStackTrace ();
            }
        } finally {
            return html;
        }
    }

    public static String bytesToHtml(byte[] src) throws UnsupportedEncodingException {
        String[] char_codes = { "UTF8","SJIS","EUC_JP","EUC_JP_LINUX","EUC_JP_Solaris" };
        for (String cc: char_codes){
            String s_tmp = new String(src, cc);
            byte[] b_tmp = s_tmp.getBytes(cc);
            if (Arrays.equals(src, b_tmp)) {
                return s_tmp;
            }
        }
        return "";
    }
}

```

##コメント
- `String[] char_codes = { "UTF8","SJIS","EUC_JP","EUC_JP_LINUX","EUC_JP_Solaris" };`　は自分のアクセスしうる可能性がある文字コードなのでご自由にどうぞ
- 変数名time_limitの代案が思いつきたかったです...
- `setConnectTimeout` : `setReadTimeout`=3 : 7で配分したけど、、普通はどうなんでしょうか？
- 8192byteずつではなく一度に読み込む方法を知りたかったけど、動けばいいやの意思に負けた

##参考
- [try-with-resources 文 - ORACLE](https://docs.oracle.com/javase/jp/7/technotes/guides/language/try-with-resources.html)
- [Javaで文字コード簡易判定 - Qiita](https://qiita.com/SAM_tak/items/c64108d472da257dd93a)
- [サポートされているエンコーディング - ORACLE](https://docs.oracle.com/javase/jp/7/technotes/guides/intl/encoding.doc.html)
UbuntuでlibEGL.so.1がシンボリックリンクでないと言われる時の対処法

#はじめに
Ubuntuを使っていてnvidiaドライバがアップデートされる度にsudo ldconfigが通らなくなる．
調べればすぐ出てくるのだが，どれだったか忘れるので覚書

#環境
Ubuntu 16.04
nvidia driver version:384.90

nvidiaドライバのバージョンは
```$ apt list nvidia-*[0-9]```
として，インストール済のバージョンを見ればわかる

#手順
基本的にはUbuntuのフォーラムにある[libEGL.so.1 is not a symbolic link](https://askubuntu.com/questions/900285/libegl-so-1-is-not-a-symbolic-link)のトップのアンサーで解決する

```
$ sudo mv /usr/lib/nvidia-xxx/libEGL.so.1 /usr/lib/nvidia-xxx/libEGL.so.1.org
$ sudo mv /usr/lib32/nvidia-xxx/libEGL.so.1 /usr/lib32/nvidia-xxx/libEGL.so.1.org
$ sudo ln -s /usr/lib/nvidia-xxx/libEGL.so.xxx.xx /usr/lib/nvidia-xxx/libEGL.so.1
$ sudo ln -s /usr/lib32/nvidia-xxx/libEGL.so.xxx.xx /usr/lib32/nvidia-xxx/libEGL.so.1
```
nvidia-xxxとなっているところはdriverのバージョンの上3桁
下2行のlibEGL.so.xxx.xxはxxx.xxにサブバージョンを含めたdriverのバージョンを入れる

シンボリックリンクでなければいけないところ，実ファイルが入っているのが要因であると思われる．

#確認
```
$ sudo ldconfig
```
としてエラーが返ってこなければ完了
GC dispose

https://collectiveidea.com/blog/archives/2015/02/19/optimizing-rails-for-memory-usage-part-2-tuning-the-gc

https://ruby-doc.org/core-2.2.3/GC.html

https://www.google.com.tw/search?ei=sYT5WfioOIHj0gTd54GICw&q=rails+dispose&oq=rails+dispose&gs_l=psy-ab.3...1658.4651.0.4884.8.7.1.0.0.0.56.346.7.7.0....0...1.1.64.psy-ab..0.6.263...0j0i131k1j0i7i30k1j0i7i10i30k1j0i8i7i30k1.0.Ywn5oXuToTE
iOSのWebアプリモードでカメラ起動するとおかしい

iOSでWebページを `ホームに追加`するブクマみたいな機能がありますが、HTMLに特定の記述をするとネイティブアプリみたいにURLの入力フィールドとかが非表示の状態で起動できます。(Webアプリモードというらしい)

```
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes" />
```

ですが、このホーム画面からこのモードでWebページを開いた状態で `<input type="file">` でカメラを起動するとうまく動作しない不具合がありました。
いろいろ調査したところ、Safariの不具合でいまのところこのモードでの起動をやめるしかないそうです。

https://stackoverflow.com/questions/46228218/how-to-access-camera-on-ios11-home-screen-web-app

iOS10だとカメラで撮影してフォームに戻ってきたときにスクロールができなくなて、iOS11だとスクリーンが真っ暗でUIは表示されているものの撮影ができない状態でした。
いずれもカメラロールからは問題ありませんでした。

今後のアップデートで改善されるかもしれませんが今の時点ではホームから起動とカメラの組み合わせは気をつけたほうが良さそうです。
unpermitted parametersのエラーでちょっとだけはまった話


下のようにparamsをrequireしようとしたら、unpermitted parametersとなって帰ってきた。

```
params.require(:course_chapter).permit(:ids)
```

原因がわからずしばらく悩んでいたら、単純なミスに発覚
***idsは配列だった***....

というわけで正しい書き方はこちら

```
params.require(:course_chapter).permit(ids: [])
```

こういうミスに気をつけましょう
CentOS6.7(AWS)LAMP環境構築からPHPMyAdminまで

AWSの無料枠で使えるCensOSへLAMP環境を構築します。
ついでにSQLの使い勝手向上のため、PHPMyAdminを導入し、GUIでSQLを管理できるところまで残しておこうと思います。

LAMP環境

#L-Linux
LinuxはCentOSを利用。
今回の環境では、AmazonWebServiceのEC2にて
AMIをCentOS Linux 6 x86_64 HVM EBS 1602-74e73035-3435-48d6-88e0-89cc02ad83ee-ami-21e6d54b.3 (ami-05cf2265)
として利用する。
#A-Apache
WebサーバはApacheを利用する。
CentOSのyumを利用してパッケージをインストール。

~~~
#yum -y install httpd
~~~

Webサーバの起動

~~~
#service httpd start
~~~

起動時自動的にサービスが立ち上がるように設定

    #chkconfig httpd on

Webサーバへの接続確認
クライアントからブラウザで接続を確認する。
※このWebサーバはデフォルトでファイアーウォールが効いており、接続できないはず。

ファイアーウォールの設定を確認

    #/sbin/iptables -L --line-numbers

Httpの通信が許可されているかどうか確認する。
許可されていないと思うので、80番ポートと443番ポートに対して許可を与える。
※途中にはいっている数字｢5｣と｢6｣はファイアーウォールの行番号

    #/sbin/iptables -I INPUT 5 -p tcp -m tcp --dport 80 -j ACCEPT
    #/sbin/iptables -I INPUT 6 -p tcp -m tcp --dport 443 -j ACCEPT

nmapによりポートが開いたか確認する。
※デフォルトではインストールされていないので、インストールする

    #yum -y install nmap

nmapの実行

    nmap -p 1-1023 localhost

下記のように表示される。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/185534/e38825ae-c1f0-7cb9-0d5e-34a13a5c12b4.png)

再度クライアントからブラウザで接続確認を行い、下図のように表示されていれば正常にインストールが終了。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/185534/de75fc15-6b28-4009-b854-68917566ade8.png)

#M-MySQL
MySQLのインストール

    #yum -y install mysql-server

MySQLの起動

    #service mysqld start

自動起動の設定

    #chkconfig mysqld on

※実行の確認はPHPMyAdminを実装した後に行う。

#P-PHP
###PHPのインストール

    #yum -y install php

つづいてPHPからMySQLを操作するためのモジュールをインストールする。

    #yum -y install php-mysql

実行前にhttpdを再起動する。

    #service httpd restart

インストール後の実行確認のため、PHPファイルを作成し確認する。
index.phpのファイルを作成し、確認

    #vi /var/www/html/index.php

~~~index.php
<?php
    phpinfo();
?>
~~~

これでPHPのインストールまで終了。

#PHPMyAdminのインストール

###GUIでMySQLを管理できるようにPHPMyAdminをインストールする。

phpMyAdminは標準リポジトリでは提供されていないため、
Fedoraプロジェクトの提供するRHEL用にビルドされたスペシャルパッケージを配布するEPELを追加する。

    #yum -y install epel-release

EPELのインストール後リポジトリを利用してphphMyAdminをインストールする。

    #yum --enablerepo=epel install -y  phpMyAdmin

ブラウザからWebサーバへ接続した`URL/phpMyAdmin/`とすると表示できるようになった。
しかし、初期設定ではローカルホストからの接続しか許していないため、外部からの接続を許可する必要がある。

###外部クライアントからの接続設定

    #vi /etc/httpd/conf.d/phpMyAdmin.conf

下図中の`Deny from All`が全ての接続を拒否しているため、コメントアウトする。
設定ファイルのコメントアウトは`#`なので、先頭に`#`を追加する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/185534/157ec225-5598-8151-7290-8419fe3d4c55.png)

設定の保存後、反映させるためにApacheを再起動する。
    
    #service httpd restart    

ここでphpMyAdminに接続する。

    URL/phpMyAdmin

###MySQLへのログイン

初期設定では、MySQLのrootへパスワードが設定されていないため、はじかれてしまう。
コマンドでMySQLのrootユーザへパスワードの付与が必要になる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/185534/c7b5fde9-23a5-2b11-0395-0383ebbd58c9.png)

MySQLへログインし、rootへパスワードを設定する
※初期はrootのパスワードが無いため、このままログインできる

    #mysql -u root

mysqlのユーザへパスワード追加

    mysql>set password for 'root'@'localhost' = password('パスワード');

ここで設定したパスワードを元にphpMyAdminへログインする。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/185534/bb1fee1a-0025-d15c-a928-6cb00329ec9e.png)

無事に設定されていれば、下図のように表示される

![image.png](https://qiita-image-store.s3.amazonaws.com/0/185534/208bdb7d-aa59-0045-23ca-aaf1ea2d8031.png)
以上。

次はphpMyAdminを用いてデータベースの設定とユーザの追加をやります。
SQLの基礎学習に使用した無料サイト

基礎学習の段階では以下の2つを押さえました。

- SQL学習 -分かりやすい説明とオンラインでの練習
 * http://studybyyourself.com/seminar/sql/course/?lang=ja

　こちらのサイトだけではちょっと説明が簡素であるのと日本語の怪しい部分が気になったので、以下のQiita記事も参照してます。

- SQLの基本を覚える【初心者向け】
 * https://qiita.com/chida09/items/d4b33a28b918958f267f

　こちらは項目ごとにシンプルにまとめられてるので、とても見やすかったです。基本的には最初にリンクを張ったサイトを閲覧し、情報を補完するような形で上記Qiita記事を参照しました。

　前述のサイトは内容的にはかなり有用なものだと思うのですが、気になったのが若干説明不足感がある点と、エイリアスを解説直後からすでに例題で多用していて、不慣れなうちは内容を咀嚼するまでに時間がかかった点。あと補足であるかのようにページ下部で触れられている内容があるのですが、欄の小ささの割に結構大事なことが書いてあるような気がします。
Local by FlyWheelはwindows 32bitでは動きませんよぉー

#32bitでは動きません。

伝えたいのは、これだけです。
僕はこんなことで5時間も悩んでいました。

WordPressをローカルで動かしたい！
そんなときに便利なのが[Local by FlyWheel](https://local.getflywheel.com/)ですよね。
UIもかっこいいし、特に設定なしでインストールしたらWordPressがローカルで動きます。

でもWindows 32bitでは動きません。
[Installation : 64 bit windows is resuired](http://local.getflywheel.com/community/t/installation-64-bit-windows-is-resuired/984)

だってインストール自体はされるんですよ！
でも[Checking System...]って画面で永久に止まります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/209322/4b914e12-de45-651b-3b4f-f5228cb82102.png)

**じゃあ、32bitはダメよって一言言ってよ...**

わからないながらもエラーログ見て、
electronが入ってるからだめなのかなぁとか、
node.jsアンインストールしてみたりとか...

はぁぁ... みなさんはこんなバカなことはしないでくださいね。
あきらめてxampp使います。