OmniAICreator/Qiita-1.07M huggingface dataset:
React 超初心者　の用語＋α　学習中メモ

Reactの勉強を開始しました。今までにWebのフロントサイドを腰を据えて学んだことがなかったため、
当たり前のように出現する用語に困惑しました。
名称が一般的な開発用語と似ているがReact独自の用法で用いられていることがさらに多くさらに困惑と導入のハードルを上げていると考えました。。
初学者が躓きそうな用語を一言でわかる言いかえ表現とシンプルな説明にしてまとめてみました。
誤りがあったらお知らせください。自身の学習とともに随時追記していく予定です。

###よく分からなかった用語


####ES2015
　=JavaScriptの標準規格。

####コンポーネント
　= HTMLで表示されるUI部品

####プロパティ
　=　コンポーネントに付加する属性

####Pros
 = プロパティ＝コンポーネント利用時に属性として設定ができる値。英語では小道具という意味

####ステート
　=そのまま「状態」　コンポーネントに状態を持たせる。textboxの文字列など保持できるようになる


###プロパティとステートの違い
　（両方ともコンポーネントに値をもたせるもの）

|      |  プロパティ  | ステート |
| ---- | ---- | ---- |
|外部からのアクセス    | 可能|不可 |
| データの可変性   |  不変|可変  |




####仮想DOM
　=　本物のDOMではないがページ上の更新が必要な部分だけを描画できる仮のDOM。

####JSX 
 JSの中にHTMLを記述できるようなもの [１つのプログラミング言語として独立している]。「JavaScript XML」の略
他のライブラリでは基本使われていないがReact特有のものではないんらしい。

#### =>()という表記
=>  という表記はアロー関数といわれています。別記事で紹介（C++のアロー演算子的なものではない）
これもReact独自のものではありません。2016年くらいからJavaScriptで取り入れられた新しい関数の書き方です。
基本は以下の３つは同じ動作をします。

#####↓もともと

```JavaScript
traditionalFunction (var x){
    console.log(x);
}
```

######↓無名関数

```JavaScript
let AnoymousFunction = function(x){
    console.log(x);
}
```
#####↓アロー関数

```JavaScript
let arrowFunction = (x) => {
    console.log(x);
}
```
【論文読み】Reducing the Model Order of Deep Neural Networks Using Information Theory

[arxiv](https://arxiv.org/pdf/1605.04859.pdf)
[IEEE](https://ieeexplore.ieee.org/document/7560179)
この論文では、重みの一部を削除することでニューラルネットを高速化する際に、重みのフィッシャー情報量に基づいて削除することを提案しています。これにより、性能の低下が抑えられるとされています。

## フィッシャー情報量とは
フィッシャー情報量の定義は[ここ](https://kriver-1.hatenablog.com/entry/2018/05/02/175855#431-%E3%83%95%E3%82%A3%E3%83%83%E3%82%B7%E3%83%A3%E3%83%BC%E6%83%85%E5%A0%B1%E9%87%8F)がわかりやすいでしょう。
誤解を恐れずに言うと「そのパラメータを変えたときに、出力結果に平均どの程度の影響を与えるか」というパラメータの性質を数量化したものです。すなわち、フィッシャー情報量の大きいパラメータは、出力結果に対して大きな情報量を持ち、重要なパラメータであると考えることができます。

フィッシャー情報量の計算方法：
$$\mathbf{F}(\boldsymbol{\theta})=\mathrm{E}_{\mathbf{y}}\left[\left(\frac{\partial \log p(\mathbf{y} | \mathbf{x} ; \boldsymbol{\theta})}{\partial \boldsymbol{\theta}}\right)\left(\frac{\partial \log p(\mathbf{y} | \mathbf{x} ; \boldsymbol{\theta})}{\partial \boldsymbol{\theta}}\right)^{T}\right] $$

## 提案手法
とは言ってもいきなりフィッシャー情報量に基づいてパラメータを削っていくわけではありません。まず重みの大きさの小さいものを除きます。ニューラルネットの重みの多くはゼロに近く、重みが小さいときは、そのフィッシャー情報量を推定するのは困難[^1]であるためです。

CNNにおけるFC層の各重みに対して出力結果とのフィッシャー情報量を計算し、小さいものを削除します。
更に残りの重みのフィッシャー情報行列対角成分でk-meansクラスタリング（要するにランキング）し、意味のなさそうなものを低ビットで表現することで更に削減を図ります。

## 理論的考察
フィッシャー情報量という言葉は聞き慣れませんが、実は有名なoptimizerである **Adam** には **フィッシャー情報量の考え方が用いられています**。
![](https://gyazo.com/6546bd8157cbd046c30011806ced51dd.png)
論文中にあるAlgorithm 1のWhileループ内4,6に示されるように、Adamでは傾きの自乗が減衰しながら更新されていますが、（損失関数が交差エントロピーロスである場合は）これがフィッシャー情報量に一致します。
そのため、この論文中ではNNの訓練にAdam optimizerを使用し、収束したときのAdamの内部パラメータを重み削減に直接利用しています。

## 結果
![](https://gyazo.com/5c49c4ac8ea8e2dd5322fcb4564293af.png)
図3で一番性能低下を免れている青色のグラフは、重みの大きさに基づいて、続いてフィッシャー情報量に基づいて重みを削除したモデルです。
論文中では「〇〇%の重みを削除しても性能があまり低下しなかった」ということが盛んに喧伝されていたように思われますが、その数字は削減する前のもともとのモデルを大きくすれば水増し可能な気がするので、むしろ重みの大きさだけに基づいて重みを削除したオレンジ色のグラフに比べて性能が少し向上しているところを評価するべきでしょう。

## まとめ
この論文では、フィッシャー情報量に基づいてニューラルネットを枝刈りし、高速化するという研究でした。これを実用目的に実装する人は少ないかもしれませんが、**Adamの2乗移動平均$v$がフィッシャー情報量に対応していること**、したがって**Adamで訓練したNNが収束した時その$v$は重みのフィッシャー情報量に収束していると考えられること**という知識[^2]は知っていて損はないと思います。読んでいただきありがとうございました。

[^2]: $v$がフィッシャー情報量に収束すると最初に指摘したのはRevisiting natural gradient for deep networks (Pascanu, 2014).また、フィッシャー情報量を学習と組み合わせるアイデアの大本としてNatural Gradient Works Efficiently in Learning (Amari, 1998)がある
[^1]: Empirical Non-Parametric Estimation of the Fisher Information (Berisha, 2014)に詳しい説明がある

なお、本記事はMETRICAの勉強会向けに作った資料を修正したものです。
python3.7(windows10)でpipがSSL接続できないと言う場合はdllの衝突のせい

# 環境

* Windows 10 Pro
* conda 4.5.2
* Python 3.7.3 (`conda create -n hoge-env python=3.7`)

# 問題

`pip install`できない。

```
C:\Users\me>activate hoge-env

(hoge-env) C:\Users\me>pip install "https://github.com/hoge/hoge.tgz"
WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
Collecting https://github.com/hoge/hoge.tgz
  WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.")': /hoge/hoge.tgz
  WARNING: Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.")': /hoge/hoge.tgz
  WARNING: Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.")': /hoge/hoge.tgz
  WARNING: Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.")': /hoge/hoge.tgz
  WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.")': /hoge/hoge.tgz
ERROR: Could not install packages due to an EnvironmentError: HTTPSConnectionPool(host='github.com', port=443): Max retries exceeded with url: /hoge/hoge.tgz (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available."))

WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
Could not fetch URL https://pypi.org/simple/pip/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/pip/ (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available.")) - skipping

```

`import ssl`もできない。

```
(hoge-env) C:\Users\me>python
Python 3.7.3 (default, Apr 24 2019, 15:29:51) [MSC v.1915 64 bit (AMD64)] :: Anaconda, Inc. on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\me\Anaconda3\envs\hoge-env\lib\ssl.py", line 98, in <module>
    import _ssl             # if we can't import it, let the error propagate
ImportError: DLL load failed: 指定されたプロシージャが見つかりません。
```

# 解決法

https://github.com/pypa/virtualenv/issues/1139#issuecomment-481847818

`C:\Windows\System32`下の`libssl-1_1-x64.dll`と`libcrypto-1_1-x64.dll`が本来のdllへの解決を邪魔しているらしいのでをどうにかする（リネームするとか）と解決した。
検索するといろいろ出てくるが、影響範囲が小さく何かあった場合の復旧も簡単なのでこれがベターではないかと思う。
Bash script to convert Android bundle .aab to .apk, .apks, .zip and ADB device install

In Android Studio, we prepare an App for public release by creating a signed .aab bundle file. The bash script below (tested in Unix/Mac OS) performs the following functions:

- converts .aab bundle located in the "release" folder to an .apks file
- extracts a universal .apk file, which can be run on any device (useful if you send it to multiple testers)
- compresses all files in an encrypted folder using zip
- installs the .apks on a connected device (optional)

The script accepts the following arguments when run in the terminal:
1. the name of the files to be created
2. (Optional) The address of a connected Android device to which the .apks file can be installed. The address can be obtained by running "adb devices" in the command line.

The script has the following placeholders, which should be replaced for your specific environment/application:

- {PASSWORD}, {KEYSTORE_FILE}, {ALIAS} are the details used to sign the .aab in Android Studio
- {PATH_TO_BUNDLE_TOOL} is the path of the bundletool e.g. ~/Downloads/bundletool-all-0.8.0.jar

The bundletool can be obtained from:
https://developer.android.com/studio/command-line/bundletool

```bash
#!/bin/sh

# convert default .aab file to other products
# - apks to install in device directly
# - universal apk to install in device

if [ "$#" -lt 1 ]; then
    echo "Illegal number of parameters - required"
    echo "1. name"
    echo "(optional) 2. device (from adb devices)"
    exit
fi

default_name=app
target_name=$1

folder=release
mode=universal
apk_container=apk_container

default_aab=$folder/$default_name.aab
default_apks=$folder/$default_name.apks
default_apk=$folder/$apk_container/$mode.apk

target_aab=$folder/$target_name.aab
target_apks=$folder/$target_name.apks
target_apk=$folder/$apk_container/$target_name.apk

password={PASSWORD}
keystore={KEYSTORE_FILE}
alias={ALIAS}


if [ -f $default_aab ]; then
	java -jar {PATH_TO_BUNDLE_TOOL} build-apks --overwrite --mode=$mode --bundle=$default_aab --output=$default_apks --ks=$keystore --ks-key-alias=$alias --ks-pass=pass:$password
else
	echo "cannot find $default_aab"
fi

if [ -f $default_apks ]; then
	unzip $default_apks -d $folder/$apk_container
else 
	echo "cannot find $default_apks"
fi

if [ ! -f $target_aab ] && [ -f $default_aab ]; then
	mv -f $default_aab $target_aab
else 
	echo "cannot find $default_aab or target $target_aab already exists"
fi

if [ ! -f $target_apks ] && [ -f $default_apks ]; then
	mv -f $default_apks $target_apks
fi

if [ ! -f $target_apk ] && [ -f $default_apk ]; then
	mv -f $default_apk $target_apk
fi

if [ "$#" -eq 2 ] && [ -f $target_apks ]; then
	device=$2
	java -jar {PATH_TO_BUNDLE_TOOL} install-apks --apks=$target_apks --device-id=$device
fi

zip -er $folder/$target_name.zip $folder/$apk_container 
```
シリアライズに失敗したとき

# シリアライズに失敗したときの対応


## はじめに

Java の話です。
オブジェクトをシリアライズしたい場合は、
インターフェースに、Serializable をつければ、シリアライズされます。
とはいえ、Serializableをつけてもシリアライズされなかった場合はどうすればいいのか、そのときのメモです。



## シリアライズとは

そもそも、シリアライズ処理とは、復元可能な文字列に変換することです。
Objectのような、メモリ空間にしか存在しないものを、読み込めるようにする際に利用します。

（詳細は下記）
https://docs.oracle.com/javase/jp/8/docs/api/java/io/Serializable.html

Redis等でObject情報を保持したいときに、一度シリアライズする（もちろん、シリアライズする方法をとる必要はない）
などして、オブジェクト情報を保持することが可能です。


## シリアライズの復元に失敗するとき

しかし、複雑なObject情報があり、シリアライズできないというJDK系のExceptionが発生したり、
不要な変数情報をシリアライズして、性能劣化になっている場合、
個別にシリアライズ対象のものを指定することが可能です。

このとき、利用できるものが
Externalizable

になります。

```java

public class HogeModel implements Externalizable {

	/**
	 * 独自シリアライズ処理
	 *
	 * @param out 出力ストリーム
	 * @throws IOException IOエラー
	 */
	@Override
	@SuppressWarnings("resource")
	public void writeExternal(final ObjectOutput out) throws IOException {

		Packer pk = MessagePackManager.getInstance().createPacker((OutputStream) out);

		pk.write(this.hogehoge);
	}


	/**
	 * 独自デシリアライズ処理
	 *
	 * @param in 入力ストリーム
	 * @throws IOException IOエラー
	 */
	@Override
	public void readExternal(final ObjectInput in) throws IOException {
		try {
			@SuppressWarnings("resource")
			Unpacker upk = MessagePackManager.getInstance().createUnpacker((InputStream) in);

			this.hogehoge = upk.readInt();

		} catch (IOException e) {
			throw e;
		} catch (Exception e) { 
			throw new IOException(e);
		}
	}

}

```
Rails 500エラーをSlackに通知

静岡市でWeb開発しているフリーランスのkazuomatzです。

表題の通りで、[Exception Notification](https://github.com/smartinez87/exception_notification)なるものの存在も知りつつ、もう少し、自分達の運用に合うような形で、[Slack500](https://github.com/kazuomatz/Slack500)というGemを作ってみました。

きっかけは、[Railsの重大な脆弱性対応](https://qiita.com/moriwm77/items/b727eb41d95509535538)や、[AWS S3の署名バージョン2(SigV2)の廃止](https://dev.classmethod.jp/cloud/aws/s3-sigv2-abolition/)*1などに対応するために、Railsとその仲間達(=Gem)をアップデートする際に、その影響範囲が網羅できないためでした。

まぁ、RSpecやっとけよってことなんですが、やはり、これらのアップデートによってもたらされることは予測できないこともあるので、アップデート後の運用の中で、いち早くエラーを検知して対応するといった対症療法的アプローチも考えようと思いました。

*1) 2020年6月24日移行も継続して延命されました

# 概要

![slack_500.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39570/5ec9c9b6-c599-dbf7-ac8e-58860a7e1337.png)

Slack500の機能としてはシンプルでControllerでrescue_fromで例外をキャッチした先でSlack500の関数を呼ぶ作りです。

エラーの内容を把握するために最低限必要な内容を通知します。


# 使い方

Gemfileに追加して、

```ruby:Gemfile
gem 'slack_500'
```

bundle.

    $ bundle

または、

    $ gem install slack_500

次に、設定ファイルを作成するために、rakeタスクを実行。

    $ rake slack_500:config


/config/initializers/slack_500.rb　ファイルができるので、ファイルを編集。


```ruby:/config/initializers/slack_500.rb
require 'slack_500'
Slack500.setup do |config|
    # pretext
    config.pretext = 'Slack Report Title'

    # タイトル
    config.title = 'Rendering 500 with exception.'

    # メッセージの左に表示されるバーのカラー
    config.color = '#FF0000'

    # フッターに表示する文字列
    config.footer = 'via Slack 500 Report.'

    # WebHook URL
    # see https://slack.com/services/new/incoming-webhook
    config.webhook_url = "https://hooks.slack.com/services/xxxxxxxxx/xxxx"
end
```

## 実装の仕方

```ruby:/app/controllers/application_controller.rb
class ApplicationController < ActionController::Base

  if Rails.env.production?
    # Exceptionを補足
    rescue_from Exception, with: :rescue_500
  end

  :
  :

  def rescue_500(exception)

    # Slackに通知
    Slack500.post(request,exception)

    render 'error/500', status: :internal_server_error, layout: 'application'
    end

  :
  :

end
```

# 使ってみて気づいた点

### 思いの外飛んでくる

テストしとけよって話なのですが、飛んできます。パラメータによる例外、nil例外など。エラーを踏んでくれたユーザー様に感謝しながら修正します。

Slack鳴り止まない状況であったら、夜も眠れない状況になるし、Slack様にもトラフィック負担をおかけしてしまうので、ご利用は計画的にお願いします。

### 何気にクローラーからのアクセスで通知が飛んでくる

予期しないクエリーパラメーターによる例外や文字コードのencode例外(incompatible character encodings: UTF-8 and ASCII-8BIT)、ResponseをJSONしか用意してないのに、クローラーがtext/htmlを要求して例外などが見つかりました。テストしとけよって話なのですが。

SEO的に影響がある場合もあるので、エラーを潰した方がよいでしょう。ほっといてもよい場合もあるので、User Agentを通知することにして判断できるようにしました。

# まとめ

前提として通常のテストで網羅できない場合を想定した導入と考えた方がよいでしょう。一昔前は、GemがいっぱいあってRailsすげぇって話だったのですが、最近は、Gemの作者もメンテナンスを放棄してしまうケースも多くなってきたような気もします。Gemの依存関係が複雑になってきて不用意にbunlde updateしたら動かなくなるケースも結構増えてきたような・・・。

そのようなことを含めてSlack500で運用をしていきたいと思います。
複数のファイル内の特定の文字を一括置換

## 動機
ファイル内の特定の文字の置換について, 私は今までテキストエディタの置換機能に頼っていました。(↓ATOMエディタ)
<img width="673" alt="スクリーンショット 2019-06-26 18.07.22.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278797/1b4fd48d-8b6b-5340-85cf-b51b9ce15199.jpeg">
しかし, 今回複数のファイルを変換する必要性が出てきたためやむを得ず `sed` コマンドと `bash` での `for` 文を学習したため, 自分用のメモを兼ねて残します。

## 単一ファイルの置換について
以下のようなファイルが有った場合, ディレクトリ名を一括変換したいと思います。

```qiita1.html
<img src="assets/public/1.png" alt="1" title="1">
<img src="assets/public/2.png" alt="1" title="2">

```

`sed -i '' 's/変換前/変換後/g' ファイル名`
で置換できます。ですのでディレクトリのエスケープを忘れずに以下のスクリプトを実行すると

```bash
sed -i '' 's/assets\/public/uploads/g' qiita1.html
```

以下のように置換されます。

```qiita1.html
<img src="uploads/1.png" alt="1" title="1">
<img src="uploads/2.png" alt="1" title="2">

```
しかし, 正直単一ファイルの置換については今までどおりテキストエディタに頼るのもありかなと思います。

## 複数ファイルの置換について
今回は, 複数ファイルの置換ということで bash での for ループを用います。

```bash
`ls -a`; do echo $i ;done

>dont_change.html
>qiita1.html
>qiita2.html
>qiita3.html
```
変更するファイルを指定します。

```bash
for i in `ls -a|find qiita*`; do echo $i ;done

>qiita1.html
>qiita2.html
>qiita3.html
```

以下のファイルのディレクトリを置換したい場合,
<img width="1221" alt="スクリーンショット 2019-06-26 18.20.06.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278797/c6704f91-52ca-1859-e6ae-b96645d9ea7a.jpeg">

sed コマンドとうまく組み合わせると以下のようになります。

```bash
for i in `ls -a|find qiita*`; do sed -i '' 's/assets\/public/uploads/g' $i;done
```
<img width="1276" alt="スクリーンショット 2019-06-26 19.03.50.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278797/a0a437f7-043c-f169-12df-ae3efa8ba304.jpeg">

`xargs` とかで引数とってもできるんですかね, また試してみます。
AWS EC2 - CentOS7 で SELinux の設定をミスしてrebootが失敗する時の対処法

# AWS EC2 - CentOS7 で SELinux の設定をミスしてrebootが失敗する時の対処法


## 現象
OS CentOS7

SELinuxの設定を間違えてreboot失敗する…という現象については色々と記事（↓）が出ていますが、AWSコンソール上での対処法がなかなか見つからなかったのでメモ

https://qiita.com/daisuke0115/items/4b0ed3a5888cf81efd0a
https://qiita.com/murabiton/items/d44fc01b9e1ac2fdcfab

ミスの内容はこちら
[SELinuxの設定変更をし再起動した場合にカーネルパニックになる、という事象の原因・よくある設定ミスについて。- SELinuxの無効化でのありがちなミス](https://qiita.com/murabiton/items/d44fc01b9e1ac2fdcfab#selinux%E3%81%AE%E7%84%A1%E5%8A%B9%E5%8C%96%E3%81%A7%E3%81%AE%E3%81%82%E3%82%8A%E3%81%8C%E3%81%A1%E3%81%AA%E3%83%9F%E3%82%B9)

同じCentOS7の別インスタンスにボリュームをアタッチして設定ファイルを正常に修正……で終わるかと思いきや、
変な設定ファイルを抱えたボリュームをアタッチしたらその別インスタンスも起動しないという事態に……。
スクリーンショットを見てみると

```
Failed to load SElinux policy, fleezing.
```

とのこと。ボリューム同士が衝突しているっぽい……


## 解決方法
ざっと流れだけメモ　具体的なコマンドなどは需要あったら追記します

AmazonLinuxで新しくインスタンスを立て、そこに問題のボリュームをアタッチ
→AmazonLinuxにログイン
→設定ファイルを正しく修正（修正方法は上記「ミスの内容はこちら」のリンク先参照）
→ボリュームをAmazonLinuxのインスタンスから引っぺがし、元のCentOSのインスタンスにアタッチ
→起動成功！:tada:

CentOS7に特有の現象かもしれなかったです。（あいまい）
View Listener to activate feature after N clicks within time limit

The following subclass of View.OnClickListener can be set as a listener to any View. When the user clicks on that view enough times within a defined time limit (here, the target is defined as 7 clicks within 2 seconds), the onCompletion handler is called. 

This is a useful feature in some cases e.g. defining a double-click handler, activating a hidden debug mode while the app is running.

```kotlin
class MultipleClickListener :  View.OnClickListener {

    val maxDuration: Long = 2000 // in milliseconds
    val minTaps: Int = 7 // minimum number of clicks to complete
    var iconTapCount: Int = 0
    var start: Long = 0

    val now: Long
    get() = System.currentTimeMillis()

    override fun onClick(v: View?) {

        // This method returns a ViewPropertyAnimator object, which we could use to 
        // animate the View per click for visual feedback.
        val animator = v?.animate()

        if(0 == iconTapCount || now - start > maxDuration) {
            iconTapCount = 0
            start = now
        }
        if(now - start < maxDuration) {
            iconTapCount += 1
        }
        if(iconTapCount == minTaps) {
            onCompletion()
        }
    }

    // do something e.g. open a new view, switch on debug mode etc
    fun onCompletion() {}

}
```
TECH ~Day4~

四日目の学習を終え、前回の投稿で書いたレビュー管理アプリケーションをやっと終えることができました。
後半になるにつれてかなり頭を抱えることが多かったように感じました。

学習内容
・変数のスコープ
・引数
・return
・eachメソッド


・変数のスコープ
簡単にいうと変数を使うことができる範囲のこと。
通常、メソッド内ではそのメソッド内で定義した変数しか使うことができない。
同じ名前の変数でも、スコープが違ければそれはまた別の変数となる。
スコープの範囲外の変数を使おうとすると、エラーになる。


・引数
引数はメソッドの外にある変数（スコープ外の変数）をメソッドの中で使用できるツール。
point
・数は「メソッドを呼び出す部分」と「メソッドを定義している部分」の両方に書く。
・上記の二つの引数の名前は一致する必要はない。

書き方
 def メソッド名 （仮引数）　←メソッドを定義している部分「仮引数」
  実行する処理
 end

 メソッド名（本引数）　←呼び出す部分「本引数」

！仮引数の名前は誰が読んでもわかりやすいものにすべき！


・return
returnの後に打った式がそのメソッドの返り値になる。
returnを使った時点で返り値がそれに決まるため、メソッドはその行までで強制終了となる。


・eachメソッド
配列の要素全てに対して共通の処理を行うメソッド。
配列に含まれる要素を順に取り出し、繰り返し処理を行う。
つまり配列の要素の数だけ処理が行われる。

書き方
 配列オブジェクト.each do |変数|
  !ここに処理結果を書く！
 end


引数がわかりにくい用語として扱われている意味がやっているうちに強く実感しました。引数を自然と使えるようになることでかなり自分の成長を感じられるのではないかと思いました。ちゃんとこの技術も自分のものにするためにもたくさん問題などを解いていこうと思います。
sqldeveloperでムカつく設定の解消

デフォルト設定が自分にはイケてない`sqldeveloper`。
設定変更の備忘録。

## date型で時刻が出ない
データとして入ってるのにデフォルトで時刻を出していないので出すようにする。
`プリファレンス` > `データベース` > `NLS` を開いて`日付書式`に時刻書式を入れる。

書式例：`YYYY-MM-DD HH24:MI:SS`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298766/dca6915d-9138-5bf4-32e3-57644112ba15.png)

## 行番号が出てない
エディタ左の余白を右クリックで出せる行番号。
デフォルトで表示するようにする。

`プリファレンス` > `コード・エディア` > `行の左余白` を開いて `行番号の表示` にチェック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298766/860c483c-486a-9e86-12fd-aa4088149b6d.png)

## データエクスポート時の形式がinsert文
なんでデフォルトが`insert`文形式。
`csv`に変える。

`プリファレンス` > `データベース` > `ユーティリティ` > `エクスポート` を開く。
`データのエクスポート` 項目のフォーマットを`csv`に変更。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298766/a8eb1eff-127a-98b1-564a-00073c2c9f11.png)

何かあれば追記する。
lstlistingにおいてLaTeXコマンドを扱う

# プログラム例
```TeX:sample.tex
\begin{lstlisting}[escapechar=\@]
void function(int R) {
    printf("R[@$\Omega$@]: %d", R);
}
\end{lstlisting}
```

# ポイント
- `escapechar=\任意の1文字`を`\begin{lstlisting}`の後に`[]`で囲んで書きます．
- LaTeXコマンドを書きたい場所の前後に指定したエスケープ文字を書きます．
- エスケープ文字で囲まれた部分は通常のLaTeXと同じ仕様であるため，数式を扱いたい場合は`$`でさらに囲む必要があります．
- 今回のプログラム例では`@`を指定しましたが，`!`や`%`などをエスケープ文字とすることもできます．ただし，lstlisting内で使用している文字をエスケープ文字に登録しないように気を付けましょう．

# 参考文献
- http://ftp.yz.yamagata-u.ac.jp/pub/CTAN/macros/latex/contrib/listings/listings.pdf
git statusの結果を文字列で絞り込んでaddするのを1行で行う

# git statusの結果を文字列で絞り込んでaddするのを1行で行う

```
git status | grep modified | awk '{print $NF}' | xargs git add

```

## 解説

### git status
言わずとしれた入力元。この結果をpipeでつなげていく

### grep 
値の絞り込み。
今回はmodified を含むもののみ。

#### 他にも使えそうなもの
```
| grep -v sandbox // sandboxを含むものを抜く
| grep -e hoge -e fuga //hoge　またはfugaを含む　特定のディレクトリ以下だけ追加した場合など
| grep foo | grep bar //fooとbarの双方を含む

```

### awk
awkは区切り文字を基準に文字列操作を行うコマンド。
デフォルトでは半角スペースまたはタブを区切り文字として利用する。
今回利用しているのは``print $NF``だが、awk においてprint ${数値}は{数値}番目の要素を出力せよということ。
なお、この時の数値0ではなく1から始まり、NFは特殊組み込み変数で要素数を示す。

```
ex
a b c という文字列をawkに与えた場合
print $1 => a
print $2 => b
print $3 => c
print $NF => c (要素数が3なのでNF=3)

```

よって、``print $NF``はスペース区切りの文字列の末尾要素を出力せよということになる。
この処理を通すことで、前半部分に関係なくファイルパスのみを取得できる。

```
ex
git statusの結果が以下のような状態で
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   src/modifiedSource1
        modified:   src/modifiedSource2

Untracked files:
  (use "git add <file>..." to include in what will be committed)

       src/newSource

git status | grep src | awk '{print $NF}' を打つと

src/modifiedSource1
src/modifiedSource2
src/newSource

という形になる
```

## xargs
xargsコマンドは入力からコマンドを組み立てて実行できる。

`` {ファイルパスを出力するコマンド} | xargs git add ``　という形で実行することで
`` git add ファイルパス `` を内部的に打ってくれる。 

## 余談
特に確認もなく一気にaddまで行ってしまうので、念のためxargsの手前で止めて一度内容を確認したほうが実務上は無難。
ブラウザー側でリダイレクトするだけのスクリプト

# redirect.js

サーバー側で設定ができない環境向けに書いた、[ブラウザー側でリダイレクトするだけのスクリプト](https://bitbucket.org/vx68k/redirect.js/)に解説を試みます。

```javascript
export function run()
{
```

一応、関数にしておきます。 ES2015 のモジュールなので `export` を付けています。

```javascript
    let root = document.documentElement;
    let newLocation = null;
    if ("newLocation" in root.dataset) {
        newLocation = root.dataset.newLocation;
    }
```

ルート要素からリダイレクト先を取得します。 `<html data-new-location="…">` のように指定ができます。

```javascript
    if (newLocation == null) {
        for (let link of root.getElementsByTagName("link")) {
            for (let type of link.relList) {
                if (type.toLowerCase() == "canonical") {
                    newLocation = link.href;
                    break;
                }
            }
        }
    }
```

ルート要素にリダイレクト先がなければ、 `canonical` リンクをリダイレクト先にします。この指定方法は、検索エンジンにリダイレクト先を認識させることができるので一石二鳥です。

```javascript

    if (newLocation != null) {
        // Redirect the browser to the new location.
        location.replace(newLocation + location.search);
    }
}
```

リダイレクト先があれば、 [`Location.replace`](https://developer.mozilla.org/en-US/docs/Web/API/Location/replace) を使ってリダイレクトします。この関数を使うと、リダイレクト元の場所がブラウザーの履歴に残りません。「戻る」ボタンを押しても安心です。

ここではさらに、クエリー パラメーターを維持するようにしています。
Toast (with custom XML Layout) with variable display time

The native Android Toast has only two options for message duration (SHORT or LONG). Here we define a custom Toast, which uses a custom XML layout, and whose display duration is calculated to be proportional to the length of the Toast message (measured in number of characters).

- the custom XML Layout is inflated with a inflater service, and assigned to the basic toast "view" member
- a basic toast is displayed with the SHORT duration, but is actually shown multiple times in a countdown loop until the predefined display time has ended

```kotlin 
class CustomToast {

    companion object {
        // NOTE: we must create a new custom toast for each tick
        public fun show(context: Context?, text: String)  {
            context?.runOnUiThread {
                val durationinMillisecondsPerCharacter: Long = 50
                val duration: Long = text.length * durationinMillisecondsPerCharacter
                val timer = object : CountDownTimer(duration, 1000) {
                    override fun onFinish() {
                        setCustomLayoutView(context, text)?.show()
                    }
                    override fun onTick(p0: Long) {
                        setCustomLayoutView(context, text)?.show()
                    }
                }
                timer.start()
            }
        }

        private fun setCustomLayoutView(context: Context, text: String) : Toast? {
            val toast = Toast(context)
            toast.setDuration(Toast.LENGTH_SHORT)
            val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            val view = inflater.inflate(R.layout.layout_custom_toast, null)
            view.findViewById<TextView>(R.id.custom_toast_text)?.let{
                it.setText(text)
            }
            toast.view = view
            return toast
        }
    }
}
```
Deployer を使ってWindows環境とLinux環境に自動デプロイ出来るようにする

# はじめに

今日もニッチ記事
Windows環境とLinux環境の両方にデプロイしたい時の対応方法です
このような場合、コマンドの自由度が非常に高い Deployer が非常に有効です

# 大前提

Windows環境は `PowerShell` が入っている前提で色々書いてます

# 公式ドキュメント

https://deployer.org/

# 最初のinstall

composer を使って管理しましょう！
composer がすでに入ってるPHP系のプロジェクトだと相性が良さそうですね
それ以外だと、composer から入れてください

```zsh
$ composer require deployer/deployer --dev
$ composer require deployer/recipes --dev
$ ./vendor/bin/dep init
```

# Hostの設定を使用

+ stage を **Windows** と **Linux** で分けたほうが `deploy_path` 管理的に楽

```php
host('YourWindowsHostName')
    ->hostname('1.1.1.1')
    ->stage('windows')
    ->roles('apps')
    ->set('deploy_path', 'C:\Apps\application');
host('YourLinuxHostName')
    ->hostname('1.1.1.2')
    ->stage('linux')
    ->roles('apps')
    ->set('deploy_path', '/Apps/application');
```

# task を作ろう

git から `clone` や `pull` するだけのタスクを書いてみました

```php

// New Task
desc('Update code');
task('deploy:deploy_code', function () {
    $repository = trim(get('repository'));
    $branch = get('branch');
    $stage = get('stage');
    $recursive = '--recursive'; // include subproject
    $quiet = '-q';              // quiet
    $delimiter = '/';           // path delimiter
    $command_delimiter = '&&';  // command delimiter
    $options = [
        'tty' => get('git_tty', false),
    ];
    if ('windows' === $stage) {
        $delimiter = "\\";
        $command_delimiter = ";";
    }
    $application_path = "{{deploy_path}}$delimiter{{application}}";
    if ('windows' === $stage) {
        $dir = run("Test-Path $application_path", $options);
    } else {
        $dir = run("if [ -d $application_path ]; then echo 'True'; fi");
    }
    if ($dir == "True") {
        run("git clone $recursive $quiet $repository $application_path 2>&1", $options);
    } else {
        run("cd $application_path $command_delimiter git pull $quiet 2>&1", $options);
    }
});
```

# 使い方

```zsh
$ ./vendor/bin/dep deploy_code windows
$ ./vendor/bin/dep deploy_code webapp
```

# ポイント

+ **PowerShell** が動けば基本何でもできる！
+ Windows特有の設定とLinux特有の設定は最初に定義すればほぼほぼ共通化出来る
+ WindowsとLinux同時にアップするのを考えるのは大変なので、LinuxとWindowsは別々にアップを実行するようにすれば設定は意外と簡単にかける

# 最後に

Windows環境の自動デプロイ（CD）ってのは事例が少ないですが、やろうと思えば出来ます
Windows環境だからといって諦めずにやってみてください！
Yahoo! JavaScriptマップAPI、FAQにある「API経由で取得したデータ」についてのカスタマーセンター様からの回答

##経緯
と、いうほどのものでもないがーー

YahooMapのAPIをjsフレームワーク「stimulus」で操作してあれこれやろうとしていた。

やろうとしていたのは
●[住所を手入力→その住所にピンを立てて、確認したらその座標を登録する](https://qiita.com/wkya_4a/items/883ad988f2ad5cf58f55)。
及び
●地図をダブルクリック→クリックした地点にピンを立てて、確認したらその座標を登録する(こっちもそのうち、別の記事にまとめるつもり)。

で、だいたいできるかなー、と思ったところでyahooのデベロッパーガイドを眺めていたら、目に飛び込んできたのが[こちら](https://map.yahoo.co.jp/promo/yolp/faq.html#14)。
**>API経由で取得したデータを保存したり、二次利用することはできません。**

……あれ、俺、規約違反してる？

###あわててアプリの仕様を変更

変更前：ダブルクリックした地点の座標を【登録のための入力枠、「緯度」「経度」】に表示させ、それをそのまま登録する。
　　↓
変更後：ダブルクリックした地点の座標を**参照情報として**表示して、ユーザーにはそれを参照して【登録のための入力枠、「緯度」「経度」】に手入力してもらう。

……登録するのはあくまでユーザーが打ち込んだ情報であり、APIのデータは参照しているだけですよー、と言い張る作戦である（狡っ辛いな、おぃ）。

ただ果たしてこの言い分が通用するかわからなかったので、、、

###Yahoo! JAPANカスタマーサービス様に問い合わせてみた。

「当初やろうとしていたこと」→「問題となるだろうFAQ内容」→「対策として変更した仕様」
をまとめてメールで送り、待つことしばし。
帰ってきた回答が、↓↓↓こちら↓↓↓

**>YOLPサービス担当部署に確認しましたところ、Yahoo! JavaScriptマップAPIで表示された地点は、「API経由で取得したデータ」には該当しないとのことでした。**
**>よって、確認された二次利用の「API経由で取得したデータを保存」には
該当しないため、当初の利用である以下内容のご利用でも問題ないとの
ことです。**

##つまり、全く問題なかった！！！
禁止されている「データ保存」や「二次利用」は、[こちら](https://www.islog.jp/entry/reverse-geocoding/)で触れられているような【地図を全く噛ませずに、座標や住所情報だけ大量に取得する】ケースのことだったと思われる。

作っていたアプリの仕様も当初通りに戻し、[無事完成](http://mappura.com/)。
対応していただいたYahoo! JAPANカスタマーサービスの皆様、誠にありがとうございました。
Gzipについて調べてみた

## 概要

* gzipについて暇だったので調べた
* gzipに圧縮/解凍するやつを実装してみた
    * ただしzlibに依存している

暇だったので普段からお世話になっているgzipについて調べて少し実装するみたいなことをやってみました。何度繰り返された記事なのだろうか。
とはいっても仕様はRFCにて公開されているのでそれの猿真似です。
すこしハマるとこもあったので暇つぶしにQiitaに投稿してみようかなと。

なお、https://www.futomi.com/lecture/japanese/rfc1952.html のドキュメントを参考にさせていただきました。

## ざっくり仕様について

Gzipファイルはbyte単位のいくつかのメンバにより構成されています。
それぞれbyte数が決まっていたり、決まっていなかったりします。
以下に順番にメンバを簡単に書きます。

* ID1(IDentification 1), ID2(IDentification 2)
    * それぞれファイルがgzipであることを示すためのもの
    * ID1 = 0x1f, ID2 = 0x8b です
    * gzipファイルをhexdumpすると簡単に確認できます.
        * 下の00000000に続く2つの16進数が1f, 8b

```bash

$ zcat test.txt.gz
abc

$ hexdump -C test.txt.gz
00000000  1f 8b 08 08 28 2e 13 5d  00 03 74 65 73 74 2e 74  |....(..]..test.t|
00000010  78 74 00 4b 4c 4a e6 02  00 4e 81 88 47 04 00 00  |xt.KLJ...N..G...|
00000020  00

```

* CM(Compression Method)
    * その名の通り圧縮方式
    * 現在使われているのは8(deflate)のみな感じ
        * 0~7は予約されている
    * 上で出したhexdumpの結果の3byte目も08であることがわかる
* FLG
    * gzipファイルにどんな情報が含まれているかを示すフラグ
    * bit flagになっていて
        * bit 0 -> FTEXT
        * bit 1 -> FHCHR
        * bit 2 -> FEXTRA
        * bit 3 -> FNAME
        * bit 4 -> FCOMMENT
        * bit 5 ~7 -> 予約
    * いろいろあるんだけど、実際に使われているのはFNAME(ファイル名)?
        * gzipコマンドで指定できそうにもない
        * FNAMEはgzipでファイルを圧縮すると自動で入る
                * ちなみに標準入力を圧縮すると入らない
* MTIME
    * modified time、ファイルの最終更新日をunit timeにしたもの
    * 4byteで構成され、秒単位になる
    * byteから直すときはそのまま直すのではなく、MTIMEのbyte列を逆順にしないといけない
        * `0x42 0xb8 0x12 0x5d` だとしたら、 `0x5d 0x12 0xb8 0x42` で読み取る必要がある
        * 不思議、そういうものなのだろうか
* XFL(extra flag)
    * deflateの圧縮方式を示す
        * 2 -> 高圧縮
        * 4 -> 高速圧縮
    * なんだけど、gzipはdefaultで0になる
        * -9, -1 optionを入れると上記の数字が入る
* OS
    * そのままOS
    * どのosがどの数字になるかは仕様書を読んでください
    * 雑な実装だと `255 = 不明` を入れるっぽい
* XLEN(optional)
    * FLGにFEXTRAがセットされると入る
    * 拡張フィールドと呼ばれる付加情報のためのメンバのサイズを示す
* 拡張フィールド(optional)
    * FLGにFEXTRAがセットされると入る
    * SI1, SI2, Dataで構成される
        * SI1, SI2はどの情報を示すかというID
    * 現在入っているのは `SI1: 0x41 ('A')  SI2: 0x70 ('P')  Data: Apollo file type information`
    * ほぼ使われていない
* FNAME(optinal)
    * ファイル名が入る
    * 最終byteに0を入れる
    * gzipファイルをcatするとファイル名がでるのはこれが入っていたから
* FCOMMENT(optional)
    * コメント
* FHCRC(optional)
    * CRC16で計算されたチェックサム
    * 後でCRC32で計算したチェックサムいれるのにどうしてあるのかは謎
* 圧縮ブロック
    * データ本体
    * deflateで圧縮されたものが入る
* CRC32
    * CRC32で計算されたチェックサムが入る
    * これもMTIME同様にbyte順が逆転してるので、利用する場合は反転してあげる必要がある
* ISIZE
    * 圧縮前のbyte数
    * これもまた逆転している

これがgzipのファイルフォーマット。

## まとめやら

byte配列が逆転してたりとかして悩まされたりしたが、わりと単純だった（本体の圧縮アルゴリズムに触れてないからだけど）
これさえわかれば、gzipファイルをbyte配列で取り出して、1つずつ要素を眺めていけば問題なく扱える。
deflateでの圧縮もzlibとかを利用してあげれば大丈夫で、たいていの言語には実装されている。
ただ、zlibでそのまま利用するとheaderとか余計なものがついてくるので、排除したりする必要がある。
Java/scalaであれば `java.util.zip.{Deflater, Inflater}`を利用すればよい。
またheaderを排除するには、constructorのnowrapをtrueにすればよい

```
val inflater = new Inflater(true)
val deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true)
``` 
これで生の圧縮結果、もしくはheaderなしのbyte列でも解凍できる。

っていうことをscalaの練習がてら書いたのが https://github.com/takeru911/scala-gzip です。

gzipファイルを読み取れたので次は圧縮アルゴリズムを調べて実装する所存。
複数台のPostgreSQLサーバを繋ぎたい

## なんで繋ぎたいんだってばよ
+ 複数のDBがある
+ プログラム上でDB結合するより、結合してるDBに対してSQL発行できたほうが楽じゃない？
+ 短期開発アサイン者には明かしたくないDBの接続情報がある…


## 手順
基本はpostgres特殊ユーザ（スーパーユーザ）で実施すること。
ポスグレは9.4以上じゃないと駄目。

### 機能拡張
`postgres_fdw`を入れる

```sql
CREATE EXTENSION postgres_fdw;

-- 確認
SELECT * FROM pg_extension;
```

### 外部接続ラッパーを作成

指定するもの

+ 接続元サーバ内で使用する接続先名称
    + 例：acces_target_server
+ 接続先のhost
    + 例：00.00.00.00
+ 接続先のデータベース名
    + 例：access_target_db
+ 接続先へのポート番号
    + 例：5432

```sql
CREATE SERVER acces_target_server FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host '00.00.00.00', dbname 'access_target_db', port '5432');

-- 確認
SELECT * FROM pg_foreign_server;
```

### 外部接続ラッパー使うユーザを指定、マッピング

指定するもの

+ 接続元サーバ内に存在・使用するユーザ名
    + 例：here_user
+ 接続先のユーザ
    + 例：postgres
+ 接続先のユーザのパスワード
    + 例：password

勿論接続先の情報が正しくて権限がないと駄目です。

```sql
CREATE USER MAPPING FOR here_user SERVER common OPTIONS (user 'postgres', password 'password');

-- 確認
SELECT * FROM pg_user_mapping;
```

### 休憩　ここまでの登録情報を確認

ふむふむ。

```sql
select
 mapping.umuser,
 auth.rolname,
 mapping.umserver,
 server.srvname,
 mapping.umoptions
from pg_user_mapping as mapping

inner join pg_authid as auth
on mapping.umuser = auth.oid

inner join pg_foreign_server as server
on mapping.umserver = server.oid
```

### 接続したいTableを繋ぐ

指定するもの

+ 接続先にあるテーブル名
    + 例：target_table
+ 接続先にあるテーブルから取得したいカラムの定義
+ 接続元サーバ内で使用する接続先名称
    + 例：acces_target_server
        + さっき作ったね

接続元DBに既存の名称のテーブルと”同名称”の接続先テーブルと繋ぎたい時ってどうしたらいいんでしょうか…？？？
最初から命名に気をつけろって話？？？

```sql
CREATE FOREIGN TABLE target_table (
  target_id integer not null
  , target_name  character varying(100) not null
)
SERVER acces_target_server;

```

### ユーザに権限をふる
`USER MAPPING`したユーザがスーパーユーザだったら問題はないけれど、そうでなければ権限を振らないとエラーになります。

```sql
GRANT SELECT ON target_table TO here_user;
```


## dblinkじゃ駄目なんですか

前提に書いたこと無視して、いろいろ丸見えのままで良ければ、多分以下のやり方が楽チン。
いちいちカラム定義を指定してあげないといけないので、View化したいところ。

```sql
-- ①「dblink」拡張
CREATE EXTENSION dblink SCHEMA public;

-- ②コネクションを繋ぐ
select dblink_connect('conn1', 'hostaddr=00.00.00.00 port=5432 dbname=access_target_db user=postgres password=password');

-- ③select
SELECT * FROM dblink('conn1', 'SELECT target_id, target_name FROM public.target_table')
t1(target_id integer, target_name character(100));

-- ④使ったコネクションは閉じる
select dblink_disconnect('conn1');

```

## 参考

+ https://www.postgresql.jp/document/9.4/html/postgres-fdw.html
+ https://www.postgresql.jp/document/11/html/catalogs.html
Extend "Any" object for convenient log method e.g. this.log()

It is convenient to use a logging function that automatically prints the object from which the log call was made. Here, we extend the native Any object (from which all objects in Kotlin derive).

e.g. Call the following function from someObject:

```kotlin
this.log(someString, someOtherObject)
```

will show the following in LogCat:

```kotlin
applicatioName => someObject => someString, someOtherObject
```

```kotlin
// we extract the name of this object (derived from Any) from its simpleName member, 
// or its fullName if simpleName is empty (or is equal to the object's Companion 
// name because we called in a static method)
val Any.logClassTag: String
    get() {
        val simpleName = this::class.java.getSimpleName()
        if(
                simpleName.isEmpty() ||
                simpleName.equals("Companion")
        ) {
            val fullName = this::class.java.getName()
            return fullName.split(".").lastOrNull() ?: fullName
        }
        return simpleName
    }


// This general purpose method takes a variable number of arguments, and adds the 
// name of the calling object. Note that it requires spread operator (*) to pass 
// the contents of the vararg  "values", not values itself
fun Any.log(vararg values: Any?) {
    globalLog(this.logClassTag, *values)
}


// define an identifying tag that can be used to filter LogCat for the current app
// e.g. use the current flavor name if it is defined
private val identifier
    get() = BuildConfig.FLAVOR


// we define a general log function that formats the variable number of arguments 
// together with the calling object tag and an application identifier
fun globalLog(tag: String, vararg values: Any?) {
    val identifierAndTag = identifier + " => " + tag + " => "

    when(values.size) {
        0 -> return
        else -> {
            Log.d(
                    identifierAndTag ,
                    values.mapNotNull {
                        if (it is String) {
                            when(it.isEmpty()) {
                                true -> "<EMPTY>"
                                false -> it
                            }
                        }
                        else
                            it.toString()
                    }.joinToString(" "))
        }
    }
}

// we can further extend Any with methods that include predefined tags, which 
// can be filtered in LogCat to show only "ERROR" or "EXCEPTION"
fun Any.error(vararg values: Any?) {
    globalLog(this.logClassTag + " " + "ERROR", *values)
}

fun Any.exception(e: Exception, vararg values: Any?) {
    globalLog(this.logClassTag + " " + "EXCEPTION", e.message, *values)
    e.printStackTrace()
}
```
【Windows】Rails+Heroku+Carrierwave+S3 　でデプロイする

小学校の先生に向けに、板書の写真を共有できるオリジナルアプリを作りました。
Herokuでデプロイしたのですが、結構手こずったので記事にしておきます。

#まずは
こちらの記事を参考に進めていきました。
https://qiita.com/kazukimatsumoto/items/a0daa7281a3948701c39
（【初心者向け】railsアプリをherokuを使って確実にデプロイする方法【決定版】）

いくつかのエラーに見舞われたものの、ひとまずこれでデプロイが完了しました。

※Users_controller.rbの中にApplicationControlleという記述があり、ややハマりました。rがないからそりゃNameErrorなんだけどさ、ローカルでもエラー出してくれよ…

#画像が消える
よっしゃーデプロイできたー！と思ったのもつかの間、投稿時には普通に表示されていた画像が、しばらく経つと見られなくなっている…！？

調べてみたら、こんな記事が
https://qiita.com/hmmrjn/items/b02f076ceaeeaaceb999
（Herokuでアップロードした画像が時間経つと消える問題）

なるほど、どうやら正常な挙動のようだ。

ということでクラウドストレージS３を導入することにしました。スクールのカリキュラムで一度やっているとはいえ、AWSを扱うのは初心者としてはドキドキするのよね。

#S3の導入
以下の記事を参考に進めました。
https://qiita.com/hmmrjn/items/479c9e9ce82771f1b6d7
（【Rails】AWS S3を使ってHerokuで画像を投稿できるようにする方法）


自分のアプリはActiveStrageではなくCarrierwaveを使って画像のアップロードを行っていたので、こちらの記事も参考にしました。
https://qiita.com/nobu0717/items/a34a896f6e7ad68dc54e
（Rails+CarrierWave+heroku環境でAWS S3へ画像をアップロードする）


記事中に

```
$ EDITOR=vim rails credentials:edit
```

ってコマンドがあるんですけど、Windowsだからなのか

```
'EDITOR' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
```

って怒られちゃうんですよね。
いろいろ調べた結果、左下の検索ボックスで「システム環境変数の編集」→「環境変数」とたどって、ユーザー環境変数のところに新規で、

変数：EDITOR
値："C:\Users\~略~\Code.exe" -w -n
（editorの場所を示すパス。自分はvscodeがある場所を指定しました。-w -nの意味はよく分かっていません汗）

って設定してやることで、

```
rails credentials:edit
```

ってうつと勝手にeditorが起動してcredentials.yml.encを編集できるようになりました。ここがハマりポイントでした。

ちなみにcredentials.yml.encについては下記の記事も参考にしました。
https://qrunch.net/@WEkFtOQhlqcyDEsy/entries/bvfUcf0RmWqQ2NVH
https://qiita.com/NaokiIshimura/items/2a179f2ab910992c4d39

#でようやく
S3の導入が完了してuploadされているのを確認することができたのでした。
ちゃんとS3に投稿した画像が送られたときには歓喜でしたね。
QRコードをRaspberryPiカメラで読む

QRコードリーダーにトラブルがあったので、急遽RasberryPiカメラでQRコードを読むことにした。

まずは、QRコードを格納したイメージファイル test.jpg から、コードを抽出できるかどうか pythonプログラム で試してみます。

```

import zbar
import PIL.Image

file = 'test.jpg'

scanner = zbar.ImageScanner()
scanner.parse_config('enable')

# greyscale L
pil = PIL.Image.open(file).convert('L')
(width, height) = pil.size

# Return image as a bytes object
raw = pil.tobytes()

# The Y800 color format is an 8 bit monochrome format.
image = zbar.Image(width, height, 'Y800', raw)

# scan the image for barcodes
scanner.scan(image)

for symbol in image:
    print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data

del(image)

```



次に、このシェルスクリプトで

```

#!/bin/bash

scan_worker=""
scan_card=""
QRcode="dummy"

while :
do
	QRcode=`/var/www/html/qr_USBcamera_led.py $QRcode`
		if [ ${#QRcode} -eq 6 ]; then
			scan_worker=$QRcode
			#echo "this is worker"
		else
			scan_card=$QRcode
			#echo "this is card"
		fi
		if [ ${#scan_worker} -ne 0 ] && [ ${#scan_card} -ne 0 ]; then
			scan_date=`date "+%Y/%m/%d/%k/%M/%S"`
			scan_machine="in"
			#echo "this is line data"
			scan_line_data=${scan_date},${scan_worker},${scan_card},${scan_machine}
			echo "$scan_line_data" >> /home/pi/scan_line_data.log
			scp /home/pi/scan_line_data.log pi@192.168.1.137:/home/pi
			scan_worker=""
			scan_card=""
		fi
done

```
MacからUbuntuのファイルをNFSでマウントする

下記コマンドでマウントできる。細かいサーバーの設定は書かない。ググればすぐに見つかる。

```bash
$ sudo mkdir /Volume/aaa
$ sudo mount_nfs -P server:directory /Volume/aaa
```
よくわからなかったのは、オプション-Pを付けずに実行するとエラーが起きる。

```bash
$ sudo mount_nfs -P server:directory /Volume/aaa
mount_nfs: can't mount directory from server onto /Volumes/aaa: Operation not permitted
```

真面目にmanページを読んでみたが、よくわからない。

```
-P (resvport)

resvport
             Use a reserved socket port number.  This is useful for mounting servers that require clients to use a reserved port number on the mistaken belief that this makes NFS more secure. (For the rare case where the client has a trusted root account but untrustworthy users and the network cables are in secure areas this does help, but for normal desktop clients this does not apply.)
```

動いたので良しとする。
rand関数からメルセンヌ・ツイスターに乗り換えた話


この記事はC++を始めたばかりの方を対象としています。
プログラムで日々のご飯を食べている方や、スーパーなプログラマーの方々は好きなプリキュアについて語っていてください。

## はじめに

初心者向けの本やサイトでは、乱数を取得する際にrand関数を使用しているのを見かけます。
実際に自分が学んだ際もまずはそれで覚えました。

rand関数で範囲を指定して値を取得する方法として
`rand() % n;`
と書くことで0～n-1までの値を得ることが可能です。
  
## rand関数のだめなところ

しかしrand関数は0～32767の値までしか（環境にもよりますが）取得できず、`% n`といった範囲の指定もわかりにくいものとなっています。

少し逸れますが、Unityであれば
`Random.Range(0, n);`
とわかりやすく取得できます。

比較すると一目瞭然ではないでしょうか。
`rand() % n;`
`Random.Range(0, n);`

**このプログラムには問題がある**  
最大値(RAND_MAX)が32767の為、nの値が大きくなるほど取得する値に偏りがでてしまいます。

以下のプログラムは、rand関数で0～9999までの値を1億回繰り返して取得し、1000毎に取得件数を出したものです。

```cpp
#include <iostream>
#include <stdlib.h>
#include <time.h>
int main()
{
	// 取得した乱数の1000の位を基準に件数を保存する配列
	int randRes[10] = {};
	// 乱数初期化
	srand((unsigned)time(NULL));
	// 1億回乱数取得する
	for (int i = 0; i < 100000000; ++i)
	{
		// 0～32767 % 10000
		int tmp = rand() % 10000;
		// 1000で割ることで1000の位がいくつか取得する
		int index = tmp / 1000;
		// 該当する値を増やす
		randRes[index]++;
	}
	// 件数出力
	for (int i = 0; i < 10; ++i)
	{
		std::cout << "取得した値が"<<i * 1000 << "～" << (i + 1) * 1000 << "の件数：\t" << randRes[i] << " \n";
	}
}
```
実行すると、0～3000までの値が多くなっていることが分かります。

出力

```
取得した値が0～1000の件数：     12208837
取得した値が1000～2000の件数：  12209757
取得した値が2000～3000の件数：  11499748
取得した値が3000～4000の件数：  9157498
取得した値が4000～5000の件数：  9147998
取得した値が5000～6000の件数：  9157796
取得した値が6000～7000の件数：  9155344
取得した値が7000～8000の件数：  9153517
取得した値が8000～9000の件数：  9155966
取得した値が9000～10000の件数： 9153539
```

## そうだ！メルセンヌ・ツイスター！
この偏りを無くす方法として、C++11から追加された乱数ライブラリ「__std::random__」を使用します。  

メルセンヌ・ツイスター(Mersenne twister)については一番下に参考サイトを載せてあります。

以下のプログラムは上の処理をstd::randomで再現したものです。

```c++
#include <iostream>
#include <random>

int main()
{
	// 取得した乱数の1000の位を基準に件数を保存する配列
	int randRes[10] = {};

	std::random_device rnd;	// 非決定的な乱数生成
	std::mt19937 mt(rnd());	// 擬似乱数生成（メルセンヌ・ツイスター）。上で生成した乱数をシード値として扱う
	std::uniform_int_distribution<int> intRand(0, 9999);// 一様分布生成器
	
	// 1億回乱数取得する
	for (int i = 0; i < 100000000; ++i)
	{
		int tmp = intRand(mt);
		// 1000で割ることで1000の位がいくつか取得する
		int index = tmp / 1000;
		// 該当する値を増やす
		randRes[index]++;
	}
	// 件数出力
	for (int i = 0; i < 10; ++i)
	{
		std::cout << "取得した値が" << i * 1000 << "～" << (i + 1) * 1000 << "の件数：\t" << randRes[i] << " \n";
	}
}
```

実行すると、ほぼ均等に乱数が生成されているのが分かります。

出力

```
取得した値が0～1000の件数：     9994603
取得した値が1000～2000の件数：  10005293
取得した値が2000～3000の件数：  10005488
取得した値が3000～4000の件数：  10001651
取得した値が4000～5000の件数：  9994822
取得した値が5000～6000の件数：  9998745
取得した値が6000～7000の件数：  9998542
取得した値が7000～8000の件数：  9999179
取得した値が8000～9000の件数：  10004467
取得した値が9000～10000の件数： 9997210
```

## まとめ
ということでメルセンヌ・ツイスターを使おう！
おわり！

## 参考にしたサイト
>メルセンヌ・ツイスタ wikipedia 
https://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%AB%E3%82%BB%E3%83%B3%E3%83%8C%E3%83%BB%E3%83%84%E3%82%A4%E3%82%B9%E3%82%BF

>C言語による乱数生成
http://www.sat.t.u-tokyo.ac.jp/~omi/random_variables_generation.html
青森をちょっとずつ解析その２

#　使ったデータ

今回はこれ。

https://www.e-stat.go.jp/stat-search/files?page=1&layout=datalist&toukei=00200533&tstat=000001095335&cycle=0&tclass1=000001095377&tclass2=000001095393&tclass3=000001095396&stat_infid=000031616831

* 平成28年社会生活基本調査

1日の行動を20種類に分類し，時間帯別の行動状況から，行動の種類別に一人1日当たりの平均時間及び該当する行動をした人の平均時間などを週全体の平均または曜日別に集計しています。

平日について、男女別、総数のあたいをグラフ化

項目の番号は次の通り

['01_睡眠', '02_身の回りの用事', '03_食事', '04_通勤・通学', '05_仕事', '06_学業', '07_家事',
'08_介護・看護', '09_育児', '10_買い物', '11_移動(通勤・通学を除く)', '12_テレビ・ラジオ・新聞・雑誌','13_休養・くつろぎ', '14_学習・自己啓発・訓練(学業以外)', '15_趣味・娯楽', '16_スポーツ',
'17_ボランティア活動・社会参加活動', '18_交際・付き合い', '19_受診・療養', '20_その他', 'R1_（再掲）１次活動','R2_（再掲）２次活動', 'R3_（再掲）３次活動']


![actiontime.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163974/613cfe01-a8ab-578a-e55c-cdcfed7f9328.png)


17_ボランティア活動・社会参加活動　⇒　男が高い。（実は元データでトップの数字。２位は佐賀県.女だったが、１位と２位の差は結構あった。


19_受診・療養　⇒　これも男女ともに高い。都道府県で比べると男２位、女４位になっている。病院の待ち時間が長いのか、時間つぶしをしているのか、調査票B側でわかる？


そして意外と18_交際・付き合い時間をとっている。

このデータは
行動の種類別行動者平均時間(10歳以上)
なんだけど、よくわからん。


次、「行動の種類別総平均時間(10歳以上)」をとってみよう。
たぶんこっちが求めるもののような気がする。

本当は２０１３年に出た統計と比べたいけどあっちは１５歳以上ってなってる。基準を変えてくるのかぁ、、うーん
SynchRoidのDAでファイルパスを指定してファイルを開く方法

#何をしたいか

SynchRoidのDAにて、ファイルパスを指定してファイルを開きたい。

#基礎編

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420678/987117ff-b8df-be92-0060-b805cdc9f32b.png)

まず、ファイルを開くために使用する「Open」ステップを挿入する。
挿入した際の初期設定は↑のようなもの。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420678/0a568b17-0201-d09c-337e-085aeb56a247.png)

Use　の箇所を今自分が使っているデバイスを選択

URIのところに、exeを記入する

そうすると、exeファイルが起動し

今回の場合だと、windows Media　プレイヤーが開く



#応用編

これを応用して、ファイルパスを指定して　ファイルを開くことが出来る。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420678/17e4983e-d779-b292-5512-3a9c03d94f1b.png)

通常このフォルダパスを指定する場合

C:\Program Files (x86)\Kapow DeviceAutomation 10.3.0.7 321 x32

となる


通常であれば「\　や　￥」を使うと思うが、

DAでファイルパスを指定する場合は「\」や「￥」を　　「/」に変更する必要があり、

また　URIでパスを指定する場合は、「file://パス」と記載する必要がある。


これに基づいて、パスを書き換えると

```
C:\Program Files (x86)\Kapow DeviceAutomation 10.3.0.7 321 x32\開きたいファイル

↓

file://C:/Program Files (x86)/Kapow DeviceAutomation 10.3.0.7 321 x32/開きたいファイル
```

となる。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420678/cd63bd4f-4d56-e2be-e44c-069cebcf2d88.png)


直接入力しなくても、事前に変数にパスを入れておいて
URIに変数を入れるやり方でも可能。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420678/c9a45eb8-a499-cc7a-4016-0ee5ec7a4f41.png)


テキスト型の変数「パス」にファイルパスを入れた状態でも、きちんとファイルを開くことが出来た。
再起SQLで擬似カレンダーテーブルを作成するメモ

週間,月間帳票系で日付のテーブルを作ってFROM句のメインにに添えたくなるが、
作成自体は簡単なクエリで作成できるのでメモ

```sql
SELECT TRUNC(SYSDATE,'MONTH') + LEVEL -1 AS DAYS
  FROM DUAL
CONNECT BY LEVEL <= LAST_DAY(SYSDATE) - TRUNC(SYSDATE,'MONTH') +1
```
月末月初の差分を取得してlevelのところで対応といった形、
これで当月の1日～月末までの疑似テーブルの生成が可能。

もしPJでカレンダーテーブルを作る等の話が出ていれば、
個人的には疑似テーブルを作るfunctionを生成して、登録した情報のみをDBに入れるほうが
好みなので検討してみてください。
既存のディレクトリに`ln -s`でシンボリックリンクを付与する

# 既存のディレクトリにシンボリックリンクを付与

### ファイル全体像
```
root
┣ public
  ├storage
┣ storage
  ├img
   ├ 画像ファイルなどをローカル保存
```

### やりたいこと
`root/storage/img`以下を`root/strage/`に同期させたい。

## 既存のディレクトリに何も考えずに`ln -s`
```
$ pwd
> root/public/

$ ln -s root/storage/img storage

$ ls -l
> storage

$ cd storage

$ ls -l
> img -> root/storage/img/
```
何故か`root/public/storage/img`が作成されて同期…
違う！`root/storage/img`以下を`root/strage/`に同期させたいんだ！

## 既存のディレクトリを削除して再度`ln -s`
どうせ同期されれば元の`storage`ディレクトリ
は存在しなくなるんだ！
消しちゃえ!

```
$ rm -r root/public/storage/
```
もう一度`ln -s`

```
$ pwd
> root/public/

$ ln -s root/storage/img storage

$ ls -l
> storage -> root/storage/img
```

成功！

## 補足
```
$ ln -s {リンク元のパス} {リンクされるパス}
```

## 参考
`ln`コマンドについての記事
https://www.atmarkit.co.jp/ait/articles/1605/30/news022.html
https://qiita.com/nat/items/5b896a66ec9d55105285
[勉強用] React hooksで非同期処理を書く (ステップ2)

## はじめに

[前ステップ](https://qiita.com/daishi/items/f78cf1b088961413170a)から続き、勉強用のuseFetchを書いていきます。

## 課題

ステップ1のコードを使うと、次のようなワーニングが出る場合があります。

>
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

破棄されたコンポーネントに対して更新処理をしようとして怒られています。このワーニングを意図的に出すには、useFetchを使っているコンポーネントに`key`プロパティを設定して、それを変更します。1秒以内に破棄されると、その後`setResult`を実行するところでワーニングとなります。

## ステップ2: cleaned-upフラグ

```javascript
const useFetch = url => {
  const [result, setResult] = useState({});
  useEffect(() => {
    let cleanedUp = false;
    const fetchData = async () => {
      const response = await fetch(url);
      const data = await response.json();
      if (!cleanedUp) {
        setResult({ data });
      }
    };
    fetchData();
    const cleanup = () => {
      cleanedUp = true;
    };
    return cleanup;
  }, [url]);
  return result;
};
```

ステップ1からの差分はcleanupの処理が入ったことです。useEffectで非同期処理を扱う場合はほぼ例外なくcleanup処理を入れることが必須です。今回のケースでは、単純に`cleanedUp`フラグを用意してcleanup後に`setResult`を実行しないようにしました。 [参考](https://qiita.com/daishi/items/4423878a1cd7a0ab69eb#アンマウントのフラグを持つ) [^1]

[^1]: 過去の記事では「アンマウントのフラグ」と書いていましたが、関数コンポーネントにおいてマウント・アンマウントという表現を使うのは正しくない気がするので、「破壊」とか「クリーンアップ」と呼ぶようにしてみようかと思います。ただ、この呼び方もより良いものが見つかれば変えるので、定着したものではありません。

このフラグによる処理の中断を「キャンセル」と読んでいる記事をたまに見かけますが、これは非同期処理のキャンセルとは呼べるものではないので注意してください。

## 動作確認

実際に動くコードはこちらです。[codesandbox](https://codesandbox.io/s/charming-minsky-gegdo)

## おわりに

本コードは勉強用ですので、そのままでは使わないでください。(ちゃんとした実装は[こちら](https://qiita.com/daishi/items/f12f524e9d1df0b52d2b))
さらなる課題と解決は[次のステップ](https://qiita.com/daishi/items/cdd1109ffa12826db44a)へ。
【VSCode】開いているファイルとサイドバーのエクスプローラーを連携する方法

# やりたいこと
- `vscode` で現在開いているファイルとサイドバーが連携されていなかった
- これを連携することで開いているファイルの場所がサイドバーにも表示されるようになる

# 方法
1. `cmd + ,` などで設定ファイルを開く
2. `reveal` と検索する
3. `Explorer: Auto Reveal` にチェックをつける