OmniAICreator/Qiita-1.07M huggingface dataset:
わかりやすいコードを書くための方法[まとめ1]

自己啓発用です。
可読性の高いコードを書くための方法をまとめました。

殆ど巷で言われているものです。

わかりやすいコードを書くための必要性と「メリット」
/Code Should be Easy to Understand/

-分かりやすいコードをかくことでプロダクトの保守性が高くなる。
->変更が容易、テストも容易、作業時間が縮小される。→仕事が早く終わる

分かりやすいコードを書くということは、簡単そうに見えるが
->上級者でないと割と難しい。しかし可読性の高いコーディング方法を先に習得していれば、徐々に体が覚える。
->他者（または未来の自分）が読んだときに理解に要する時間を最小限になるように努める。

@example
どちらかが読みやすいか

```Java
for(Node node = head; node != NULL ; node = node.next())
{
	system.out.println ("読む時間");
}
```


```Java
Node node = head;
if (node == NULL) return;

while (node.next() != NULL) {
    system.out.println("読む時間");
    node = node.next();
}
```

短いコードのほうが基本は見やすい。ただし、短いだけがいつも正義とは限らない。

<基本的な原則>
変数・関数名　良い名前を付けて整理する。
関数　複雑なものは、小さく分割する。

良い名前＝意味がわかりやすい。
意味が分からない名前は原則使わない。

たとえば

```Java
int d
```

変数d では意味が伝わりません。

```Java
int distance
```

とすることで距離を入れる変数であることが分かります。
さらに

```Java
int movingDistance 
```

とすることで、移動距離と使用用途が明確になります。

ただし配列の添字や関数内のローカル変数には、i,j,kなどの短い名前をつけます。


<<マジックナンバー>>

書いた本人しか知りえない。意味を持った数字です。

```Java
if(Action == 1)
{
	do('パンチ');
}
if(Action == 2)
{
	do('キック');
}
```

たとえば、Actionという定数があったとして、定数をみたときに
意味はわかるものの、それぞれの数字がなにをするのかはコードを追わないと把握できません。

このような場合、列挙型を使うことで明確になります。


参考文献
Dustin Boswell,Trevor Foucher,2011,The Art of Readable Code,O'Reilly Media
大圖 衛玄,2015,ゲームプログラマのためのコーディング技術,技術評論社
自分用.vimrc

SunOSでエディタの存在を知り、るんるんLinuxを片手にSlackwareで遊び、気が付くとviだけで仕事をするようになってから20年以上経ちました。
*set nu* だけだった **.virc** はvim時代でどうなったか、備忘録かねて晒します。

##.vimrc
```:.vimrc
set nu
set nowrap
set ts=4
set noai
set nocompatible
set enc=utf-8
set fencs=ucs-bom,utf-8,iso-2022-jp,enc-jp,cp932,utf-16le,utf-16,default,latin1
set mouse=a
set paste
set statusline=%<%f\ %m%r%h%w%{'['.(&fenc!=''?&fenc:&enc).']['.&ff.']'}%=%l,%c%V%8P
set fileformats=unix,dos,mac
set hlsearch
"8進数での加算にならないように
set nf=

"colorscheme desert
"colorscheme murphy
"colorscheme pablo
"colorscheme peachpuff
"colorscheme ron
"colorscheme zellner
"colorscheme koehler
colorscheme torte
"colorscheme elflord
"colorscheme darkblue
colorscheme delek

"set scrolloff=9999
"set noequalalways
"set lines=15
"set cursorline
"syntax on
```

というわけでコメントで大事に!?残したりはしているものの結局私に必要なのは上の方の10行程度だったようです。
バカソート

- 最小値を探すことを繰り返すことでソートしていく
- バカだから時間かかる

```go
package main

import (
	"log"
	"math/rand"
	"time"
)

func DumbSort(target []int) []int {
	for i := 0; i < len(target)-1; i++ {
		for j := i + 1; j < len(target); j++ {
			if target[i] > target[j] {
				target[i], target[j] = target[j], target[i]
			}
		}
	}
	return target
}

func main() {
	rand.Seed(time.Now().UnixNano())
	target := prepare(100000)
	log.Printf("Target: %#v\n", target)
	sorted := DumbSort(target)
	log.Printf("Sorted: %#v\n", sorted)
}

func prepare(size int) []int {
	ret := make([]int, size)
	for i := range ret {
		ret[i] = i
	}
	length := size - 1
	for i := length; i > 1; i -= 1 {
		r := rand.Intn(i)
		ret[i], ret[r] = ret[r], ret[i]
	}
	return ret
}

```
Plone5.2とVoltoを気軽に試すためのdocker-compose


# 概要

VoltoというReactベースのPlone用(厳密には他でも使える)のSPA実装がある。
以下を参照

[Volto というPloneのReactによるフロントエンド実装のインストール方法](https://qiita.com/terapyon/items/587600cf5eff17b7146d)


手元で簡単に試すために、以下を準備した。

- VoltoのDockerイメージ
- docker-composeファイル
- 起動に必要なcfgファイル


# 準備した物

## VoltoのDockerイメージ

docker hub に `volto-demo` イメージをアップした

https://cloud.docker.com/repository/docker/terapyon/volto-demo


## docker-composeファイル

- Ploneは公式に公開されているイメージを使う。
- Voltoは上記のイメージを使う



```docker-compose.yml
plone:
  image: plone/plone:5.2.2
  volumes:
    - ./plone-data/filestorage:/data/filestorage
    - ./plone-data/blobstorage:/data/blobstorage
    - ./plone-data/src/:/plone/instance/src/
    - ./custom.cfg:/plone/instance/custom.cfg
  ports:
    - "8080:8080"
  environment:
    ZCML: /plone/instance/custom.cfg
volto:
  image: terapyon/volto-demo
  ports:
    - "3000:3000"
    - "3001:3001"
```

## 起動に必要なcfgファイル

```custom.cfg
[buildout]
extends = buildout.cfg

develop +=

[instance]
eggs +=
    Plone
    Pillow
    plone.restapi    

zcml-additional =
  <configure xmlns="http://namespaces.zope.org/zope"
             xmlns:plone="http://namespaces.plone.org/plone">
  <plone:CORSPolicy
    allow_origin="http://localhost:3000,http://127.0.0.1:3000"
    allow_methods="DELETE,GET,OPTIONS,PATCH,POST,PUT"
    allow_credentials="true"
    expose_headers="Content-Length,X-My-Header"
    allow_headers="Accept,Authorization,Content-Type,X-Custom-Header"
    max_age="3600"
    />
  </configure>
```

# 起動方法

## ファイルの設置

適当なフォルダに、上記に書いた2ファイルを置く

- docker-compose.yml
- custom.cfg

## 起動コマンド

```
$ docker-compose up
```

## 起動後の作業

**重要** 以下2つの作業

### Ploneインスタンスを作る

ブラウザで、 `http://localhost:8080` に行き、Ploneインスタンスを作る。
ユーザ名: admin / パスワード: admin
その際に必ず、 `Plone` というIDで作る必要がある。
(Voltoが接続する先が、 `http://localhost:8080/Plone` となっているため。(変更には、Voltoの起動コマンドを変更する必要がある。)

### plone.restapiを有効化

Ploneの管理画面のアドオンで、 `plone.restapi` を有効化

### 以下で動作確認可能

- Ploneへのアクセス: http://localhost:8080/Plone
- Voltoへのアクセス: http://localhost:3000


## データファイル

カレントディレクトリの、 `plone-data` 以下にPloneのデータが保存される。


# TODO

- このままだと、Voltoのカスタマイズができないので、カスタマイズ用のフォルダをボリュームとしてマウントするように変更する


# 更新情報

- Voltoのバージョンを 8.9.2 のDocker Imageをアップした (2020年11月11日 )
- Plone5.2.2 が使われるようにバージョンの書き換えを行った (2020年11月11日 )
数学の理論構築パターン

数学には理論展開を進めていく中で特定のパターンがあります。

 　パターン１：概念を拡張する
 　パターン２：都合のいいものだけで考える

この２つを繰り返してより高度な理論になります。

　・パターン１の例
　　①自然数⇒整数⇒有理数⇒実数⇒複素数と数の概念を拡張する
　　②１次元⇒２次元⇒・・・ｎ次元⇒無限次元と次元を拡張する
　　③繋がっている関数を連続関数と定義する⇒開集合の逆像が開集合のときに連続関数と定義する（位相空間でも定義可能になる）


　・パターン２の例
　　①割り算では分母を０にすると理論が矛盾するので分母が０になることを禁止する
　　②ルベーグ外測度は完全加法性が成立しないので、都合のいい可測集合上に制限することで完全加法性を成立させる（ルベーグ測度という）

パターン１によって、道具を増やし、具体的な空間でしか扱えなかった概念をより抽象的な空間でも扱えるようにします。新たな空間では重要な性質を引き継ぐように、その性質自体を定義にもってきます。

パターン２は、数学の理論に矛盾しないようにするためのアイデアです。新たな定義は数学的に矛盾を含むわけにはいきません。なので、都合のいいものだけを取り出して矛盾を解消します。

-定義について-
　・これまでに構築された理論と矛盾してはいけない（well-definedという）
　・定義をしても汎用性がないと意味がない

　例えば極端にいうと、分母に０を入れると$0=1$になるなど矛盾しますが、０だけでなく２以外の数字を入れたときも矛盾するとなった場合、割り算の定義は分母が２のときしか使えません。分母が２限定の計算など使えないでしょう。しかし実際は、０以外が使えるのだから計算でも困ることはなく、汎用性があると言えます。

数学の概念の定義には、矛盾しないことと汎用性が重要だと思います。
JFrameの setDefaultCloseOperation() の使い方

#初めに
- この記事は*Qiita初心者*が書いたものです。
- もしかしたら上級プログラマーの中では一般的かもしれません...
- 若干、備忘録感があります

##setDefaultCloseOperation(int operation)
この関数は、ウィンドウをどう閉じるかを設定できます。(ウィンドウの×のボタンを押したとき)
引数にJFrameの定数をいれてあげることで処理のパターンを変えることができます

- `DO_NOTHING_ON_CLOSE`
    - 何も行いません、終了処理は JFrame に登録している WindowListener クラスの WindowClosing() で行います。
- `HIDE_ON_CLOSE`
    - 上の WindowClosing() を実行した後にフレームを隠します。
- `DISPOSE_ON_CLOSE`
    - 上の WindowClosing() を実行した後にフレームを隠し、破棄します。
- `EXIT_ON_CLOSE`
    - javaの標準ライブラリの System.exit() を使って終了させます。

##サンプルプログラム
このプログラムでは DO_NOTHING_ON_CLOSE を引数としてとり、自身で終了処理を記述しています。
この方法を使うと、ゲームデータのセーブの処理などが記述できます。← ~~それだったら DISPOSE_ON_CLOSE 使えよ~~

```java:WindowTest.java
import javax.swing.JFrame;
import java.awt.*;
import java.awt.event.*;

public class WindowTest extends JFrame{
	
	public WindowTest(String title,int width,int height){
		super(title);
		setSize(width,height);
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		addWindowListener(new MyWindowListener());
		setResizable(false);
		requestFocus();
		setVisible(true);
	}
	
	public static void main(String args[]){
		new WindowTest("テスト",200,300);
	}
	
	
}

class MyWindowListener extends WindowAdapter {
    public void windowClosing(WindowEvent e) {
        System.out.println("終了処理を実行します");
        System.exit(0);
    }
}
```
迷路自動生成アルゴリズムを書いてみた。

# はじめに
ちょいと興味がわいたので、迷路自動生成アルゴリズムをC言語で実装してみた。

# 処理内容
一般的にDIG(穴掘り)法といわれる超有名なアルゴリズム。
以下におおまかな処理内容を記載する。

1. 縦横共に奇数のフィールドを用意する。
2. 外周は通路とし、外周以外は壁で埋める。
3. 基準点から2ブロック先までが全て壁になっている方向のリストを作成する。
4. 作成したリストの中からランダムに掘る方向を決め、2ブロック先までを掘る。
6. 掘り終わった時点の座標を開始座標リストに追加する。
7. どこにも進めなくなったら、作成した開始座標リストの中からランダムに掘り始める座標を選ぶ。
8. 開始座標リストがなくなったら終了。
9. 最後に外周の通路を壁に書き換える。

# コード

```c:mazetest.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define M_WIDTH     59
#define M_HEIGHT    25
#define M_ARRLEN    (M_WIDTH*M_HEIGHT)
#define GetX(A)     ((A)%M_WIDTH)
#define GetY(A)     ((A)/M_WIDTH)
#define GetIdx(X,Y) ((Y)*M_WIDTH+(X))
#define rnd(A)      (rand()%(A))
#define randomize() (srand((unsigned)time(NULL)))

// 迷路のフィールド属性
enum maze {
    M_FLOOR, // 床
    M_WALL   // 壁
};

// 迷路のフィールド
int Fld[M_ARRLEN];

// 配列の要素を縮小し、配列の最終位置を返す
int arr_shrink(int *arr,int idx,int max){
    for(int i=idx;i<max;i++) arr[i]=arr[i+1];
    return --max;
}

// 迷路フィールド配列を初期化する
void init_maze(void){
    // 外枠以外を壁で埋める
    for(int i=0;i<M_ARRLEN;i++){
        if(i>=M_WIDTH&&(i%M_WIDTH>0&&i%M_WIDTH<M_WIDTH-1)&&i<M_ARRLEN-M_WIDTH) Fld[i]=M_WALL;        
    }
}

// DIG法を用いて迷路を作成する
void make_maze(int x,int y){
    int lidx=0;
    const int vvx[]={1,0,-1,0},vvy[]={0,1,0,-1};
    int vx[4],vy[4];
    int lf[M_ARRLEN/2+1];

    randomize();
    init_maze();
    while(1){
        // 進める(2ブロック先までが壁)方向リストを作成する
        int vidx=0;
        for(int i=0;i<4;i++){
            const int x1=GetIdx(x+vvx[i],y+vvy[i]);
            const int x2=GetIdx(x+(vvx[i]*2),y+(vvy[i]*2));
            if(Fld[x1]&&Fld[x2]){
                vx[vidx]=vvx[i];
                vy[vidx++]=vvy[i];
            }
        }
        if(vidx){ // 進める方向がある場合
            // ランダムに壁を掘り進める
            const int r=rnd(vidx);
            int fidx;
            for(int i=0;i<=2;i++){
                fidx=GetIdx(x+(vx[r]*i),y+(vy[r]*i));
                Fld[fidx]=M_FLOOR;
            }
            // 掘り進めた終点の座標を始点リストに追加する
            lf[lidx++]=fidx;
            // 現在位置を更新する
            x=GetX(fidx);
            y=GetY(fidx);
        }else if(lidx){ // 始点リストがある場合
            // 始点リストからランダムに始点を選択し、現在位置とする
            const int r=rnd(lidx);
            x=GetX(lf[r]);
            y=GetY(lf[r]);
            // 選択された始点リストの要素を配列から削除する
            lidx=arr_shrink(lf,r,lidx);
        }else{ // 進める方向も始点リストも枯渇した場合
            // ループから抜ける
            break;
        }
    }
    // 床に設定しておいた外枠を壁にしなおす
    for(int i=0;i<M_WIDTH;i++){
        Fld[GetIdx(i,0)]=Fld[GetIdx(i,M_HEIGHT-1)]=M_WALL;
    }
    for(int i=0;i<M_HEIGHT;i++){
        Fld[GetIdx(0,i)]=Fld[GetIdx(M_WIDTH-1,i)]=M_WALL;
    }
}

// 迷路を表示する
void print_maze(void){
    for(int i=0;i<M_ARRLEN;i++){
        if(i>0&&i%M_WIDTH==0) printf("\n");
        if(Fld[i]){
            printf("@@");
        }else{
            printf("  ");
        }
    }
    printf("\n");
}

// エントリポイント
int main(void){
    make_maze(1,1);
    print_maze();
    return 0;
}
```

# 実行結果
![コメント 2019-06-13 200907.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298004/60c84222-3c96-c01b-4ead-6697d10457a4.png)
useRef は何をやっているのか

useRef は元々あった createRef の hooks 版です。その名の通り、DOMに対する参照を持つために使われるのが主な目的です。

ですがそれ以外の用途にも利用することができます。

最初に私が知ったのはこちらのReact本体のドキュメントにも記されている「以前のstateの値を参照する方法」です
https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state

```tsx
function usePrevious(value: any) {
  const ref = useRef(null);
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
}
```

なにやら useRef で前回の値を保持しているようですね。それまで ref と言えばDOMに対して使うものと思っていたので「え、useRefってDOM以外の値を参照するのに使えるの？」と驚きました。驚きましたが当時の私はとりあえずスルーしました。

次に出会ったのがこちらの記事のこの節。

https://www.codebeast.dev/react-memoize-hooks-useRef-useCallback-useMemo/#memoizing-with-useref

特に気になったのが次の useRef の特徴です。

> 1. Stores data
2. Does not cause re-render when the data it stores changes
3. Remembers its stored data even after state change in useState causes a re-render.

気になったものの、この記事を読んだ当時の私は useRef の詳細については華麗にスルーしました。

ですが日々開発していて、たま〜〜〜に useRef をDOM以外に使ったテクを見かけるので、今回深ぼろうと思った次第です。

なのでこの記事では次のようなことを書きます。

- useRef は具体的になにをしているのか
- どんなユースケースが考えられるか

useRef は具体的になにをしているのか
-----

実際の実装を見てみましょう。

まずは初期化の処理から。

```ts
function mountRef<T>(initialValue: T): {|current: T|} {
  const hook = mountWorkInProgressHook();
  const ref = {current: initialValue};
  if (__DEV__) {
    Object.seal(ref);
  }
  hook.memoizedState = ref;
  return ref;
}
```

https://github.com/facebook/react/blob/dd7e5e4f5ac2ffac3171ef61daee2cb1edc69635/packages/react-reconciler/src/ReactFiberHooks.js#L1170

単純に useRef() の引数に入ってきた値を代入しているだけですね。なにも難しいことはないです。次に初期化以降の再描画の時を見てみましょう。

```ts
function updateRef<T>(initialValue: T): {|current: T|} {
  const hook = updateWorkInProgressHook();
  return hook.memoizedState;
}
```

これだけです。少な過ぎてこの記事が企画倒れになる気もしましたが、強い気持ちで書き進めます。このコードを読む限り、 useRefは再描画が行われても単純にメモ化された値を返すだけです。

明示的に値を変えたい場合は 

```tsx
const hoge = useRef(null)

const handleSomething = () => {
  hoge.current = "new value"
}
```
のように明示的に `current` というプロパティに代入するしかありません。

ここから直感的に冒頭にあった「Does not cause re-render when the data it stores changes」がなんとなく腹落ちした方もいらっしゃるかもしれません。どういうことかと言いますと useRef で保持した値を変える時はただの値の代入でしかないため `state` を変えるわけではありません。このため再描画が発生しないのです。そしてグローバルな hooks の領域に値が保存されているため、再計算が行われても値は失われません。

どんなユースケースが考えられるか
-----
useRef で値を保持することの特性は 「再描画を発生させないこと」 これに尽きます。

なのでユースケースとしては

- 描画には関係のない状態

を扱うために使うのが主となるでしょう。

usePrevious の例は分かりやすいですね。前回の値を保持しておいて、それをコンポーネント内の関数やらの分岐に使うわけです。ただ正直これ以外は私はあまりユースケース思いつかないです。多分ノリ的にはClassコンポーネント時代に、Classのプロパティとして `this.xxx` という風に扱っていたものと同じな気がするんですが、それもあまりやった覚えがないのでいい具体例が出てこない…。

ただ覚えておいて損はない特性だと思うので、この記事がいつか役に立てると幸いです。
Project Euler 52をPythonでやってみる

# 問題 52
125874を2倍すると251748となる. これは元の数125874と順番は違うが同じ数を含む.
2x, 3x, 4x, 5x, 6x が x と同じ数を含むような最小の正整数 x を求めよ.

[http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2052](http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2052)
#解答
正直なんの工夫もなく調べていっても1秒ちょっとで解けるのですがそれじゃあ味気ないのでxと6xの桁数が一致するための必要条件として上2桁が17以下であるかの判定をしました。

```python:ProjectEuler52.py
def check(n):
    n_sort = sorted(str(n))
    for i in range(2,7):
        if n_sort != sorted(str(i*n)):
            return False
    return True

def main():
    n_max =10000000
    for n in range(100,n_max):
        if int(str(n)[:2]) > 17: #桁チェック
            continue
        if check(n):
            return n

print(main())
```

0.383 seconds
Unity2019.1.5f1でのskybox変更で詰まった話


*2019/06/14更新*

この記事は

|Unity|2019.1.5f1|
|:---:|:---:|
|Visual Effect Graph| 5.7.2|
|Core RP Library|5.7.2|
|High Definition RP|5.7.2|

の構成です、レガシーレンダーパイプラインの場合やLWRPの場合は従来通りの設定方法でskyboxが変更できるとのことです

---


そろそろUnity2019を触ってみようかな～って思ってVisualEffectGraph勉強用に作ってたプロジェクトでskyboxを設定しようとしたらいつもの場所にヤツがいない!!

別の2018のプロジェクト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212999/a566f339-6607-38ba-0248-fd474afaab7e.png)

今回触ってたプロジェクト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212999/8f53167e-4a88-1f66-0f99-a68606b64134.png)
スクロールの陰に隠れてるのでは?と思いスクロール部分がなくなるように大きめに表示してもEnvironmentのSkyboxMaterialが見当たらない!!!
見つからない!!!

![SkyboxMaterialをどこへやった.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212999/35ea356e-fb1f-58bb-1c27-8f696f144622.jpeg)


## 苦悩の末
いろんなところをポチポチしてたら...

![Skyboxの設定の仕方_0.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212999/bb3d07a3-ff1f-c26b-999f-5c47862b2b64.jpeg)

なんかそれっぽい物を発見、Inspectorを見てみると
![Skyboxの設定の仕方_4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212999/12f9842a-ec0e-eca4-349c-fc3ddb187647.jpeg)

ProceduralSkyだのなんだのSkyboxの設定っぽいものが並んでおる、もしやとおもいまたもポチポチ
するとAdd Overrideの項目から
Sky > Gradient Sky
Sky > HDRI Sky

の選択しが有るじゃあーりませんか、今回はHDRI Sky を設定しAssetStoreから落としてきたCubeMapのSkyboxファイルを設定

![Skyboxの設定の仕方_1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212999/c986a7c4-0625-9cc8-da85-c9ed624848c8.jpeg)

**表示された!!   Unity2019完全に理解した!!**
![Skyboxの設定の仕方_2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212999/4ad24a23-49c5-50bc-4ba1-30b1314e528d.jpeg)


### 余談


Visual Effect Graph で宇宙戦争的なものを作ってみたからそれのSkyboxを設定しようとしたらこうなった...

![これが作りたかった.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212999/946979f7-975b-108d-e477-7c68b9eca8f6.gif)


もうね...ポチポチしてる間ずっと↓みたいな顔してましたよ...、今後Unity2019触る人の参考になれたらと思う
もしかしたら公式のドキュメント見ればすぐに解決できたかも???
![img_0_m.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212999/10f7437a-bf60-00fe-2eba-575133a4dc59.jpeg)


## 追記

ザバイオーネさんから情報提供していただきましたHDRPの場合はいろいろと今までと勝手が違うようでドキュメントを熟読することを勧められました( ゲームを取説読まずにプレイする性格がこんなところで仇となるとは... )

https://twitter.com/z_zabaglione/status/1139116015848050688

[ドキュメント](https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@6.7/manual/Static-Lighting-Sky.html)
Eclipseのスニペット/テンプレート

# Eclipseのスニペット/テンプレート
VSCodeのスニペットが便利なので、Eclipseでも似たような機能がないか探したところ、
同様の機能として「スニペット」と「テンプレート」が見つかりました。
それぞれ概要を説明しつつ比較してみます。

## スニペット
予め記録しておいたコードをそのままカーソル位置に挿入する機能です。

### スニペットへの追加方法
1. スニペット化したい範囲を選択した後、右クリック=>スニペットに追加を選択
2. カテゴリー選択ダイアログが開くのでカテゴリーを選ぶか入力します。一見入力できなさそうに見える選択欄ですが、入力できます。
3. パレットのカスタマイズ画面が開きますので、そこでスニペット名や変数を定義します。(なぜかここで名前が変わります)

### スニペットの呼び出し方法
1. スニペットビューを開きます。出ていない場合はウィンドウ＞ビューの表示＞その他から
2. 登録されたスニペットが一覧で表示されますので、クリックします。
3. 変数がある場合は変数を入力するダイアログが表示されますので、入力します。

### 長所
#### 登録が楽
いちいち設定画面を呼び出さなくても、書いたコードをドラッグ＋右クリックで設定できるのは楽です。
コンテキストなど複雑な設定もないのでとっつき易いと思います。

### 欠点
#### キーボードだけで完結できない
ショートカットキーの類が設定されていない上ダイアログがやたらと多いので、
マウスでの操作が多くなります。
なるべくキーボードで済ませたい派はイライラするかも知れません。

## テンプレート
Ctrl⁺Spaceなどで呼び出すコードアシストに独自のテンプレートを追加する機能です。
変数定義はその部分にフォーカスが当たり、タブで移動できるタイプで
VsCodeのスニペットに近い挙動をします。

### スニペットへの追加方法
1. テンプレート(java)を開きます。ウィンドウ＞設定＞Java＞エディタ＞テンプレートで到達できますが、``Ctrl + 3 ``でクイックアクセスを開き　テンプレートと打ったほうが早いです。余談ですがスニペットとクイックアクセスに打っても出ます。
2. 新規ボタンから追加または編集ボタンで既存のものを変更できます。きちんと適用してから閉じましょう。
3. 変数に関しては、様々な組み込み変数が用意されています。[参考](https://www.ibm.com/support/knowledgecenter/ja/SS5JSH_9.1.1/org.eclipse.jdt.doc.user/concepts/concept-template-variables.htm)

### 長所
呼び出しがとにかく楽です。
通常のコードアシストと同様の形で呼び出せるので、キーボードだけでも快適に利用できます。

### 短所
上記の通り設定が面倒です。
そもそも設定箇所がかなり奥まったところにありますし、
コンテキストや変数の扱いも複雑なので慣れるまでに時間がかかります。


## まとめ
* スニペットはマウス中心でとっつき易い
* 高度な補完やキーボードのみでの完結を目指すのならテンプレートを
[AWS]VPC Endpoint がいい感じ

# VPC Endpoint
インターネットに出ることなく、AWS の各サービスとやりとりできたりするやつです。
https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-endpoints.html

# 使ってます
みなさん使ってますか？結構な種類の Endpoint が提供されています。
メリットとしては以下が代表的なものでしょうか。

- 通信料金が安い
- AWS 内部通信なのでセキュリティー的にも安全

あとはパフォーマンスもいいかもしれません。

# Firehose が提供されていた
これだけだったら記事にする必要ないと思うのですが、4月から Firehose の Endpoint が提供されていたので記事にしました。
私も6月に入ってから気づいて速攻で利用開始したのですが、やはり安い！

ログの転送などで Firehose は利用しているのですが、NAT Gateway と比べて約 1/6 の料金になります。
利用方法も以下をやるだけなので非常に簡単です。

- VPC Endpoint を作成する VPC と Subnet Group を決める。
- Security Group を作成する。
- VPC Endpoint を作成する。


# まとめ
1つの VPC Endpoint を作成すると年間で 122.64USD かかりますが、それを十分補えるメリットを享受できると思いますので、ぜひ一度導入してみてはいかがでしょうか。
[MSTest]テストエクスプローラーでユニットテストが見つからない場合の対処法

MSTestを使ってユニットテストを書いた際にテストエクスプローラーに表示されない問題が多発していましたが、私の場合は以下の方法で見つかるようになりました。

# 結論

`TestClass`属性を付けたテストクラスのアクセス修飾子を`public`にしましょう。

```C#
[TestClass]
public class SampleTests
{
    [TestMethod]
    public void SampleTest(){
        Assert.IsTrue(true);
    }
}
```

# 経緯

C#での開発をしているのですが、テスト用のプロジェクトを追加しています。
テスト対象のクラスが増えるたびにテスト用のプロジェクトにも以下のようにソリューションエクスプローラーから新しいクラスを追加していました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245628/a98a355a-10ff-d2a3-06fc-d3f45762b4b0.png)

しかし、この方法でクラスを追加した場合、テンプレートで作成されるクラスはアクセス修飾子が`private`になっています（※実際には`private`も`public`も記述されていないですがそのような場合は`private`として認識されます）。
`private`なクラスはテストエクスプローラーから見えないようなので、このクラスのアクセス修飾子を`public`にする必要があります。


# 単体テスト用クラスの追加方法

と、ここまで書いて気づいたんですが、単体テスト用クラスの追加メニューありますね。。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245628/6b6133c2-94ec-fb5d-5802-b634ead59ac0.png)

これを使えば初期状態で`public`なクラスが生成されました
めでたしめでたし

# その他の対処法たち

テストエクスプローラーからテストが見えない問題はいろいろな原因があるようです。
いくつか見つけたその他の対処法を載せておきます。（その他の症状・対処法をご存知の方は教えてください）

- [テスト設定のプロセッサアーキテクチャを自分の環境に合わせる](https://trsing.hatenablog.com/entry/2019/01/09/225349)
- [テスト用のライブラリのバージョンアップを行う](https://qiita.com/hirocueki2/items/438aa7294f773f6a644e)
- [VisualStudioの再インストールを行う](https://teratail.com/questions/100374)
- [VisualStudioを管理者として起動する](https://codeday.me/jp/qa/20181127/26321.html)
Bash の短絡評価・非短絡評価

株式会社オズビジョンのユッコ (@terra_yucco) です。
監視スクリプトなどをはじめ、LAMP でサービスやっている企業でも Bash を書く機会はまだまだたくさんあります。
そんな中、複数条件で判断するとき、短絡評価なのか？非短絡評価なのか？が気になったので調べてみた。

# 短絡評価

短絡評価とは、

- `A == 真`
- `B == 真`

の命題があった場合において、

- `A || B`

を判断する場合、B 側の判断を行わないような評価方法のことを言います。
A と B どっちかが真ならば条件を満たすので A が真である時点で B 側は見ない、非常に効率的です。

ちなみに `&&` においても同様であり

- `A == 偽`
- `B == 偽`

の命題があった場合において、

- `A && B`

を判断する場合、やはり B 側の判断は行われません。上記と同じロジックによるものです。

## Bash における条件判断

実態は `test` コマンドですが、スクリプト内では以下の書き方をすることが (少なくとも私は) 多いです。

```bash
#!/bin/bash -u
if [ ! -f /path/to/file ]; then
    echo 'NG'
    exit 1
fi
echo 'OK'
exit 0
```

複合条件の場合に短絡評価と非短絡評価をする方法を考えてみます。
特定の日だけファイルの行数をチェックし、それ以外の日は一律 OK とするような処理を例にします。

### 短絡評価

以下のようにそれぞれの条件式を `[]` で分割し `&&` 演算子でつなぐことで短絡評価になります。

```bash:minimal.sh
#!/bin/bash -u
if [ $( date +%Y%m%d ) -eq 20190601 ] && [ $( cat /path/to/file | wc -l ) -eq 1 ]; then
    echo 'NG'
    exit 1
fi
echo 'OK'
exit 0
```

1 つ目の評価式に記載した date は実行されていますが、2 つ目の評価式に記載したファイルのチェックは行われていません。

```terminal
$ bash -x minimal.sh
++ date +%Y%m%d
+ '[' 20190613 -eq 20190601 ']'
+ echo OK
OK
+ exit 0
```

### 非短絡評価

1 つの `[]` の中に評価式を入れ `-a` でつなぐことで非短絡評価になります。

```bash:non-minimal.sh
#!/bin/bash -u
if [ $( date +%Y%m%d ) -eq 20190601 -a $( cat /path/to/file | wc -l ) -eq 1 ]; then
    echo 'NG'
    exit 1
fi
echo 'OK'
exit 0
```

実際に `cat` も呼び出され、エラーなども発生していることがわかります。

```terminal
$ bash -x non-minimal.sh
++ date +%Y%m%d
++ cat /path/to/file
++ wc -l
cat: /path/to/file: そのようなファイルやディレクトリはありません
+ '[' 20190613 -eq 20190601 -a 0 -eq 1 ']'
+ echo OK
OK
+ exit 0
```

## man test の記載
### bash バージョン
```
$ bash --version
GNU bash, バージョン 4.2.46(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
ライセンス GPLv3+: GNU GPL バージョン 3 またはそれ以降 <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
```

### man の該当項目

```
       EXPRESSION1 -a EXPRESSION2
              both EXPRESSION1 and EXPRESSION2 are true
       EXPRESSION1 -o EXPRESSION2
              either EXPRESSION1 or EXPRESSION2 is true
```

これを見ると、評価が短絡かどうかは明記されていないので、もしかしたら系に依存するかもしれません。

## Conclusion

`[ EXPRESSION1 ] && [ EXPRESSION2 ]` は短絡評価
`[ EXPRESSION1 -a EXPRESSION2 ]` は非短絡評価

手が覚えているレベルでよく使う Bash の評価式でしたが、この 2 つの書き方に評価の違いがあるということは調べてみて初めて知りました。
Androidで起動アプリを固定する方法


# 背景

端末につき専用のアプリだけ起動したい、余計なものを触れられないようにしたいという要望がありました。
業務アプリを開発している人にはあるあるネタだと思います。

Androidでこれを実現する方法を調査しました。

# 方法

ルートアクティビティのonCreateメソッドに```startLockTask();```を追加するだけ！簡単！:clap:

# 実際の画面
実際の画面では下の画像のようになり、固定化を解除するまでアプリが固定されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155013/282b99c8-32b8-0b98-a147-e618fab7f042.png)
AWS スポットインスタンスの中断をCloudWatch Eventsでなんとかする

# 概要
ユーザーデータでやってたけど、Amazon Linux2からUpstartが廃止されてSystemdに移行されたこともあり、今後も何かあると正直めんどくさいと思ったからCloudWatch Eventsに移行しました。

# なぜまだスポットインスタンスなんて使っているの？
Fargateにしたいけど高いからです。オンデマンドと比べて8%~20%超で割高なのでまだ使えないです。
あとは起動が若干遅かったりするみたいなので。

# やり方
## CloudWatch Event を作成

以下のコンディションで作成すると全てのスポットインスタンスの中断が拾えます。

```json
{
  "detail-type": [
    "EC2 Spot Instance Interruption Warning"
  ],
  "source": [
    "aws.ec2"
  ]
}
```

## Lambda Function を作成
CloudWatch Event の通知先にする Lambda Function を作成します。
今のアプリケーションは以下の構成で動いています。
- LB
- AutoScaling Group
- ECS(EC2)

 なので、イベントが通知されたら以下の処理を Lambda で実行するように実装します。(boto3)
- `autoscaling.describe_auto_scaling_instance`s でインスタンスの情報を取得
- `autoscaling.detach_instances`で AutoScaling Group からインスタンスをデタッチ
    - この時 `ShouldDecrementDesiredCapacity=False` で DesiredCapacity を変更しないように注意
- `ecs.list_container_instances` で `containerInstanceArns` を取得
- `ecs.update_container_instances_state` で DRAINING


# まとめ
AutoScaling Group の Desired Capacity を変更しないことと、即座に ECS Instance を DRAINING にすることでパフォーマンスに影響させることなくスケーリングを持続できます。

# 注意すること
中断リクエストから EC2 Instance の Terminate まで2分しか余裕がないので、Fluentd　などでログを転送している場合などは Flush のインターバルを考慮するなど、アプリケーションが中断される際に気をつけることを先にやっておくと良いかもしれません。
AWS api gatewayでstagesごとにIP制限をかける

## やりたいこと
API Gateway のstages ごとにIP許諾の設定をする。

## やったこと
Resource Policyで各stagesにIPを指定する。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:region:account-id:api-id/stage-name1/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "hogehoge"
                }
            }
        },
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:region:account-id:api-id/stage-name2/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "fugafuga"
                }
            }
        }
    ]
}
```

参照：[Amazon API Gateway ： API を呼び出すためのアクセスの制御](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-control-access-using-iam-policies-to-invoke-api.html)
composer requireで「Your requirements could not be resolved to an installable set of packages.」エラーが出たときの対処法。

##問題
composer require 〇〇でパッケージをインストールしようと以下のエラーが出てインストールができない。

```
Using version ^1.0 for abraham/twitteroauth
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.
  Problem 1
    - abraham/twitteroauth 1.0.1 requires ext-curl * -> the requested PHP extension curl is missing from your system.
    - abraham/twitteroauth 1.0.0 requires ext-curl * -> the requested PHP extension curl is missing from your system.
    - Installation request for abraham/twitteroauth ^1.0 -> satisfiable by abraham/twitteroauth[1.0.0, 1.0.1].
  To enable extensions, verify that they are enabled in your .ini files:
    - C:\php-7.3.5-nts-Win32-VC15-x64\php.ini
  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.
Installation failed, reverting ./composer.json to its original content.
```


##解決策
エラーの内容を見るとcurlが見当たらないことが問題らしい。

```
the requested PHP extension curl is missing from your system.
```

php.iniを開き、curlのコメントアウトを外し。有効化すればインストールが可能になる。

```
;extension=curl
↓
extension=curl
```

##参考
composerで怒られた. the requested PHP extension curl is missing from your system
https://kengotakimoto.com/post-2754/
Alibaba CloudのWebサイトのspmとは何か

## Alibaba CloudのURL

<img width="1028" alt="alibaba_spm01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131345/95d3c819-064b-69b1-f222-39e3a3fdec93.png">

Alibaba CloudのWebサイトを見ていると、URLに **?spm〜〜〜** とついているのに気づきます。
Webサイトは、[中国](https://cn.aliyun.com)、[インターナショナル](https://www.alibabacloud.com)、[日本](https://jp.alibabacloud.com)とありますが、漏れなくspmが付いてきます。
この謎のspmについて調べてみました。

## SPM (super position model) はアクセス解析のためのもの

公式情報は発見できなかったのですが、元々は淘宝（taobao）などでアクセス解析のために使われていたようです。Alibaba Groupで広く使われている手法みたいですね。

どのページのどのボタン経由でアクセスしてきたか等といった、アクセス解析をするためのものです。
spmのフォーマットは、spmA.spmB.spmC.spmD.spmEと、ドット(.)区切りで5つを連結したものになっています。

```
// spm=spmA.spmB.spmC.spmD.spmE  
SpmA サイトを一意に識別する
spmB サイトのページを一意に識別します
spmC ページのブロックを一意に識別します
spmD ブロックの特定の位置を一意に識別します
SpmE ランダムに生成された文字列は、時間に関連し、ループページを計算するときにクリックのタイミングを区別できます。
```

##spmって必要？

SPMはアクセス解析のためのものなので、それが無くても問題なくアクセスできます。
URLをシェアする際は?spm以降は削除しましょう。

## 参考ページ(中国語)
http://blog.sina.com.cn/s/blog_78d7e8f10102y2n2.html
https://blog.csdn.net/qq_15071263/article/details/81015996
Product Advertising API が使えないなら Google Books APIを使えばいいじゃない

### 前書き

これは、本を読むのが好きだけど探すのが嫌いな僕が、適当な説明文を書いておけば誰かが勝手におすすめのものを教えてくれる「[積んでけ](https://tsundeke.me)」というサービスを作った際に学んだことを書いているものです。

# Product Advertising APIがエラーを返答する

昔、AmazonのProduct Advertising APIを使って本を検索するWebアプリを作った事があったので、そのWebアプリを流用して作ろうとしたところ、`You are submitting requests too quickly. Please retry your requests at a slower rate.`というエラーが返答されて使えなくなっていました。調べてみたところ、以下のポリシー変更が行われていたようです。

[[重要] Product Advertising API 利用ポリシーの変更について](https://affiliate.amazon.co.jp/help/topic/t52)

```
売上実績の発生がない場合は、PA-APIの利用開始はできません。
また、発送済み商品売上が過去30日以内に発生していない場合、PA-APIをご利用いただけなくなる恐れがございます。
```

サービスを作らないと売上実績は作れないけど、サービスを作るためにはProduct Advertising APIで商品を検索する必要があるというデッドロック状態にハマってしまったわけですが、本を検索するだけでよければGoogle Books APIという便利なものがあります。

# Google Books APIの使い方

Google Books APIを使った本の検索は `Volume` APIを使うことになります。`search terms`の部分に検索文文字を入れることで検索することができます。

```
GET https://www.googleapis.com/books/v1/volumes?q={search terms}
```

返答されるJsonは以下のURLに記載されています。

[Google Books APIs - Volume Resource Representations](https://developers.google.com/books/docs/v1/reference/volumes#resource-representations)

Goolg Books APIで返答される値には一般販売されているものとは限りません。一般販売されているものだけを使いたい場合は、 `volumeInfo.industryIdentifiers[]`のtypeの値が`ISBN_10`か`ISBN_13`であるパラメータが存在するかどうかで判定すれば良いと思います。


### 宣伝

もし興味があれば使ってくれると嬉しいです。

[積んでけ](https://tsundeke.me)

> 世界にはあなたやわたしがまだ出会っていないすばらしいものが無数に存在します。 あなたが知っている素晴らしいものは、だれかが探し続けているものかもしれません。 あなたが探し続けているものは、だれかがすでに素晴らしいと思って使っているものかもしれません。 「積んでけ」はだれもが気軽に軽い気持ちで自分が知っている素晴らしいものを教えあうサービスを目指しています。
ディープラーニングで日経平均株価を予測

#ディープラーニングで日経平均株価を予測#
この記事は、ディープラーニングの勉強の一環です。
間違いなどはご指摘頂ければ幸いです。

今回は、RNN との比較のため、まずはニューラルネットワークで予測をしました。
日経平均株価を選んだのは、特に理由はありません。

今回のソースファイルは[こちら](https://github.com/Fukuhaku/MachineLearning/blob/master/NN%E3%81%AB%E3%82%88%E3%82%8B%E6%97%A5%E7%B5%8C%E5%B9%B3%E5%9D%87%E6%A0%AA%E4%BE%A1%EF%BC%88%E7%B5%82%E5%80%A4%EF%BC%89%E3%81%AE%E4%BA%88%E6%B8%AC.py)

__※この記事を参考にした取引によって発生した損害、またはトラブルについては、一切の責任を負いかねます。__
##環境##

+ Windows 7 Proffessional 64bit
+ Python 3.6.7 (anaconda)
+ TensorFlow 1.12.0
+ Keras 2.2.4

##データのダウンロード##
以下のサイトより日経平均株価の日時データをダウンロード
[日経平均プロフィル　ダウンロードセンター](https://indexes.nikkei.co.jp/nkave/index?type=download)
##データの確認##
###データの取り込み###
```python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

data_file = 'nikkei_stock_average_daily_jp.csv'
df = pd.read_csv(data_file, index_col=0, encoding='cp932')

## 最終行はデータではないため削除
df = df[:-1]

## 終値
closing_price = df['終値'].values
```
###欠損値の確認###

```python
print('欠損値の個数')
print(df.isnull().sum(), '\n')
```
実行結果　欠損値なし

```
欠損値の個数
終値    0
始値    0
高値    0
安値    0
dtype: int64 
```
###基本統計量の確認（終値）###
```python
print('終値の基本統計量')
print(df['終値'].describe(), '\n')
```
実行結果

```
終値の基本統計量
count      843.000000
mean     19990.357865
std       2341.431256
min      14952.020000
25%      17862.420000
50%      20163.800000
75%      22011.195000
max      24270.620000
Name: 終値, dtype: float64
```
###終値を時系列にプロット###
```python
plt.title('日経平均株価（終値）の推移')
plt.plot(range(len(closing_price)), closing_price)
plt.show()
```
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425339/e60109ff-522b-affb-1039-81f9ac75077a.png)

##訓練・検証・テスト用データを作成##
各データを以下のように設定

+ 過去300～61日分を訓練用データ
+ 過去60～31日分を検証用データ
+ 過去30～0日分をテスト用データ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425339/d999f0c7-0b8e-24d4-2dec-d4daacb38bae.png)
また、各データは過去30日分の株価を説明変数（X）、当日の株価を目的変数（y）とする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425339/4947b83c-2e8d-7c8b-cf37-5e8777621c7a.png)

##訓練##
今回は入力層・隠れ層1つ・出力層の3層のニューラルネットワークとしています。
損失関数は mae、エポック数は 3,000 としています。

```python
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import RMSprop

model = Sequential()
model.add(Dense(32, activation='relu', input_shape=(X_train.shape[-1],)))
model.add(Dense(16, activation='relu'))
model.add(Dense(1))

model.compile(optimizer=RMSprop(), loss='mae', metrics=['accuracy'])

result = model.fit(X_train, y_train, 
                   verbose=0, 
                   epochs=3000, 
                   batch_size=64, 
                   shuffle=True, 
                   validation_data=(X_valid, y_valid))
```

##訓練結果（損失値）##
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425339/448a448c-14a9-5f8b-0e17-7b451b5c553b.png)

##予測（テスト）結果##
直近30日を予測（テスト用データを予測）した結果です。
二乗平均平方根誤差（RMSE）は 313.059
まあまあ良い精度が出ました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425339/6d0d67b0-d284-4011-2ee2-5692444cfb24.png)
Mac OS X, Zsh の環境で pyenv

Mac OS X, Zsh の環境で pyenv の設定をします。

https://github.com/pyenv/pyenv 


```
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
```

以下を ``~/.zshenv`` に追加する。``~/.zprofile``ではないことに注意。

```
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
if command -v pyenv 1>/dev/null 2>&1; then
  eval "$(pyenv init -)"
fi
```

https://github.com/pyenv/pyenv/wiki に従って環境を整えます。（Mojaveの場合）

```
brew install openssl readline sqlite3 xz zlib
sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /
```

## Update
```
cd $(pyenv root)
git pull
```
Netlifyを使った開発途中サイトの簡易プレビュー。開発用ブランチを一時公開する方法。

## こんなときに
* Githubを使っている
* Netlifyでホスティングをしている。したい。
* 開発中の状態をスマホでプレビューしたり、人に見せたい。けど公開状態にはしたくない。


## 手順
1. Githubと連携したリポジトリを用意する
2. Netlifyと接続する
3. 開発用ブランチを切って作業を進めて、そのブランチをpush
4. Githubを開いてプルリク
5. プルリクの画面でnetlifyが反応する。


### 1. Githubと連携したリポジトリを用意する
githubと連携できれば中身はなんでも。もちろんフロント系の何か。


### 2. Netlifyと接続する
ホスティングサービス。いろいろできる、そしてオシャレなUI。
[Netlify: All-in-one platform for automating modern web projects.](https://www.netlify.com/)

Githubアカウントで登録できる。

Githubと連携して、そのmasterブランチをpushがあるたび自動でビルドして公開することができる。
netlify側にビルドのコマンドを任せることもできる。だからvueとかreactとかも載せられる。しゅごい。


とりあえずnetlifyでサイトをデプロイできたら、準備完了。


### 3. 開発用ブランチを切って作業を進めて、push
ひとまず公開状態になっているmasterではなく、開発用にブランチを切って作業をする。そしてそのブランチをpush。

```bash
git checkout -b dev
git commit -a -m "message"
git push -u origin dev
```


### 4. Githubを開いてプルリク
以下のように、デフォでmasterの画面に出ていることもある。

![スクリーンショット 2019-06-13 18.06.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235781/e35c7252-52f3-7731-eb67-5ec5d1f2a7dd.png)


画面通りにプルリクを出す。
（自分で自分にプルリクって出せるんだね…）
![スクリーンショット 2019-06-13 18.09.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235781/d1c7d8e0-7395-f15e-3076-f51191b5784d.png)


### 5. プルリクの画面でnetlifyが反応する。

![スクリーンショット 2019-06-13 18.12.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235781/a0ac01b3-4991-61df-8c52-10b83346ca52.png)

netlifyと連携していると、何やらいろいろチェックしてくれるっぽい。（何チェックしてるのかは不明
一番下の、`deploy-preview`の横のdetailsを開く。

なんとmasterに公開する前のプレビューが、「deploy-preview…」というURLでデプロイされている。
https://deploy-preview-1--netlify-sample01.netlify.com/


特にこっちで設定する必要なく自動でデプロイしてくれてた。しゅごい。

このリンクは、マージしても有効だった。（いつまで有効なのか謎…


## 参考
[Netlify + GitHub + VueJSのPWAでdeploy previewをやってみた – Takeshi Amano – Medium](https://medium.com/@takeshiamano/netlify-github-vuejs%E3%81%AEpwa%E3%81%A7deploy-preview%E3%82%92%E3%82%84%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F-30a50f2e56e7)
Tomcatサーバ起動失敗時の対応

Tomcatサーバ起動時のエラー対応に関する覚え書き。
またしても研修中です。

#起こったエラー

サーバ再起動の際に、

```
Failed to initialize end point associated with ProtocolHandler...
```

とメッセージが。

不勉強でよく分からなかったのがどうやらポート番号が競合していたみたいです。

#対処
google先生に頼った結果得られた資料に従って`netstat -ano`でポートとPIDを確認してみました。

どうやらPID3616が8005, 8009, 8080ポートを使用しているよう。

タスクマネージャで確認したところ、`javaw.exe`が原因でした。タスクを終了してもう一度サーバ再起動かけたところ無事起動しました。

#所感
[参考資料](http://blog.livedoor.jp/baradagi/archives/66992051.html)の場合はVMWare関連と競合していたみたいですが、僕の場合はeclipse上でうまくサーバ落とせなかったとかなんですかね。
（よくよく考えてみると直前の挙動も少しおかしかった）

ググって出てきた対処法はいくつかあったんですが、アラート出てるパターンが多かったです。
今回はコンソールに文章が出てきただけだったので情報の取捨選択に少し苦戦しましたね。

やっぱりエラーログはちゃんと見るべき。

（あと単純に知識が足りないので要勉強（この記事すら理解が曖昧（頑張ります）））

#参考
[JavaEE: Tomcatを開発用途でインストール（VMware Server Web Accessとバッティング）](http://blog.livedoor.jp/baradagi/archives/66992051.html)
Javascriptでセレクトボックスで選択された値を取得する方法

# Javascriptでセレクトボックスで選択された値を取得する方法

セレクトボックスの値を取得して、条件次第で次のセレクトボックスの内容を変えたりしたいことはありませんか？

イベントはonchangeで発火させて、セレクトボックスの値はgetElementByIdで取得できます。

```post.js
// セレクトボックスで値が選択されたらイベント発火
  $("セレクトボックスのID").on('change',function(){

    // セレクトボックスで選択された値を取得、コンソールにセレクトボックスの値が表示されることを確認
    const str = document.getElementById("セレクトボックスのID").value;
    console.log(str)
  })
```
awkを使ってvmstatに日時をつける


awkを使えばvmstatだけではなくなんにでも日時をつけることが出来ます。


vmstatに日時をつける

```
vmstat 1|awk '{print strftime("%Y/%m/%d %H:%M:%S",systime()) " " $0 }'
```


```
2019/06/13 09:27:35 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
2019/06/13 09:27:35  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
2019/06/13 09:27:35  2  0      0 265972  12900 233000    0    0   274   163  511  423 15  2 83  0  0	
2019/06/13 09:27:36  0  0      0 296276  12900 233116    0    0     0  5072  593 2685 31  3 66  0  0	
2019/06/13 09:27:37  0  0      0 296160  12900 233296    0    0     0     0  397  300 14  0 86  0  0	
2019/06/13 09:27:38  0  0      0 296160  12908 233484    0    0     0    28  428  329 14  0 85  0  1	
2019/06/13 09:27:39  0  0      0 296036  12908 233704    0    0     0     0  488  393 14  1 85  0  0	
2019/06/13 09:27:40  0  0      0 295788  12908 233932    0    0     0     0  465  343 14  0 86  0  0	
2019/06/13 09:27:41  1  0      0 295540  12908 234148    0    0     0     0  424  311 13  2 85  0  0	
2019/06/13 09:27:42  0  0      0 295292  12908 234348    0    0     0     0  431  310 14  1 85  0  0	
2019/06/13 09:27:43  0  0      0 295168  12916 234492    0    0     0    12  431  325 13  1 86  0  0	
```



tail -f したデータに日時をつける

```
tail -f access_log | awk '{print strftime("%Y/%m/%d %H:%M:%S",systime()) " " $0 }'
```

```
2019/06/13 09:31:14 1.2.3.4 - - [13/Jun/2019:09:09:08 +0000] "GET / HTTP/1.1" 200 479 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:56.0) Gecko/20100101 Firefox/56.0 Waterfox/56.2.10"
2019/06/13 09:31:14 1.2.3.4 - - [13/Jun/2019:09:09:08 +0000] "GET /css/demo.css HTTP/1.1" 304 - " "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:56.0) Gecko/20100101 Firefox/56.0 Waterfox/56.2.10"
2019/06/13 09:31:14 1.2.3.4 - - [13/Jun/2019:09:09:08 +0000] "GET /js/jquery.min.js HTTP/1.1" 304 - "" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:56.0) Gecko/20100101 Firefox/56.0 Waterfox/56.2.10"

```
Rasberry pi 3BにDocker-composeを使ってREDMINEを入れる。

超初心者なワタシがRaspberry pi 3BにDocker-composeを使ってREDMINEを入れたときのメモです。
暖かい目でなにかあれば指摘してください。

# 構成
- Raspberry Pi 3B
- 2019-04-08-raspbian-stretch-lite VERSION 9.9

上記がインストールされてSSH接続されているもしくはHDMIなどで画面に接続されている前提で始めます。

# やり方　
# 1. まずはアップデートしましょう。

```
sudo apt update
sudo apt upgrade
```
# 2. Dockerを入れましょう。

これを参考にさせていただきました。(投稿者に感謝！)
https://qiita.com/HyunwookPark/items/6e4854248c6d63958060
簡単に言うと下を実行して～

```
curl -sSL https://get.docker.com | sh
```
ユーザーの権限をつけて～

```
sudo usermod -a -G docker pi
```
再起動して～

```
sudo reboot
```
DockerのVersionを確認します。

```
docker -v
```
こんな感じで表示されます。

```
Docker version 18.09.0, build 4d60db4
```
次にDockerの動作確認をします。
Hello-worldをpullして

```
docker pull hello-world
```
hello-worldを走らせます。

```
docker run hello-world
```

下記がが表示されたらOK

```
Hello from Docker!
```
Dockerのインストールに成功しました。

# 3. Docker-composeを入れましょう。

これを参考にさせていただきました。(投稿者に感謝！)
https://qiita.com/tkyonezu/items/ceaaf41924df39254058
ここのコメント欄に簡単にインストールできるスクリプトを作ってくださった方が
いたのでそれを利用しました。
このコマンド打つだけ！30分くらいかかったと思います。

```
curl -sSL https://git.io/fjGM3 | sh -s -- -c -b 1.24.0
```
日本にはたくさんの神がいると思いました。。。
たしか再起動したと思います。

```
sudo reboot
```
そのあと以下のコマンドを打ちます。

```
docker-compose version
```
次のメッセージが出たら成功。

```
docker-compose version 1.24.0, build d9fa815
docker-py version: 3.7.2
CPython version: 3.6.8
OpenSSL version: OpenSSL 1.1.0j  20 Nov 2018
```
Docker-composeのインストールに成功しました。

# 4. REDMINEとPostgreSQLを入れましょう。

まずはmkdirでフォルダを作り、そのフォルダに移動します。
場所は/home/piになると思います。

```
mkdir ~/docker-redmine
cd ~/docker-redmine
```
そこにymlファイルを作ります。

```
sudo touch docker-compose.yml
```
中身を見ます。個人的には初心者はlessが使いやすいと思う。。。

```
less docker-compose.yml
```
中身はこう書きました

```
version: '3.5'
services:
  redmine:
    image: arm32v7/redmine
    restart: always
    ports:
      - 8080:3000
    environment:
      REDMINE_DB_POSTGRES: db
      REDMINE_DB_DATABASE: redmine
      REDMINE_DB_USERNAME: redmine
      REDMINE_DB_PASSWORD: exsample
      REDMINE_DB_ENCODING: utf8
    depends_on:
      - db
    volumes:
      - /var/www/redmine/files:/usr/src/redmine/files
      - /var/www/redmine/log:/usr/src/redmine/log
      - /var/www/redmine/plugins:/usr/src/redmine/plugins
      - /var/www/redmine/public/themes:/usr/src/redmine/public/themes

  db:
    image: postgres
    restart: always
    environment:
      POSTGRES_DB: redmine
      POSTGRES_USER: redmine
      POSTGRES_PASSWORD: exsample
    volumes:
      - ./dbdata/:/var/lib/postgresql/data
```

あとは次のコマンドを打つのみ

```
docker-compose -f docker-compose.yml up -d
```
ざっくり10分くらい待てばできてるはず。Dockerコンテナを確認しましょう。

```
docker ps
```
arm32v7/redmineとpostgresというIMAGEのコンテナが出来ていたらOK
ではここからWebブラウザでアクセスすればREDMINEが動いているのが見れるはずなんですが
先にRaspberry piのipアドレスを確認しましょう。

```
ip address
```
そうするとザーーーと何やらたくさん表示されると思います。
その中からeth0:と書かれた場所を探します。(ただし、Raspberry pi有線で接続している場合)
そこにinet 192.168.0.???/24 のような感じでアドレスが書かれているのをメモします。

webブラウザ(Google chromeやFirefox)を起動する。

urlのアドレスバーに
http://ipアドレス:8080　と入力します。
入力例：　http://192.168.0.99:8080

REDMINEが表示されたら成功！　おつかれさまでした。
初期IDとPWはadmin adminです。

最初はトラッカーの設定をしないとチケットの作成が表示されないので注意してください。

困ったときに教えてくれた「優しい世界」人たちに感謝。
ちょっと便利なnpmコマンドたち

# 目次
1. この記事の目的
2. ちょっと便利なnpm コマンド集
3. 終わりに
4. 参考

# この記事の目的
こちらの[サイト](https://dev.to/borrellidev/impress-your-colleagues-with-these-npm-tricks-3fcb)で、便利なnpmコマンドがまとめられていたので、一部をシェアします。

# 各npm コマンド
### - パッケージの初期化を実行する
サクッとパッケージを初期化する場合に。
下記コマンドであれば、すべての選択肢にYesを返すので、Yes/No 選択を求めらません。

```
$ npm i -y
```

### - パッケージのホームページにアクセスする
各パッケージのホームページにアクセスできます。
ドキュメントを参照する場合に。

```
$ npm home PACKAGE_NAME
```

### - パッケージのGithubレポジトリにアクセスする
各パッケージのGithubページにアクセスできます。
ソースコードを参照する場合に。

```
$ npm repo PACKAGE_NAME
```

### - インストールされているすべてのパッケージを一覧表示する
package.jsonを、都度確認する手間が省けます。

```
$ npm ls --depth 0
```

### - package.json内に記述されていないパッケージを整理する
コマンドを実行すると、package.jsonに記述されていない/node_modules内パッケージをすべて削除します。

```
$ npm prune
```

### - インストールされているパッケージに、新しいバージョンが存在するか一覧表示する

```
$ npm outdated
```
# 終わりに
何かの役に立てば幸いです。
打倒、!important。こいつを上回るカスケード順序

# すごいCSSがすごかった（語彙）・・・
　長年継ぎ足しされてきて巨大戦艦みたいになってるCSS。新たなデザインが加わったところで、ちゃんと表示されなくなる部分が出てきていたので、それの修正作業をした時の話です。
応急処置感が半端じゃないので、もっと綺麗に書き直すのにいい方法を見つけたいところです・・・

## !importantが乱用されている
強制的に新しいデザイン部分を入れ込むのにそこかしこに!importantで読ませている。これのせいで影響を与えてはならないところまで影響が出たので、なんとか新たに加えられたCSSには影響を与えることなく、影響を与えられてしまったところだけをなんとかするにはどうしたらいいか？

## 解決策
セレクタを詳細に書き込むことで、!importantを超えるカスケード順序にすることができる。
ということで、セレクタを詳細にして、優先順位をあげることができる仕組みをCSSの固有性と呼ぶそうです。

```ex.csss
ul {background:#dd6300!important;}

#hoge .fuga li ul {background:#f0f8ff;}
```

上記のようにしてあげると、下の方が優先されて読まれる。
mojaveにあげたらrails 使えんくなったよ〜

mojaveにあげたら、rails sもrails -vもできなくなってしまいました。

```
$ rails -v
rbenv: rails: command not found

The `rails' command exists in these Ruby versions:
  2.3.1
  2.3.3
  2.5.0

```

ということで、方法を箇条書きで
command_line toolを最新のものにする。

bundlerがうまく入ってなかったので、
bundler のversiionを指定してinstall

gemfile.lockと照らし合わせて、bundler -vがずれていたらGemfile.lockを削除

自分の場合は、gemfileのruby -vがずれていたので修正 1.1.0 => 1.1.1みたいに

その状態でbundle installしました。

解決。

あと、記事見たらいいねください。。。
PySparkでspark-testing-baseを使ってみる

# 概要

spark用のテストライブラリの[spark-testing-base](https://github.com/holdenk/spark-testing-base)をPySparkでどのように使うかを軽く調べてみた。

# 調べたこと

- unittest2のTestCaseを継承しており、`unittest2.main()`でテスト実行できる
- クラス内部でspark contextを立ち上げており、テストでわざわざ自力で立ち上げる必要がない
    - 自分でspark contextを立ち上げていると、テスト実行時にエラーになる
- DataFrameの場合、スキーマと件数と各レコードの並びが一致するかを確認しているみたい
 
```python:DataFrameのテストサンプル
from sparktestingbase.sqltestcase import SQLTestCase
import unittest2


class DataFrameTest(SQLTestCase):
    def test_expected_equal(self):
        data = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
        df = self.sqlCtx.createDataFrame(data, ['a', 'b', 'c'])
        self.assertDataFrameEqual(df, df)
        
    @unittest2.expectedFailure    
    def test_expected_unequal(self):
        data = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
        df1 = self.sqlCtx.createDataFrame(data, ['a', 'b', 'c'])
        df2 = self.sqlCtx.createDataFrame(data, ['a', 'b', 'd'])
        self.assertDataFrameEqual(df1, df2)


if __name__ == "__main__":
    unittest2.main()
```


# 関連

- [Spark でUnit Testを書く](http://lab.astamuse.co.jp/entry/spark-testing-base)
Azure Search Service に Add Document する (Java)


#事前準備
* Indexを作っておく
* フィールドを定義しておく

#コード

```java

package hello.azure;

import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class AzureSearchDocumentAdd {

	public static void main(String[] args) throws Exception {

		// @see
		// https://docs.microsoft.com/ja-jp/rest/api/searchservice/create-index
		// https://docs.microsoft.com/ja-jp/rest/api/searchservice/addupdate-or-delete-documents

		// POST https://[service name].search.windows.net/indexes/[index name]/docs/index?api-version=[api-version]
		// Content-Type: application/json
		// api-key: [admin key]

		// from console
		String adminKey = "xxx";

		HttpClient httpclient = HttpClients.createDefault();

		String serviceName = "yyy";
		String indexName = "zzz";

		String dateValue = (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")).format(new Date());

		String json = "{" //
				+ "'value': [" //
				+ "{" // フィールドと同じ構造
				+ "'@search.action': 'upload'" + "," // <-コマンドに相当
				+ "'id': '001'" + "," //
				+ "'description': 'Hello'" + "," //
				+ "'date': '" + dateValue + "'" + ", " //
				+ "'item1': 'aaa'" + ", " //
				+ "'item2': 100" + ", " //
				+ "'item3':[{'item3_1':'bbb'}]" //
				+ "}" //
				+ "]" //
				+ "}" //
		; // 

		try {
			URIBuilder builder = new URIBuilder("https://" + serviceName + ".search.windows.net/indexes/" + indexName
					+ "/docs/index?api-version=2019-05-06"); //

			URI uri = builder.build();
			HttpPost request = new HttpPost(uri);
			request.setHeader("Content-Type", "application/json");
			request.setHeader("api-key", adminKey);

			// Request body
			StringEntity reqEntity = new StringEntity(json);
			request.setEntity(reqEntity);

			HttpResponse response = httpclient.execute(request);
			HttpEntity entity = response.getEntity();

			int responseCode = response.getStatusLine().getStatusCode();
			if (responseCode == 200) {
				System.err.println(
						"200 is returned for a successful response, meaning that all items have been stored durably and will start to be indexed.");
			} else if (responseCode == 201) {
				System.err.println("201 (for newly uploaded documents)");
			} else {
				System.err.println(responseCode);
			}
			if (entity != null) {
				System.out.println(EntityUtils.toString(entity));
			}

		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

}


```

#結果

```javascript
{
"@odata.context":"https://yyy.search.windows.net/indexes('zzz')/$metadata#Collection(Microsoft.Azure.Search.V2019_05_06.IndexResult)",
"value":[
 {"key":"001","status":true,"errorMessage":null,"statusCode":200}
]
}

```

#確認

インデックスに対するクエリーは管理コンソールからも試せます。