OmniAICreator/Qiita-1.07M huggingface dataset:
俺でも泣いたAWS CodePipeline未対応なSCMを使っちゃってるので俺ージドにJenkinsからAWS CodeBuildを蹴り倒すためのtips

俺です。

GitなどのSCMつかうのが呼吸なワケですが、
AWS CodePipelineやAWS CodeBuildのSourceが未対応だったときってあるじゃないですか。

例えばBacklogのGitとか。

source未対応だった衝撃をうけて、現世からいなくなりたいと思う気持ちを抑えて
以下のようにJenkinsに寄せた俺の記録を残します。

- CodePipelineを捨てる
- Jenkins Pipelineに寄せる
- JenkinsにAWS CodeBuild Pluginを導入して蹴る

なお、すでにCode3兄弟がsourceとして対応してるSCMを使えてる人は[帰って](http://yahoo.com)どうぞ。

当初 @inokappa の [エントリ](https://inokara.hateblo.jp/entry/2017/06/11/105245) を実装して幸せ一直線なんじゃないかとおもうてましたがRepositoryがLambdaの一時ストレージサイズ超えたらどうすんべとなり諦めました。悲しい



# 構成

![non-supported-scm.png](https://qiita-image-store.s3.amazonaws.com/0/42755/c84c1529-3191-fdee-ceba-09e835228e5b.png)

# IAM Policy

Jenkins用EC2に適用するIAM RoleのPolicyを[ドキュメント参照](https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/jenkins-plugin.html)して作ります。

# Jenkinsfile

GUIでポチポチするのはしんどいのでPipelineジョブを使います。
便利ですねーJenkinsfile.appspec書くより楽かも..と思ってしまった俺達はJenkins初老丸の仲間入りです。

具体的なJenkinsfileの書き方は[こちら](https://jenkins.io/doc/book/pipeline/jenkinsfile/)参照してください。

```
pipeline {
  agent any
  parameters {
    string(name: 'SyncTargetS3', defaultValue: 'orenosaikoubucket', description: 'codebuild source s3 bucket')
  }
  stages {
/*
// Pipeline from SCMしない場合は以下なかんじでgit cloneするstepを作る
    stage('git clone') {
      steps {
        git(
          url: "${params.GitURL}",
          credentialsId: '<Jenkinsで作ったCredentialsID>',
          branch: "${params.GitBranch}"
        )
      }
    }
*/
    stage('zip archive ${env.WORKSPACE} to /tmp/${env.WORKSPACE}.zip') {
      steps {
        sh("cd ../ && zip -r /tmp/${env.JOB_NAME}.zip ${env.JOB_NAME} -x *.git*")
      }
    }
    stage('aws s3 cp') {
      steps {
        sh("aws s3 cp /tmp/${env.JOB_NAME}.zip s3://${params.SyncTargetS3}")
        sh("aws s3 ls s3://${params.SyncTargetS3}/")
        sh("rm -f /tmp/${env.JOB_NAME}.zip")
        echo "done"
      }
    }
    stage('start AWS CodeBuild'){
      steps {
        awsCodeBuild(
          projectName: 'sandbox',
          region: 'ap-northeast-1',
          credentialsType: 'keys', // Jenkins用EC2でIAM InstanceProfileを呼ぶ場合はこのパラメータをkeysとして、credentialsとsecret_keyは設定しないこと
          sourceControlType: 'jenkins'
        )
      }
    }
  }
}
```

良いJenkins Pipelineライフを！！！！！！
コマンドラインから大量のURLをChromeのシークレットモードで開く

# なにこれ
動作検証の際に、複数のURLをシークレットモードで開きたくなることがあった（cookieをなくして画面を出して欲しいとか）。
これの件数が増えてくると、そりゃもう何回もポチポチしなくちゃいけなくて「腱鞘炎になりそうで辛いなー」と思ったので簡単に済ませたかった。

# そもそもChromeをCLIから開くには
macの場合かなーり簡単（windowsの場合は手元に環境がないのでわからないけど、多分簡単なはず）

```
open -a "Google Chrome" "https://example.com"
```

こんだけ。
URLを変えてあげれば基本的に好きなページが開ける

# シークレットモードを開くには
今回の本題。
ミソとしては、複数タブで開く場合 `-n` でopenしてあげるところ。

```
open -n -a "Google Chrome" --args --incognito "https://example.com"
```

これでシークレットモードでページが開かれる。
~~ていうかシークレットモードが`incognito mode`って表現されるって知らなかった・・・~~

# じゃあ沢山のURLを開くには？
上記の応用と力技でスクリプトを組む。

```sh
#!/bin/sh

count=0

while read line
do
  echo "$((++count)): $line"
  open -n -a "Google Chrome" --args --incognito "$line"
done < ${1}
```

コマンドは
`./open_chrome.sh input.txt`

これやると一時的に新規ウィンドウがいっぱい開かれるのでちょっと笑える。
zshでpre-commitを導入する際の注意点

## はじめに

個人開発でpre-commitを導入したのですが、zshに切り替えてからというものの、

```zsh

Could not find nokogiri-1.8.5 in any of the sources
Run `bundle install` to install missing gems.
```

というエラーに悩まされたので、解決方法を記します。

## 解決方法

### git configに設定を追加

```zsh

$ git config pre-commit.ruby "bundle exec ruby"
```

まずは`pre-commit`の公式サイトに基づいて、上記のコマンドを実行する。

### libxml2をbrewでいれ、シンボリックリンクを削除

```zsh
$ brew install libxml2
$ brew unlink libxml2
```

>1.1. libxml2とは
libxml2とは、XMLを解析・操作するC言語のライブラリです。
xmlsoft(http://www.xmlsoft.org/)で配布されています。

### rbenvの再設定

```zsh
$ rbenv exec gem install bundler
$ rbenv rehash
$ bundle install
```

### bundlerの再設定

```zsh
$ bundle config build.nokogiri --use-system-libraries
```

今回のキモはここで、systemのlibrariesにあるnokogiriを使うように指定してあげれば良かったようですね。


## 参考サイト

[bundle install で nokogiri をインストールしろと言われる解決方法](https://qiita.com/pugiemonn/items/4b23a709ed194b02be6d)

[Homebrewメモ](https://qiita.com/saba1024/items/0f397b3f59d28e0ef527)

[libxml2](http://saj.co.jp/techinfo/htmls/xml-libxml2-introduction.html)

[Bundlerでビルドオプションを指定する](https://qiita.com/thunders/items/101c6b329830fb1fb27d)
switch文 break漏れ 警告 

### 目次
C/C++のswitch文では、case文の最後にbreak文を設定しなくても、コンパイルエラーにはなりません。
これをフォールスルーといい、意図的に処理を統一して使用するケースでは便利なのですが、誤ってbreak文を入れ忘れた場合にはバグが埋め込まれてしまいます。

そのため、コンパイラで警告を出す方法がないか調べた所、gcc7からはフォールスルーのWarningが追加されたようなので下記使用イメージを記載します。

###　前提条件
    $ g++ --version
      g++ (GCC) 8.1.0
                ^^^^^★ここがバージョン7以上でないとコンパイラが
                       対応していないため、バージョンアップして下さい
　　※gccをバージョンアップする場合、以下が参考になります。
　　　https://qiita.com/knutpb1205/items/fc6dbc15fbd052f7560a



#### エラー例
    $ vi sample.cpp
           ：
    switch(aaa)
    {
        case 2:
            bbb=2;
            ★ここがbreak漏れ
        case 3:
            bbb=3;
           break;

#### コンパイル
    ### コンパイルオプションに -Wextra か -Wimplicit-fallthrough=3を指定する
    $ g++ -Wall -Wextra sample.cpp
             or
    $ g++ -Wall -Wimplicit-fallthrough=3 sample.cpp

      sample.cpp: In function ‘int main()’:
      sample.cpp:50:16: warning: this statement may fall through [-Wimplicit-fallthrough=]
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                        ★ちゃんと警告が出ている
                   bbb=2;
      sample.cpp:52:9: note: here
               case 3:
               ^~~~

ただ、こうすると今度は意図的にフォールスルーしたい箇所でも警告が出てしまいますが、
対象外の場所には特定のコメント文 or C++17の***[[fallthrough]]属性***を挿入することで警告をスキップできます

#### 警告スキップコメント挿入後(コメント文)
    $ vi sample.cpp
           ：
    switch(aaa)
    {
        case 2:
            bbb=2;
            /* Falls through. */
            ^^^^^^^^^^^^^^^^^^^^
            ★上記のコメントを入れるとスキップ出来る。
        case 3:
            bbb=3;
           break;

#### 警告スキップコメント挿入後([[fallthrough]]属性)
    $ vi sample.cpp
           ：
    switch(aaa)
    {
        case 2:
            bbb=2;
            [[fallthrough]];
            ^^^^^^^^^^^^^^^^
            ★上記の属性を入れるとスキップ出来る。
        case 3:
            bbb=3;
           break;



※コメント分の種類は以下を参照して下さい
■RED HAT DEVELOPPER(-Wimplicit-fallthrough in GCC 7)
　https://developers.redhat.com/blog/2017/03/10/wimplicit-fallthrough-in-gcc-7/

■cpprefjp - C++日本語リファレンス([[fallthrough]]属性)
　https://cpprefjp.github.io/lang/cpp17/fallthrough.html
Unity + OpenCVで目の領域を拡大する（IndexがIncrementalじゃないのに対応）; How to scale eye region in Unity + OpenCV

* FaceTracker.csに追記

```csharp
        private void ScalePoints(int startIndex, int endIndex, float scale)
        {
            int pointNum = endIndex - startIndex + 1;
            int[] indexArray = new int[pointNum];
            for (int i = startIndex; i <= endIndex; i++)
            {
                indexArray[i - startIndex] = i;
            }
            ScalePointsByIndexArray(indexArray, scale);
        }

        private void ScalePointsByIndexArray(int[] indexArray, float scale)
        {
            double xSum = 0;
            double ySum = 0;
            foreach (int i in indexArray)
            {
                xSum += points[0][i].x;
                ySum += points[0][i].y;
            }
            double xMean = xSum / indexArray.Length;
            double yMean = ySum / indexArray.Length;

            // scale from mean
            foreach (int i in indexArray)
            {
                double relativeX = points[0][i].x - xMean;
                double relativeY = points[0][i].y - yMean;
                relativeX *= scale;
                relativeY *= scale;
                points[0][i].x = relativeX + xMean;
                points[0][i].y = relativeY + yMean;
            }
        }
```

* 使いたい所で

```csharp
            ScalePoints(37, 45, 1.4f); // nose
            ScalePoints(48, 59, 1.4f); // mouse

            int[] arr = { 27, 68, 28, 69, 29, 70, 30, 71 }; // left eye
            ScalePointsByIndexArray(arr, 2.4f); // eye
```

* なんでIndexが飛び飛びやねん！と思いながら対応した
* 想定通り目の領域が拡大されることを確認した
OpenCVでWebカメラから画像が取得できない場合の対処（C++）

#環境
- Ubuntu 16.04
- OpenCV 3.2.0
- g++ gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.10) 

#状況
C++からOpenCVを利用してWebカメラの画像を得るためのコードはこちら
[OpenCVによるUSBカメラ画像の取得](https://qiita.com/vs4sh/items/4a9ce178f1b2fd26ea30)
Pythonからだと画像が取得できるのにC++からカメラデバイスをオープン出来なかった。

#解決策
OpenCVをインストールする際、こちらの記事を参考にしていた。
[Linux環境でのOpenCVビルド](https://github.com/atinfinity/lab/wiki/Linux%E7%92%B0%E5%A2%83%E3%81%A7%E3%81%AEOpenCV%E3%83%93%E3%83%AB%E3%83%89)
[OpenCV 3.0 Makefile生成用スクリプトファイル（Ubuntu15.04）](
https://gist.github.com/atinfinity/aa0d4efb98837abd39bb)

Makefile生成用スクリプトファイル98行目の

```
-D WITH_V4L=OFF
```
を

```
-D WITH_V4L=ON
```
に変更して再インストールすると成功。
pandasのget_dummiesで横持ちにできないケースの対応

# 2020/7/4 追記
「１つのカラムに concat されている場合」で、 sklearn 使わなくても出来たのでメモ
（2019/8/16 追記のヤツのほうが良いかもしれないけど）

```python:結論こんな感じ
def one_hot_encoder(df, column, delimiter=','):
    # 文字列をリスト化
    tmp = df[column].str.split(delimiter)
    # 一旦縦持ち(複数の値持ってるヤツ対策)
    exploded = tmp.explode()
    # 横持ちに戻し、index毎に集計する
    return pd.get_dummies(exploded).groupby(level=0).sum()
```


# 2019/8/16 追記
2つ目のケースに関しては sklearn の `MultiLabelBinarizer` を使うといいんじゃない？
という情報を頂きました。なるほど、これは良さそう♪

参考：https://stackoverflow.com/a/51335634

# 2018/11/14 追記
本記事の読後に [こちらの記事](https://qiita.com/MysteriousMonky/items/7ed8ea6edce8b7204fd8) と [コメント](https://qiita.com/d_desuyon/items/e5ccaf6ccc073c104660#comment-90a666a42dade790d109) をも読むことをオススメします！

# はじめに
もしも以下のようなカラムを横持ちにしたい場合、`pd.get_dummies()`を使うと思います。

|categoricay_col|
|:---:|
|a|
|b|
|a|
|c|

でも、最近`pd.get_dummies()`で対応できないデータ構造のケースに出会い、
対応に割りと苦しんだので備忘として記事に残しておこうと思った次第です。

# 1. 複数カラムを対象に横持ちにする場合
たとえば「Qiita記事のタグデータがあり、これを横持ちにする」場合を考えます。
尚、元データは以下のようになっているとします。

- タグ情報が tag_1, tag_2 の2カラムにまたがっている
- タグの数は記事(行)ごとに異なる　※tag_2 が nan (NULL) の場合もある

|index|tag_1|tag_2|
|:---:|:---:|:---:|
|1|jupyter|nan|
|2|python|numpy|
|3|python|anaconda|
|4|java|nan|

　　　　↓ (横持ち)

|index|python|jupyter|numpy|anaconda|java|
|:---:|:---:|:---:|:---:|:---:|:---:|
|1|0|1|0|0|0|
|2|1|0|1|0|0|
|3|1|0|0|1|0|
|4|0|0|0|0|1|

自分はこのようなデータを以下のように横持ちにしました。

```python
# 重複なし tag 集合をつくる
tag_1= set(df['tag_1'].dropna().unique())
tag_2= set(df['tag_2'].dropna().unique())
tag_all = sorted(tag_1.union(tag_2))

# tag を横持ち化したリスト作成
dummy = []
for t1, t2 in zip(df['tag_1'], df['tag_2']):
    tmp = []
    for ta in tag_all:
        if t1 == ta or t2 == ta :
            tmp.append(1)
        else:
            tmp.append(0)
    dummy.append(tmp)

# DataFrame型へ
df_tag = pd.DataFrame(dummy, columns=tag_all)
```

# 2. １つのカラムに concat されている場合
1カラムに concatされている場合(情報が詰め込まれている場合)も単純に
`pd.get_dummies()`を出来ません。

|index|tag|
|:---:|:---:|
|1|jupyter|
|2|python,numpy|
|3|python,anaconda|
|4|java|

　　　　↓ (横持ち)

|index|python|jupyter|numpy|anaconda|java|
|:---:|:---:|:---:|:---:|:---:|:---:|
|1|0|1|0|0|0|
|2|1|0|1|0|0|
|3|1|0|0|1|0|
|4|0|0|0|0|1|

こちらも上と同じようなアプローチを取りました。

```Python
# 重複なし tag 集合をつくる
tmp = []
for row in df['tag']:
    if type(row) == str: # こうしないと nan の行でエラー
       tmp.extend(row.split(','))
tag_all = sorted(set(tmp))

# tag を横持ち化したリスト作成
dummy = []
for tag in df['tag']:
    tmp = []
    if type(tag) == str: # こうしないと nan の行でエラー
        tag_list = tag.split(',')
        for ta in tag_all:
            if ta in tag_list:
                tmp.append(1)
            else:
                tmp.append(0)
    else:
        tmp = [0 for i in tag_all] # nan の場合は全要素が 0 のリストを返す
    dummy.append(tmp)

# DataFrame型へ
df_tag = pd.DataFrame(dummy, columns=tag_all)
```

# 感想
本当にただの力技です。for でぶん回しただけです。
動かしてみるとわかりますが、結構処理時間もかかります。。。
高速化したいなぁ。

あと、せっかく pandas 使ってるんだから apply, map とか使って出来ないかなぁ。
Raspberrypi3の初期設定

# パッケージのアップデート

まずはRasbianのパッケージをアップデートします。

```
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get dist-upgrade
```

続いてファームウェアのアップデート

```
$ sudo apt-get install -y rpi-update
$ sudo rpi-update
```

ここまでしたところで再起動をします。


# 画面サイズの変更

1. 右上のスタートメニューから"設定＞Raspberry piの設定"を選択すると"Raspberry Pi の設定"のウィンドが開く。
1. "システム"タブにある"オーバースキャン"と"Pixel Doubling"を無効にする。
1. "/boot/config.txt"をスーパーユーザーで下記のように編集する。

```C
# コメントアウトを外し値を変更する
hdmi_group=2
hdmi_mode=87
# 追記する
hdmi_cvt=1920 1080 60 3 0 0 0
```


# CapsLockキーのキー割り当て変更

左CtrlをCapsLockキーに移動させます。
/etc/default/keyboardを開いて

```c
# 変更前
XKBOPTIONS=""
```
```C
# 変更後
XKBOPTIONS="ctrl:swapcaps"
```

と書き換える。
Unity + OpenCV FaceTrackerで点の位置をスケールさせる; How to scale face parts in Unity + OpenCV

* FaceTracker.csに書き足す

```csharp
        private void ScalePoints(int startIndex, int endIndex, float scale)
        {
            int pointNum = endIndex - startIndex + 1;
            double xSum = 0;
            double ySum = 0;
            for (int i = startIndex; i <= endIndex; i++)
            {
                xSum += points[0][i].x;
                ySum += points[0][i].y;
            }
            double xMean = xSum / pointNum;
            double yMean = ySum / pointNum;

            // scale from mean
            for (int i = startIndex; i <= endIndex; i++)
            {
                double relativeX = points[0][i].x - xMean;
                double relativeY = points[0][i].y - yMean;
                relativeX *= scale;
                relativeY *= scale;
                points[0][i].x = relativeX + xMean;
                points[0][i].y = relativeY + yMean;
            }
        }
```

* 平均をとってそこを中心にスケールさせる
* 片方の眉毛の領域を拡大したい時は、
  * ScalePoints(15, 20, 2.2f);
* 顔は1つを想定
* ハマりポイント
  * points[0][i].xと書く必要がある
  * points[i]で二次元ベクトルが取れると思ったが違った
* 想定通り動くことを確認した
ReactのRefsを正しく取り扱う

Reactで同一コンポーネント内でDOMの操作を行いたい場合、ref属性を使って参照をするという方法があります。しかしこれを扱う場合には注意が必要なので、備忘録として残しておきます。

# Refsを使うべきシチュエーション

そもそも、Refsはあまり多用すべきでないと公式でアナウンスされています。というのもReactでは、親コンポーネントから子プロセスへの一方向データフローを原則としていて、Refsを使ってコンポーネントに作用をすると、その原則が崩れてしまうためです。

Refsを使って良い例は

- テキストの選択、フォームへのフォーカスもしくはメディア（動画、音声）の再生の制御
- アニメーションを発火させる場合
- サードパーティのDOMコンポーネントを組み込む場合

と公式のドキュメントに記載されています。
JQueryのDOM操作的なことをしたい場合に例外的に使うイメージですかね。


# Refsの使い方

Refsを扱うには３つ方法があります。

- React.createRefメソッドを用いる（v16.3.0以上で利用可能）
- refコールバック属性を用いる
- ref文字列属性を用いる（非推奨 v17で削除）

３番目は非推奨なので省力します。


## React.createRef メソッドを用いる

Reactがv16.3.0以上の場合、この方法で対処するのがベターです。

```Example.jsx
import React, { Component } from 'react';

class Example extends Component {
 	constructor(props) {
  		super(props);
  	 	this.hugaRef = React.createRef();
	}
	render() {
		return (	
			<input 
				className="_hoge"
				type="text"
				ref={this.hugaRef}
			/>
		)
	}
	componentDidMount() {
		this.hugaRef.current.focus();
	}
};

export default Example;
```

refsは```this.hogeRef.current```で取得できます。

## refコールバック属性を用いる

現時点でバージョンが16.2.0以下で、当分バージョンアップの予定がないのであれば、コールバック関数でDOMをセットしています。

```Example.jsx
import React, { Component } from 'react';

class Example extends Component {
 	constructor(props) {
  		super(props);
  	 	this.hugaRef = null;
  	  	this.setHugaRef = element => {
  	   		this.hugaRef = element;
  	   }
  	}
	render() {
		return (	
			<input 
				className="_hoge"
				type="text"
				ref={this.setHugaRef}
			/>
		)
	}
	componentDidMount() {
		this.hugaRef.focus();
	}
};

export default Example;
```




# 出典


[Refs and the DOM - React](https://reactjs.org/docs/refs-and-the-dom.html)
Opalとは(2018年版)

OpalはRubyのコードをJavaScriptに変換するコンパイラです。Opalを使うと、Rubyのプログラムをブラウザ上で動かすことができます。

- [Opal: Ruby to JavaScript Compiler](http://opalrb.com/)

## Opalの用途

**ブラウザで動くアプリケーションをRubyで書ける**よ、というのが主な用途になります。JSでいいじゃん、という人には訴求しないですけど…:frowning2:、Rubyをブラウザでも使いたい、という人にはとても良くできているツールだと思います。筆者はJSも書けなくはないですがRubyが一番長く使っていて手に馴染むので、Opalの可能性には期待しています。というだけではなくて、DXOpalというゲームフレームワークと、OvtoというWebフレームワークを実際に作って使っています。

## Opalでゲームプログラミング

DXOpalは筆者が作ったゲームフレームワークです。Rubyist Magazineにチュートリアルを兼ねた紹介記事があります。

- [Rubyで始めるゲームプログラミング \- DXOpal編 \-](https://magazine.rubyist.net/articles/0057/0057-GameProgramingWithDXOpal.html)

実際に動いているところは以下で見られます。(作者の方々に感謝。)

- [ステージ１ボス実装その２ \| クレインハウス開発室](http://www.cranehouse.dojin.com/wordpress/?p=258)
- [mieki256's diary \- DXRubyをブラウザ上で動かせるというDXOpalを試用してみたり](http://blawat2015.no-ip.com/~mieki256/diary/201709221.html)
- [DXOpal；ブロック崩しdemo \- noanoa 日々の日記](http://blog.livedoor.jp/noanoa07/archives/2159950.html)

## OpalでWeb開発

ゲームでない普通のアプリケーション(SPA)向けのフレームワークもあります。筆者はこれで[TODOアプリ](https://github.com/yhara/vision)を作って実用しています。

- [Ovto\(オブト\)というRubyで書けるシンプルなクライアントサイドWebフレームワークを作りました \- Qiita](https://qiita.com/yhara/items/07eeb2c165e35964db76)

Ovtoについてはまた別の日に記事を書こうと思っています。

Web開発でいうと他にも[Menilite](https://github.com/youchan/menilite)というフレームワークがあります([記事](https://qiita.com/youchan@github/items/27d988a9a2d9a38256a7))。isomorphic programmingといって、一つのコードをサーバ側とクライアント側の両方で動かせるのが特徴です。(明日の記事で紹介があるかも？)

## ブラウザ外でのOpal

OpalはJavaScriptが動くところならどこでも使えるので、例えば

- [PhoneGap](https://phonegap.com/)と組み合わせてモバイルアプリを作る

とか、

- [Electron](https://electronjs.org/)と組み合わせてデスクトップアプリを作る

といった応用が考えられます。後者については[過去のアドベントカレンダー](https://qiita.com/advent-calendar/2016/opal)に記事があります。

## Opalの情報

英語での情報は以下があります。

- 公式サイト http://opalrb.com/
- ソースコード https://github.com/opal/opal
- Opalのライブラリ一覧 http://opalrb.com/libraries/
- チャットルーム https://gitter.im/opal/opal

日本語情報としては、@youchan@githubによる書籍があります。

- [『Pragmatic Opal - Rubyで作るブラウザアプリケーション開発ガイド』](https://nextpublishing.jp/book/9555.html)

また過去のアドベントカレンダーにも情報があります。

- [Opal Advent Calendar 2016 \- Qiita](https://qiita.com/advent-calendar/2016/opal)
Excel以外でも日付入力のショートカット(ホットキー)を使う

ファイルサーバーで日付でファイル・フォルダを管理するという悲しい現実の前に、
「日付入力を簡単にしたい」という逃避しかできなかったんですが、それをやってくれるソフトウェアが無さそうだった(AutoHotKeyを使えばできそうだったけど、そこまでしたくなかった)ので、ユーティリティを作りました。

## 使い方
1. まず GitHubからソースコードをクローンしてください。  
   https://github.com/udaken/yyyymmdd
2. ご自身で**ソースコードをビルドしてください**(要Visual Studio 2017)  
   一応プレビルドもおいていますが、アンチウイルスソフトウェアの対応が面倒なのでサポートしていません。
3. 作成された `yyyymmdd.exe` を起動すると、タスクトレイに常駐します。
4. ホットキーで、ローカル日付をアクティブウィンドウに入力します。   
   `Ctrl+;` で `2018/11/14`形式  
   `Ctrl+Alt+;` で`20181114`形式  
   `Ctrl+Shift+;` で`2018-11-14`形式  
   になります。

## やっていること
`RegisterHotKey` でホットキーを登録して、ホットキーイベントで`SendInput` で入力しているだけです。

## 既知の不具合
- IMEがONだと、正しく入力できないことがあります。
- Edge, Crome(およびElectronベースのソフトウェア)だと、`Ctrl+数値`のショートカットが反応してしまい、正しく入力できません。
JavaScriptでオセロ作ってみた。２

## 前回からその後

前回「[JavaScriptでオセロを作ってみた。](https://qiita.com/tanimoto-hikari/items/c5daefd9af9989b9b8dd)」という記事を書かせていただきましたが、ソースコードに納得できず少しずつ書き直して自分のベストプラクティスを探しています。

早速ですが、修正したのはここ！
すごくめんどくさいことをやってました。

```JavaScript:index.js
changeOthello = (index) => {
    //両隣とその隣のオセロの色（値）を取得
    let prevLeftOthello = $tableElements[index - 2].innerHTML;
    let prevOthello = $tableElements[index - 1].innerHTML;
    let nextRightOthello = $tableElements[index + 2].innerHTML;
    let nextOthello = $tableElements[index + 1].innerHTML;

    //黒
    //左隣の次のマスの色が置いたオセロと同じ色の場合隣のオセロの色を変える
    if (prevLeftOthello.match(othelloBlack) && prevOthello.match(othelloWhte)) {
      let targetIndex = index - 1;
      putOthello(targetIndex, index);
    }
  }
```
なんとスマートではないこと・・・。
石をおいたら丁寧に隣その次の石をチェックする仕様にしてましたが下記のように変更を加えました。

### 1 - まずどこにオセロを置いたのかをチェック 
```JavaScript:index.js
//index番号から配列のどの位置にオセロを置いたのかを判断するための配列
    let rowSpot = [
      [0, 1, 2, 3, 4, 5, 6, 7],
      [8, 9, 10, 11, 12, 13, 14, 15],
      [16, 17, 18, 19, 20, 21, 22, 23],
      [24, 25, 26, 27, 28, 29, 30, 31],
      [32, 33, 34, 35, 36, 37, 38, 39],
      [40, 41, 42, 43, 44, 45, 46, 47],
      [48, 49, 50, 51, 52, 53, 54, 55],
      [56, 57, 58, 59, 60, 61, 62, 63]
    ];

    let arrayNumber;
    let itemNumber;
    let valid = [];
    let changeIndexs = [];

    for(let i=0; i < 8; i++) {
      if (rowSpot[i].indexOf(index) !== -1) {
        arrayNumber = i;
        itemNumber = rowSpot[i].indexOf(index);
      }
    }
```
これを実行するだけで石を置いた列と行の位置を返してくれるようにします。

前回書いたコードでは隣のマス目が何かを確認、判定して、変更していました。
そこを置かれたところから縦横全てを確認し、同じ色のオセロが置かれていた場合にオセロの色を変更できるようにしました。
（もしかしたら不具合がのこってるかも。なので現在テスト中）

```JavaScript:index.js

    //オセロを置いたとことから上のマスをチェック
    //オセロを置いたところを含ませないように初期値を1に設定
    for (let i=1; i < arrayNumber; i++) {
      let checkNumber = index - (8 * i);
      if($tableElements[index - (8 * i)].innerHTML.match(othelloColor)) {
        //間のオセロの色を変える
        //同じ色までのオセロの数
        let changeNumber = -((checkNumber -index) / 8);
        for (let n=0; n < changeNumber - 1; n++) {
          changeIndexs[n] = checkNumber + (8 * (n + 1));

          $tableElements[changeIndexs[n]].innerHTML = othelloColor;
        }
      }
    }

```

これをアレンジして縦横、斜めの文を作成して一度にチェックをかけます。
もうちょっと進化させたいですが、一休みします。
Githubの便利な機能をまとめてみる

# はじめに
半年ほど前からプログラミングを勉強しはじめ、
幸運にも勤務先で簡単な開発に携われることになり
その際、複数人でGithub上でバージョン管理するため
教えてもらった便利な機能等を自分用にまとめていこうと思います。
あと初めてなのでまとめ方とかは下手くそなのと情報はこれから知っていくことがほとんどなのでそのあたりはご愛嬌。

# 対象
あくまで私自身が初心者なので、自分用のメモ帳および得た知識を固めるためのアウトプット的な部分が大きいのですが
同じようにこれからやっていくぞといった方のちょっとした手助けになればいいなと思いつつまとめていきます。

# Githubとは
### 開発者のためのプラットフォーム
　GitHubは、ユーザのみなさんからヒントを得て作成された開発プラットフォームです。オープンソースプロジェクトやビジネスユースまで、GitHub上にソースコードをホスティングすることで数百万人もの他の開発者と一緒にコードのレビューを行ったり、プロジェクトの管理をしながら、ソフトウェアの開発を行うことができます。([Github](https://github.co.jp/)より抜粋)


　つまるところ大勢の開発者が利用していて、Github上でそれぞれの携わっているプロジェクトのソースコードを保存・管理したり他のソースコードを参考にしたりしながら開発を進めていきましょうねってことだと理解しています。
　まあこの辺りは目的から逸れるので簡単にしておきます。

# ブランチ
### ブランチを切るときにprefixを付ける
　これは現場によるのかもしれませんが、何らかの作業時にブランチを切る際、ブランチ名に`add`とか`fix`とか`feature`とか、大まかな目的のprefixを記入して、その後に実際にする作業の内容をブランチ名として設定しておくとパッと見で判断できるので便利でした。
ざっくり`add/add_user_id_columns_to_users`みたいな感じ。

# プルリクエスト
### PR作成時に対応するissueと関連付ける
　issueに対してプルリクエストを作成する際、descriptionに対応するissueの番号を記入しておくと
そのissueの情報が勝手に紐付いてくれて便利でした。
`#1928`　<=　こんな感じに書いておくとマウスオーバーした際に情報が参照できる。

### PRがマージされたタイミングで自動的にissueをクローズする
　PR作成時のコミットメッセージに`fix #1928`のように`fix/fixed/fixes + issueの番号`を記入しておくと
そのPRがマージされたタイミングで対応するissueが自動的にクローズされるので手間が省ける。

### 見た目を改変するPRの際は手っ取り早く写真を見せた方が良さそう
　もちろんコードの差分を見てレビューしてもらうのですがそれだけではパッとわかりにくいこともあると思うので
変更前と変更後の写真をPRのdescriptionに貼っつけとくと良さそうでした。
markdown使えるのでテーブル作って

|変更前|変更後 |
|:-:|:-:|
|変更前の写真|変更後の写真|

こんな感じで並べとくとわかりやすいなって思いました。
必要/不必要は場合によると思うのでその辺りは時と場合による感じで。

# おわりに
　一人で勉強しているときはとりあえずコード書いていたのですが、実際に現場で作業するとなるとgithub等でのレビューフローにも慣れないとなと思ったのでまとめてみました。
まだそれほど知識も溜まっていないので少ない中でもある程度必須かなと思う部分を抜粋してます。
今後も出来るだけ追記して行きたいですね。
新しいMacを起動したらとりあえずやっておく設定一覧

新しく購入したMacを今まで使い慣れた環境にするために行なった設定の一覧です。

いざ新しいMacの設定を行おうと思うと、「あれ、この設定ってどこでやってるんだっけなー」みたいなことがあると思うのでまとめました。

### WiFiのパスワードの確認方法(旧Macで確認する)
- Finder -> アプリケーション -> ユーティリティ -> キーチェーンアクセス -> 分類 -> パスワードを選択。そして該当のWiFiパスワードの確認をする

### カーソル移動の速度を変更する
- システム環境設定 -> キーボード -> キーボード -> キーのリピートとリピート入力認識までの時間を調整。最速・最短でカーソル移動が最速になる

### ControlとCapsの入れ替え
- システム環境設定 -> キーボード -> 修飾キー

### Macで勝手にスペル変換させられるのをやめる
- システム環境設定 -> キーボード  -> 「ユーザー辞書タブ」を選択して「英字入力中にスペルを自動変換」のチェックを外す
- システム環境設定 -> キーボード  -> 「入力ソース」を選択して「ライブ変換」のチェックを外す

### Macのスポットライト検索のショートカットキー変更
- システム環境設定 -> Spotlight -> キーボードショートカット -> ショートカット -> Spotlight検索を表示をチェック

### カナと英語をショートカットキーでトグル変換する
- システム環境設定 -> ショートカット-> 入力ソース -> 前の入力ソース

### FinderのサイドバーにHomeとかを追加する
- Finder -> 環境設定 -> サイドバー で表示したい項目にチェックをする

### 電源の残りパーセントを表示させる
- 電源ボタンをクリック -> 割合を表示

### スピーカーのボリュームを表示させる
- システム環境設定 -> サウンドでメニューバーに音声を追加

### mac起動時に起動するアプリの設定
- システム環境設定 -> グループとユーザ -> ログイン項目

### Dockの幅の調整など
- システム環境設定 -> dock

### Fキーのデフォルトの挙動をファンクションキーにする
- システム環境設定 -> キーボード -> F1, F2などのキーを標準のファンクションキーとして使用

### Macをロックしたらパスワード認証されるようにする
- システム環境設定 -> セキュリティとプライバシー -> 一般 -> パスワード要求を「すぐに」に変更
- ショートカットは「control + shift + 電源ボタン」

### カーソルの大きさ調整
- システム環境設定 -> アクセスシビリティ -> ディスプレイ -> カーソルのサイズ

### 画面がすぐに暗くならないようにする
- システム環境設定 -> 省エネルギー
【Java】タイマー処理実装方法

# はじめに
今回はJavaのタイマー処理の実装方法を解説します。
今回のサンプルでは、ある特定のタスクを作成し、そのタスクを数秒後に実行するという処理を実装していきます。

以降、以下のバージョン、環境での解説となります。

IDE：eclipse
Javaバージョン：8

それでは、早速解説していきます。

# 1. フォルダ構成
今回作成するサンプルソースのフォルダ構成は以下の通りです。

<img width="291" alt="スクリーンショット 2018-11-14 0.12.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/298750/a1e7c9c9-8910-c480-a26c-7daa43892566.png">

# 2. タイマー処理の実装
## 2-1. タイマー処理の構文
まず、タイマー処理を実装する際、TimerTaskクラスのオブジェクトを作成します。

そして、TimerTaskクラスの中にrun()メソッドを入れ、タイマーで実行したい処理を実装します。

最後にタイマークラスのオブジェクトを作成し、タイマークラスのscheduleメソッドで実行したいタスクとタイマー時間を指定します。

```
TimerTask task = new TimerTask() {
  public void run() {
    // タイマーで実行したい処理
  }
};

Timer timer = new Timer();
timer.schedule(task, タイマー時間(ms));
```

## 2-2. タイマー処理サンプル実装
上記構文を利用して、3秒後に「タスクが実行されました。」という文言がコンソールに出力される処理を実装していきましょう。

```SampleTimer.java
package main;

import java.util.Timer;
import java.util.TimerTask;

public class SampleTimer {

    public static void main(String[] args) {
        System.out.println("タスクを3秒後に実行されるようセットしました。");
        TimerTask task = new TimerTask() {
            public void run() {
                System.out.println("タスクが実行されました。");
            }
        };

        Timer timer = new Timer();
        timer.schedule(task, 3000);

    }

}
```

上記記述完了しましたら、SampleTimer.javaを右クリック>Javaアプリケーションの実行で実行してみましょう。
3秒後に「タスクが実行されました。」という文言が出力されればOKです。

```Bash:コンソール
タスクを3秒後に実行されるようセットしました。
タスクが実行されました。
```

# さいごに
2020年から個人ブログはじめました！

フリーランスエンジニアになって得た知識と経験をもとに、フリーランスエンジニアに関する情報をはじめ、IT技術情報や業界情報、エンジニアライフハック等のコンテンツを配信していく予定です。

まだまだ記事数は少ないのですが、週単位で更新してますので、もしご興味ございましたら、みていただけると嬉しいです。

https://yacchi-engineer.com/
プロキシ環境下でpip等が使えないときの解決方法

# 課題
学校や職場のWifiでプロキシを使用している場合、pip等のコマンドが使えないことがある。

# 環境
Windows 10

# 解決方法
システム環境変数に

変数名: `HTTP_Proxy`
変数値: `http://proxyserver:8080`

変数名: `HTTPS_Proxy`
変数値: `https://proxyserver:8080`

> 変数値には 任意のアドレス:任意のポート番号 を入力する

を追加。

以上です。お疲れ様でした。
無料ではじめるRPA - Uipath Community Edition インストール編 -

# はじめに
最近はpythonだったり、Uipathだったり技術的な活動が増えてきたので、勉強用の環境を新調しました。
ついでにUipathCEも入れ直したので、備忘かねて構築手順を残しておきます。
（何番煎じかわからないですがｗ）
# 環境
今回構築した環境は次の通り

- EC2 ( Windows_Server-2016-Japanese-Full-Base-2018.09.15 )

# インストール手順
1. Uipath公式HPにアクセスする（ https://www.uipath.com/ja/ ）
2. リソース＞Uipath Community エディションにアクセスする
![image.png](https://qiita-image-store.s3.amazonaws.com/0/79318/0dfc0c0b-15e6-e8fd-ff5c-ed9ebcf89f2f.png)
3. 下部の「Community Editionをダウンロードする」ボタンを押下する
![image.png](https://qiita-image-store.s3.amazonaws.com/0/79318/7fa6ca8b-897d-3521-64c8-718b22807088.png)
4. 「Community エディションを使用する」ボタンを押下する
![image.png](https://qiita-image-store.s3.amazonaws.com/0/79318/5f30cf5a-c003-4f22-9056-6a2d520b7cba.png)
5. 【性】【名】【Eメール】を入力し【プライバシーポリシーを～】にチェックする。
※メールアドレスにインストーラーのURLが送られてくるため、受信できるメールアドレスを使用してください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/79318/b3335062-1201-3507-5962-68355f377c72.png)
6. 折り返し送られてくるメールに記載のURLまたは、下記ページの「こちらから」のリンクから「UipathStudioSetup.exe」を入手し、実行する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/79318/d15972db-483b-e5d5-369f-ac00a2f33b9b.png)
7. 「Community Edition のアクティベート」を押下する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/79318/4f55e500-9777-99ff-72f5-1360885b7873.png)
8. 【メールアドレス】に先ほど登録したメールドレスを入力して「アクティベーション」ボタンを押下する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/79318/e1db8fac-fc9e-ab64-4649-c3dc14d9287d.png)
9. アクティベート完了！これでUipathが使えます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/79318/8619ea9e-9b66-a3d5-dc4b-9d4748719b37.png)

# 最後に
個性のある記事を書くって難しいですね。

今日はおしまいです。
FargateをDatadogでモニタリングする

投稿内容は私個人の意見であり、所属企業・部門見解を代表するものではありません。

##目的
FargateをDatadogでモニタリングするまでのメモ

##事前準備

###Datadog連携用にIAMポリシーとIAMロールを作成する
https://docs.datadoghq.com/ja/integrations/aws/

###DatadogのAPIキー確認
Datadogコンソールの「Integration」「APIs」
![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/5a25c59e-90f5-a8d8-0777-fd0022a9867a.png)

API keyを確認する
![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/b98c2a49-8415-3225-9681-59df689c23cd.png)

##タスク定義作成
以下を参考にモニタリング対象のコンテナとdatadog-agentコンテナを定義する
https://www.datadoghq.com/blog/monitor-aws-fargate/

###Fargateを選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/e2add3b9-0462-de0e-538c-696381a9b755.png)

###Redisコンテナ設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/4f05f85e-853d-4454-20fb-6d236fb4892d.png)

```
"dockerLabels": {
    "com.datadoghq.ad.instances": "[{\"host\": \"%%host%%\", \"port\": 6379}]",
    "com.datadoghq.ad.check_names": "[\"redisdb\"]",
    "com.datadoghq.ad.init_configs": "[{}]"
}
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/a5217c41-3374-8871-7101-9b7f9ddfd1dc.png)

###Datadog-agent設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/39c61b64-b304-a550-d0f2-2c7db8320833.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/beca1d45-4c08-61a5-fe51-7870af96070b.png)

```
"environment": [
    {
        "name": "<API_KEY",
        "value": "$YOUR_API_KEY"
    },
    {
        "name": "ECS_FARGATE",
        "value": "true"
    }
]
```

##サービス作成

###サービスを作成して先程作成したタスク定義を登録する

##Datadogのコンソールで確認する
「Infrastructure」「Containers」をクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/7dbb2cf8-a4b6-79ac-256f-86c3a915b5e2.png)

今回はタスク数を2に設定したため2台のコンテンが確認できる
![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/d9b51bec-5361-2118-9a88-b1ba65bfdc51.png)
systemd-nspawn メモ

# machinectl shell で終了ステータスを取得したい

`machinectl shell`でコンテナ側で実行したコマンドの終了ステータスがプロパゲートしてこないですが、[systemd-run --wait を使え](https://github.com/systemd/systemd/issues/4215#issuecomment-269059851) とのことのようです。
`-M`でコマンドを実行するmachineを指定します。

```shell-session
$ sudo systemd-run -M test_01 --wait /bin/false 2>/dev/null
$ echo $?
1
$ sudo systemd-run -M test_01 --wait /bin/true 2>/dev/null
$ echo $?
0
```
PHP：可変変数を使って動的に変数を操作してみる

#変数を動的に扱いたいなぁってとき
CSVやら配列やらから取得したデータを変数に代入したいなぁと思うケースって稀にないでしょうか。

```php
//csvから取得したデータ
$csvData = "太郎,21,男性";
//配列化
$arrData = explode(",", $csvData);

//各変数に代入する
$name = $arrData[0];
$age  = $arrData[1];
$sex  = $arrData[2];
```

~~書いておいて思ったけど格納先も最初から配列で作成しておけばいいんでは…と思ったのは内緒だ。~~
上記の例のように変数が3種類だったらなんとかなりそうですが、多数の変数に対して同様に取得データの代入が必要になるケースもあるかと思います。

もっと楽にコードを書く方法がないかなと探したところ、可変変数を使って動的に代入することができることを知りましたので備忘録として投稿します。

#可変変数の記述例
変数名を文字列から動的にセットして扱うことができます。

```php
$test = "aaa";  //普通の変数①
$var  = "test"; //①の変数名

echo $$var."<br/>";     //"aaa"が出力されます。

echo ${"test"}."<br/>"  //これも"aaa"が出力されます。

echo ${$var}."<br/>"  //これでも"aaa"が出力されます。
```

上記のように`$$変数名を値として持つ変数`だったり`${変数名の文字列}`として記述することで、対象の変数のように扱うことができます。

```php
$test = "aaa";  //普通の変数①
$var  = "test"; //①の変数名

$$var = "bbb";  //代入してみると

echo $$var."<br/>";     //"bbb"が出力されます。
```
もちろん代入もOKです。
これで最初の例をいい感じに書き直してみると以下のようになります。

```php
//csvから取得したデータ
$csvData = "太郎,21,男性";
//配列化
$arrData = explode(",", $csvData);
//代入先の変数一覧
$vars = array("name", "age", "sex");

foreach($vars as $key => $var){
    $$var = $arrData[$key]
}
echo $name."<br/>"; //太郎
echo $age."<br/>";  //21
echo $sex."<br/>";  //男性
```
変数が3個なので有り難みがないどころか行数増えてますが…対象の変数が増えていけばスッキリするはず…！

#クラスを使った応用
もちろん、インスタンスのプロパティに対しても可変変数は有効です。

```php
class Animal{
    public $name = "Taro";
    
    function set($var, $value){
        $this->{$var} = $value; //変数にセット
    }
}
$animal = new Animal();
echo $animal->{"name"}."<br/>"; //Taro

$animal->set("name", "Jiro");
echo $animal->{"name"}."<br/>"; //Jiro
```
上記の場合は`インスタンスの変数名->{変数名}`といった記述ですね。

また、下記のようにサブクラスのインスタンスから親クラスのメソッドを実行した時、
親クラスのメソッドからサブクラスのプロパティに対しても同様に扱うことができます。

```php
//親クラス
class Animal{
    public $name = "Taro";
    function set($var, $value){
        $this->{$var} = $value; //変数にセット
    }
}

//サブクラス
class Dog extends Animal{
    public $type = "マルチーズ";
}

$dog = new Dog(); //サブクラスのインスタンス
echo $dog->{"type"}."<br/>"; //マルチーズ

$dog->set("type", "芝犬");
echo $dog->{"type"}."<br/>"; //芝犬
```

ベースとなる親クラスに共通的に持たせるメソッドから、サブクラス固有のプロパティにアクセスできるのは何か使い道がありそうですなぁ。

#最後に
もうちょっと応用すれば色々動的な処理ができそうです。
ただ、その反面、自由度高すぎて不具合の原因となりそうな怖い部分もあります。
未宣言の変数だろうと作成されてしまうので、`isset()`で変数宣言の有無を確認するなどのチェック処理も必要そうです。
Node.jsにおけるWebアプリで、音が鳴らないので対処(Nodeではそのままでは音声再生できない)

##環境
mac book
chrome(バージョン: 71.0.3578.98（Official Build） （64 ビット）)
ConoHa[VPS]

## 原因を探す
同じディレクトリに音声ファイルを置いて以下のようなパスを指定した場合、再生されなかった。

```javascript:I_am_hentai.js
        var aud; //Audioオブジェクトを入れる変数を最初に用意
        function PlaySound(){
                aud = new Audio();//Audioオブジェクトを作成する
                aud.src="timer.mp3";//同じディレクトリに音声ファイルはあるが、誤ったパス
                aud.play();//音声ファイルを再生する
        }
```


原因は、nodeサーバーから音声ファイルが送られていないからなんです。
ローカルに置いたHTMLファイルならAudioオブジェクトを生成したやり方で再生できるが、、、

## 解決方法
nodeでの音声再生をする場合は、それ専用のプログラムを書く必要がある。
play-soundモジュール使ったりその他いろんな方法で再生できるけど、今回はさっさと簡単に再生したかったので直接パスを指定してしまうおうと考えた。
●まず、音声ファイルをnode.js関係のフォルダからドキュメントルートに移動させる。
●以下のようにパスを直接指定したらすぐに再生された。

```javascript:I_am_hentai.js
        var aud; //Audioオブジェクトを入れる変数を最初に用意
        function PlaySound(){
                aud = new Audio();//Audioオブジェクトを作成する
                aud.src="http://IP/~てきとうなフォルダ/timer.mp3";
                aud.play();//音声ファイルを再生する
        }
```

## 感想
Nodeまだわからないことが多いけど楽しい
[cocoa][swift]2018年の勉強会の活動を振り返る

<p>今年一年も、ほぼ毎月、勉強会を開催しました。今年のAdvent Calendarでは、各勉強会を振り返っていきたいと考えています。</p>

<p>以下が、その一覧です！</p>

<ul>
<li>BUKURO.swift 2017-12
	<ul>
	<li>第106回 Cocoa勉強会 関東</li>
	<li>2017年12月6日</li>
	<li>池袋コワーキングスペース OpenOffice FOREST</li>
	<li>https://cocoa-kanto.connpass.com/event/71296/</li>
	</ul>
</li>
<li>関東swift勉強会2018-01
	<ul>
	<li>第107回 Cocoa勉強会 関東</li>
	<li>2018年1月19日</li>
	<li>池袋コワーキングスペース OpenOffice FOREST</li>
	<li>https://cocoa-kanto.connpass.com/event/75006/</li>
	</ul>
</li>
<li>BUKURO.swift 2018-02
	<ul>
	<li>第108回 Cocoa勉強会 関東</li>
	<li>2018年2月16日</li>
	<li>池袋コワーキングスペース OpenOffice FOREST</li>
	<li>https://cocoa-kanto.connpass.com/event/75430/</li>
	</ul>
</li>
<li>PubHack.swift 2018-03
	<ul>
	<li>2018年3月9日</li>
	<li>THE DUBLINERS' IRISH PUB 新宿店</li>
	<li>https://cocoa-kanto.connpass.com/event/80501/</li>
	</ul>
</li>
<li>関東swift勉強会2018-03
	<ul>
	<li>第109回 Cocoa勉強会 関東</li>
	<li>2018年3月16日</li>
	<li>池袋コワーキングスペース OpenOffice FOREST</li>
	<li>https://cocoa-kanto.connpass.com/event/80036/</li>
	</ul>
</li>
<li>BUKURO.swift 2018-04
	<ul>
	<li>第110回 Cocoa勉強会 関東</li>
	<li>2018年4月4日</li>
	<li>池袋コワーキングスペース OpenOffice FOREST</li>
	<li>https://cocoa-kanto.connpass.com/event/80016/</li>
	<li>https://mosa.connpass.com/event/80018/</li>
	</ul>
</li>
<li>PubHack.swift 2018-04
	<ul>
	<li>2018年4月12日</li>
	<li>THE DUBLINERS' IRISH PUB 新宿店</li>
	<li>https://cocoa-kanto.connpass.com/event/84473/</li>
	<li>https://mosa.connpass.com/event/82985/</li>
	</ul>
</li>
<li>関東swift勉強会2018-05
	<ul>
	<li>第111回 Cocoa勉強会 関東</li>
	<li>2018年5月11日</li>
	<li>池袋コワーキングスペース OpenOffice FOREST</li>
	<li>https://cocoa-kanto.connpass.com/event/85331/</li>
	</ul>
</li>
<li>BUKURO.swift 合同勉強会 WWDC18特集！ : The Bash in Tokyo
	<ul>
	<li>第112回 Cocoa勉強会 関東</li>
	<li>2018年6月15日</li>
	<li>hoops link Tokyo</li>
	<li>https://peatix.com/event/391019</li>
	<li>https://cocoa-kanto.connpass.com/event/85554/</li>
	<li>https://mosa.connpass.com/event/85556/</li>
	</ul>
</li>
<li>BUKURO.swift 2018-07
	<ul>
	<li>第113回 Cocoa勉強会 関東</li>
	<li>2018年7月25日</li>
	<li>池袋コワーキングスペース OpenOffice FOREST</li>
	<li>https://cocoa-kanto.connpass.com/event/91202/</li>
	</ul>
</li>
<li>BUKURO.swift 2018-09
	<ul>
	<li>第114回 Cocoa勉強会 関東</li>
	<li>2018年9月12日</li>
	<li>池袋コワーキングスペース OpenOffice FOREST</li>
	<li>https://cocoa-kanto.connpass.com/event/97193/</li>
	</ul>
</li>
<li>Cocoa.swift 2018-10 （BUKURO.swift 関東）
	<ul>
	<li>第115回 Cocoa勉強会 関東</li>
	<li>2018年10月17日</li>
	<li>池袋コワーキングスペース OpenOffice FOREST</li>
	<li>https://cocoa-kanto.connpass.com/event/101034/</li>
	</ul>
</li>
</ul>

【関連情報】
<a href="https://qiita.com/advent-calendar/2018/cocoa">Cocoa Advent Calendar 2018</a><br />
<a href="https://cocoa-kanto.connpass.com/">Cocoa.swift</a><br />
<a href="https://www.facebook.com/groups/cocoa.kanto/">Cocoa勉強会 関東</a><br />
<a href="http://www.bitz.co.jp/weblog/">Cocoa練習帳</a><br />
<a href="https://qiita.com/m_yukio">Qiita</a><br />
Node.jsにおけるWebアプリで、音が鳴らないので対処(Chromeでの制限が原因)

##環境
mac book
chrome(バージョン: 71.0.3578.98（Official Build） （64 ビット）)

## 原因を探す
エラー文は「Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first.」

エラー文ググってみたらChrome側で問題があるよ的な記事がいくつか出てきた。

クロームは音声の自動再生に対して、制限がされているそうだ。
試しにSafariで開いてみたら問題なく再生はされるが、どうしてもChromeが使いたい(なんとなく)

※これはあくまでローカルでの解決であって一般公開するのでれば他のユーザーはChromeの設定は変わらない状態なので解決するのは自分の環境のみです。
全てのユーザーが音が鳴る状態にしたければ音声再生系のライブラリ使えばいいです。


## 解決方法

chrome://flags/#autoplay-policy
上記URLにアクセス。
「Autoplay policy」という部分の選択ボックスがあるので、「No user gesture is required」に変更。
「変更内容は次に Google Chrome を再起動したときに有効になります。」って表示されるので、その右のボタンの「RELAUNCH NOW」を押してブラウザを再起動します。

音が鳴るようになりました

## 感想
Nodeまだわからないことが多いけど楽しい
robotframework + seleniumlibraryのお役立ち実例集

# robotframeworkとは
テスト自動化ができるフレームワーク。
簡単にいえば、「○○をクリックする」「画面が表示されるまで2秒まってからタブ遷移する」みたいな形で命令を書くと、ブラウザが立ち上がって命令通りに操作を実行し、異常がないかをテストしてくれるもの。
RailsのRspec+capybaraと感覚は似ている。

# 使用用途
自分はリグレッションテストの一環で実施している。コマンドを叩くだけでテストアカウント作成〜表示・削除までを実行してくれるので、１度書いてさえしまえばかなりテストが楽になる。
（複雑なテストパターンであればあるほど効果が実感できると思う。）

# なぜこれをまとめるか。
比較的新しめのフレームワークということもあり、日本語での実例集の数が少ないので、詰まった点やこういう時どう切り抜けるか？というかなり実践的なポイントをまとめてみた。
(※robotframeworkのそもそもの基本的な機能は後日まとめてみたい。)

# 実施環境
windows10
robotframework3.0
seleniumlibrary(2の後のバージョン)
python 3.0
主な使用ライブラリ:builtIn,string,seleniumlibrary

## 新しいタブを開き、開いたタブ先でテストを続行したい。
target=”_blank”とかのリンクを押すと別タブが開くが、robotframeworkの処理は開いた先のタブではなく、元のタブでそのまま処理を継続させようとする。（そしてテストがエラーになる。）
それを防ぐために、以下を実行する。

```robot:testcase.robot
// 開いているタブ名を取得
Get Window Names

// 上記で取得した遷移先のタブ名(=locator)を指定
Select Window  name=locator
```

これで開いたタブに移動し、処理は開いたタブ上で始まる。
なお、たまにnameが一緒なタブ（undefinedとか）もあるので、そういう時は 

```robot:testcase.robot
// 開いているタブ名を取得
Get Window Titles

// 上記で取得した遷移先のタブ名(=locator)を指定
Select Window  title=locator
```

でいけることもある。なお、もちろんnameやtitileを取得したら``Get Window``は不要なので消してok。

# locatorをidや一意のclassで指定してクリックさせたいのに、エレメントがnot foundと言われる
これもよく起きる。対策としてClickの前に

```testcase.robot
Wait Until Element Is Enabled  エレメント名
Click Element  id=エレメント名
```

とする。ポイントはWait Untilで有効化するまで待つこと。
それか、xpathで指定するとうまくいくケースもある。

```testcase.robot
Wait Until Element Is Enabled  xpath: エレメントのxpath
Click Element  xpath: エレメントのxpath
```

実感としては、読み込みに時間がかかるページ内のエレメントを指定した時や、ダイアログが表示されOKボタンを押したい時みたいな場合によくこの種のエラーに遭遇した。

# if文で条件がtrueの時に処理を実行する
ここが1番詰まった。何せ日本語でif文の書き方的な情報が圧倒的にない。
ここでは実例として、「ページ内にqiitaという文言があれば``<div id="test">``をクリックしてページをリロード、なければ普通にページをリロード」という条件文を書く。

```testcase.robot
// Run Keyword And Return Status: 後続のキーワードを実行し、結果を返す
// Page Should Contain Text： ページ内に指定のテキストが含まれているか

${result} =  Run Keyword And Return Status  Page Should Contain Text  qiita

Run Keyword If  '${result}' == 'True'  Run Keywords  Click Element  test  AND  Reload Page  ELSE  Reload Page

```

ポイントは4つあって、１つは``Run Keyword And Return Status``で成否をとりたいキーワードを指定してあげ、それを${result}という変数に入れること。
2つ目は${result}の中身と``True``という文字列を``Run Keyword If``で比較してあげること。
3つ目は``'${result} == 'True' ``とシングルクォートで変数も文字列も囲う必要があること。
最後に、ELSEは必ず大文字で書くこと。

これを実現するのにとても時間がかかった・・。なお、``Run Keywords  AND``は、ANDでつなぐことでいくらでも後ろにキーワードを追加できる。

もしこういう場合にもっといい書き方があればコメントください。


# タブを閉じて、そのまま処理を実行させようとするとwindowがすでにクローズされていますというエラーが出る

例えば何かの処理を終えてタブを閉じ、すでに開いていたタブで継続の処理を走らせたい時に、そのままclose後に処理を続けようとするとエラーが起きる。そういう場合は

```robot:testcase.robot
// タブがクローズしてしまう処理と仮定
Click Element  quit

// 処理を続行したいタブ名(=locator)を指定
Select Window  name=locator
```

と一度タブ名を指定すればOK。


# 最後に
robotframeworkは使いこなせれば便利だけど、いかんせん日本語の情報量が少ないので、こういう時どうすればいいんだろう？というのがわかりづらいのが現状だと思う。
これからもrobotframeworkは触っていく予定なので、随時アップデートしていきたい。
【UiPath】Invoke WorkFlowFileと変数と引数

Invoke WorkFlowFileを使うにあたって、変数と引数の関係を一度整理しようと思い、記事にまとめました。

##サブフローから値を受け取る方法
今回は、サブフローから値を受け取って、メインフローでその値を利用する方法を説明します。

###フローチャートイメージ
メインフローからサブフロー（処理対象年月指定～）をInvoke WorkFlowFileアクティビティを使い、呼び出します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/186221/5f860a6a-b02e-bf40-5b7d-4513ff40983a.png)

サブフローのフロー図と引数一覧です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/186221/7375fa5f-aadd-43fb-38ce-0e7779df49bb.png)

###ここがポイント
ここで重要なのは、<font color="Red">**サブフローの引数名とメインフローで設定する引数名を揃えること**</font>です。

今回の場合、サブフローで**out_yyyy, out_mm**という引数名を使用しているため、それをメインフローで受け取るためには同名の引数名で引数を定義する必要があります。

また、「サブフローから受け取った値を格納している」ということを明示するために、引数名をわざと**out_yyyy, out_mm**としています。
そのため、この引数をそのままメインフローで使うのはあまりキレイではないので、メインフローで定義された変数に一度代入してから使うと良いでしょう。
今回は**out_yyyy ⇒ YEAR, out_mm ⇒ MONTH**に引数値を詰めなおしています。

##（おまけ）デバッグ時の変数と引数について
サブフローにおいて、変数も引数もアクティビティで普通に使うことができます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/186221/563d6d89-5740-0441-add8-7df61ecf78a2.png)

ただ、デバッグ時に
**変数はローカルパネルで値を確認できるが、引数はローカルパネルで値を確認できない**
という違いがあります。

なので、引数をそのまま使って、サブフロー内の諸々のアクティビティで処理をしていると、
デバッグで値を確認したい場合に、メッセージログのアクティビティに引数を出力するような作業が必要になり、ちょっと面倒です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/186221/6a6de28b-cec5-cb1c-3671-8df7c78cc421.png)

したがって、サブフローでは引数ではなくローカル変数を使いまわし、
最終的にメインフローに返したい値を引数に代入して、メインフローに返す
といった作りにしたほうが実装はしやすいでしょう。
【homeディレクトリが共用の人へ】.vimrcの設定

homeディレクトリが共有なっているなど、トリッキーな環境で開発する人用。
※同じユーザー名でログインするケースは非対応です。
## 手順
1. 自分専用の作業ディレクトリを作成
2. .bash_profileをそこに作成→書き込み
3. .vimrcをそこに作成→書き込み
4. .vimディレクトリを作成

## 事前準備

自分の作業ディレとクリに.bash_profleを作成する。
Tera Termなど使っている人は、Tera Termマクロ使ってログイン時にsourceすると良い。

```bash
$ touch 作業ディレクトリ/.bash_profile
```
## .bash_profileの中身
vim コマンドを打つ際に.vimrcを読み込むようにする。
.vimrcは自分の作業用ディレクトリなどに置くとよい。

```bash:.bash_profile
alias vim="vim -S 作業ディレクトリ/.vimrc"
```
```bash
$ source 作業ディレクトリ/.bash_profile
```

## .vimrcの中身
vimのプラグインを使いたいときの設定。
3/23 追記: ↓これじゃできない気がするので訂正
~~set runtimepath+=~/プラグインのディレクトリまでのパス/.vim~~


```vim:.vimrc
source ~/プラグインのディレクトリまでのパス/plugin/○○1.vim
source ~/プラグインのディレクトリまでのパス/plugin/○○2.vim
source ~/プラグインのディレクトリまでのパス/autoload/○○3.vim
```
bitcoin-cliでウォレットのインポート時、所持コインは上書きでなく加算だった

# はじめに
Bitcoindのバックアップととるとき、バックアップ先にもともとコインがあった場合、それは上書きされるか加算されるのか気になったので調べてみました。

# バックアップ方法
bitcoin-cliにて以下のコマンドを実行

- バックアップ

```
bitcoin-cli dumpwallet a.dump
```

- リストア

```
bitcoin-cli importwallet a.dump
```

# 試してみた
以下のようなそれぞれコインを所持している2つのウォレットを用意しました。
A・・・0.55 BTC
B・・・0.10 BTC

Aからdumpwalletでデータを出力し、Bにimportwalletで入力したところ以下のようになりました。

A・・・0.55 BTC
B・・・0.65 BTC

BはA+Bの合計値になりましたね。
ここでBから0.6BTCコインを送金してみると以下のようになりました。

A・・・0 BTC
B・・・0.05 BTC

Bから0.6BTCひかれてるのは当然ですが、Aからもひかれていました。
もとの数字から考えると、送金することでAから0.55BTCひかれて、Bから0.05BTCひかれたようですね。
※送金手数料は割愛しています。

# まとめ
まとめというほどもないですが、タイトルの通りインポート時はコインは加算してくれるようです。
macOS Mojaveでのbrew updateエラーを解消する

#Mojaveでbrew updateするとエラー
```
$ brew update
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
```

ググって見たらとりあえずbrew doctorすると良いらしい

```
$ brew doctor
Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry or file an issue; just ignore this. Thanks!

Warning: The following directories do not exist:
/usr/local/sbin

You should create these directories and change their ownership to your account.
  sudo mkdir -p /usr/local/sbin
  sudo chown -R $(whoami) /usr/local/sbin

Warning: Your Xcode is configured with an invalid path.
You should change it to the correct path:
  sudo xcode-select -switch /Applications/Xcode.app

Warning: Broken symlinks were found. Remove them with `brew prune`:
  /usr/local/bin/docker-credential-osxkeychain.backup
  /usr/local/bin/hyperkit.backup
  /usr/local/bin/notary.backup
  /usr/local/bin/scan
  /usr/local/bin/vpnkit.backup
  /usr/local/share/man/man1/scan.1
```

なんか色々出てきた

元々のエラーに関連するWarningは真ん中のやつっぽい

```
Warning: Your Xcode is configured with an invalid path.
You should change it to the correct path:
  sudo xcode-select -switch /Applications/Xcode.app
```

~~[ここ](https://github.com/Homebrew/brew/issues/4997)とか見ても単にinstallしてしまえば良さそう。LaunchPadからXcodeを実行すると確認ダイアログが出てinstallで終了~~
~~再びbrew updateするとエラーが解消済みだった~~

(2018/11/20 更新)再度brew updateすると同じエラーが再発したのでWarningのコマンドを実行して解消


```
$ brew update
Already up-to-date.
```

他のWarningは何だろう。docker関連かな。。。。
OGP画像を設定してみよう！

お疲れ様です。

SNSなどをシェアしたりすると、サムネイルとして表示される画像のことをOGP画像と言います。

少し前まで、勝手に画像が付いてくるものだと思っていました.....

エンジニアになって、OGPの設定をすることがあったので、
忘れないように備忘録としてQiitaを書いておきたいと思います。
最後に便利なツールもまとめておきますので、よろしければご活用ください。

また、この記事を読んでアドバイス等ありましたら
是非コメントをよろしくお願いいたします。

#そもそもOGP画像とは？

ちなみにOGPとは、”Open Graph Protocol”の略です。
プロコトルと付いているのでお約束事ってことですね！！
「OGP画像」とか「ogpイメージ」と呼ばれることが多いです。

WEBページをシェアしたときに表示される画像は、Webサイトであらかじめ設定する必要があります。
OGPという仕組みによってWebページとSNSが連携しているということなんですね。


#OGP画像の重要性

×デメリット
・FaceBook側が自動的に説明文や画像を表示してしまう。

◯メリット
・どのようなページなのかを伝えることができ、ユーザーの訴求率が高まる
・より多くの人にWebページを見てもらえる。

サムネイル画像の表示される方がユーザーの目に留まりやすくなり、
Webサイトに飛んでもらえる確率がUPするので、とても大切ですね！


# OGP設定方法
基本的にはmetaタグをHTMLのheader要素に記述することで設定ができます。
WEBサイト・FaceBook・Twitterの３つを設定する必要があります。

```
/* 共通 */
<meta property="og:url" content="サイトのURL" /> 
<meta property="og:title" content="サイトのタイトル" /> 
<meta property="og:image" content="画像のURL" /> 
<meta property="og:description" content="サイトのディスクリプション" /> 

/* twitter　　*/
<meta name="twitter:card" content="カード種類" /> 
<meta name="twitter:site" content="@ユーザー名" /> 

/* FaceBook */
<meta property="fb:app_id" content="AppID" />
```

## POINT

### ■ カードの種類
summary　(小)　/  summary_large_image（大）　のどちらかを設定します。
サムネイルの大きさを選ぶことができます。

### ■ ＠ユーザー名
＠から始まるアカウント名を入れます。

### ■ AppID
Facebook上でOGP画像を表示させる場合は、必ずfb:app_idを記載します。
idの発行に付いては下記の記事をご覧下さい。
https://design-plus1.com/tcd-w/2018/01/facebook_app_id.html

## 使用する画像はどんなものが良いか？
①真ん中に被写体がきている画像
②文字を入れる場合は大きめに

デバイスによっては、横長の画像が正方形で表示される場合があります。
正方形の場合は左右が切り落とされる感じになるので、中心に被写体があるとGOODです。

### 画像
 1200 × 630 (1：1.91)が推奨されています。
比率を守って入れば大丈夫ですが、スマホの表示の際に画質が悪くなる可能性があるので上記のサイズをオススメします。
画像はできる限り大きいほうが良いですね。なお、拡張子は.pngが推奨されています。
.jpgも問題なければ良いかと個人的に思っています。

#### シュミレーター
作成した画像を確認することができます。
http://ogimage.tsmallfield.com/

# 注意点
OGP画像を更新した際に、注意すべき点があります。
それは、キャッシュです。

WEBサイトの情報をあらかじめ取得して保存をしています。
あらかじめ保存（キャッシュ）することで、多くのユーザーにシェアされたときにその記事を繰り返し取得する必要がなくなります。
しかし、あらかじめ取得し保存したことで変更がされない場合があります。
そんな時は、OGP情報を更新しましょう。
下記のページにキャッシュをクリアしたいサイトのURLを入れるとクリアすることができます。

## Twitter
https://cards-dev.twitter.com/validator
## FaceBook
https://developers.facebook.com/tools/debug/og/object/


### 雑談
instagramやLINEは、手動でクリアすることができず三日ほどかかりました....とほほ



# まとめ
OGP設定を行うことで、人の目にふれる機会が多くなります。
どんな画像や文章ならクリックしてもらえるのだろうか？興味を持ってもらえるのだろうか？
と考えながら正しく作成することが大切だと感じました。
docker-composeのlinksがいつのまにやら必要なくなってた


# はじめに
docker-composeでコンテナ間をつなげる時の方法として、検索するとよくlinksを使うソースがかかれていることが多い。
こんな感じに

```
version: '3'
services:
  app:
    image: node
    links:
    - db
  db:
    image: mysql
```

この`links`オプションだがもうレガシー機能でそのうち削除されるらしい。

# 公式リファレンス
[英語](https://docs.docker.com/compose/compose-file/#links)
[日本語](http://docs.docker.jp/compose/compose-file.html#links)
日本語のほうにはまだ書いていない模様

# 試してみた
node.jsからmysqlのテーブル情報を読み出してjsonで表示する簡単なページを作成
DB名：testdb
テーブル名：user
カラム：name, password

### ディレクトリ構成
構成はで以下のように設定

```:project/
├── app.js
├── docker
│   ├── construct_app
│   │   └── Dockerfile-app
│   └── construct_db
│       ├── Dockerfile-db
│       └── init-conf.sql
├── node_modules
├── docker-compose.yml
├── package-lock.json
└── package.json
```

### ファイルの中身（一部）
```app.js
var express = require('express');
var mysql = require('mysql');
var app = express();

app.get('/', function(req,res){
  var connection = mysql.createConnection({
    host     : 'db',
    user     : 'testuser',
    password : 'testpass',
    database : 'testdb'
  });
  connection.connect();
  connection.query('SELECT * FROM user;', function (error, results, fields) {
    if (error) throw error;
    res.json({
      username:results[0].name,
      password:results[0].password
    });
  });
  connection.end();
});

app.listen(5000);
```

```docker-compose.yml
version: '3'
services:
  app:
    build:
      context: ./docker/construct_app # Dockerfile保存場所
      dockerfile: Dockerfile-app      # Dockerfileファイル名
    image: links-test-app             # イメージ名
    container_name: links-test-app    # コンテナ名
    ports:
      - 5000:5000
    volumes:                          # mount workdir
      - ./:/src
    command: [sh, -c, npm install && node app.js]
#    links:
#      - db

  db:
    build:
      context: ./docker/construct_db # Dockerfile保存場所
      dockerfile: Dockerfile-db      # Dockerfileファイル名
    image: links-test-db             # イメージ名
    container_name: links-test-db    # コンテナ名
    environment:
      - "MYSQL_ROOT_PASSWORD=root"   # ルートのパスワードが必要
```
Dockerfileにはベースイメージと環境変数などを記載
init-conf.sqlはmysqlの初期設定をデータを記載

### 結果
普通に接続できた。
<img width="392" alt="スクリーンショット 2018-12-03 20.01.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/304531/0f612d1a-50ae-d97b-6bcc-e7cafd0be8b8.png">

名前解決は特に何も設定しなくても行なってくれるようです。

尚、起動順を設定する`depends_on`はまだまだ現役ですのでこちらは必要に応じて使っていけますね。