OmniAICreator/Qiita-1.07M huggingface dataset:
[メモ] SQL学習1 (WHERE, 比較演算子, LIKE, NOT, IS NULL, IS NOT NULL, AND, OR, ORDER BY, LIMIT)

# はじめに

- 表自体を「テーブル」と言う
- 縦の列を「カラム」と言う
- 横の列を「レコード」と言う
- SELECTで全カラムから取得する場合は「*」を使う
- SQLは大文字小文字は区別されない
- 最後は必ずセミコロン(;)をつけてクエリの終わりをデータベースに教える
- データ指定時にテキスト型と日付は必ずダブルクォーテーション(")またはシングルクォーテーション(')で囲む、数値データはその必要はない

# WHERE

特定のデータを取得する「どこの」を意味を持つ「WHERE」を使う。
どこのレコードを取得するかを指定できる。

```sql
SELECT 取得したいデータが入っているカラム名
FROM 上記で指定したカラム名が存在するテーブル名
WHERE 特定のカラム名と様々な条件;
```

以下の例はUserテーブルのnameカラムのデータが「森田」であるデータを取得している。

```sql
SELECT *
FROM user
WHERE name = "森田";
```

# 比較演算子

| 比較演算子の種類    |       意味                 |
|:----------------:|:--------------------------|
| a < b            |   a が b より小さいデータを検索 |
| a > b            |   a が b より大きいデータを検索 | 
| a <= b           |   a が b 以下のデータを検索   | 
| a >= b           |   a が b 以上のデータを検索   |

以下の例はEventテーブルのpurchased_atカラムのデータが2019-11-01以降のデータを検索している。

```sql
SELECT *
FROM event
WHERE purchased_at >= "2019-11-01";
```

# LIKE

ある特定の文字を含むデータを取得したい場合は「LIKE」を使う。
基本形は以下のようになる。

```sql
SELECT *
FROM user
WHERE name LIKE "文字列";
```

LIKEを使う際は**ワイルドカード(%)**を用いる。
**ワイルドカードは必ずクォーテーション内につけること。**

以下の例は「おでん」を含むデータを全て取得している。

```sql
SELECT *
FROM food
WHERE name LIKE "%おでん%";
```

「おでん」を例にワイルドカードを以下にまとめた。

|                  | 検索結果         | 意味                                    |
|:-----------------|:----------------|:---------------------------------------|
|      %おでん%    | 味噌おでん, おでんくん | 前後関係なく、「おでん」を含む全ての文字列を検索 |
|      %おでん      | おでん, 関西風おでん | 最後の文字が「おでん」を含む文字列を検索(後方一致) |
|      おでん%      | おでん, おでん定食 | 最初の文字が「おでん」を含む文字列を検索(前方一致) |

# NOT

特定のものを含まない条件でデータを取得する際に使われる。

以下の例は価格が1000円以上を含まないフルーツを検索している。

```sql
SELECT *
FROM fruit
WHERE NOT price >= 1000;
```

ワイルドカードと併用可能。

```sql
SELECT *
FROM food
WHERE NOT name LIKE "%チョコ%";
```

# IS NULL

なんのデータも保存されていない場合はNULLとなる。
NULLを含むデータを取得したい場合は「IS NULL」を使う。

以下の例はuserテーブルのageカラムのデータがNULLであるものを取得している。

```sql
SELECT *
FROM user
WHERE age IS NULL;
```

# IS NOT NULL

IS NULLとは逆に、NULLを含まないデータを取得したい場合は「IS NOT NULL」を使う。

以下の例はuserテーブルのageカラムのデータがNULLでないものを取得している。

```sql
SELECT *
FROM user
WHERE age IS NOT NULL;
```

なお、NULLを含む/含まないデータを取得する際に以下(A,B)のようにイコール「=」を使うことはできない。

```sql
-- A
SELECT *
FROM user
WHERE age = NULL;

-- B
SELECT *
FROM user
WHERE NOT age = NULL;
```

# AND

複数の条件を満たすデータを取得したい場合に使われる。

以下の例はuserテーブルの出身地カラム(北海道)と年齢カラム(20歳)の両方を満たすデータを検索している。

```sql
SELECT *
FROM user
WHERE local = "北海道"
AND age = 20;
```

# OR

複数の条件のうち、どちらか片方を満たすデータを取得したい場合に使われる。

以下の例はuserテーブルの出身地カラム(北海道)と年齢カラム(20歳)のどちらか片方を満たすデータを検索している。

```sql
SELECT *
FROM user
WHERE local = "北海道"
OR age = 20;
```

# ORDER BY

取得したデータを並び替える際は「ORDER BY」を使う。
クエリの末尾に記述する。 WHEREと併用可。

- ASC(昇順)は、小 → 大へ
- DESC(降順)は、大 → 小へ

以下の例は取得した結果を降順に並び替えている。

```sql
SELECT *
FROM fruit
WHERE price >= 300
ORDER BY price DESC;
```

# LIMIT

取得したいデータ件数を制限できる。
ORDER BYと同様にWHEREと併用可。
クエリの末尾に記述する。

以下の例はWHEREで指定した条件で5件のデータを取得している。

```sql
SELECT *
FROM fruit
WHERE price >= 300
LIMIT 5;
```
Ubuntu 18.04 に fess をインストールする

公式のドキュメントに沿ってFessをインストールしてみた。
[Fessインストールガイド](https://fess.codelibs.org/ja/13.4/install/index.html)
[Fessチュートリアル](https://fess.codelibs.org/ja/tutorial.html)
[Install Elasticsearch with Debian Package](https://www.elastic.co/guide/en/elasticsearch/reference/7.4/deb.html#deb-repo)


今回、インストールした環境

- OS : Ubuntu 18.04.3 LTS 64bit
- Java : OpenJDK 11.0
- Elasticsearch : 7.4
- Fess : 13.4

Javaのインストール
-
公式ドキュメントの要件にJava11とあるのでJavaのインストールから。

```shell
$ sudo apt-get install openjdk-11-jdk
```

elasticsearchのインストール
-
"elasticsearch"の公式ドキュメントに従ってインストールしていく。
Fessに対応するバージョンのElasticsearchをインストールする。
Fess 13.4は最新のElasticsearch 7.4をサポートしているので今回はこれをインストール。
[Install Elasticsearch with Debian Package](https://www.elastic.co/guide/en/elasticsearch/reference/7.4/deb.html#deb-repo)


```shell
$ wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
$ sudo apt-get install apt-transport-https
$ echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-7.x.list
$ sudo apt-get update && sudo apt-get install elasticsearch
```

Fess にアクセスするために設定ファイル（/etc/elasticsearch/elasticsearch.yml） に以下を追記する。

```text
configsync.config_path: /var/lib/elasticsearch/config
```

Fessのインストール
-
```shell
$ wget https://github.com/codelibs/fess/releases/download/fess-13.4.2/fess-13.4.2.deb
$ sudo dpkg -i fess-13.4.2.deb
```
Elasticsearch の機能を拡張するためのFessプラグインを Elasticsearch の plugins ディレクトリにインストールする。

```shell
sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install org.codelibs:elasticsearch-analysis-fess:7.4.0
sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install org.codelibs:elasticsearch-analysis-extension:7.4.0
sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install org.codelibs:elasticsearch-configsync:7.4.0
sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install org.codelibs:elasticsearch-dataformat:7.4.0
sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install org.codelibs:elasticsearch-minhash:7.4.0
```

これでインストール完了。


下記のように起動・停止できるはず。

```shell
$ sudo systemctl start elasticsearch.service
$ sudo systemctl start fess.service
$ sudo systemctl stop fess.service
$ sudo systemctl stop elasticsearch.service
```

自動起動を設定するなら

```shell
$ sudo systemctl daemon-reload
$ sudo systemctl enable elasticsearch.service
$ sudo systemctl enable fess.service
```

デフォルトで利用するポートは8080なので、
起動して http://localhost:8080/ にブラウザでアクセスできればOK。
Opencv4.1 + Windows10 + Python3.7.5のcv2.VideoCaptureで正しく表示されない

# 症状
### 環境
- os : windows10
- opencv4.1
- python3.7.5(3.6でも同様の環境)
- 仮想環境：venv, anaconda　どちらも試したが同様の現象

### Opencv
```VideoCapture.py
import cv2
 
camera = cv2.VideoCapture(0)
camera.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
 
while True:
    ret, frame = camera.read()
    cv2.imshow('camera', frame)
 
    if cv2.waitKey(1) & 0xFF == ord('q'):
        cv2.imwrite("capout.jpg", frame)
        break
 
camera.release()
cv2.destroyAllWindows()
```
![capout.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264392/d8de34e4-7b9d-c792-cda6-b59a2fa054a0.jpeg)  

### Windows標準カメラ
![WIN_20191122_16_41_19_Pro.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264392/f7deb3d3-c43e-07b4-6d6d-e3fb34e45d73.jpeg)  
Windows標準カメラでは、1080pを選択時、正常にWebカメラから映像が出力されるが、OpencvのVideocaptureを使用時は、参考画像のように、両サイドが黒く埋められる他、解像度自体も、引き延ばしたような粗さを感じる。他にも1080pで60fpsの動画が撮影可能なカメラにも関わらず、フレームレートが上がらない。（VideoCaptureのget関数では、設定値が反映されるが、実際にフレームレートを計測すると30fpsで頭打ちされる。）

# 解決策
以下のサイトで同様の現象が報告されていたため、解決方法を実行してみた結果解決。
[OpenCV capturing imagem with black side bars](https://stackoverflow.com/questions/52043671/opencv-capturing-imagem-with-black-side-bars)

```VideoCapture2.py
import cv2
# ストリーミングをDSHOWに変更
camera = cv2.VideoCapture(0, cv2.CAP_DSHOW)
camera.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
 
while True:
    ret, frame = camera.read()
    cv2.imshow('camera', frame)
 
    if cv2.waitKey(1) & 0xFF == ord('q'):
        cv2.imwrite("capout.jpg", frame)
        break
 
camera.release()
cv2.destroyAllWindows()
```
# 原因
直接の原因はWindowsが悪いのか、Opencvのバージョンの問題なのかわからないが、DirectSHOWと呼ばれるストリーミング形式を使用すると解決できた。以下に、DirectSHOWについての解説を参照しておく
[qiita_directshow](https://qiita.com/watarus0208/items/294ed15c4c7d27f7de23)
今まで、普通にOpencvのVideocaptureを使用してきたが、今まで（別環境）デフォルトのストリーミングで問題なかったため、疑問が残る。また、この変更によって利用できないオプション等や著しい遅延が確認出来たら追記していきます。
【Swift】UIPageControlをインスタストーリーっぽくしてみる

## はじめに
デフォルトのUIPageControlが微妙だったのでインスタストーリーっぽくしてみました</b>

### これを
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192874/74a1a336-62dc-01ae-67d6-cd48f4459868.gif">
### こうする
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192874/d2f1fc70-6eac-5196-d4c0-2e9b809b2656.gif">

## やりかた
`UIPageControl`クラスの`layoutSubviews()`を以下のようにoverrideする

```swift
import UIKit

class CustomUIPageControl: UIPageControl {
    
    override func layoutSubviews() {
        super.layoutSubviews()
        guard !subviews.isEmpty else { return }
        
        let numberOfSubview = CGFloat(subviews.count)
        
        // 横棒同士の空白、横棒の長さ・高さを設定
        let spacing: CGFloat = 3
        let width: CGFloat = (frame.size.width - ((numberOfSubview - 1) * spacing)) / numberOfSubview
        let height = spacing
        
        var total: CGFloat = 0
        
        // ドットのビューを横棒に修正
        for view in subviews {
            view.layer.cornerRadius = 1.5
            view.frame = CGRect(x: total, y: frame.size.height / 2 - height / 2, width: width, height: height)
            total += width + spacing
        }
    }
}
```

## おわりに
意外とあっさりできますよね！
今回はドットを横棒にしただけですが、画像を埋め込むなどもっと工夫できそうです！
デフォルトのUIPageControlが微妙だけどライブラリを入れるほどでもないなー、、と思ってる方！よろしければ参考にしてみてくださいm(_ _)m
ラズパイのCPU温度をAmbientに送ったりそれまでの環境構築など

# はじめに
ゼミ室のラズパイ(Volumio)がよく落ちているのでそれの原因突き止めるためにやってみました。
みんなで開発できやすいようにと、公開もできるように環境構築もやってみたのでメモです。

今回はまず原因突き止めのためにCPU温度のAmbientに送ってログをとってます。

# 環境
- ラズパイ2B+ (Volumio ver2.668)
- (ラズパイ内)node v8.11.1
- (ラズパイ内)npm v5.6.0

最新のvolumioでもnodeのバージョンはv8ですのでこれからあえて変えずにいきます。

# 実装
## 概要
<img width="547" alt="スクリーンショット 2019-11-22 15.34.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76572/06329849-7ef1-2180-c792-d3b69d5aa196.png">

ラズパイは前述したとおりなんかよく落ちるし、起動しなくなっちゃってOS再インストールなんてこともある。
ので、ラズパイだけにソースコードがあるのがよくないでした。(落ちなかったとしても怖いですよね)
さらにアプリ導入も簡単にしたかったでした。
本来ならばdockerなど環境そのままもっていきたいのですが、dockerを入れるところで躓いたのでそれはまた今度で...

## keyファイルについて
https://www.rhoboro.com/2016/06/28/environment-variables.html
これのうちの「別ファイルに書き出し、そこから読み取る」でやってみました。
環境変数は犯したくないってのは思いますよね。
また、githubのプライベートリポジトリにしてもよかったのですが、あえてパブリックにしてオープンなゼミにしようという感じです。
ちなみに自分はすでに卒業して結構経ってます...

## Githubで共有しています
ということでコードはオープンにgithubにあげています。
https://github.com/amaokalab/LabpiDev

オーガナイズなアカウントっぽいのでゼミ生で共同開発できるのもいいところですね。
使い方、実行方法もいちようreadmeに書いたあります。
簡素ですがこれでゼミ生全員がラズパイ復旧できるようにできたらなと思っています。

## foreverについて
### 実行タイミング
CPUTempLog/send2AmbiInterval.js内から一部抜粋

```javascript
async function main() {
  // 0分ちょうどだけ送りたい
  let nowTime = new Date();
  if (nowTime.getMinutes() != 0) {
    return;
  }

  ...
}

// 1分に一回だけ処理
setInterval(main, 60000);
```

foreverを使ったものってcronと違い「1時間毎」になってしまい「00分の時」にできなかったでしたが、このようにすることで同じように「00分の時」を実現しました。
そもそもvolumioにcronは最初からは入ってないですし...

### ローカルにインストール
本来は

```
npm i -g forever
```

でグローバルにインストールするのが普通ですが、グローバルを犯さないということを徹底してみました。
foreverを同じように実行するにはプロジェクトフォルダ内にて

```
./node_modules/forever/bin/forever list
```

などで実行します。
逆に面倒ですかねぇ...

### 追記
ptxコマンドを使うとよさそうです
https://qiita.com/lambda_funtaro/items/865f178628a035acbe5a

## 再起動時
https://qiita.com/karaage0703/items/ed18f318a1775b28eab4

```
sudo nano /etc/rc.local
```

ちなみにvolumioにはviも入っていないのでnanoで

```
cd /home/volumio/LabpiDev
npm run cpuForever

exit 0
```

こんな感じに書きました。
グローバルを犯しました。残念...

これで実行されるとsudoで実行したことになるので、foreverのlistを見たいときもsudoをつけます。

```
sudo ./node_modules/forever/bin/forever list
```

これも結局グローバルにインストールすべきかもなぁ...

# ゼミ生はこれで使えるようになったのか
これから見ていきたいです。
肝は

- keyファイル
- Ambientのキー類の入力
- 再起動時の設定

今度は、UPSやモバイルバッテリーを使ったりして対策するのが普通ですね。
政見放送動画をIPPONグランプリ風にしてみた(OpenCV:Python版)

# きっかけ
動画内の文字を抽出しようと二値化してみたところ、背景が自然環境下ではなくクリアで何も写っていないためか人物とテロップのみが抽出された訳ですが、、、背景色黄色にしたらIPPONグランプリっぽくなるんじゃないかと思い実装してみました。

# 開発

```Python
import cv2
import numpy as np

if __name__ == '__main__':

	cap = cv2.VideoCapture('one_minutes.mp4')

	cap_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
	cap_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
	fps = cap.get(cv2.CAP_PROP_FPS)

	telop_height = 50

	fourcc = cv2.VideoWriter_fourcc('m','p','4','v')
	writer = cv2.VideoWriter('threshold_raw.mp4',fourcc, fps, (cap_width, cap_height + telop_height))

	kernel = np.ones((3,3),np.uint8)

	count = 0
	try :
		while True:
			if not cap.isOpened():
				break

			if cv2.waitKey(1) & 0xFF == ord('q'):
				break

			ret, frame = cap.read()

			if frame is None:
				break

			frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
			ret2, frame = cv2.threshold(frame, 0, 255, cv2.THRESH_OTSU)

			#収縮 -> 膨張
			frame = cv2.morphologyEx(frame, cv2.MORPH_OPEN, kernel)

			background = np.zeros((cap_height, cap_width, 3), np.uint8)
			background[:] = tuple((80,235,247))

			telop = np.zeros((telop_height, cap_width, 3), np.uint8)
			telop[:] = tuple((128,128,128))

			#一旦モノクロ(dim=1)からカラー(dim=3)に変換
			frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)
			#背景色と合成
			frame = cv2.bitwise_and(frame, background)

			images = [frame, telop]

			frame = np.concatenate(images, axis=0)
			font = cv2.FONT_HERSHEY_SIMPLEX
			cv2.putText(frame, "{:.4f} [sec]".format(round(count/fps, 4)), 
						(cap_width - 250, cap_height + telop_height - 10), 
						font, 
						1, 
						(0, 0, 255), 
						2, 
						cv2.LINE_AA)

			writer.write(frame)
			count += 1

	except cv2.error as e:
		print(e)	

	writer.release()
	cap.release()

```

### 補足

`ret2, frame = cv2.threshold(frame, 0, 255, cv2.THRESH_OTSU)`
で二値化しています。 ここでは大津のアルゴリズムを使っています。

`frame = cv2.morphologyEx(frame, cv2.MORPH_OPEN, kernel)`
では二値化した画像から収縮 -> 膨張して収縮の段階で白い斑点が黒く塗りつぶされてノイズが除去されます。

```python

background = np.zeros((cap_height, cap_width, 3), np.uint8)
			background[:] = tuple((80,235,247))
background[:] = tuple((80,235,247))

#一旦モノクロ(dim=1)からカラー(dim=3)に変換
frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)
#背景色と合成
frame = cv2.bitwise_and(frame, background)
```
では黄色の単一背景色を作成し、二値化した画像と`bitwise_and`で合成しています。

# 結果

### オープニング処理なし(加工なし)
![threshold_raw.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288206/1389ffde-9b2a-4ddb-1f2e-d8e5a34d5f29.gif)


### オープニング処理あり
![threshold_open.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288206/1cf286f7-26fb-7a1e-ecae-c9d24d9a4fba.gif)

少しわかりにくいかもしれませんが、上の政党名をみていると収縮縮小をした方がノイズが消えているのがわかると思います。


# おわりに
割ときれいにオブジェクトを分離することができたので、次回は文字を抽出してみようと思います。


# 参考にしてみたリンク
- [opencv-python オープニング(Opening)](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_morphological_ops/py_morphological_ops.html#opening)
- [opencv-python ビット単位での処理](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_gui/py_video_display/py_video_display.html)
- [IPPONグランプリ](https://www.fujitv.co.jp/ippon/)
VScodeでマークダウン記法をプレビューするまで

## Markdown記法って書いてて気持ちいいですよね
シャープでタイトルになるとかすごい

## VScodeでマークダウンのプレビューができなかった
拡張機能をいくつか入れてたのが
原因だったんだろうかと考えました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/365e9971-f021-47b3-7a1d-4b6001b3ca08.png)

## まずは考えなしに入れた拡張機能をすべてアンインストール
こちらを参考にさせていただきました！
[macos – Mac上でvscodeを完全にアンインストールする方法](https://codeday.me/jp/qa/20190228/339314.html)

```bash:Mac上でvscodeを完全にアンインストールする
rm -fr ~/Library/Preferences/com.microsoft.VSCode.helper.plist 
rm -fr ~/Library/Preferences/com.microsoft.VSCode.plist 
rm -fr ~/Library/Caches/com.microsoft.VSCode
rm -fr ~/Library/Caches/com.microsoft.VSCode.ShipIt/
rm -fr ~/Library/Application\ Support/Code/
rm -fr ~/Library/Saved\ Application\ State/com.microsoft.VSCode.savedState/
rm -fr ~/.vscode/
```

## 結局そんなことではなかった…

`cmd-k,v`でもダメ`cmd+shift-v`でもダメ
そもそもVScodeを仕組みを理解してないんですよね

## ここでした

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/fe33996d-f35a-4d8c-75ec-98b999c0cb4e.png)
VScode画面の右下`Plain Text`となっているところをクリック
### すると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/8d34147b-fd70-6ab2-61c0-b06046a68cb5.png)

## あるやん！Markdown
選択すると、あらかじめMarkdown記法で書いたテキストに色がつきました（ワクワク）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/ba5cbc7b-ad7d-2e1e-fd41-bd6158974886.png)

## 願いを込めて…`cmd-k,v`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/f0a67dbc-3475-dea2-fcca-53b568e5c3d4.png)
来ました！！

### 保存をしてみると
mdファイルとなるようです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/cf13b89f-3b69-621a-4eb4-7738c2253c3c.png)
### 右下もMarkdownになってる…
そりゃそうですわな
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/7708dddf-1de0-5070-3742-89460eafa052.png)

**これで何時間費やしたことか…**

# 最後に
Markdownを書くとき
シャープとかの後にはスペースを入れるそうです
タイムゾーンの設定

# アプリケーションのタイムゾーンを日本時間に設定する。

### 現状は..協定世界時の現在時刻(UTC/UTC+0000)表示となっている。
<img width="184" alt="スクリーンショット 2019-11-22 17.08.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378066/f22f6579-9dc4-d6b3-35cf-f4676b06da1f.png">



### 日本時間..日本標準時の現在時刻(JST/UTC+0900)へ変更したい。

### どこを変えるのか？
`root/config/application.rb`ディレクトリの中に、`config.time_zone = 'Tokyo'`を記述する。

```root/config/application.rb
require_relative 'boot'

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module BoardApp
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.0

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.
    config.time_zone = 'Tokyo'  #<= ここに記述する。
  end
end
```
### 表示の確認
<img width="190" alt="スクリーンショット 2019-11-22 17.12.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378066/78b3c9a4-44b2-c55a-f3d3-692488d5eafe.png">
かわった！

だけど、いまいち見にくい。。。


### strftimeメソッドを使って表示を見やすくする。
```rb

<td><%= board.created_at.strftime('%Y年 %m月 %d日 %H時 %M分') %></td>
```
created_atの後に`strftime('%Y年 %m月 %d日 %H時 %M分')`メソッドを追加。


<img width="194" alt="スクリーンショット 2019-11-22 17.17.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378066/0b2696dc-3504-846c-32b2-99b88eab5cbc.png">

見やすくなりました！！パチパチ

#### でも毎回これを書くのは面倒。

`root/config/initializers/ここに任意のファイルを作成`

予め表示形式を定義しておくことができる。

```ruby

Time::DATE_FORMATS[:datetime_jp] = '%Y年 %m月 %d日 %H時 %M分'
```
`[:datetime_jp]`名は任意でOK!

そしてViewファイルにはこのように記述

```ruby
<td><%= board.created_at.to_s(:datetime_jp) %></td>
```

便利...ほっこり
pip3でTypeエラーが出るようになった時の対処



Mac にて pip3 のアップデートを行ったところ、以下のエラーが出るようになった。

```
Traceback (most recent call last):
  File "/Library/Developer/CommandLineTools/usr/bin/pip3", line 10, in <module>
    sys.exit(main())
TypeError: 'module' object is not callable
```

直前に

```
xcode-select --install
```

は実施済だったため別の対処方法を探したところ、同様の事象で stack overflow に  [Problems using zsh with Catalina, Python/Python3, pip/pip3, PATH, zshrc, etc](https://stackoverflow.com/questions/58423609/problems-using-zsh-with-catalina-python-python3-pip-pip3-path-zshrc-etc) というのがあったので参考にし、以下の通りHomebrewでPython3の再インストールを実施しました。
　※元々Python3をHomebrew経由でインストールしていたため

```
brew install python3
```

この後ターミナルを再起動し pip3 コマンドが正常に動くことを確認しました。
ターミナルを再起動せずに pip3 コマンドを実行してもエラーが出たままだったので、エラーが解消しない場合はご参考にしてください。
【ElasticSearchエラー】Specifying types in urls has been deprecated

- 現象

LaravelでElasticSearch使ってる時にsearchメソッド呼んだ時に死亡。


- 対策

7.0.0バージョンからurlでの型指定が廃止になってるので、バージョン下げれば動いた。
バージョン下げるかフォーマット変えるかすれば良い。


```
composer require elasticsearch/elasticsearch:7.1
>
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 0 installs, 1 update, 0 removals
  - Downgrading elasticsearch/elasticsearch (v7.4.0 => v7.1.0): Loading from cache
Writing lock file
Generating optimized autoload files

```

# 参考

https://stackoverflow.com/questions/57428399/error-while-creating-a-mapping-for-document-type-under-an-index-in-elastic-searc

https://www.elastic.co/guide/en/elasticsearch/reference/master/removal-of-types.html
java初級編 4

こちらを読んでいただく前にまずjava初級編3がありますのでそちらを拝見ください⬇️⬇︎＾＾

https://qiita.com/shinpachix/items/6f6f972e7980f4c59d3d


##continueとbreak
continue - 繰り返しの最初に戻って次の周回へ行く
break - 繰り返しを終了して次へ

```
int x = o;
while(true) {
//xが1の時ここへ戻る(printlnは実行されない)
x++;
if(x==1)continue;
System.out.println(x);
if(x==10)break;
}
//breakするとここへ
```

##配列

```
String[] a = new String[3];
a[0] = "こんにちは";
a[1] = "おはよう";
a[2] = "さよなら";

for(int i = 0; i < 2; i++) {
System.out.pintln(a[i]);

```

一つの変数を複数の変数の列のように扱える
[]の中を添字と言う。　0から始まる。　添字の数を次元と言う
。
添字の指定に変数が使えるのでfor文と組み合わせると使い勝手がいい。

##多次元配列

```
String[][] cell = new String[9][9];
a[0][2] = "歩";
a[5][5] = "飛車";
a[3][3] = "王将";

System.out.println(a[5][5]);
//飛車

```

配列変数をさらに配列にすると次元を増やす事ができる。
二次元配列は将棋やオセロの駒などの管理に使える。

##右辺の評価

AND演算子は&&と&、OR演算子は||と|がありますが挙動に若干違いがあります。

(ANDで左辺がfalseだったり、ORで左辺がtrueの時)
右辺を見ないので早い(意図的に右辺を実行したい時に&と|を使う)

```
int a = 5;
if(true || a++ > 0) {
System.out.println(a);
}
//5がでる

if(true | a++ > 0) {
System.out.println(a);
}
//6が出る
```


##関数(function)

数学での関数


```
f(x) = 3x+1

f(4) = 13

```


入力された値に対して決まった演算を行う。

##プログラムでの関数

プログラムでの関数


```
public static int hoge(int x) {
return (int) Math.pow(x,2)+3*x+1;

System.out.println(hoge(4));

```

値(引数)　を渡すと処理を行い、値（返り値）を返す

呼び出された時に実行される

プログラムでは引数がない関数もある

返り値はreturnで返す(javaの場合)
publicやstaticについてはまた今度、、、

##メソッドと関数

クラスの中に書いてある関数はメソッドと言います。（すごく大雑把な言い方ですが、）

クラス自体の話はまた今度、、
javaではクラスがあってその中にプログラムを書くのでメソッドと呼びます。

##メソッドの書き方

メソッドの定義

```
public static int hoge(int x) {
return (int)Math.pow(x,2)+3*x+1;
}
```

返り値の型　メソッド名（引数の型　引数名、引数の型　引数名）

引数が複数ある場合カンマで区切ってかく

引数がない場合何も書かない　hoge()

返す値がない場合、返り値の型はvoidとなる

書く場所はmainメソッドの外、クラスの中！　（mainもメソッドです）



とりあえず今はstaticをつけよう（今後解説します）

##メソッドの呼び出し方

メソッドの呼び出し

```
hoge(3);
int n = hoge(4);
```

メソッド名（引数）で呼び出し

引数が複数ある場合はカンマ区切りで書く
渡す引数の型は定義と同じにする

返り値を変数に代入したりするとさらに計算に使うことも可能。

##メソッドを作るメリット

同じ作業をまとめて実行できる

例⬇︎
洗濯物を入れる➡️洗濯物を動かす➡︎洗濯物を干す

まとめて"洗濯する"と言うだけで済む

何度も実行する時に便利（動作を変更するときに楽）

スコープがメソッドの中だけの変数を使えば他の部分に影響を与えない。

##メソッドの中と外では影響する範囲が違います。

```
public static int hoge(int x) {
x* = 2;
return x;
}

public static void main(String[] args) {
int a = 3;
int x = 10;
System.out.println(hoge(a)); //6
System.out.println(a); //3(intの場合メソッドの中に計算は外側に影響しない)
System.out.println(a); //10(hogeの中のxとmainの中のxは別物)
}
Macでrbenvを使ってRubyとRailsをインストールする


# 環境

macOS Mojave 10.14

# 0. Homebrewをインストール

```bash
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

公式ページ(https://brew.sh/index_ja)

# 1. Rubyをインストール

### rbenvをインストール

Rubyのバージョン管理ツールであるrbenvとそれに必要なツールをインストールします。

```bash
$ brew update
$ brew install rbenv ruby-build

$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile
```

rbenvを最新版に更新します。

```bash
$ brew upgrade rbenv
```

rbenvをインストールできたか確認します。
バージョンが表示されれば無事インストールできています。

```bash
$ rbenv -v
rbenv 1.1.2
```

### rbenvを使ってRubyをインストール

rbenvでインストールできるRubyのバージョンを確認しましょう。

```bash
$ rbenv install --list
```

このような形でインストールされるので、`2.6.*`の中で最新のものをインストールします。
今回は`2.6.5`をインストールする予定なのでリストに含まれているか確認しておきましょう。

<img width="210" alt="スクリーンショット 2019-11-22 16.31.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191025/587754c0-1111-c2f5-39ce-b0489c074a11.png">

Ruby2.6.5をインストールしましょう。

```bash
$ rbenv install 2.6.5
$ rbenv global 2.6.5
```

インストールできたかrbenvから確認しましょう。
2.6.5という文字が見えれば大丈夫です。

```bash
$ rbenv versions
  system
* 2.6.5 (set by 〜〜)
```

rubyコマンドからも確認してみます。

```bash
$ ruby -v
ruby 2.6.5〜〜
```

### 参考

- [MacのターミナルでRubyをバージョンアップする方法](https://qiita.com/Ficus/items/bdef5c2b504d7a4008fb)


# 2. Railsをインストールする

### 注意事項

- ターミナルで今見ているディレクトリにRailsのプロジェクトディレクトリが作成されます


### Railsをインストールする

Rubyのパッケージ管理ツールとRailsをインストールします。

```bash
sudo gem install bundler
sudo gem install rails
```

Railsのプロジェクトを作成し、サーバーを立ち上げます。
今回は仮にtodosという名前でプロジェクトを作成します。

```bash
sudo rails new todos
cd todos
sudo rails server
```

サーバーがうまく立ち上がれば、`http://localhost:3000`を開くと`Yay! You're on Rails!`という画面が見えるはずです。
以下のコマンドでも開けます。

```bash
open http://localhost:3000
```

### (解決)Railsサーバー立ち上げで怒られる

場合によってはwebpackerの設定をインストールしろと怒られます。
その場合は以下の手順で解決してから、再度サーバーを立ち上げてください。

もしyarnコマンドがインストールされていない場合は以下のコマンドでインストールしてください。

```bash
$ brew install yarn
```

その後、railsの指示に従ってwebpackerの設定をインストールします。

```bash
$ sudo rails webpacker:install
```

これでファイルがいろいろ生成されれば完了です。
再度、サーバーを立ち上げなおしてみてください。

# まとめ

これで一通りの導入が完了したと思います。
場合によってはSQLiteのエラーが発生したり、権限のエラーが発生する場合もありますが一旦ここまでとします。
後日追記するかもしれません。
git操作のまとめノート

##1.gitの基本設定
###1.1 アカウントの設定

```
$ git config --global user.name "Your Name"
$ git config --global user.email your@example.com
```
###1.2 ブランチをpushするときの設定:
ブランチは指定されていない場合、現在のブランチへpushしたい時に、

```
$ git config --global push.default simple
```


##2.gitの初期化
###2.1 gitの初期化

```
$ cd ~/Code/Laravel
$ git init
```

###2.2 ファイルの内容を全てステージングする
```
$ git add -A
```

###2.3 Gitの状態を確認

```
$ git status
```

###2.4 変更をコミット、コメントする

```
$ git commit -m "コメント"
```

###2.5 コミットの歴史を探る

```
$ git log
```

###2.6 ソースをGitHubへ

```
$ cd ~/Code/Laravel
$ git remote add origin git@github.com:your_username/hello_laravel.git
$ git push -u origin master
```

##3 ブランチの操作（ローカル編）
###3.1　ローカルで新しいブランチを作る
```
$ git checkout master
$ git checkout -b static-pages
```

###3.2 別のブランチをmasterブランチにマージ

```
$ git checkout master
$ git merge static-pages
```
###3.3 コードをGitHubへpush

```
$ git push
```
###3.4 ローカルのブランチを削除する

```
$ git branch -d static-pages
```

##4 ブランチの操作（リモート編）

###4.1　Githubのリモートアドレスを確認

```
$ git remote -v
```

###4.2　全てのリモートブランチを確認

```
git branch -a
```

###4.３　ログを確認する

```
$ git log origin/master -n 3
```


###4.4　ローカルブランチとリモートブランチとの対応関係を確認する

```
$ git branch -vv
```


###4.5　リモートブランチを作る
```
//ローカルブランチを作る
$ git checkout -b new-branches

//リモートへpush
$ git push origin new-branches
```

###4.6　リモートブランチをローカルへpullし、名付ける

```
$ git pull
$ git checkout -b ローカルブランチ名x　origin/リモートブランチ名x
```


###4.7　リモートブランチを削除する
```
$ git branch -r -d origin/new-branches
$ git push origin :new-branches
```
A-FrameでWebVRアプリケーションを作成する-アニメーションを追加する

#はじめに
[前回の記事](https://qiita.com/yuya-s/items/5e0a59ea14c93f6c2c80)では動的なオブジェクトの追加について書きました。
今回はアニメーションを追加してオブジェクトを動かしていきたいです。

#箱を上下に動かす
```html:index.html
<html>
  <head>
    <script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script>
  </head>
  <body>
    <a-scene background="color: #FAFAFA">
      <a-box id="box1" position="0 0.5 -3" height="1" color="#4CC3D9" shadow></a-box>
    </a-scene>

    <script>
        var box = document.getElementById("box1");
        var t = 0;
        function render() {
          t += 0.01;
          window.requestAnimationFrame(render);
          box.setAttribute('position', '0 '+(Math.sin(t*2)+1)+' -3');
        }
        render();
    </script>
  </body>
</html>


```
![04_demo1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496841/d7918201-4765-c73d-ae5d-8e2e53ab3a78.gif)


（参考）https://developer.mozilla.org/ja/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_A-Frame

#箱を右方向に動かし、一定以上動いたら箱追加
アニメーションと動的な追加を組み合わせて。

```html:index.html
<html>
  <head>
    <script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script>
    <script src="./js/jquery-3.4.1.min.js"></script>
  </head>
  <body>
    <a-scene background="color: #FAFAFA"></a-scene>
    <script>
        var boxes = [];
        function createBox() {
          var scene = document.querySelector('a-scene');
          var box = document.createElement('a-box');
          box.setAttribute('color', '#4CC3D9');
          box.setAttribute('position', '0 0 -3');
          scene.appendChild(box);
          boxes.push(box);
        }

        function move(box, x) {
          box.setAttribute('position', x + ' 0 -3');
        }

        function render() {
          window.requestAnimationFrame(render);
          for(var i = 0; i < boxes.length; i++)
          {
            var pos = boxes[i].getAttribute('position');
            var x = pos.x + 0.01;
            move(boxes[i], x);
            if(x > 2 && i == boxes.length - 1)
              createBox();
          }
        }

        createBox();
        render();
      </script>
  </body>
</html>
```

![04_demo2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496841/f4172274-4409-7762-ba8d-e4f3726b780c.gif)

#おわりに
動いた。次回こそ何か簡単なゲームを作りたい。
すぐに役立つRails tutorialのメモ　「rails console でのデータ変更を反映させない方法」

##rails console --sandbox
"Any modifications you make will be rolled back on exit" (ここで行ったすべての変更は終了時にロールバックされます) というメッセージにわかりやすく示されているように、コンソールをサンドボックスで起動すると、そのセッションで行ったデータベースへの変更をコンソールの終了時にすべて “ロールバック” (取り消し) してくれます。(引用:第6章　rails tutorial)

https://railstutorial.jp/chapters/modeling_users?version=5.1#cha-modeling_users
SQLで列から偶数、奇数を出す方法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526362/ec4d2d49-2545-a394-f9d7-9f3f5240ac2a.png)
問題文の要点は２つ：
１、「ID」の列で偶数("even number")の要素を出します。
２、同じ（duplicates）要素を排除(exclude)します。

対策：
１、MODを使います。
２、DISTINCTを使います。

解決コード：
```Select distinct city from station where mod(ID,2)=0;```
***奇数の場合：***
```Select distinct city from station where mod(ID,2)=1;```
laravelログイン機能重大欠陥


デフォルトはメールアドレスでログインですが。

ユーザ名 username でログインへ変更した場合、

users テーブルはname 唯一キーではないなので、

当然重複したユーザ名登録可能です。ただし、メールアドレスは唯一チェックなので、以下のデータが登録しました。

```

name  |   email     |   password
testname test@mail.com  password1

testname test1@mail.com password2

testname test2@mail.com password3

```


しかし、ユーザ名 testname password3 でログインすると、なんとログイン不可エラーになりました。なにこれ？

ログインできるのは以下だけ。どういうこと？
testname test@mail.com  password1

つまり、もしユーザ名でログイン機能拡張する場合、

潜在的な不具合は存在しているではないか？？？

フレームワークやはり簡単に使えない？
Streamの終端処理

[Streamの生成処理](https://qiita.com/key_sleep/items/758067cde4f054d61010)および[Streamの中間処理](https://qiita.com/key_sleep/items/e1684f2e12532f37f507)
で処理をあたえたあとのStreamをどのような要素として終えるのか処理する

## find系
検索および要素がのこっているかどうかの確認に使用

```java
List<String> list = Arrays.asList("a","b","c","d","e");

// findFirst
String a = list.stream().filter(s -> s.equals("a")).findFirst().orElse(null);

// findAny
String any = list.stream().filter(s -> s.equals("a")).findAny().orElse(null);
```

## match系
指定した条件式にあてはまるものがあるかどうかを判別する

```java
List<String> list = Arrays.asList("alex","benjamin",null,"","elsa");

boolean nonNull = list.stream().allMatch(Objects::nonNull); //false

boolean isEmpty = list.stream().anyMatch(""::equals); //true

boolean isTom = list.stream().noneMatch("tom"::equals); //true
```

## toArray
配列要素として処理したい場合に使用
toArray（引数なし）で処理するとObject[]になってしまうので注意

```java
List<String> list = Arrays.asList("alex","benjamin","charley","dante","elsa");

Integer[] length = list.stream().map(String::length).toArray(Integer[]::new);
```

## collect
ListなどのCollection要素として処理したい場合に使用
使いやすいのでよく使ってます（小並感）

```java
List<String> list = Arrays.asList("alex","benjamin","charley","dante","elsa");

List<Integer> length = list.stream().map(String::length).collect(Collectors.toList());
```

## count
生成処理、中間処理を終えたStream要素の数を集計する

```java
List<String> list = Arrays.asList("alex","benjamin","charley","dante","elsa");

long count = list.stream().filter(s -> s.length() == 4 ).count(); // 2
```

## forEach
Java8で追加された内部イテレータ
実はStreamにも使える。標準のforEachを使えばいいと思う()
下記のサンプルはどちらも同じ結果を得られます

一部ではStreamのforEachは禁忌として扱われているとか
（ほかの要素に変換するためのStreamなのに値を返さないから）

```java
List<String> list = Arrays.asList("alex","benjamin","charley","dante","elsa");

// stream().forEach()
list.stream().filter(s -> s.length() == 4 ).forEach(System.out::println);

// list.forEach()
list.forEach(s -> {{if (s.length() == 4)System.out.println(s);}});
```

## min,max
編集中

##
【iOS13】モーダルをスワイプで閉じないようにする


# `modalPresentationStyle = .pageSheet` で表示されたモーダルをスワイプで閉じないようにする

[公式のサンプル](https://developer.apple.com/documentation/uikit/view_controllers/disabling_pulling_down_a_sheet)があるのだが、イマイチ読みづらい…ような気がした:frowning2:
特に、`presentationController.delegate`への受け渡しが遷移元に書いてあるので、見落としてしまう。
<img width="584" alt="PageSheetDismiss_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297266/762ce641-5c3d-6524-85f6-1e7d5b8f58d7.png">



## Storyboard
<img width="906" alt="PageSheetDismiss.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297266/46609865-8046-1558-f347-60cebcf1e69a.png">


## ViewController
```swift
class PageSheetViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // UIAdaptivePresentationControllerDelegateを渡す
        navigationController?.presentationController?.delegate = self
    }
}

extension PageSheetViewController: UIAdaptivePresentationControllerDelegate {
    // true: スワイプで閉じる false: スワイプで閉じない
    func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool {
        false
    }
    
    // スワイプで閉じない場合に実行したい処理
    func presentationControllerDidAttemptToDismiss(_ presentationController: UIPresentationController) {
        
        let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
        alert.addAction(UIAlertAction(title: "閉じる", style: .default) { _ in
            self.dismiss(animated: true)
        })
        alert.addAction(UIAlertAction(title: "キャンセル", style: .cancel, handler: nil))
        present(alert, animated: true)
    }
}
```

## とりあえず動かしたい場合はGithubへ
https://github.com/hira22/PageSheetDismissHandling

## 疑問
NavigationControllerを配置しないと実現できなかった。
`navigationController?.presentationController?.delegate = self`を`presentationController?.delegate = self`と書きたくなるが、これはできない。


#参考
[【iOS13】.pageSheetなmodalのdismiss時のライフサイクル・制御について](https://qiita.com/hirothings/items/554288583d581a8a929c)
`UIAdaptivePresentationControllerDelegate` でできることについて参考になりました。
詳細な挙動が知りたい場合は読んでおくといいと思います。

[iOS13からのUIModalPresentationStyle.pageSheetでユーザにプルダウンで閉じられないようにする方法](https://qiita.com/yimajo/items/7d329fa341d31476eb99)
サンプルコードでなぜhasChangesを使うのかの考察が参考になりました。

[WWDCのセッション動画](https://developer.apple.com/videos/play/wwdc2019/224)
ストリームAPI(自分用)(工事中)

#ストリームAPIとは
データソース(コレクション、配列、I/Oリソース)をもとに、集計操作を行うAPI

**★ストリームのパイプライン処理**
ストリームAPIは複数の入出力を繋ぐための仕組みを提供しており、処理を行う流れは、データソースをもとに「ストリームオブジェクト」を生成し、後続する処理を連結させることでパイプライン処理を可能とする。

**★パイプライン処理の分類**
***①操作・問い合わせ対象となるデータソース***
・コレクション、配列、I/O、リソース...
***②中間操作***
・ストリーム・パイプラインを形成
***③終端操作***
・ストリーム・パイプラインを実行して結果を生成

※中間操作(filter()やmap())では、実際の処理結果を返さずに指定した中間操作を保持したストリームが返される。実際にすべての処理が実行されるのは終端操作のメソッドで成される。

##1. ストリームの種類と生成
データソースとなり得るクラスにはストリーム生成用のメソッドが提供されている。

###1-1. ストリーム生成用の主なメソッド
####・java.util.Collection

|メソッド名| 説明 |例|
|:-:|:--|:--|
| `default Stream<E> stream()` | このコレクションをソースとして使用し、逐次的なStreamオブジェクトを返す  | new ArrayList<>().stream()

####・java.util.Arrays

| メソッド名 | 説明 | 例 |
|:-:|:--|:--|
| `static <T> Stream<T> stream(T[] array)`  | 指定された配列ををソースとして使用し、逐次的なStreamオブジェクトを返す  | Arrays.stream(new Object[]{10, 20, 30})
| `static IntStream stream(int[] array)`  | 指定されたint型の配列をソースとして使用し、逐次的なIntStreamオブジェクトを返す  | Arrays.stream(new int[]{10, 20, 30})
※IntStream...プリミティブ型用(int)ストリームオブジェクト

####・java.util.stream.Steram

| メソッド名 | 説明 | 例 |
|:-:|:--|:--|
| `static <T> Stream<T> of(T t)`  | 指定された単一の要素をソースとして使用し、逐次的なStreamを返す  | Stream.stream("abc")
| `static <T> Stream<T> of(T... values)`  | 指定された要素をソースとして使用し、逐次的なStreamオブジェクトを返す  | Stream.stream("Tokyo", "Hakone", "Okinawa")
| `static <T> Stream<T> empty()`  | 空のStreamオブジェクトを返す  | Stream.empty()
| `static <T> Stream<T> generate(Supplier<T> s)`  | 指定されたSupplier(ラムダ式)によって生成される要素に対する順序付けされていないStreamオブジェクトを返す  | Stream.generate(() -> 100)
| `static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)`  | 順序付けされた無限順次Streamを返す(第一引数seedは初期値を指定し、第二引数は無限順次させる抽象値を指定する | Stream.iterate(1, n -> ++n)

####・java.util.stream.DoubleStream

| メソッド名 | 説明 | 例 |
|:-:|:--|:--|
| `static DoubleStream of(double... values)`  | 指定された要素をソースとして使用し、逐次的なDoubleStreamオブジェクトを返す | DoubleStream.of(2.5, 10.0, 6.7)

####・java.util.stream.IntStream
| メソッド名 | 説明 | 例 |
|:-:|:--|:--|
| `static IntStream range(int startInclusive, int endExclusive)` | startInclusive(含む)からendExclusive(含まない)の範囲の値を含む、順序付けされた順次IntStreamを返す | IntStream.range(1, 11)
| `static Intstream rangeClosed(int startInclusive, int endInclusive)` | startInclusive(含む)からendInclusive(含む)の範囲の値を含む、順序付けされた順次IntStreamを返す |IntStream.ranceClosed(1, 10)  |


###1-2. ストリームの種類
| インターフェース名 | 説明 |
|:-:|:--|
| Stream<T> | 順次及び並列の集約操作をサポートする汎用的なストリーム |
| IntStream | 順次及び並列の集約操作をサポートするint値のストリーム。但し、intの他、short、byte、char型に使用可能 |
| LongStream | 順次及び並列の集約操作をサポートするlong値のストリーム |
| DoubleStream | 順次及び並列の集約操作をサポートするdouble値のストリーム。但し、double値の他、float型に使用可能 |
シンプルなサーバーをDocker/Node.jsで構築してみた

# はじめに
業務でログ監視システムの構築を行い、その際にログを出力するだけのシンプルなサーバーをDocker/Node.jsで作りました。
スタブ用途等ですぐに建てれる、サーバーの雛形としてお使い頂ければと思い、記事投稿に至りました。

# 前提
`Docker` / `docker-compose`を用いているので、インストールをお願いします。
インストール手順は、他の方がいっぱい書いておりますのでそちらをご参考に。

# リポジトリ
下記のリポジトリになります。
[simple_server](https://github.com/inagacky/simple_server)

# 使い方
`docker-compose build` や `docker-compose up` 等々は、
当リポジトリでは シェルスクリプトでラップしています。

## ビルド手順
下記のシェルを実行し、イメージのビルドを行います。

```
/bin/sh build.sh
```

上記のシェルを実行すると、イメージの構築が出来ます。

```
% docker images
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
simple_server_simple-server   latest              45163213fabc        4 hours ago         110MB
```

## 実行手順
下記のシェルを実行し、コンテナの起動を行います。

```
/bin/sh run.sh
```

下記でコンテナが起動できたことを確認できます。
ポートはhostの `30000` ポートを、 コンテナの `3000` ポートにバインドしています。

```
% docker ps
CONTAINER ID        IMAGE                         COMMAND                  CREATED             STATUS              PORTS                     NAMES
fb6bc7a1a37e        simple_server_simple-server   "docker-entrypoint.s…"   7 seconds ago       Up 5 seconds        0.0.0.0:30000->3000/tcp   simple_server_simple-server_1
```

# アクセス確認
ここまででサーバーを立てることができたので、アクセスの確認を行います。
現状はログファイルにログを出力するだけの簡単な仕組みですが、お好きなように変更頂ければと。

### ルートURL
```
% curl http://localhost:30000/
Hello World
```

### infoログ
```
% curl http://localhost:30000/info
info logging
% tail -n 1 ~/workspace/simple_server/simple-server/log/app.log
{"message":"info logging","level":"info"}
```

### warnログ
```
% curl http://localhost:30000/warn
warn logging
% tail -n 1 ~/workspace/simple_server/simple-server/log/app.log
{"message":"warn logging","level":"warn"}
```

### errorログ
```
% curl http://localhost:30000/error
error logging
% tail -n 1 ~/workspace/simple_server/simple-server/log/app.log
{"message":"error logging","level":"error"}
```

## 備考
リポジトリ内の `docker-compose.yml` をご覧頂いたら分かるかと思いますが、
下記のように `app` ディレクトリ配下、 `log` ディレクトリ配下に関してはマウントしており、
起動したままホスト環境側で変更可能です。

```docker-compose.yml
    volumes:
      - ./simple-server/app:/app
      - ./simple-server/log:/var/log
      - /app/node_modules
```

## 最後に
`docker` やっぱりめちゃくちゃ便利ですね。
作って捨てることが出来るのは嬉しいです。
ご自身のgithub等々にストックとして追加しておくことで、実案件時に助かることが多いのではないでしょうか。
雛形としてお使い頂けたら幸いです！

# 共に働くWebエンジニアを募集しています!
不動産SHOPナカジツでは自社サービスを作っていく仲間を募集しています。
詳しくは[Wantedly](https://www.wantedly.com/projects/134741)からお問い合わせください。
お待ちしております！
[ Android ] サーバから取得した値をsetterでアクティビティに引き渡す

今回はサーバから取得した値をアクティビティに引き渡す方法を記す。

##setter()
セッターというメソッドを作れば簡単に実装できる。
取得値を引き渡したいクラスに、引き渡し用の変数を作り、セッターメソッドでその変数に代入すれば完成である。
具体的には以下のように実装する。

MainActivity.java

~~~java
public class MainActivity extends Activity {
    private String serverValue = null;

    public void onCreate(Bundle state) {
        //...
        new MyAsync(this).execute();
    }

    public void setList(String serverValue) {
        this.serverValue = serverValue;
    }
}    
~~~

MyAsync.java

~~~java
public class MyAsync extends AsyncTask<Void, Void, List<String>> {

    String serverValue;
    private YourAcitivity activity;

    public MyAsync(MainAcitivity activity) {
        this.activity = activity;
    }

    @Override
    protected List<String> doInBackground(Void... arg0) {
    }

    @Override
    protected void onPostExecute(String serverValue) {
        activity.setList(serverValue);
    }
}
~~~
UiPathの認定資格(Advanced Certificate)とったよ話

#概要
UiPathの認定資格である「UiPath Advanced Certificate」を取ったので、試験の流れと受験に向けたアドバイスを備忘録としてまとめました。
問題の詳細は試験の公平性を欠くため記載はしていません、悪しからず:wink:

#UiPathの認定資格って？
UiPathの開発に関するスキル(Studio、Orchestratorどちらも)を有していることを証明できる試験とのことです。
>UiPathの製品と機能について深い知識を持ち、ベストプラクティスと原則に基づいた開発スキルを証明する資格です。UiPathから認定を受けることで、RPA分野の能力・知識・スキルを持つプロフェッショナルであることを証明できます。現在は英語のみ。順次日本語化も予定しております
([UiPath公式サイト](https://www.uipath.com/ja/rpa/academy)より引用)

- [UiPath Academy](https://academy.uipath.com/)でレベル1~3を取得していたこと
- ~~１２月末までは無料(1月以降の料金体系については不明)~~  
**２０２０年３月まで無償期間が延長されてました！**


もあり、受けてみることにしました。

#試験について
##対応言語
**全編英語**です。
UiPath ForwardというUiPathのイベントで担当者の方にお聞きしたところ、
「日本語対応も検討中だが、日本語対応のタイミングで有料化する可能性が高い」とのことでした。

##第一試験：クイズ
まずは、一次試験としてクイズが出題されます。
クイズはAcademyのLv1~3の総集編というイメージで、出題比率としてはLv3からの出題が多かったです。
(Lv3が1と2の総集編ということもあるので…)

|  |  |
|:-:|:-:|
| 制限時間 | 90分(1時間半) |
| 出題数 | 45問 |
| 選択肢 | 問題によって可変(基本４択問題が多かったです) |
| 再受験 | 再受験には24時間の待機時間が必要 |
| 回数制限 | 3回 |
※回数制限を超えての再受験には**新しいバウチャーの申請**が必要

###受験にあたっての注意(クイズ編)
- 受験を開始すると1時間半の制限時間があります
- 受験を開始すると画面が最大化されます  
→**Esc,F11キーを押すと終了とみなされ、その時点での回答問題で点数が出ます**
- Academyのようにクリア後にクイズの結果が表示されません  
→代わりに解答した時点で正解か否かが分かる(何問正解したか表示される)
- 当然ですが問題はすべて英語

###対処法(クイズ編)
- 時間に余裕をもって行う
- 試験ページのタブと、翻訳用のタブは異なるブラウザにしておく  
（同じブラウザの異なるタブを見ようとすると終了します）
- 異なるブラウザを見る、試験に戻る場合はAlt + Tabで移動する  
- 拡張機能でブラウザにマウスジェスチャーを入れている場合はオフにしておく  
（ドラッグで選択文章を検索するジェスチャーで別タブに移動し試験が終了します）
- 英語に自信がない方はChromeブラウザで実行する場合は拡張機能で選択した文章をリアルタイム翻訳してくれる[Google翻訳](https://chrome.google.com/webstore/detail/google-translate/aapbdbdomjkkjkaonfhkkikfgjllcleb)を入れておく
- **折れない心を持つ(だいじ)**

##第二試験：実技
クイズに合格すると、次は実技試験となります。
実技試験にも制限時間と回数制限が設けられていました。

|  |  |
|:-:|:-:|
| 制限時間 | 210分(3時間半) |
| 出題数 | 1問(与えられた仕様に沿ってロボットを作成) |
| 回数制限 | 3回 |
※回数制限を超えての再受験には**新しいバウチャーの申請**が必要

###受験にあたっての注意(実技編)
- REFrameworkの使用が前提となっています  
- Academyでさんざんお世話になった[ACME System1](https://acme-test.uipath.com/)の操作が多かったです  
- 採点結果が出るまでには若干タイムラグがあります。ここは制限時間はないので、気長に待つとよいと思います
- しつこいようですが**全編英語**です

###対処法(実技編)
- AcademyのLv3を再履修してみる
- UiPath Go!で配布されている[日本語版REFramework](https://go.uipath.com/ja/component/japanese-reframework#)を使用してREFrameworkの仕組みを理解しておく
- Google翻訳を使用してもよいが、**選択すべき項目や型名まで翻訳**されるので注意する   
(Stringが「弦」とかになる)
- **折れない心を持つ(とてもだいじ)**

#合格すると修了証がもらえます
やったぜ。（本名バレが怖いので名前を隠してます、すみません。。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176879/4fb73dba-0c04-e4d9-4057-6c47e070f0a1.png)

#受けてみた感想
自身が英語に苦手意識があることもあり、全編英語にだいぶ悩まされました。
また、筆記は前述した全画面解除の瞬間に強制終了食らう問題もあり、最後の1回で合格しなければ…というプレッシャーがすさまじかったです:sob:
実技試験はLv3の問題の方が難しいなと感じていたので、Lv3を取った方なら勢いで受けるのもありかもしれません！
Lv3を受けてみようかな…と思った方は[こちらの記事](https://qiita.com/odm_knpr0122/items/8cf1b02b7df9203fb15a)もぜひどうぞ！(熱い宣伝)
C++ Builder 10.2 Tokyo > バイナリファイル > 新規作成と追記

```txt:動作環境
RAD Studio 10.2 Tokyo Update 3
```

### 概要

- バイナリ形式でのファイル書出し
- ファイルがないときは新規作成
- ファイルがあるときは追記

### 実装

```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::Button1Click(TObject *Sender)
{
	char szbuf[20] = {0};
	int pos;

	strcat(szbuf, "hello");
	pos = strlen(szbuf);
	szbuf[pos++] =0x0A; // バイナリデータ
	szbuf[pos++] =0x0B; // バイナリデータ
	szbuf[pos++] =0x0C; // バイナリデータ

	TFileStream *fstream;

	static const String aFile = "test.bin";

	if (FileExists(aFile)) {
		fstream = new TFileStream(aFile, fmOpenReadWrite);
	} else {
		fstream = new TFileStream(aFile, fmCreate);
    }
	fstream->Seek(0, (int)soEnd);  // (int): 関数の区別が曖昧を回避するため
	fstream->WriteBuffer(szbuf, strlen(szbuf));
	fstream->Free();
}
//---------------------------------------------------------------------------
```

TFileStream()のコンストラクタで処理を分岐しているが、一行でできる方がもっといいだろう。


### 関連

- [TFileStream.Create コンストラクタ (string, Word)](http://docs.embarcadero.com/products/rad_studio/radstudio2007/RS2007_helpupdates/HUpdate4/JA/html/delphivclwin32/Classes_TFileStream_Create@string@Word.html)
    - RadStudio 2007の情報ではある
中身が違う多次元配列を重複チェックする

## 通常の配列を操作する場合
```javascript
const arr = [ 'hoge', 'fuga', 'poke', 'wakuteka', 'hoge', 'hoge' ]
```
今回はこんなデータを使用します

### 重複データのみ抽出する
```javascript
const arr2 = arrarr.filter(function (val, idx, arr){
  return arr.indexOf(val) === idx && idx !== arr.lastIndexOf(val)
})

// 以下のようになります。
console.log(arr)
// (6) ["hoge", "fuga", "poke", "wakuteka", "hoge", "hoge"]

console.log(arr2)
// ["hoge"]
```

### 重複を取り除く
```javascript
const arr3 = arr.filter(function(val, idx, arr){
  return arr.indexOf(val) === idx
})

// 以下のようになります。
console.log(arr)
// (6) ["hoge", "fuga", "poke", "wakuteka", "hoge", "hoge"]

console.log(arr2)
// (4) ["hoge", "fuga", "poke", "wakuteka"]
```

他以下記事を参考にしてみてください。

* [二次元配列から値の重複した要素を削除する](https://qiita.com/dadayama/items/ae5cd50bbb644a12a91a)
* [配列で重複する項目を取り除くやつ4種。（配列とかおれおれAdvent Calendar2018 – 18日目）](https://ginpen.com/2018/12/18/array-unique/)



## 本題
ようやく、本題です。
今回は以下のような多次元配列を使用します。

```javascript
const arr = [
  { id: 1, name: '太郎', money: 3000 },
  { id: 2, name: '次郎', money: 1000 },
  { id: 3, name: '三郎', money: 1200 },
  { id: 2, name: '次郎', money: 500 },
  { id: 1, name: '太郎', money: 1300 },
  { id: 1, name: '太郎', money: 10000 }
]
```
こんな感じの配列で、idで重複を確認しmoneyを加算させたデータを作りたいとします。


### 実装
```javascript
let nonDupArr = arr
let dupArr = []

let dupObj = {}
let dupIdxArr = []
arr.filter((o, i, arr) => {
  arr.filter((o2, i2) => {
    if (i !== i2 && o.id === o2.id) {
      // 重複分を取得
      if (!dupIdxArr.includes(o.id)) {
        dupObj = {
          id: o.id,
          name: o.name,
          money: o.money + o2.money
        }
        // 配列に追加
        dupArr.push(dupObj)
      }
      // 重複分のidを配列に追加
      dupIdxArr.push(o.id)
    }
  })
})

// 重複分のidを回して、該当する要素を配列から削除
dupIdxArr.forEach(id => {
  let idx = nonDupArr.findIndex(e => e.id === id)
  nonDupArr.splice(idx, 1)
})
```
1. まず、重複分を格納する配列と重複分を除いた要素を格納する配列を用意します
2. `const`で定義した配列（※以下A配列）をfilterし、更に第三引数で元の配列（※以下A´配列）を更に中でfilterします。
3. A配列でfilterした要素のインデックスとA´配列でfilterした要素のインデックスが違う且つ、A配列でfilterした要素のidとA´配列でfilterした要素のidが同じことを確認します。
4. 重複して保存されない様に、重複した分の要素のidを専用の配列（以下B配列）に格納し、B配列にA配列からfilterした要素のidをincludesで確認、入っていなければ、新たなオブジェクトとして配列に保存していきます。

→ここまでで重複分の要素を入れた配列が完成です。


1. 次に先程保存したB配列をforEachで回します。
2. A配列から、findIndexでB配列に保存されているidと重複するidの要素を取得します。
3. 取得したオブジェクトをA配列から削除します

→これで重複分を除いた配列の完成です。



## まとめ
いかがでしたでしょうか？
配列から完全一致の要素を削除したり、抽出するパターンは往々にしてあると思いますが、重複する要素を更に加工するケースの際是非ご活用ください。
また、より良い記述ご存知の方是非コメントでご教授いただけますと幸いです。
Discordのテキストチャットからマイクラサーバに管理者コマンドを差し込む

# ≒ screenで起動しているプログラムに管理者コマンドを差し込む
## やりたいこと
- マイクラプレイヤーの方であれば、「一緒に遊んでいた人が寝落ちてしまって、ゲーム内で夜を明かせない」というとき、その人をマルチサーバから一時退出させたいといった場面が稀によくあるかと思います。
- マイクラはサーバコンソールから直接コマンドを入力すれば、operator権限の処理を実行できます。
  - 或いは、サーバコンソールから、 `op HOGE` とすればユーザHOGEにop権限を付与し、HOGEがゲーム内チャットでop権限の処理を実行することも可能です。
- op権限を持つとkickコマンドが扱えるようになります。
- しかし、大人数がアクセスするワールドで参加者全員にop権限を与えるのは無謀の極み…。
- そこで、**特定のopコマンドのみを別インタフェースから誰でも実行できるような手段を用意したい**

## 運用しているマイクラサーバの状況
- 1つのサーバで4つのワールドを同時に建てています。
- それぞれのワールドをscreen内で実行し、別々のポートを開放して割り当てることで容易に並列動作が可能です。(そこそこサーバスペックが必要ですが)
- 僕が建てているサーバで遊んでいる人は例外なく、 **とあるDiscordサーバにも参加している**
ということで…

## そりゅーしょん
- Discord botにお願いしよう！(Discord botについては[こちら](https://qiita.com/charichuma_hack/items/dfcdd422be46ffc311aa))

- 以下のようなshellscriptの実行で、screenに文字列を差し込めます。
  - (今回は"minecraft"という名前でscreenを起動)

```minecraft_scripts/kick.sh
screen -S minecraft -X stuff "kick $1\n"
```

- discord botに追加するメソッドがこちら。

```main.py
# send kick signal to Minecraft
# メソッドへの入力(text) = discordチャンネルからのテキストメッセージ
def send_signal_to_minecraft(text):
    response_string = ''
    if text.find("minecraft kick") > -1:
        index_st = text.find('kick ') + 5
        #index_ed = text.find('')
        user_name = text[index_st:]
        response_string = "了解いたしました。"+ user_name + "さんをキックします。"
        try:
            subprocess.call(["sh", "minecraft_scripts/kick.sh", user_name])
        except Exception as e:
            response_string = '構文エラーです＞＜ :cold_sweat:\n' + e.message + '\n' + str(e)
    else:
        response_string = "構文エラーです＞＜ :cold_sweat:\n 正しく入力してね！"

    return response_string
```

## 使い方
- Discordのチャットチャンネルで`雲さん minecraft kick マイクラID名`と入力すると、botがマイクラの管理コンソールから指定ユーザをキックしてくれます！
- 今回はキック機能のみ実装しましたが、管理コンソールから実行できるコマンドであればどんな内容でもbot経由で実行することができます。
- 勢いでダダダっと書いてしまいましたが、皆さんの快適マイクラライフの参考になれば幸いです🌟
サブディレクトリ動かすNuxt.jsでもルートディレクトリの.envを読み込む

# 背景

Nuxt.jsをサブディレクトリで動かして、ルートディレクトリの`.env`を読もうとすると

```
WARN  No .env file found 
```

んなものないって警告でる。


## 対策

dotenvのpathを設定する。

```nuxt.config.js
require("dotenv").config();

export default {
  srcDir: "hogehoge",

  // ~~略~~
  buildModules: ["@nuxtjs/dotenv"],
  dotenv: {
    path: process.cwd()
  },
```

## Herokuとかでも環境変数を読みたい場合

envを設定する。

```nuxt.config.js
require("dotenv").config();

export default {
  srcDir: "hogehoge",

  // ~~略~~
  env: {
    APP_ID: process.env.APP_ID,
    APP_KEY: process.env.APP_KEY,
  },
```

Herokuで環境変数を設定するのをお忘れなく。

## 参考

[nuxt-community/dotenv-module](https://github.com/nuxt-community/dotenv-module)
[API: env プロパティ](https://ja.nuxtjs.org/api/configuration-env/)