OmniAICreator/Qiita-1.07M huggingface dataset:
macにFiddlerをインストールしてみる

アプリの通信ログを見たかったので、Fiddlerをmacにインストールしてみました。

Fiddlerのダウンロードは[こちら](https://www.telerik.com/fiddler-everywhere)。


Fiddlerのインストールガイドは[こちら](https://www.telerik.com/blogs/details/introducing-fiddler-for-os-x-beta-1)。

こちら、英語が苦手な方（私）のためのメモです。

OS:macOS 10.14.6
Monoframwork:6.4.0
Fiddler:v4.6

---
**①If you don’t have the Mono framework installed on your Mac, please download it and install it. If you already have it installed, please update it to the latest version.**

MonoプロジェクトからMonoのフレームワークをインストールしろ、ということなのでインストールします。[リンク先](https://www.mono-project.com/download/stable/#download-mac)には、macOS/Linux/Windows/Docker用のパッケージがあるので、今回はもちろんmac用を選択。僕はStable channelをインストールしました。
<img width="498" alt="mono.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277136/fd33e0e2-b91c-c2b7-3c5f-d5ce6b8f955d.png">

**②If you just installed Mono, please open Terminal and type in:
/Library/Frameworks/Mono.framework/Versions/<Mono Version>/bin/mozroots --import —sync**

Monoをインストール後に、試しににターミナルでコピペしてみました。

>macName:~ username$
/Library/Frameworks/Mono.framework/Versions/6.4.0/bin/mozroots --import --sync
Mozilla Roots Importer - version 6.4.0.0
Download and import trusted root certificates from Mozilla's MXR.
Copyright 2002, 2003 Motus Technologies. Copyright 2004-2008
Novell. BSD licensed.
WARNING: mozroots is deprecated, please move to cert-sync instead.
Downloading from 'https://hg.mozilla.org/releases/mozilla-release/rawfile/default/security/nss/lib/ckfw/builtins/certdata.txt'...
Importing certificates into user store...
151 new root certificates were added to your trust store.
Import process completed.


ワーニングは出てるけどインストールは出来たみたいです。

**③Extract fiddler-mac.zip to a folder you have write access to. It is recommended that the full path to the Fiddler install folder does not contain any Windows path illegal characters. (At present it is possible that some Fiddler functionality, e.g. various file exports or Fiddler Script won’t handle such paths.)**

ここ、ちょっとはまっちゃいました。fiddler-mac.zipを展開したフォルダーの属性をwriteを追加しろ、ということなんですが、Macの場合右クリック→情報を見る、で属性も変更できますが、これがいちいちどこまでになっているのか、よく分からない。

ということで、コンソール上、1つ上段のフォルダに移動して、

`chmod -R 777 fiddler_mac`

で、一挙に変更しちゃいます。

**④Open Terminal and navigate to the folder form 3.**

ターミナルで③のフォルダへ行けということなので移動。

**⑤Type mono Fiddler.exe in Terminal.**

ココも、はまってしまいました。

`mono Fiddler.exe`

だとエラーが出て起動しません。

いろいろと調べていると、

`mono --arch=32 Fiddler.exe`

で、32bitとして起動すると良いです。

---

最後にアンインストールですが、Fiddlerはフォルダを削除すれば良いですが、Monoは以下にそってアンインストールしてください。

>Run this script in a terminal:
sudo rm -rf /Library/Frameworks/Mono.framework
sudo pkgutil --forget com.xamarin.mono-MDK.pkg
sudo rm /etc/paths.d/mono-commands

最後に実行してみて、あっ、これVM上のWindows10にインストールしてた…、という落ちがありました（汗）。

自分の端末に何のアプリをいれているか、しっかり管理した方が良いですね（笑）。
docker-composeコマンドメモ

いまさらながらdocker真面目に使い始めたので、コマンド等を忘れないように
書き留めておきます。

#Docker Composeとは
複数のコンテナから成るサービスを構築・実行する手順を自動的にし、管理を容易にする機能です。

今の現場でGrafanaとかinfluxDbとか使ってるんで、そこら辺を構築してみてます。

#コマンド

## up
コンテナを作成して起動します。「-d」オプションをつけることで、バックグラウンドで起動します。

```bash
# docker-compose up -d
Starting docker_influxdb_1 ... done
Starting docker_grafana_1  ... done      
```

## stop
コンテナを停止します

```bash
# docker-compose stop
Stopping docker_influxdb_1 ... done
Stopping docker_grafana_1  ... done
```

## logs
各インスタンスのログを確認する。

```bash
# docker-compose logs
```

以下のように、インスタンスを指定することもできます。

```bash
# docker-compose logs influxdb
```

また、「-f」オプションをつけることで、「tail -f」のようにログを監視することができます。

```bash
# docker-compose logs -f influxdb
```
## ps

```bash
コンテナの一覧を表示します。

# docker-compose ps
      Name                 Command           State           Ports
---------------------------------------------------------------------------
docker_grafana_1    /run.sh                  Up      0.0.0.0:3000->3000/tcp
docker_influxdb_1   /entrypoint.sh influxd   Up      0.0.0.0:8086->8086/tcp
```
Goで行列計算をいくつか実装してみる

この記事は[tomowarkar ひとりAdvent Calendar 2019](https://qiita.com/advent-calendar/2019/tomowarkar)の10日目の記事です。

行列計算がしたかった...

### 行列の構造体定義
```go
// Matrix ...
type Matrix struct {
	height int
	width  int
	field  [][]float64
}
```

### ゼロ行列生成
```go
// ZerosMatrix ...
func (m *Matrix) ZerosMatrix(h, w int) {
	m.field = make([][]float64, h)
	for i := 0; i < h; i++ {
		m.field[i] = make([]float64, w)
	}
	m.height = h
	m.width = w
}
```
```go
m.ZerosMatrix(2, 3) //  {2 3 [[0 0 0] [0 0 0]]}
```
$$
\left[
    \begin{array}{rrr}
      0 & 0 & 0 \\\
      0 & 0 & 0 \\\
    \end{array}
  \right]
$$
### 任意の行列生成
```go
// CreateMatrix ...
func (m *Matrix) CreateMatrix(h, w int, arr []float64) error {
	if h*w != len(arr) {
		return xerrors.New("Mattrix size error")
	}
	m.field = make([][]float64, h)
	for i := 0; i < h; i++ {
		m.field[i] = arr[w*i : w*(i+1)]
	}
	m.height = h
	m.width = w
	return nil
}
```
```go
m.CreateMatrix(2, 3, []float64{1,2,3,4,5,6}) //  {2 3 [[1 2 3] [4 5 6]]}
```
$$
\left[
    \begin{array}{rrr}
      1 & 2 & 3 \\\
      4 & 5 & 6 \\\
    \end{array}
  \right]
$$
### 転置
```go
// T ...
func T(m Matrix) Matrix {
	var ans Matrix
	var arr []float64
	for i := 0; i < m.width; i++ {
		for j := 0; j < m.height; j++ {
			arr = append(arr, m.field[j][i])
		}
	}
	ans.CreateMatrix(m.width, m.height, arr)
	return ans
}
```
```go
T(m.CreateMatrix(2, 3, []float64{1,2,3,4,5,6})) //  {3 2 [[1 4] [2 5] [3 6]]}
```
$$
\left[
    \begin{array}{rrr}
      1 & 4 \\\
      2 & 5 \\\
      3 & 6 \\\
    \end{array}
  \right]
$$
### 行列の積
```go
// Multiplication ...
func Multiplication(ma, mb Matrix) (Matrix, error) {
	ans := Matrix{}
	if ma.width != mb.height {
		return ans, xerrors.New("Mattrix size error")
	}
	ans.ZerosMatrix(ma.height, mb.width)
	for i, a := range ma.field {
		for j := 0; j < mb.width; j++ {
			mul, _ := sumOfProducts(a, T(mb).field[j])
			ans.field[i][j] = mul
		}
	}
	return ans, nil
}

func sumFloatArr(arr []float64) float64 {
	var ans float64
	for _, a := range arr {
		ans += a
	}
	return ans
}

func sumOfProducts(a, b []float64) (float64, error) {
	var ans []float64
	if len(a) != len(b) {
		return 0, xerrors.New("size error")
	}
	for i := 0; i < len(a); i++ {
		ans = append(ans, a[i]*b[i])
	}
	return sumFloatArr(ans), nil
}
```
```go
var ma, mb Matrix
ma.CreateMatrix(2, 3, []float64{1, 2, 3, 4, 5, 6})
mb.CreateMatrix(3, 2, []float64{1, 2, 3, 4, 5, 6})
Multiplication(ma, mb) // {2 2 [[22 28] [49 64]]} <nil>
```

$$
\left[
    \begin{array}{rrr}
      1 & 2 & 3 \\\
      4 & 5 & 6 
    \end{array}
  \right]\left[
    \begin{array}{rrr}
      1 & 2  \\\
      3 & 4  \\\
      5 & 6  \\\
    \end{array}
  \right]=\left[
    \begin{array}{rrr}
      22 & 28  \\\
      49 & 64  \\\
    \end{array}
  \right]
$$
# 終わりに
もっとこうした方がいいよ等あればご指摘いただけると嬉しいです😍

以上明日も頑張ります！！
[tomowarkar ひとりAdvent Calendar Advent Calendar 2019](https://qiita.com/advent-calendar/2019/tomowarkar)
Splunk REST APIの玄関を叩いてみる

はじめに
----
- SplunkにはREST APIコマンドリファレンスが用意されている
    - 検索を実行。
    - オブジェクトと構成を管理。
- GUIで出来ることはなるべくAPIでプログラマティックに実装したい人向け
- RESTを調べたきっかけは、「あるトリガーをきっかけに”特定のログファイルの監視を有効化”させる方法」を探していてたどり着きました

REST APIで何ができるか
----
1. サーチして結果をcsvで出力する

<img width="1234" alt="スクリーンショット 2019-12-10 13.31.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/352fe3bf-2f31-a96c-7b54-936f3e3e4e50.png">

<img width="1088" alt="スクリーンショット 2019-12-10 13.32.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/bf9237c7-1069-3374-cdd8-735cc436f49a.png">


2.inputs設定を変更する（詳細は以下で）


手順
----
- やりたいこと
    - あらかじめ用意したsecureログ監視の設定（無効）を、REST APIで有効（呼び起こす）
    - 監視スクリプトなどでトリガー検知後のスクリプト実行に本REST APIをあわせる利用を想定

- まずはsecureログの監視設定を用意しておく(無効)
![スクリーンショット 2019-12-10 13.44.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/d33f43a9-38c3-783e-6e62-b0d887c21ed6.png)



- REST APIを実行

```sh:monitor有効化
curl -k -u admin:(password) https://13.xx.xx.xx:8089/servicesNS/nobody/Splunk_TA_nix/data/inputs/monitor/%2Fvar%2Flog%2Fsecure -d disabled=false
```

- point
    - -k ：SSL証明書のチェック無視
    - -u ：User/Pass認証
    - /Splunk_TA_nix ：設定内容の保存先appを指定
    - %2Fvar%2Flog%2Fsecure →：監視対象ファイルpath（/）は「%2F」または「%252F」のURI-Encodingで指定（https://docs.splunk.com/Documentation/Splunk/8.0.0/RESTUM/RESTusing）
    - -d disabled=false　→: 有効化の設定
   

- 設定変更を確認（有効）
![スクリーンショット 2019-12-10 13.41.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/aa2d9f32-04f3-8fd7-4282-27109953b54c.png)


- 他にもindexの保存先のパラメータ変更なども可能

```sh:indexの変更（secure→windows）
curl -k -u admin:(password) https://13.xx.xx.xx:8089/servicesNS/nobody/Splunk_TA_nix/data/inputs/monitor/%252Fvar%252Flog%252Fsecure -d index=windows
```

- 結構いろいろできそう
    - https://docs.splunk.com/Documentation/Splunk/8.0.0/RESTREF/RESTinput
![スクリーンショット 2019-12-10 13.54.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/a7e0dbd3-75ce-8190-72fc-69fbd42c2f91.png)

- 今回はinputsで利用可能なAPIをcheckしました
    - https://docs.splunk.com/Documentation/Splunk/8.0.0/RESTREF/RESTinput
![スクリーンショット 2019-12-10 13.55.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/15e05cf0-045c-3387-52bc-c0dfa11069ca.png)



参考
----
- 参考になったAnswer
    - [How can we programatically disable/enable a data input?
](https://answers.splunk.com/answers/594871/how-can-we-programatically-disableenable-a-data-in.html)
- 本家ガイド
    - [REST API User Manual](https://docs.splunk.com/Documentation/Splunk/8.0.0/RESTUM/RESTusing)
Google Apps Script(GAS)でNEM Catapultを使う

# はじめに

nem2-sdk-browserify をGASから読み込ませて、ウェブアプリケーションとしてNEM Catapultを使う方法です。


browserifyの記事については以下のURLを参考ください。
[nem2-sdkを使ってブラウザで動くブロックチェーンのアプリを開発する方法](https://qiita.com/nem_takanobu/items/e23b6d10198e630664cd)

また、今回は以下の記事を大変参考にさせていただきました。
[【GAS】WebアプリやAPIも作れちゃう！HtmlServiceについて、できることをまとめてみた。](https://webird-programming.tech/archives/423)


# gsファイル

```js

// コード.gs
function doGet(e) {
  return HtmlService.createTemplateFromFile("javascript").evaluate();
}

```

# JavaScriptファイル

```html:javascript.html

<script src="https://s3-ap-northeast-1.amazonaws.com/xembook.net/nem2-sdk/nem2-sdk-0.16.1.js"></script>
<script>

const NODE = 'https://jp5.nemesis.land:3001';
const GENERATION_HASH = "CC42AAD7BD45E8C276741AB2524BC30F5529AF162AD12247EF9A98D6B54A385B";
const nem = require("/node_modules/nem2-sdk");
const alice = nem.Account.generateNewAccount(nem.NetworkType.TEST_NET);
console.log("アカウント作成しました。")
console.log(alice.address.address)
console.log(alice.privateKey)

console.log("送金テスト")
const bob  = nem.Account.createFromPrivateKey('DF1A2101A6BA32F33C60B6A59AA72170BB0AC5A4E1057FBA706DC2B999E902C4', nem.NetworkType.TEST_NET);
console.log(bob.address.address);

    const tx = nem.TransferTransaction.create(
        nem.Deadline.create(),
        alice.address,
        [
            new nem.Mosaic(
                new nem.MosaicId('75AF035421401EF0'),
                nem.UInt64.fromUint(0)
            )
        ],
        nem.PlainMessage.create('Hello World!'),
        nem.NetworkType.TEST_NET,
        nem.UInt64.fromUint(100000)
    );

    const signedTx = bob.sign(tx,GENERATION_HASH);
    const txHttp = new nem.TransactionHttp(NODE);
console.log(NODE + "/transaction/" + signedTx.hash + "/status");

    txHttp
    .announce(signedTx)
    .subscribe(_ => console.log("ネットワーク通知"), err => console.error(err));



</script>
```

# 公開
Webアプリケーションとして公開してください。
ビルド終了後、指定されたURLにアクセスするとnem2-sdkを読み込み、NEMへの接続を試みます。（F12consoleで確認してください）

スプレッドシートのサイドバーをhtmlで実装したりしてアドレス一覧に送金するとか、いろいろ用途がありそうですね。
今まで興味がなかった人もこの機会にぜひ活用方法を検討してみてください。

こちらもご参考ください。

https://qiita.com/nem_takanobu/items/cc28ee8daa0f6532a05d
core-js/modules/es6（以下略）が見つかりません。の場合

少し前に調べた事をメモっておく。
nodeか、vue-cliのバージョンとかを上げた時に、babelが古いと言われるので７に上げて…

```
$ npm run serve
$ vue-cli-service serve
```
serveすると…

```
These dependencies were not found:

core-js/modules/es6.array.iterator
core-js/modules/es6.function.name
core-js/modules/es6.number.constructor
core-js/modules/es6.object.assign
core-js/modules/es6.object.to-string
core-js/modules/es6.promise
core-js/modules/es6.regexp.match
core-js/modules/es6.regexp.replace
core-js/modules/es6.regexp.split
core-js/modules/es6.regexp.to-string
core-js/modules/es6.string.includes
core-js/modules/es6.string.iterator
core-js/modules/es6.typed.uint8-array
core-js/modules/es7.array.includes
core-js/modules/es7.promise.finally
core-js/modules/web.dom.iterable
```
が出ました。何かなと思ったら…
https://babeljs.io/docs/en/babel-preset-env#usebuiltins

>Since @babel/polyfill was deprecated in 7.4.0, we recommend directly adding core-js and setting the version via the corejs option.
>@ babel / polyfillは7.4.0で非推奨になったため、core-jsを直接追加し、corejsオプションでバージョンを設定することをお勧めします。

だそうです。なので、とりあえず

```
$ npm install --save core-js
```
これだけでは動かないので、babel.config.jsを書き換える必要があるみたいです。

```babel.config.js
module.exports = {
  presets: [
    '@vue/app'
  ]
}
```
@babel/polyfillをimport/requireする方法だそうです。

```babel.config.js
module.exports = {
  presets: [
    [
      "@vue/app", { useBuiltIns: "entry" } //entry または false
    ]
  ]
}
```
babel-preset-envのなにかを読み込める設定らしいです。

参考にしたページ
https://github.com/vuejs/vue-cli/issues/3678
https://aloerina01.github.io/blog/2018-11-29-1
HiveでNOT EXISTSの代わりにLEFT OUTER JOINを使ってみる

この記事は[MicroAd Advent Calendar 2019](https://qiita.com/advent-calendar/2019/microad)の10日目の記事です。

# はじめに

MySQLなどのクエリで集合差を表現する方法に`NOT EXISTS`があります。`NOT IN`を使うよりはマシですが、この処理のパフォーマンスが気になる場面があり、以下の記事にあるような`LEFT OUTER JOIN`を使う方法を知りました。

参考：[MySQLで集合差を出す](https://qiita.com/Hiraku/items/71873bf31e503eb1b4e1)

例えば、`NOT EXISTS`を含む次のような「ブラックリストに入っていないメンバーの情報を取得する」クエリ

```sql
SELECT
  id
  ,name
FROM
  member
WHERE NOT EXISTS (
  SELECT
    id
  FROM
    black_list
  WHERE
    member.id = black_list.id
  LIMIT 1
)
```

を

```sql
SELECT
  id
  ,name
FROM
  member
LEFT OUTER JOIN black_list
ON member.id = black_list.id
WHERE
  black_list.id IS NULL
```

のように表現することができ、MySQLではこちらの方が高速であるケースが多いようです。

業務でHiveを使うことがあり、Hiveの場合はパフォーマンスにどの程度差が出るのかを簡単に調べてみました。

# 検証

Hive上の2つのテーブル`table1`と`table2`を用いて、2つの記法の所要時間を比較しました。レコード数は1億5000万件ほど用意し、集合差の大きさによる所要時間の違いも検証しました。

- 集合差0: `table1`, `table2`が完全一致で、集合差が0
- 集合差10%: `table2`には`table1`のレコードの10%だけが入っている
- 集合差50%: `table2`には`table1`のレコードの半分が入っている
- 集合差90%: `table2`には`table1`のレコードの90%が入っている
- 集合差100%: `table2`が空で、集合差が`table1`と完全一致

なお、CDHのバージョンは`5.14`で、テーブルの圧縮形式は`Parquet`です。

## `NOT EXISTS`を使う場合

```sql
SELECT
  id
FROM table1
WHERE NOT EXISTS (
  SELECT
    id
  FROM table2
  WHERE table1.id = table2.id
)
```

- 集合差0: 97 (sec)
- 集合差10%: 97 (sec)
- 集合差50%: 99 (sec)
- 集合差90%: 100 (sec)
- 集合差100%: 97 (sec)

## `LEFT OUTER JOIN`を使う場合

```sql
SELECT
  id
FROM table1
LEFT OUTER JOIN table2
ON table1.id = table2.id
WHERE table2.id IS NULL
```

- 集合差0: 99 (sec)
- 集合差10%: 96 (sec)
- 集合差50%: 101 (sec)
- 集合差90%: 100 (sec)
- 集合差100%: 98 (sec)

# 結果

今回の検証では、この2つの記法と集合差の大きさによるパフォーマンスに明確な差は見られませんでした。

`NOT EXISTS`はあまり速くないというイメージがありましたが、意外とそんなことはないのかもしれません。

# おわりに

Hiveでの`NOT EXISTS`と、その代わりに`LEFT OUTER JOIN`を使った場合とのパフォーマンスを、簡易的ではありますが比較しました。

何らかの参考になれば幸いです。

より良い記法や検証方法などがありましたら、ご指摘いただけますと有難いです。
NewRelicを利用して性能問題を簡単に切り分けることができた事例の紹介

#はじめに

NECの井元です。
NewRelicさんからAdvent Calendarのお誘いを受けましたので、機能説明や使い方などは本家の方にお任せするとして、こちらではNewRelicを使って性能問題の原因を簡単に切り分けることができた事例を紹介します。

#負荷テストでの利用

とあるプロジェクトのオンプレからAWSへのリフト案件の性能検証でNewRelicを活用しました。
今回、以下の構成でEC2インスタンスにBrowser, APM, Infrastructureエージェントを、ELB、RDSサービスにはAWS連携でINFRASTRUCTUREエージェントを設定しています。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495725/d6584699-199f-7ea9-3f14-c1d1a9baf295.png)


性能評価では、JMeterを使って一定の負荷をかけ、負荷がかかった状態でブラウザからアクセスし、その表示時間、リソース使用量などを測定しました。

#性能問題の検出

性能検証の結果、スマホ経由でのある処理が数回に一度の割合で10秒近くかかっていることが判明しました。
まずは、APMの応答時間を見てみます。平均 0.2秒近くでサーバ側には問題がないように見えます。

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495725/c913e2ea-3deb-123b-3be0-72b95371a607.png)

つぎに、BROWSERの PageViewで表示時間を見てみます。
あきらかに、Page Renderingがその大部分の時間をしめていることがわかります。

![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495725/abf765a0-dd5c-f261-8331-c3d66347c690.png)


さらに、原因を分析するため Sssion Trace で代表的なトレースを確認してみます。

![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495725/1a66214e-3be3-015d-9008-2a8ab0a585fb.png)


domContentLoadEventEnd から domComplete まで、つまりファイルのダウンロードなどは完了し、画像、HTMLファイルなどのブラウザでのレンダリング処理が10秒近くかかっています。
サーバ、ネットワークは問題なく、HTML、CSSなどの描写処理が原因であることが数分の解析で判明し、デザイナーに結果と合わせて対策を依頼しました。

このように、NewRelicによる測定を仕込んでおくことで、性能検証で問題があった時の切り分けが数分で簡単にできます。

#良かった点

NewRelicを使ってモニタリングしながら性能テストをすると、テスト実行時のスループットの状況、リソースの使用量、トレースなどをその時間までさかのぼって確認、分析することができます。
特に、今回のように数回に一度のみ発生する問題では、発生条件を確認して再現する必要がなく、その時点の挙動、性能状況から原因を分析することができるため、簡単に性能問題の原因を特定することができます。
ウェブ解析士認定試験に行ってきました

先週末、ウェブ解析士の試験（初級）を受けてきました。
（なんとか合格することができました）

自分の一夜漬け脳に知識があるうちに紹介したいと思います！

##ウェブ解析士認定試験とは？

※下記、ウェブ解析士協会（WACA）のサイトより抜粋
>ウェブマーケティング、ウェブ解析の基礎知識を習得、
営業・制作・開発・社内ウェブマスター業務等の遂行・業務効率化を可能にすることを目指します。

>・ウェブマーケティング、ウェブ解析を行う上で必要な用語（定義～使い方）
・アクセス解析から得られる情報の認識・分析方法・計算方法（用途に応じた適切な利用）
・ウェブ解析による課題の発見方法と改善手段（事業成果に繋がる解析の考え方）

>職種としては、ウェブマーケティング担当やウェブサービス運用担当、デザイナー、プログラマー、ディレクターなど、ウェブに係る幅広い職種の方々が取得されています。

ちなみに...
「上級」では、さらにコンサル的な提案スキルの向上につながる内容を学び、
「マスター」では、ウェブ解析士を育てるスキルを学び、教室や講座を開けるようになるそうです。


##やってみて良かった点、悪かった点
#####良かった点
いわゆる資格商法の一種ではあると思うのですが、ウェブマーケ/解析の知識が「体系的に」「実践を前提として」学べた所が良かったです。業務を通して独学で覚えていくより、抜け漏れなく効率的に学べると思いました。

#####悪かった点
講座 11,000円、試験 17,600円、公式テキスト 4,400円となかなかの出費。
（追記※弊社は会社持ちで受けられるらしい）
特にテキストは毎年変わるので、自分は18年版を持っていたのですが、19年版も購入するハメになりました…。この辺は毎年業界の状況やGA等ツールの新仕様などが反映されているので、悪いことではないかもしれませんが。

さらに合格してからも6,000円の年会費があり、年度ごとにフォローアップテストを合格しないと資格が維持できないそうです。

#####解析経験者にとっての意味
初級は用語と考え方の理解が中心なので普段からウェブ解析に関わる方には既知の内容も多いかもしれませんが、EC/オウンドメディア/アプリなど、様々なケースの運用が学べますし、解析の方法も多岐に渡ります。
網羅的に知識を再確認してみると、意外と知っているようで知らなかったことや、新しい発見もあると思います。

#####受けようと思っている人へ
資格取得のコツを紹介します。
▼効率の良い勉強法
テキスト（教科書的な本）は500ページ位あり、全部読むのは大変です。（だるい）
オススメは問題集を買って間違えた問題の部分のテキストだけを読み込むという方法。
これで大分時間を短縮できます。
（２週目以降、問題集を解く際は1問1分以内の回答を意識しましょう）

▼試験当日
当日はテキストが持ち込みOKなのですが、60問60分と試験時間がかなり短く、いちいち逆引きしている時間はないです。
覚えきれない用語はテキストに書き込んでまとめておくと便利かもしれません。
自分は[用語集](https://docs.google.com/spreadsheets/d/1igyULCuWWPXBi6FcIQ4bWrkIiiuhfgIvsLyQT8k8Grc/edit?usp=sharing)を作ったら自然と覚えました。


##試験の擬似体験
ウェブ解析士認定試験の問題を擬似体験できるページを作ってみました。
いやらしい問題を集めました（笑
試験の雰囲気を感じてもらえればと。（実際は電卓で計算する問題もあります）
↓
[ウェブ解析士なんちゃって模擬テスト](https://kentei.cc/k/1552331/)
laravel + mariadb 10.x 設定

## レポジトリ

https://mariadb.com/downloads/#aptyum
より

```
# curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash
```

## Mariadbインストール

```
インストール
# yum install MariaDB-server MariaDB-client
サービス起動
# systemctl start mariadb
初期起動設定
# systemctl enable mariadb
初期設定
# mysql_secure_installation 
```

## UTF-8
初期はlatin1になっているのでutf-8に変更。
`vi /etc/my.conf.d/server.conf`

```
[mysqld]
character-set-server=utf8

[client]
default-character-set=utf8
```

再起動
`systemctl restart mariadb`

## タイムゾーンの設定
[MySQLでタイムゾーンを設定する](https://qiita.com/tailak/items/63dce2dd7dfe049b038e)
こちらを参考に設定した

## laravelの文字コード
初期設定はutf8mb4という絵文字対応の文字コードになっているため
そのまま`php artisan migrate`すると文字コードがおかしくなる。

```config:config/database.php
        'mysql' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
※ここを変更する
            'charset' => 'utf8',
※ここを変更する
            'collation' => 'utf8_general_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],
```
rails-tutorial拡張編（userとmicropostの検索機能)

#userの検索機能を作るぞ

まずはransackというgemをbundle installする。


次にユーザー検索用のフォームのパーシャルを作成する。

```app/views/users/_search_form.html.erb
<%= search_form_for @q do |f| %>
  <%= f.label :name_cont, 'User Search' %>
  <div class="input-group">
    <%= f.text_field :name_cont, placeholder: "Enter username...",
                      class: 'form-control' %>
    <span class="input-group-btn">
     <%= f.submit 'Go', class: "btn btn-primary" %>
    </span>
  </div>
<% end %>
```

このパーシャルを後ほどuserのindexアクションのviewに埋め込む


次に、usersコントローラのindexアクションの処理を変える。


```app/controllers/users_controller

def index
    if params[:q] && params[:q].reject { |key, value| value.blank? }.present?
      @q = User.ransack(search_params, activated_true: true)
      @title = "Search Result"
    else
      @q = User.ransack(activated_true: true)
      @title = "All users"
    end
    @users = @q.result.paginate(page: params[:page])
  end
~
省略
~
private
    def search_params
      params.require(:q).permit(:name_cont)
    end
```

params[:q][:name_cont]にユーザーが指定した検索ワードが含まれており、検索ワードの指定がない場合は全アクティブユーザーを取得します。
「モデル名.Ransack(検索条件)」の結果を「result」で取得します。
また、検索なしの時と検索ありの時でタイトルを変更しています。

ということらしい


次に作ったパーシャルを埋め込む

```app/views/users/index.html.erb
<% provide(:title, @title) %>
<h1><%= @title %></h1>

<div class="row">
  <div class="search_form">
    <%= render 'users/search_form' %>
  </div>
</div>

<%= will_paginate %>

<% unless @users.empty? %>
  <ul class="users">
    <%= render @users %>
  </ul>
<% else %>
  <p>
    Couldn't find any user.<br>
    Please check username you are looking for.
  </p>
<% end %>

<%= will_paginate %>
```


最後にcssを整える

```app/assets/stylesheets/custom.scss
.search_form {
  overflow: auto;
  margin: 10px;
  float: right;
  .input-group {
    width: 300px;
    .form-control {
      width: 250px;
    }
    .btn {
      width: 50px;
    }
  }
}
```

これで完成！！！


#micropostの検索機能
【Java/Kotlin】unbescapeでHTML5対応のエスケープ（サニタイズ）処理をする【SpringBoot】

# やること
`HTML`テンプレートのマクロ文字列をパラメータで置換する際のエスケープ処理をやります。

# やり方
この記事では`unbescape`を用います。

`HTML5`対応が明示されていませんが、`Apache Commons Text`を用いる方法なども有ります。

## 導入
このライブラリは`spring-boot-starter-thymeleaf`に入っていたため、`SpringBoot`関連のものを入れていれば何もする必要が無いかもしれません。
一応ですが、`Maven`のリポジトリは以下です。

- [Maven Repository: org\.unbescape » unbescape](https://mvnrepository.com/artifact/org.unbescape/unbescape)

## エスケープする
以下の記事を参考にエスケープ処理をやってみました。

- [JavaScriptでHTMLエスケープ処理 \- Qiita](https://qiita.com/saekis/items/c2b41cd8940923863791)

`HtmlEscape.escapeHtml5`でエスケープできます。

```kotlin:検証用コード
fun main() {
    val value = """
        &: &amp;
        ': &#x27;
        `: &#x60;
        ": &quot;
        <: &lt;
        >: &gt;
    """.trimIndent()

    println(HtmlEscape.escapeHtml5(value))
}
```

### 実行結果
バッククォート以外はエスケープされました。

```:実行結果
&amp;: &amp;amp;
&apos;: &amp;#x27;
`: &amp;#x60;
&quot;: &amp;quot;
&lt;: &amp;lt;
&gt;: &amp;gt;
```

# その他エスケープ可能な内容
パッケージを覗いてみた様子が以下です。
色々とエスケープできます。

![スクリーンショット 2019-12-10 13.02.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280230/f1cda246-05ce-fa8f-ba74-fed705a693cb.png)

# 参考にさせて頂いた記事
- [テックノート – javaでHTMLタグをサニタイジングしてみる](http://javatechnology.net/java/html-sanitizing/)
ChatWork Extensionの有効活用

## はじめに
ChatWork Extensionと言われて、前に使っていたよという方もいるのではないでしょうか。

Chatwork左側のルーム一覧はデフォルトでは余白が多く、使い辛く感じる方もいます。
そんな方の強い味方であった[ChatWork Extension](https://chrome.google.com/webstore/detail/chatwork-extension/kdpcnbofhlgnkpefjkngkpjbeebbabed?hl=ja)([Neo](https://chrome.google.com/webstore/detail/chatwork-extension-neo/lgdckbcnkgfbdadaemibgknbfigiacoe?hl=ja)含む)ですが、Chatworkのアップデートにより残念ながら使い物にならなくなってしまいました。

今回の記事では代替のextensionを当てることも自作する事なく、その上でChatWork Extensionを消さずに放置している層向けに有効活用する方法を紹介していきます。
（もちろん今から入れてもOKです）

## InjectUserCustomScriptsオプションの利用
今回紹介する方法は、最終的にcssをガリガリ書いていく方法になります。
ChatWork ExtensionではオプションでInjectUserCustomStylesheets機能を提供していますが、残念ながら現在では沈黙してしまっています。
幸いInjectUserCustomScriptsは生存していますので、jsを経由してcssを書き換えていきます。

## 記入方法
ベースとなるコードは下記のような形になります。

```js:InjectUserCustomScripts
var text = '';
var ss = document.createElement('style');
ss.textContent = text;
window.document.head.appendChild(ss);
```

こちらをベースにtext変数にスタイルシートへの記述と同じように書いていけば、お好みのスタイルを適応させる事ができます。
注意点として、改行を含む文字列を書き込んでしまうと正常に反映させる事ができません。
気合を入れて1行で書き切る、メモ帳などで書いた後に改行を消す等の対処方法もありますが、改行を\でエスケープする事もできます。
お好みの方法で記入していってください。

## 最後に
この記事だけに言える事ではないですが、今後のChatworkアップデートにより本記事の内容も使えなくなる可能性があります。
私も現在の設定に落ち着くまで何度も修正を余儀なくされました。
ぜひともChatworkさんにはお手柔らかにして頂きたいものです。

## おまけ
私は普段こちらの設定を使っています。
自前で書くのが面倒だという方、スタイルシートの書き方がよくわからないという方はご活用ください。

```js:サンプル
var text = '\
#_roomListArea roomlist ul li[role="listitem"] {\
  padding: 0px 16px 1px 0px !important;\
}\
#_roomListArea roomlist ul li[role="listitem"] > div:nth-child(1) > div:nth-child(1),\
#_roomListArea roomlist ul li[role="listitem"] > div:nth-child(1) > div:nth-child(1) > img {\
  width: 24px !important;\
  height: 24px !important;\
}\
#_roomListArea roomlist ul li[role="listitem"] > div:nth-child(1) > div:nth-child(1) {\
  margin-right: 2px !important;\
}\
#_roomListArea roomlist ul li[role="listitem"] > div:nth-child(2) {\
  top: 0px !important;\
  right: 4px !important;\
  width: 16px !important;\
  height: 16px !important;\
}\
#_roomListArea roomlist ul li[role="listitem"] > div:nth-child(1) > div:nth-child(2) {\
  width: calc(100% - (16px + 16px)) !important;\
}\
';
var ss = document.createElement('style');
ss.textContent = text;
window.document.head.appendChild(ss);
```

# お知らせ
エイチームグループでは一緒に活躍してくれる優秀な人材を募集中です。
興味のある方はぜひとも[エイチームグループ採用ページ](https://www.a-tm.co.jp/recruit/requirements/career/lifestylesupport-webengineer/)よりご応募ください！

Qiita Jobsの[エイチーム引越し侍社内システム企画 / 開発チーム](https://jobs.qiita.com/employers/a-hikkoshi/development_teams/176)、[社内システム開発エンジニアを募集！](https://jobs.qiita.com/postings/309)からチャットでご質問いただくことも可能です！

# 明日
明日は @andmorefine さんの記事です。
乞うご期待！
Oracle Spatial and Graph/Advanced Analytics無償化、さらにSE2でも利用可能になった件


[Mike Dietrich](https://mikedietrichde.com/2019/12/06/great-license-news-spatial-and-graph-machine-learning/)のブログによると、2019/12/5から

**<font color="blue">Oracle Spatial and GraphとAdvanced Analyticsが無料化されただけでなく、SE2でも使えるようになったらしい。</font>**

**いずれもオンプレミスとOracle Cloud共通の変更事項だ。またAdvanced AnalyticsはMachine Learningに改名されたとのこと。**

* Mike Dietrich's Blog「[Great License News: Spatial and Graph, Machine Learning](https://mikedietrichde.com/2019/1![spatial02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/3c3b5f8b-091e-4d5a-86ca-3434789c570b.png)
2/06/great-license-news-spatial-and-graph-machine-learning/)」
* Oracle Spatial and Graph Blog「[Spatial now free with all editions of Oracle Database](https://blogs.oracle.com/oraclespatial/spatial-now-free-with-all-editions-of-oracle-database)」
* Oracle Machine Learning Blog「[Machine Learning in Oracle Database](https://blogs.oracle.com/machinelearning/machine-learning-in-oracle-database)」
* [Machine Learning, Spatial and Graph - No License Required!](https://blogs.oracle.com/database/machine-learning%2c-spatial-and-graph-no-license-required-v2)

ライセンス・マニュアルを確認すると、[英語マニュアル](https://docs.oracle.com/en/database/oracle/oracle-database/19/dblic/Licensing-Information.html#GUID-0F9EB85D-4610-4EDF-89C2-4916A0E7AC87)は反映済みだけれど、[日本語マニュアル](https://docs.oracle.com/cd/F19136_01/dblic/Licensing-Information.html#GUID-0F9EB85D-4610-4EDF-89C2-4916A0E7AC87)はこれからのようだ。

<font color="blue">また「PDBが3つまでOK」になったのは19c以降だけれど、今回の変更は12.2以降に適用されるようだ。</font>

Machine Learningは各社が力を入れている分野だし、GIS（地理情報システム）はずいぶん前からPostGIS（PostgreSQLの拡張機能）でも利用できた。ともにNoSQLの苦手分野だし、巻き返し戦略のためなのか。

[Database Licensing Information User Manual (E94254-12) December 2019](https://docs.oracle.com/en/database/oracle/oracle-database/19/dblic/Licensing-Information.html#GUID-0F9EB85D-4610-4EDF-89C2-4916A0E7AC87)
![spatial01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/5d4a75a6-730f-51d3-64cd-df800d12507f.png)
![spatial02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/bb7fbbf4-797b-f4c7-3357-1799a88f37fb.png)
Nuxtの紹介

## フロントエンドを開発する時に、気づいたこと

### フロントアプリコードのフォルダー構成
vue router, model, vue component, vue page, vue template, style, api ... ってのファイルがありますけど、どうやって管理するか、どういうフォルダー構成にした方が良いか、答えがないです。　つまり良い構成がないです。　メンバーと相談して、フォルダー構成を決めましたが、人によって違いますので、相談しにくい

### VueXの使い方
ある場合、Vuexが便利ですが、ある場合Vuexはちょっと面倒です。 vuexはどの場合使うか使わないか分からないです。

### フロントの最初の設定
vue, vuex, vue router, lintのライブラリーをインストールしれば良いですが、一括で出来れば良い

### プロジェクトが大きくになると、リファクタリング必要になります。 
ちゃんと設計しないと、毎回リファクタリング必要になるかもしれません 

### Build/デプロイ手順
webpackやVue CLIなど使えば、Build/デプロイは簡単ですが、プロジェクトによって、なにか修正しないといけないことが必要になるかもしれません。

### 自動作成と自動インポートがないです
新しい機能を開発する時に、色々なコード書かないといけないです。例えば
- vuexモジュール準備
- vue router準備
- vue component準備
- api/model準備
全部出来たら、インポートが必要になるかもしれません

### まとめて
バックエンドの話ですが、railsを使った時、ファイル生成とか、router・controller・htmlは名前が同じなら、自動連携されます。プロジェクト作成もめっちゃ簡単です、`rails new`実行するだけです。 

フロントエンドでもそういうことができれば良いなと思います。

## NuxtJS はじめ
https://ja.nuxtjs.org/
### Nuxtとは? 
Vue.js アプリケーションを構築するためのフレームワークです
- Vuejs
- vuex
- vuerouter
→ Nuxtに入ります。

### Nuxtのメリット
- Vue ファイルで記述できること（*.vue）
- コードを自動的に分割すること
- サーバーサイドレンダリング
- 非同期データをハンドリングするパワフルなルーティング
- 静的ファイルの配信
- ES2015+ のトランスパイレーション
- JS と CSS のバンドル及びミニファイ化
- <head> 要素（<title>、<meta> など）の管理
- 開発モードにおけるホットリローディング
- プリプロセッサ: Sass, Less, Stylus など
- HTTP/2 push headers ready
- モジュール構造で拡張できること

### Nuxtでフォルダー構成が決まった。　ページとrouterがちゃんとマッチングされます。
Nuxtフォルダーはこんな感じ
<img width="229" alt="スクリーンショット 2019-12-10 12.39.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318767/c03e5fb9-851a-08fe-380a-2f6a6326cdda.png">

### Nuxt使う時に、ルールが決まりました。
基本のルールが決まったので、コードの書き方が一緒になります。

### 簡単にページ追加されます。
SEOもう出来ます。

### Nuxt Typescript
https://typescript.nuxtjs.org/

## まとめ
フロントエンドを開発する時に、たくさん書き方がありますが、自由に決めるといつかいくつか違和感があると思います。ですので、安全のためフレームワークを使った方がいいと思います。 Nuxtは良いフレームワークですので、是非お試してくださいませ。
GitHub超入門

この記事は[【Digital Identity Creative Div. Advent Calendar 2019】](https://adventar.org/calendars/4714 "【Digital Identity Creative Div. Advent Calendar 2019】")の11日目です



いくつかあるGitホスティングサービスの内、Bitbucketしか使ったことがない。
GitHubの知見がない。
そんな状態だったので実際に触ってみて備忘録として纏めました！

#GitHubとは
「Git」というバージョン管理の仕組みを利用してプログラムコード等を保存したり公開することができる「Gitホスティングサービス」です。
視覚的、直感的に操作できることができます。

#GitHubを使うメリット
・ファイルの変更履歴を管理できる
・過去のログを遡って更新前の状態に戻すことができる
・チーム共有できるので共同開発に向いている
・開発中の「やっちまったヨ...」が減るのでストレスと無駄な工数削減に繋がり働き方改革
などが挙げられます。


#まずは基礎知識
まずは前提となる基礎知識が必要なので最低限、
・ローカルリポジトリ&リモートリポジトリ
・コミット&プッシュ
・ブランチ
これらを押さえておくと良いかもしれません。

ググったら分かり易い記事がたくさん出てくるのでなんとなく頭に入れておきましょう。

#実際に触ってみる
それでは、アカウント登録をして実際に触っていきます。
※ GitHubのアカウント登録、Gitのインストール方法については省きます

##リポジトリの作成
![img01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229249/7507efc5-7e1a-cbfb-08e2-9cc8bbd0dd24.png)
右上の「+」から「New repository」をクリックします。

すると
![img02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229249/92c0486e-7d63-b233-c151-4a77776eed56.png)
このような画面に遷移するので①〜⑤まで入力します。
① リポジトリ名を入力
② 説明文を入力
③ 公開リポジトリにするのか、非公開リポジトリにするのかをチェックで選択
④ READMEを作成する場合はチェック
⑤ .gitignore、ライセンス設定
※ ④と⑤は後からでも作成できるため未チェック、noneでOK

入力が終わったら「Create repository」ボタンをクリックしてリポジトリの作成が完了します。

##ローカルリポジトリを作成してコミット&プッシュしてみる
まずは開発用ディレクトリの作成です。

```ruby
mkdir [ディレクトリ名]
```

適当な場所に作成するのではなくDocuments直下に「Local_repository」ディレクトリを作成するなどして今後管理していくことも視野に入れておきましょう。
今の状態だとただのディレクトリなので、Gitリポジトリ化します。
cdコマンドでカレントディレクトリに移動して下記コマンドを実行しましょう。

```ruby
git init
```

ディレクトリの中身をみてみると.gitが出来ているはずです。
これでGitリポジトリにすることができました。

次は適当なファイルを作成してインデックスに保存してみましょう。

```ruby
git add [作成したファイル名]
```

これで一時的にインデックスに保存することが出来たので、コミットをします。

```ruby
git commit -m ["add 作成したファイル名"]
```

実際の開発では後からログを確認した際になんの作業をしたか一目で分かるようにすると良いかもしれません。

ファイルが追加されていること、リモートリポジトリの情報が追加されていることを確認してプッシュをしましょう。

```ruby
git push origin [対象のブランチ]
```

ここでGitHubのユーザ名とパスワードを聞かれるので入力した後、
GitHubへアクセスしてリモートリポジトリに今回追加したファイルがあることを確認できれば完了です！

明日は【能勢弘光】さんです
[python]複数ユーザーのTwitterタイムラインを取得する

#背景、目的
複数のTwitterアカウントのscreen_name(@----)を格納したリストが用意してあります。

　（参考） [python]リスト内の文字列を含むツイートをしたユーザのリストを作成する
　　　　　　https://qiita.com/Yoocie/items/5ba57645d38ee5203ef7

今回は、作成したリストに含まれるユーザーのタイムラインを取得し、txtファイルとして保存していきます。一つのタイムラインにつき、一つのtxtファイルが作成されるようにします。

なお、一つのタイムラインあたり取得する最大のツイート数は3,200とし、RTは取得しないこととしました。

#ユーザーリスト
用意したリストは、こんな感じです。(実際には、文字列が各ユーザーのscreen_nameになります。)

```python3:users.py
users=['---','vvv','^^^',...(中略)...,'+++',')))']
```

#関数の作成（タイムラインの取得、テキストファイルの作成）

```python3:get_timeline.py

import tweepy
import config  #同じディレクトリに'config.py'というファイルがあります。

'''
config.py
CK = "*****" #CONSUMER_KEY
CS = "*****" #CONSUMER_SECRET
AT = "*****" #ACCESS_TOKEN
ATS = "*****" #ACCESS_TOKEN_SECRET
'''

CK = config.CK
CS = config.CS
AT = config.AT
ATS = config.ATS

# OAuth認証
auth = tweepy.OAuthHandler(CK, CS)
auth.set_access_token(AT, ATS)
api = tweepy.API(auth)


#1ユーザー分のタイムラインを取得し、テキストファイルとして保存する関数の定義
def get_timeline(name,i):
    #一人あたり最大3200件のツイートを取得
    pages = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
    data = []
    for page in pages:
        results = api.user_timeline(screen_name=name,\
                                    include_rts=False,\#リツイートは取得しません。
                                    count=200,\#上限の200件ずつ、ツイートを取得します。
                                    page=page)
        for result in results:
            data.append(result.text)
    
    line=''.join(data)
    #タイムラインの内容を含むテキストファイルの作成、保存
    #テキストファイルの名前は '20191210_user3_^^^.text' というような形式
    with open('20191210_user'+str(i)+'_'+name+'.txt', 'wt') as f:
        f.write(line)
```

#関数の使用
上で定義した関数を用います。ここでは、ユーザーリストの最初の6アカウントのタイムラインを取得します。

```python3
for i in range(6):
    get_timeline(users[i],i)
```

#環境
macOS Catalina
Jupiter notebook
GitHub Actions で Slack に通知をお手軽に送る

これは [ゆめみ その2 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/yumemi2) の１０日目の投稿です。

使ってますか？ GitHub Actions。

今回は GitHub Actions で何かしらの通知を Slack へ送る、簡単なスクリプトの例を紹介します。

[GitHub の Marketplace](https://github.com/marketplace?utf8=%E2%9C%93&type=actions&query=slack) を見ると、Slack 通知系のサードパーティの action がいくつかありますが、自分でスクリプトを書いても curl コマンドを叩くだけなので、その action が用途にばっちり合ってる場合を除いて、わざわざ既存の action を使う必要はありません。カスタマイズする際に自由にいかないことも多いですしね。

## 事前準備

Slack API アクセス用のトークン(文字列)を、GitHub の対象リポジトリに登録します。このトークンは GitHub Actions のワークフローの中から参照します。

<img width="800" alt="スクリーンショット_2019-12-10_0_49_59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35733/6c523e00-a34f-ee94-049c-48e2f4dc46ee.png">

※ トークンの用意の方法が分からなければ拙作の https://qiita.com/hkusu/items/a899e51bdd260ab908d7#slack あたりの記事を参照ください。

## スクリプト

curl コマンドで Slack API を叩くだけです。

```yaml
# ...

- name: Notify Slack
  run: |
    data=$(cat <<EOF
    {
      "channel": "hoge_channel",
      "username": "github-actions",
      "text": "Success"
    }
    EOF
    )
    curl -X POST \
         -H "Content-type: application/json; charset=utf-8" \
         -H "Authorization: Bearer ${{ secrets.SLACK_BOT_TOKEN }}" \
         -d "$data" \
         https://slack.com/api/chat.postMessage
```

`${{ secrets.SLACK_BOT_TOKEN }}` の箇所が、事前準備で登録したトークン(文字列)に置き換えられます。

ちなみにヒアドキュメント(`EOF`の箇所)を利用しているのは、JSON の内容を見やすくしたいだけです。（今回はシンプルな内容の JSON ですが、複雑な内容になってくるとこれは重要。）

動作させると、次のように Slack の指定したチャンネルへ通知が送られます。

<img width="400" alt="スクリーンショット_2019-12-10_0_59_43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35733/2532f5f0-e0f8-bd42-7412-ce51a5f3d6b5.png">

通知の内容をもっと見栄えよくするには [Attachments](https://api.slack.com/docs/message-attachments) 等を利用するとよいでしょう。









それでは！
Dockerでのバルス

Dockerでのbuildを繰り返ししまくって、わけわからなくなってきたときにこのコマンドを使うのでメモ。
※コメント頂き修正しました。@poad1010さんありがとうございます！

## Dockerでのバルス！

```
$ docker system prune -fa　　　　　　 　　　　　　# 全てのコンテナ、イメージ、ネットワークを削除
$ docker volume rm `docker volume ls -q`　　　 # volumeの削除
```

これ気持ち新たにbuildができます！
エラーコードを見ることは大事だと気付いた話

現在、visual studio codeにて、Home-brewのパッケージを作ろうとしてました。
ですが、エラーが出てしまいました。

```
Error: /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/bar.rb already exists
```

already exists の部分を自分で調べていれば、すぐに解決したことに気づきました
already exists = もう存在している　という意味です。
今回はメンターさんに聞いて、解決しましたが、今後エラーコードは、しっかりと調べようと思えた出来事でした。
v-slot:activator="{ on }"の仕組みの考察

:::note warn
本記事はVuetify.jsのv1.5.x系の記法について考察したものです。
内容の最新更新日は2019/12/10です。
:::

# 環境
Vuetify.js: v1.5.x

# はじめに
Vuetifyの[v-tooltip](https://v15.vuetifyjs.com/en/components/tooltips/)を使おうとして、公式ドキュメントのサンプルコードを目にしました。

```vuejs
    <v-tooltip bottom>
      <template v-slot:activator="{ on }">
        <span v-on="on">This text has a tooltip</span>
      </template>
      <span>Tooltip</span>
    </v-tooltip>
```
とりあえずコピペで使えますが、
「`v-slot:activator="{ on }"`は何なのか」「`v-on="on"`ってなにやってるの？？？」
という風に疑問を持ったので調べてみました。

# v-slot:activatorとは
まず、前半の`v-slot:activator`は**v-tooltipからactivatorというスロットを取得する**という意味でした。
もう一回[公式ドキュメント](https://v15.vuetifyjs.com/en/components/tooltips#api)を見てみましょう。
APIのところにPROPSとSLOTSがありますよね？（←今まで気づかなかった💦）

![v-tooltip API](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/12ef1151-9a56-9b9f-4f42-f4287b14eaef.png)
SLOTSにはactivatorとdefaultの二種類のスロットがありました。
そう、このactivatorが`v-slot:activator`のactivatorなんです。

`v-slot:activator`は名前付きスロットの書き方です。
`<template v-slot:activator="{ on }">`を`<template #activator="{ on }">`に略すこともできます。
ちなみに、v-slotはtemplateでしか使えません。


# #activator="{ on }"とは
activatorのヒントを掴んだところで、後半の`="{ on }"`の謎に迫っていきます。

鋭い方はお気づきかと思いますが、activatorのPropsには、こういう記述がありました。

```javascript
{
  on: { [eventName]: eventHandler }
  value: boolean
}
```
onだ！！！
onはスロットactivatorのプロパティなのです！

「でもそれって、`#activator="{ on }"`と何の繋がりがあるの？」
今度はVue.js公式のドキュメントから[v-slot](https://v2.ja.vuejs.org/v2/api/#v-slot)の記述を見てみます。
こんな書き方があったではないですか！
```vuejs
<!-- 分割代入でプロパティを受け取るデフォルトスロット -->
<mouse-position v-slot="{ x, y }">
  Mouse position: {{ x }}, {{ y }}
</mouse-position>
```
そう、`"{ on }"`は分割代入の書き方だったのです！
厳密的ではないですが、噛み砕くとこんな役割があります。
1. スロットactivatorから`プロパティon`を受け取る
1. 分割代入（`変数on`に`プロパティon`を代入）する
1. スロット内で`変数on`が利用可能になる

では、気になるonの中身は？
activatorの**イベントリスナー**でした。
SLOTS - activator - Descriptionを引用します。
> When used, will activate the component when clicked (or hover for specific components).

スロットactivatorはClickイベント（もしくはHoverイベント）に反応します。
v-tooltipだと、Hoverイベントが対象になると考えられます。（そのため、ポインターを重ねる時に反応する）
実際に入っているイベントリスナーを確認していないので、気になる方はご自身でお調べください。

# v-on="on"とは

`<template v-slot:activator="{ on }">`がやっていることが分かりました。今度は`<span v-on="on">`を見ていきます。

Vue.js公式のドキュメントの[v-on](https://jp.vuejs.org/v2/api/index.html#v-on)にこんな構文が書かれていました。
```vuejs
<!-- オブジェクト構文 (2.4.0+) -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
```

`v-on:[event]`／`@[event]`以外の書き方は初めて知りました。
どうやらオブジェクト構文を使用するとイベントの種類を指定しなくても、オブジェクトの中身で指定できます。
（そうすることによって複数のイベントハンドラーを一気に指定できます）

さて、これを踏まえて、もう一回振り返りましょう。
activatorのPropsのonの定義がこうなります。

```javascript
on: { [eventName]: eventHandler }
```
つまり`v-on="on"`は`v-on="{ [eventName]: eventHandler }"`で、上記のオブジェクト構文に当てはまります。

余談ですが、`@on`に省略できないか試してみましたが、
`v-on:on="eventHandler"`ではないので、当然エラーになります。

# 参考資料
[[Documentation] v-slot:activator="{ on }" #6866](https://github.com/vuetifyjs/vuetify/issues/6866#issuecomment-499709110)
このIssueがものすごく参考になりました！
おかげでモヤモヤ解消しました。

# さいごに
自分なりに解読して考察してみたんですが、
納得できる答えを出せたのはやはり上記のIssueのおかげだと思います。
しかし英語の解読力とフレームワークの構造自体に対する理解に自信がなくて、
自分なりの解釈でなんとか説明してみたものの、正確さが欠けている部分があると思います。
ご指摘、ご指導をいただけたら幸いです。
Android Studioで独自のGitサーバへGitする設定

GitHubとかの連携ではなくて、自前でGitサーバを構築している場合で、鍵認証を使っている場合の設定方法です。
# Step1：Gitを有効にする
まず、基本的なGitを有効化する方法は下記がとっても参考になります！
https://qiita.com/hkusu/items/45fc32a46efcb7d9a44a


# Step2：鍵ファイルを作成する
OpenSSHの鍵を用意する必要があります。Puttyはダメっぽいです。下記がとっても参考になります！
https://stackoverflow.com/questions/41563973/git-clone-key-load-public-invalid-format-permission-denied-publickey

ここでは「id_rsa_openssh.ppk」で秘密鍵を作成し、下記に保存します。
`C:\Users\Tetsuji Okuno\.ssh\`

# Step3：configファイルを用意する
Windows前提ですが、ログインしているアカウントのホームディレクトリにconfigファイルを作成します。
`C:\Users\Tetsuji Okuno\.ssh\config`


内容は下記を参考にしてください。

```
Host 192.168.6.60
HostName 192.168.6.60
Port	22
IdentityFile ~/.ssh/id_rsa_openssh.ppk
```

# Step4：Android Studioで設定する
最後にAndroid Stdioに適用するだけです！リモートリポジトリのURLは下記の様になります。
`ssh://hoge@192.168.6.60/fuga/git/gitpath.git`

![image.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24113/eee5cbd2-b87a-703b-c542-ae4207bdb0b9.jpeg)


Gitマスターなら当たり前のことだと思いますが、Step3がポイントです。
Maplat Coreでラインを地図上に表示する

何を書くか悩んだMaplat Advent Calendar 10日目ですが、Maplat Coreでラインを地図上に表示する方法にいたしました。
今日の動くものはここで確認できます。 => [CodeSandBox Maplat Advent Calendar day 10](https://codesandbox.io/s/maplat-advent-calendar-day-10-zj3pb)

どうせならば地図上に加えたラインが正確な地図と古地図上でどう違って見えるかが見えたほうがおもしろいので、地図切り替えがついている5日目のコードをベースにして、改造を加えていきます。
変更を加えるのは、JavaScriptファイルだけで大丈夫でしょう。

```app.js
import "@maplat/core/dist/maplat_core.css";
import { MaplatApp } from "@maplat/core";

var option = {
  appid: "maplat_ac_day10"
};

var app = new MaplatApp(option);
app.waitReady.then(function() {
  var ring = [
    [139.53184, 36.251013],
    [139.534322, 36.249581],
    [139.533853, 36.24814],
    [139.530729, 36.248649],
    [139.53184, 36.251013]
  ];
  app.addLine({
    lnglats: ring,
    stroke: {
      color: "#ffcc33",
      width: 2
    }
  });
  document.getElementById("gsi").addEventListener("click", function(e) {
    app.changeMap("gsi");
  });
  document.getElementById("osm").addEventListener("click", function(e) {
    app.changeMap("osm");
  });
  document.getElementById("ojo").addEventListener("click", function(e) {
    app.changeMap("tatebayashi_ojozu");
  });
  document.getElementById("aki").addEventListener("click", function(e) {
    app.changeMap("tatebayashi_castle_akimoto");
  });
});
```

5日目の切り替えボタン押し下げ時の処理部分の前に、線の定義と線を描画する処理を加えています。
`ring`変数に経緯度の羅列を設定し、それを`addLine`メソッドを使って、描画する線分の見た目なども`stroke`で指定しながら、描画しています。

実行した感じの見た目は、下のような感じになります。

![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10108/173cc050-251f-a445-b8f0-248ce76c45a8.gif)

明日は、この描画したラインの上に、バスを走らせてみましょう。
正規表現の記号一覧

## 正規表現の記号一覧

|記号|意味|
|:--|:--|
|&#124;|or|
|[]|range|
|^|not include|
|*|zero or more|
|?|zero or one|
|+|one or more|
|.|any one|
|^|leading|
|$|trailing|
|\\|backreference|
|{}|specific amount|
|\\s|space|

not includeの `^` は `[]` 内の全文字にかかります。
`*` `?` `+` は直前の文字にかかります。

## 例

```shell-session:全ての/を\/に置換する
sed 's/\//\\\//g'
```

```shell-session:カレントディレクトリのフルパスを削除する
sed -E "s/$(pwd|sed 's/\//\\\//g')\///"
```

ファイル名のフルパスからファイル名を抜き出すときに使います。

```shell-session:ダブルクォーテーション内の文字列を\1に抽出する
sed 's/^.*"\(.*\)".*$/\1/'
```

```shell-session:全ての4桁の数字の上2桁を削除する
sed 's/\([0-9][0-9]\)\([0-9][0-9]\)/\2/g'
```

## 参考リンク

- [Regex Crossword](https://regexcrossword.com/)
- [action-swiftlint/entrypoint.sh at master · norio-nomura/action-swiftlint](https://github.com/norio-nomura/action-swiftlint/blob/master/entrypoint.sh)
- [sedでダブルクォーテーションの中にある文字列を抽出する - Qiita](https://qiita.com/teru__san/items/fe89c4f37633b6841ce0)
- [sed | Linuxシェルスクリプト入門](http://shell.prognavi.com/sed/)
マンガでわかる Facade

![22AF0B0A-38AD-4FCD-A9F6-DF999F159297.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/59e0f9fd-b3bf-e2cd-986a-652190b4009c.png)

みんなそれぞれ得意な技術を持ったすごいエンジニアなんだけど、いっぺんに全員来るとわけがわからないですね。まずは上司のこみっとさんを通してからにしましょう。

複数のオブジェクトの連携でひとつの大きな問題に対処する必要があるとき、問題解決の責務を持つオブジェクトが各オブジェクトと直接関係を持ってしまうと、本当にやりたいことの知識と、誰に何を頼むのかのコントロールが混ざってしまいます。やはり関心の分離が重要です。

Facade 役のオブジェクトには、やりたいことの実現に応答できるプリミティブな語彙だけを設けます。問題そのものには踏み込みません。なるべく素朴に、複数の実機能オブジェクトのへ委譲コントロールし、連携の複雑さだけをラップします。

そうすると、問題そのものに調整が必要になっても、変更は Facade を使うオブジェクトにしか発生しません。Facade そのものには、問題解決の知識はないのですから。

また、実現機能の側に変更が必要になった場合は、コール側の変更をいっさいせずに、その内部の連携コントロールだけを変更すれば済むようになります。つまり、オブジェクト指向の基礎の基礎、カプセル化 = 抽象によって詳細が隠蔽されている、ということです。(abstract class を使うかどうかだけが抽象か否かを決めるわけではありません)

[Adapter](https://qiita.com/tanakahisateru/items/866f8938781984c98ef6) や [Decorator](https://qiita.com/tanakahisateru/items/d20be921079496c3aef5) パターンなどの、単一のオブジェクト関係に着目したものと異なり、Facade は複数のオブジェクトを集約するラッパークラスです。

ラッパークラスのメソッドが、つねにひとつの内部オブジェクトに 1:1 でマップされる場合、それがいくら矢面に立つ受付であっても、それは Adapter です。

(PHP のフレームワーク Laravel の機能に、デザインパターンとは無関係な Facade と名付けられたものがあります。前述の意味で、Facade パターンとは異なり、むしろデザインパターンでは Adapter なので注意してください)
｢Migrate to AndroidX｣をやってみたけれどハマってしまった(凡ミス)

# simple_permission(flutter)が、AndroidX対応されていなかっただけの話

自分のprojectを必死に`Refactor > Migrate to AndroidX...`
しかし、｢No Usages Found in the Project｣…。

![スクリーンショット 2019-12-10 12.13.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32839/147f1954-dad3-f3aa-a0e4-3cb949d37488.png)

｢なんでや!エラーが出てるのになんでMigrateされんのや!!｣って思ってハマってた。

エラーが出ちゃってる所はsimple_permissionの中でした…エラーちゃんと見れば、なんでもなかった!!

そしてpermission_handlerを使いました…simple_permission…ごめん…。
任意の点から円錐面までの最短距離を求める方法

### はじめに
「ある点から円錐面までの最短距離を求める方法」を検索しても特にまとめられていないようなので，解法をまとめました．
ひとまず，数学的な解法だけ載せますが，せっかくQiitaにあげるので後日PythonもしくはC++でのプログラム例も書こうと思っています．

## 問題
以下の円錐を使って考えます．
任意点A(X,Y,Z)から円錐表面までの最短距離を求めていきます．
円錐の中心軸と母線のなす角度は&phi;です．
![white1_3アートボード 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264475/b1f95869-7c5f-935d-2c2b-1df73bcabcea.png)

### Step 1
まず，点Aと円錐の中心Oを通る平面で，円錐を切ります．この平面をA-A'とします．
x軸と平面A-A'のなす角度を&theta;<sub>yaw</sub>とおきます．
これをxy平面に対して垂直方向から見ると，以下の図のようになります．

![white2アートボード 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264475/4b4de89d-c94f-48c3-a93f-16b0fb97ad81.png)

&theta;<sub>yaw</sub>は以下の式で表すことができます．
$$\theta_{yaw} = tan\frac{Y}{X} $$

### Step 2
A-A'平面で切った断面図は下図になります．
ここで，点Aから母線まで垂線を引き，その線と母線との交点を点Bとします．

![white3_2アートボード 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264475/ee54176f-7354-427d-ab75-be6ffa69d428.png)

OBの単位ベクトル$\frac{\vec{OB}}{|\vec{OB}|}$を${\bf b}$とします．

![white3_3アートボード 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264475/5595b1a7-1d97-0c49-c4ad-6edac927f3f1.png)

${\bf b}$は以下の式で表せます．

```math
{\bf b} =
\left( 
\begin{matrix}
sin\phi cos\theta_{yaw} \\
sin\phi sin\theta_{yaw} \\
cos\phi
\end{matrix}
\right)
```

図からわかるように，点Aと円錐の最短距離問題は，点Aと母線の最短距離問題に置き換えることができます．

### Step 3
最後はベクトルを使って解いていきます．
$\vec{OB}┻\vec{BA}$なので，
$${\bf b} \cdot \vec{BA} = 0 $$
ここで，

```math
\begin{eqnarray}
\vec{BA} &=& \vec{OA} - \vec{OB} \\
&=& \vec{OA} - t{\bf b} \ (tは媒介変数)
\end{eqnarray}
```

と表せます．
したがって，

```math
\begin{eqnarray}
{\bf b}\cdot \vec{BA} &=& {\bf b}\cdot (\vec{OA}-t{\bf b}) \\
&=& {\bf b}\cdot \vec{OA}-t = 0
\end{eqnarray}
```
となります．
$$\therefore t = {\bf b} \cdot \vec{OA}$$
よって，$\vec{BA}$は，$\vec{BA}=\vec{OA}-t{\bf b}$となり，その大きさが求める距離となります．
rbenv installがopensslで失敗する

2020-03-26追記: Ruby 2.3の場合を追加。

環境: macOS Catalina

結論から先に：環境変数RUBY_CONFIGURE_OPTSを足す。

rbenv installがopensslで失敗する。Homebrewで最新のopensslが入っているが、それを見に行かないもよう。

```
$ rbenv install 2.6.5
Downloading openssl-1.1.1d.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/1e3a91bc1f9dfce01af26026f856e064eab4c8ee0a8f457b5ae30b40b8b711f2
Installing openssl-1.1.1d...

BUILD FAILED (OS X 10.14.5 using ruby-build 20191205)

Inspect or clean up the working tree at /var/folders/d4/lpd3cnrd16l4z2ttkrnx168w0000gn/T/ruby-build.20191210115949.43308.JhVuyt
Results logged to /var/folders/d4/lpd3cnrd16l4z2ttkrnx168w0000gn/T/ruby-build.20191210115949.43308.log

Last 10 log lines:
      _s_server_main in s_server.o
  "_verify_stateless_cookie_callback", referenced from:
      _s_server_main in s_server.o
  "_wait_for_async", referenced from:
      _s_client_main in s_client.o
      _sv_body in s_server.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]: *** [apps/openssl] Error 1
make: *** [all] Error 2
```

.bash_profileを確認すると、次の環境変数があるが、それでも失敗。

```
export PATH="/usr/local/opt/openssl@1.1/bin:$PATH"

export LDFLAGS="-L/usr/local/opt/openssl@1.1/lib -L/usr/local/opt/readline/lib"
export CPPFLAGS="-I/usr/local/opt/openssl@1.1/include -I/usr/local/opt/readline/include"
export PKG_CONFIG_PATH="/usr/local/opt/openssl@1.1/lib/pkgconfig:/usr/local/opt/readline/lib/pkgconfig:/usr/local/opt/libxml2/lib/pkgconfig"
```

次の環境変数を足すと成功。

```
export RUBY_CONFIGURE_OPTS="--with-openssl-dir=/usr/local/opt/openssl@1.1"
```

参考: https://github.com/rbenv/ruby-build/issues/1353#issuecomment-537749304

## Ruby 2.3 の場合

Ruby 2.3の場合、OpenSSLの1.1ではなく、1.0が必要なもよう。ただし、2.3.8、2.3.7では成功するが、2.3.6以前では失敗する。

```
$ brew install rbenv/tap/openssl@1.0
$ export RUBY_CONFIGURE_OPTS="--with-openssl-dir=/usr/local/opt/openssl@1.0"
$ rbenv install 2.3.8
```

参考: https://github.com/rbenv/ruby-build/issues/1353#issuecomment-573414540


## 記録

- 2.3.6 (2017-12-14) 失敗 OpenSSL 1.0
- 2.3.7 (2018-03-28) 成功 OpenSSL 1.0
- 2.3.8 (2018-10-17) 成功 OpenSSL 1.0
- 2.4.2 (2017-09-14) 成功 OpenSSL 1.1
- 2.4.7 (2019-08-28) 成功 OpenSSL 1.1
- 2.4.8 (2019-10-01) 失敗 OpenSSL 1.1
- 2.4.9 (2019-10-02) 成功 OpenSSL 1.1
- 2.5.8 (2020-03-31) 成功 OpenSSL 1.1
- 2.6.6 (2020-03-31) 成功 OpenSSL 1.1