OmniAICreator/Qiita-1.07M huggingface dataset:
データの可視化シリーズ 第13弾 - 散布図を使って2つの数値データの関係を可視化する

# データの可視化シリーズ 第13弾 - 散布図を使って2つの数値データの関係を可視化する


こんにちは

Exploratoryの[白戸](https://exploratory.io/author/GMq1Qom5tS/notes)です。

[前回](https://qiita.com/takatoshiroto/items/45edec2aecd86e2e7c28)は、ヒートマップを使用してカテゴリーどうしを組み合わせて集計した数値を繰り返しごとにみていきました。

今回は２つの数値データが交わる位置にデータを点でプロットする散布図を可視化していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192148/2d9ee7ba-7ef8-d0e6-aec6-abaec75144e3.png)


# 使用データ

今回から従業員のデータを使用していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192148/dc9f74a1-e4fb-ad01-1fa4-38b4f8612a27.png)


このデータは各行が従業員ひとりひとりのステータスを表し、年齢や勤続年数や所属部署、そして月収などのデータがあります。

データのダウンロードは[こちら](https://exploratory.io/data/GMq1Qom5tS/HR-Employee-Data-ijP7NiA7Zs)から

データのインポート方法がわからない場合は、下記にある過去の記事を参照してください。

[Exploratoryを使ったデータの可視化シリーズ 第1弾 - はじめに](https://qiita.com/takatoshiroto/items/281f777ebc9945ecb0c6)



# データの可視化の目的

**目的**

* 年齢と月収の関係を知りたい
* 勤続年数と月収の関係を知りたい

**使用機能**

* 散布図


# 可視化


## 年齢と月収の関係

新しくチャートを作成し、チャートタイプに散布図を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192148/f46aa930-8336-c1b5-bb3c-e27b12d7578b.png)


X軸には**Age**を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192148/fd97e6d2-ff82-f65c-efa8-3bb0bd715b08.png)


Y軸には月収を表す**MonthlyIncome**を選択してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192148/5bbd8a58-61a8-e594-2004-8e6dc259b68f.png)


年齢と月収の関係性を表す散布図を作成することができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192148/ce99b7a9-3b85-51b9-3d7e-92a0a5a56ec3.png)


散布図は、X軸(年齢)とY軸(月収)の交わる位置にデータを点でプロットします。また、今回のデータは一行が一人の従業員のデータのため、一つの点が従業員一人のデータということになります。

この散布図を見ると、年齢が上がるにつれて月収も上がっているように見えます。

また、40歳までは月収が$10k以下の人が多いようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192148/5d9a77bc-9a5e-c313-f5f2-7ed65df213c3.png)


年齢と月収の関係性をみていきましたが、年齢が上がるからといって、月収が必ず上がるというわけではなさそうです。
次に、勤続年数と月収をみていきたいと思います。

## 勤続年数と月収の関係

先ほど作成したチャートのX軸を勤続年数を表す、TotalWorkingYearsに変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192148/d3ed82c8-b826-25c6-7cf0-c60cfc3a611f.png)


勤続年数と月収の散布図を作成することができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192148/e41dc5db-086e-b6a6-68ef-45eb82036274.png)


勤続年数が20年を超えたあたりから、月収が$10k以下の人が少なくなり、月収の水準がかなり高いことが読み取れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192148/49a1325b-9401-3d75-9468-72855b930aa8.png)


2つの散布図を可視化してきましたが、勤続年数の方が、年齢よりも月収に影響がありそうです。


# まとめ

今回は散布図を使用して、２つの数値データに対応する位置にデータを点でプロットして可視化していきました。

散布図は2つの数値データのばらつきをみたい時に便利なチャートです。

今回は年齢と月収、勤続年数と月収の2つの散布図をみてきましたが、相関関係はあるのか気になるところです。
そのため、次回は散布図にトレンドラインを引くことで、相関をみていきたいと思います。

* [データの可視化シリーズ 第14弾 - 散布図とトレンドラインを使って相関を可視化する](https://qiita.com/takatoshiroto/items/039fc4568b45892bbde3)

-----

# Exploratoryデータ・アカデミー

データの可視化、またはデータ分析に関してもっと知りたい、学びたいという方は、私達が提供しているトレーニングやセミナーに参加してみてください。

[こちら](https://ja.exploratory.io/data-academy-jp?utm_campaign=chart_intro_13&utm_medium=blog&utm_source=qiita)のExploratoryデータ・アカデミーのページに詳細情報があります。

データを使ってより良い意思決定を行っていきたいと言う方は、ぜひこの機会に参加をご検討ください！
【Java】APIのレスポンスで日付型のJSONに"T"が含まれてしまう

JavaでWeb APIを作ったとき、レスポンスにおいてLocalDateTime型などの日付型が

```
2019-01-01T01:00:00
```
のようになってしまう場合の解決方法

# 解決方法
- シリアライズのアダプタを作成
- レスポンスのモデルがあるパッケージにpackage-info.javaを作成し、作成したアダプタを読み込む

## JAXBでの例
アダプタを作成

```LocalDateAdapter.java
package api.adapters;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class LocalDateAdapter extends XmlAdapter<String, LocalDate> {
	@Override
	public LocalDate unmarshal(String s) throws Exception {

		if (s == null) {
			return null;
		}
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
		LocalDate dateTime = LocalDate.parse(s, formatter);
		return dateTime;
	}

	@Override
	public String marshal(LocalDate d) throws Exception {
		if (d == null) {
			return null;
		}
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
		String formattedDateTime = d.format(formatter);
		return formattedDateTime;
	}
}
```

```LocalDateTimeAdapter.java
package api.adapters;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class LocalDateTimeAdapter extends XmlAdapter<String, LocalDateTime> {
	@Override
	public LocalDateTime unmarshal(String s) throws Exception {

		if (s == null) {
			return null;
		}
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		LocalDateTime dateTime = LocalDateTime.parse(s, formatter);
		return dateTime;
	}

	@Override
	public String marshal(LocalDateTime d) throws Exception {
		if (d == null) {
			return null;
		}
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		String formattedDateTime = d.format(formatter);
		return formattedDateTime;
	}
}
```

package-infoで読み込む

```package-info.java
//アダプタをアノテーションで付与
@XmlJavaTypeAdapters(value = { @XmlJavaTypeAdapter(value = LocalDateTimeAdapter.class, type = java.time.LocalDateTime.class),
@XmlJavaTypeAdapter(value = LocalDateAdapter.class, type = java.time.LocalDate.class) })
package api.model.response;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;

// アダプタをインポート
import api.adapters.LocalDateAdapter;
import api.adapters.LocalDateTimeAdapter;
```
Vue-RouterをVue-CLI3で使った。

Vue-CLI3でvue-routerを使いました。
おおよそこんな感じです。

```router.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import List from './views/List.vue'
import Detail from './views/Detail.vue'
import NotFound from './views/NotFound.vue'
Vue.use(Router)

let router = new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home,
    },
    {
      path: '/list/*',
      name: 'list',
      component: List,
    },
    {
      path: '/detail/*',
      component: Detail,
    },
    {
      path: '*',
      component: NotFound,
    },
  ],
  scrollBehavior () {
    return { x: 0, y: 0 }
  },
});

export default router;
```

コンポーネントは上にまとめた方が分かりやすい。

```router.js
import Home from './views/Home.vue'
import List from './views/List.vue'
import Detail from './views/Detail.vue'
import NotFound from './views/NotFound.vue'
```

SEO的にhistoryモードは必須。

```router.js
mode: 'history',
```

スクロールされたままで困るので、scrollBehaviorもほぼ必須。

```router.js
scrollBehavior () {
  return { x: 0, y: 0 }
},
```

普通は下のように書くのだけど
`routes:` にエンドポイントの配列を機械的に追加できるんじゃないかとか。
いろいろためしながら追加してたので、分かれてます。

```router.js
let router = new Router({（・・・省略・・・）}}
export default router;
　↓↓
export default new Router({（・・・省略・・・）});
```
DjangoのキャッシュバックエンドをRedisにする

## はじめに
筆者自身が、NoSQL、cacheの知識が乏しいため、この記事の対象者は以下のような方を想定しています。

- windowsユーザー
- NoSQL初学者
- キャッシュ初学者
- Djnagoプロジェクトを作成済みで、キャッシュを使いたい方 

この記事のメインは、Djangoのキャッシュバックエンドで、Redisを使うことなので、
~~Redisのインストールは完了している前提です。~~
Redisのインストールについては、ほぼすっ飛ばします！

## Redisのインストール
#### 1．windows向けのRedisのmsiファイルをダウンロードする。
https://github.com/microsoftarchive/redis/releases/tag/win-3.0.504 から
「Redis-x64-3.0.504.msi」をダウンロードして、起動する。

#### 2．インストーラが起動したら、どんどんNext。
インストーラの内容は普通のインストーラと同じです。笑

- 規約同意 
- インストール先ディレクトリ<br/>
　　→**環境変数にpathを追加のチェックボックスがあるので、チェックを付けておくことのが無難。**
- 何番ポートを使用するか<br/>
　　→デフォルトは「6379」。ファイアーウォールの規則に追加するかのチェックボックスがあるので、
     個別で設定したくない場合は、チェックを入れることを推奨する。

#### 3．一応インストール完了確認。
コマンドプロンプトを立ち上げて、以下のように入力し、Enterを押下する。

```
 > redis-cli.exe
```

その後、プロンプトが以下のようになれば、インストール完了。

```
 127.0.0.1:6379> 
```

## django-redisをインストールする
#### 1．pipでdjango-redisをインストールする。

```
 > pip install django-redis　
```

#### 2．djangoプロジェクトのsettings.pyにcacheの設定を追加する。
settings.pyに以下の記述を追加する。

```python:settings.py
  CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://localhost:6379/',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient'
        }
    }
  }
```

*参考までに、デフォルトのCASHESの設定はこちら

```python:django.conf.global_settings.py
  CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
    }
  }
```

#### 3．今回は、テンプレートの一部をキャッシュする。
現在時刻をキャッシュするのがわかりやすかったので、現在時刻をキャッシュして確認する。
参考：[キャッシュを使う](https://www.gesource.jp/programming/python/django/020.html)

```html:test.html
{% load cache %}
  <h2>こっちはキャッシュせず</h2>
  <span>{{ now }}</span>
{% cache 240 now_cache%}
  <h2>ここはキャッシュする</h2>
  <span>{{ now }}</span>
{% endcache %}
```

↓表示画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250217/a96990ea-9584-0178-d366-94315ddf83b6.png)

ちなみに、redis-cliで参照すると、
htmlがエスケープされて文字列として格納されていることが確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250217/8177f2d5-39b9-e8c8-a0c6-0101166ead71.png)

キャッシュできる範囲はview単位や、サイト単位などさまざまなので、
参考サイトの「[キャッシュを使う](https://www.gesource.jp/programming/python/django/020.html)」を参考にしてほしい。

## さいごに
　RDBばかり使っていたせいで、Redisの値の格納の仕方に違和感を感じてしまう。
　データベース名は？テーブル名は？となるが、そこがKVS(Key Value Store)の特徴といえよう。
　柔軟な使用が見込めそう。
　
　○謎の宣言
　　**ページのキャッシュなどを活用して、レスポンスの早いwebページの作成を心掛けたい。**

## 参考サイト
- [33分4秒で理解できるDjangoアプリのキャッシュ実装 - LT対策と賞味期限という話](https://shinyorke.hatenablog.com/entry/django-cache)

- [django-redisを使う](https://riptutorial.com/ja/django/example/14226/django-redis%E3%82%92%E4%BD%BF%E3%81%86)

- [キャッシュを使う](https://www.gesource.jp/programming/python/django/020.html)
Vue.jsとThree.jsでwebカメラアプリ作った

#経緯
- バイト先ではjqueryでバリバリ書いているので、もっとモダンな開発をしたくなった。
- どうせならおしゃれにwebGLしたい　→　Three.js

#学習に使ったもの
- [Vue.js & Nuxt.js超入門](https://www.amazon.co.jp/Vue-js-Nuxt-js%E8%B6%85%E5%85%A5%E9%96%80-%E6%8E%8C%E7%94%B0%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798056596/ref=pd_lpo_sbs_14_img_1/355-4453951-3730560?_encoding=UTF8&psc=1&refRID=WRMM2W72VMV74ZF9RF9D)
- [Three.js examples](https://threejs.org/examples/)
- Three.js使ってもアッツアツにならないぐらいのPC

#結果
- こんな[webアプリ](https://diedreigroschenoper.cfbx.jp/camerasample/#/)が出来ました。
- 以下、アプリの説明です。

#ぼやっとした内部構造
![プレゼンテーション1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303906/49a6399f-c5b3-0779-336c-298e98392308.jpeg)

#役に立つかわからない技術tips
###Vueの中でThree.jsを書くには...
1. Three.jsの[コアパッケージ](https://www.npmjs.com/package/three)をnpmとかyarnとかでwork directryにインストール。
2. Three.jsのサブパッケージはインストールできるものもあるが、現状githubから必要なものだけ持ってきてファイル内最上部でコアパッケージをimportするのがいいかも。（フルインストール出来たら楽なのに...）
3. 使う変数はdata()内でconst宣言しておくのがよい。
4. 映像を扱う関係上、バグるとPCがフリーズ＆アツアツになり死ぬので、出来るだけ最小のモジュール単位でデバッグする（当たり前）。
5. シェーダ書き換える必要がある場合もあるので、[veda](https://atom.io/packages/veda)でも使って動くコードに直すといいんじゃないかな。

#まとめ
- Vueはいいぞ（あまり恩恵を受けていない気はするが）
- Three.jsもいいぞ（むずいけど）
- 雑魚スマホで見ると固まったりするので、Nuxt.js使ってSSRで書き直すのもいいかも。
- UI/UXもっと勉強します。（[誰のためのデザイン？](https://www.amazon.co.jp/%E8%AA%B0%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3-%E2%80%95%E8%AA%8D%E7%9F%A5%E7%A7%91%E5%AD%A6%E8%80%85%E3%81%AE%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E5%8E%9F%E8%AB%96-%E6%96%B0%E6%9B%9C%E7%A4%BE%E8%AA%8D%E7%9F%A5%E7%A7%91%E5%AD%A6%E9%81%B8%E6%9B%B8-%E3%83%89%E3%83%8A%E3%83%AB%E3%83%89%E3%83%BB-%E3%83%8E%E3%83%BC%E3%83%9E%E3%83%B3/dp/478850362X/ref=cm_cr_arp_d_product_top?ie=UTF8)読みました。）
SwiftUI で ボタンクリック　Helloworld

```swift:ContentView.swift

import SwiftUI

struct ContentView : View {
    
    @State var totalClicked: Int = 0
    
    var body: some View {
        VStack {
            Text("\(totalClicked)").font(.title)
            Spacer()
            Button(action: {self.totalClicked = self.totalClicked + 1}) {
                Text("Increment Total")
            }.padding(.all)
        }.padding(.all, 40)
    }
}

#if DEBUG
struct ContentView_Previews : PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif
```

Github https://github.com/maeganjwilson/totalClicked_tut/tree/master/button-push
Amazone linux にwgetでinstallしたcertbot-auto が動かなくなったときの対応（2019年版）

この記事は下記記事をもとに、2019年版を作成させて頂きました。感謝。
https://qiita.com/hogehoge-banana/items/0f8285c5dcccab3f11bc

# なにがおきたの？

Amazone linux にwgetでinstallしたcertbot-auto が、SSL証明書発行時に走るアップデートで、以下のエラーが発生しました。

```
# certbot-auto certonly --webroot -w /srv/letsencrypt/example.com/ -d example.com -m info@example.com --agree-tos
Upgrading certbot-auto 0.34.2 to 0.35.0...
Replacing certbot-auto...
Creating virtual environment...
Installing Python packages...
Installation succeeded.
Traceback (most recent call last):
  File "/opt/eff.org/certbot/venv/bin/letsencrypt", line 7, in <module>
    from certbot.main import main
  File "/opt/eff.org/certbot/venv/local/lib/python2.7/dist-packages/certbot/main.py", line 10, in <module>
    import josepy as jose
  File "/opt/eff.org/certbot/venv/local/lib/python2.7/dist-packages/josepy/__init__.py", line 44, in <module>
    from josepy.interfaces import JSONDeSerializable
  File "/opt/eff.org/certbot/venv/local/lib/python2.7/dist-packages/josepy/interfaces.py", line 8, in <module>
    from josepy import errors, util
  File "/opt/eff.org/certbot/venv/local/lib/python2.7/dist-packages/josepy/util.py", line 4, in <module>
    import OpenSSL
  File "/opt/eff.org/certbot/venv/local/lib/python2.7/dist-packages/OpenSSL/__init__.py", line 8, in <module>
    from OpenSSL import crypto, SSL
  File "/opt/eff.org/certbot/venv/local/lib/python2.7/dist-packages/OpenSSL/crypto.py", line 12, in <module>
    from cryptography import x509
ImportError: No module named cryptography
```

# 要約

cryptographyも必要だけど、`pip install cryptography`でインストールできなかったため、
pipでcertbotインストールする。

# 環境

```
$ cat /etc/system-release
Amazon Linux AMI release 2018.03
```

wgetで `/usr/bin/` に `certbot-auto` をインストールしてました


# やったこと

```
# rm -rf /opt/eff.org/*
# pip install -U certbot
# certbot renew --debug
```
https://github.com/certbot/certbot/issues/1680#issuecomment-358728515
上記より引用

`certbot-auto`コマンドはエラーのままなので、削除しておく。
この`certbot`コマンドは、Amazone linux特有の `--debug` フラグすら不要で動作しました。ここらへんの動きはわからず。もし判る方いらっしゃったら、教えてくれると嬉しい限りです。

# [補足] `pip install cryptography`でインストールできなかった

```
# python -V
Python 2.7.16

# which pip
/usr/bin/pip

# pip install cryptography
Requirement already satisfied: cryptography in /usr/local/lib64/python2.7/site-packages
Requirement already satisfied: cffi!=1.11.3,>=1.8 in /usr/local/lib64/python2.7/site-packages (from cryptography)
Requirement already satisfied: six>=1.4.1 in /usr/local/lib/python2.7/site-packages (from cryptography)
Requirement already satisfied: ipaddress; python_version < "3" in /usr/local/lib/python2.7/site-packages (from cryptography)
Requirement already satisfied: asn1crypto>=0.21.0 in /usr/local/lib/python2.7/site-packages (from cryptography)
Requirement already satisfied: enum34; python_version < "3" in /usr/local/lib/python2.7/site-packages (from cryptography)
Requirement already satisfied: pycparser in /usr/local/lib/python2.7/site-packages (from cffi!=1.11.3,>=1.8->cryptography)
```
Angular 4.0+のモーダルウィンドウ外を押してもクローズにならない実装

## 対象
・Angularの4系以上
・Angular Material使用

## 背景
Angular Materialのモーダルウィンドウのデフォルト設定では、モーダルウィンドウ以外の範囲をクリックするとクローズします。（モーダルウィンドウ以外の範囲をクリックすると、ウィンドウが閉じてしまいます。）
このデフォルト設定によって、ユーザーが意図しない動作を発動しやすくなるため、ウィンドウが閉じないように実装する必要がありました。

## 実装
```typescript:app.component.ts

import { Component } from '@angular/core';
import { MatDialog } from '@angular/material';
import { DialogComponent } from './dialog/dialog.component';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.scss' ]
})
export class AppComponent  {
  constructor(
    public dialog: MatDialog
  ){}

  openDialog(){
   const dialogRef = this.dialog.open(DialogComponent, {
     width: '300px',
     height: '200px',
     disableClose: true//これによってモーダルウィンドウ範囲外のところをクリックしても閉じない
   });
  }
}

```

デモ→
https://stackblitz.com/edit/angular-doclj4?file=src%2Fapp%2Fapp.component.ts
Liberty on Docker(ubuntu)

[websphere-liberty](https://hub.docker.com/_/websphere-liberty)を日本語化してみた。
Dockerfileを以下としました。

```Docker:Dockerfile
FROM websphere-liberty:springBoot2
USER root
RUN apt-get update \
    && apt-get -y install language-pack-ja tzdata \
    && update-locale LANG=ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
RUN cp /etc/localtime /etc/localtime.org && \
    ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

USER 1001
```
最初、apt-getする際、rootにしなかったのでエラーになった。websphere-libertyはユーザdefault(idは1001)で動くよう作られているんですね。サイズの差は以下の通りです。

```
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
liberty             jp                  b79a2f7f929b        48 seconds ago      384MB
websphere-liberty   kernel              8dadc89b1b46        7 days ago          290MB
```
動かすとこんな感じです。

```
IBM J9 VM バージョン 8.0.5.41 - pxa6480sr5fp41-20190919_01(SR5 FP41) (ja_JP) で、defaultServer (WebSphere Application Server 19.0.0.10/wlp-1.0.33.cl191020191002-0300) を起動しています
[AUDIT   ] CWWKE0001I: サーバー defaultServer が起動されました。
[AUDIT   ] CWWKE0100I: この製品は、開発使用向け、および限定的な実動使用向けにライセンスが交付されています。 全ライセンス条項は以下で表示可能です: https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/wasdev/license/base_ilan/ilan/19.0.0.10/lafiles/ja.html
[AUDIT   ] CWWKG0093A: 構成ドロップイン・リソースを処理中です: /opt/ibm/wlp/usr/servers/defaultServer/configDropins/defaults/keystore.xml
[AUDIT   ] CWWKZ0058I: アプリケーションの dropins をモニター中です。
[AUDIT   ] CWWKF0012I: サーバーは次のフィーチャーをインストールしました。[el-3.0, jsp-2.3, servlet-4.0, springBoot-2.0, ssl-1.0, transportSecurity-1.0, websocket-1.1]。
[AUDIT   ] CWWKF0011I: defaultServer サーバーは、Smarter Planet に対応する準備ができました。defaultServer サーバーは 13.215 秒で始動しました。
[AUDIT   ] CWPKI0803A: SSL 証明書の作成に 9.014 秒かかりました。 SSL 鍵ファイル: /opt/ibm/wlp/output/defaultServer/resources/security/key.p12
```

ベースをkernelからspringBoot2に変更しました。springBootも色々試したいなぁ。
##不満な部分
ベースOSがubuntu 16.04と古いこと。
本体のLibertyリリースとdockerのリリース時期がずれていること。
cf. 11/14現在、ベースOSはubuntu 16.04のままで、Liberty-19.0.0.10がlatestです。
3年ぶりに同じことをやってみた。springBoot2は変わらんやんけー。websphere-liberty:kernelだと22.0.0.6でした。最新は22.0.0.7ですが、、
##変更履歴
(2019/7/24)versionを明記していたのを廃止。JSTに変更するのを一緒に行うこととした。
(2019/9/27)Libertyのバージョンアップ対応。タイムゾーン設定を追加。
(2019/9/28)環境変数「DEBCONF_NOWARNINGS」の指定を削除。1MBほどサイズが大きくなるようですが、、
(2019/9/29)kernelからspringBoot2に変更。
(2019/11/14)libertyのバージョンを19.0.0.10に変更。
(2022/7/13)3年ぶりの状況に更新。
PHP で GET, POST のどちらからでもパラメーターを受け取る

GET, POST のどちらでパラメーター渡されても楽に受け取りたい
## 方法
```php
function fetch_param($param)
{
    return $_SERVER['REQUEST_METHOD'] === 'GET'
        ? filter_input(INPUT_GET, $param)
        : filter_input(INPUT_POST, $param);
}
```

## やってること
PHP のスーパーグローバル変数である `$_REQUEST['REQUEST_METHOD']` を用いると、いまアクセスされている httpメソッドが`GET` なのか `POST` なのか確認できるので、それに応じて `filter_input()` の第一引数を変更する。

もうちょっとスマートな方法がありそうな気はしますね。
Docker環境ゴミ掃除3選

Docker使ってると気づいたらディスクがいっぱいになってたことありませんか？

私はあります。
そのたびに要らなくなったイメージを探して、消して、使ってないボリューム探して、消して、とかやってたのですが、つらくなってきたのでゴミ掃除的なコマンドを使うようになりました（ `docker system prune` とかね）。

でも、実はこのコマンドだけじゃ全てのゴミを掃除できません。
Docker環境には他にも色んなゴミが眠ってて、ある程度ヘビーに使おうとすると他の方法も組み合わせて使う必要があります。
ただし、消してはいけないデータも意図せず消してしまう危険もあるので、状況に応じて適切な方法でゴミ掃除しましょう。

本記事の読者として、以下のような方を想定しています。

- Dockerを使ったことがある
- イメージやコンテナなどの用語をとりあえず知っている

# Dockerの資材

Dockerコンテナ周りの主な資材は以下があり、それぞれ使わなくなるとゴミができます。

| 資材 | ゴミの例 |
| :--- | :----------- |
| イメージ | もう使わなくなったコンテナのイメージや古いイメージなど。 |
| コンテナ | もう使わなくなって停止したコンテナなど。 |
| ボリューム | コンテナが停止/削除されてアンマウントされたボリュームなど。 |
| ネットワーク | もう使わなくなったネットワークなど。 |

図にすると以下のような感じです。

![qiita_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432518/e3795854-e811-5712-d6d7-5a1c50aa3e5f.png)

大事な点として、アプリエラーで停止しちゃったけど調査のために残しておきたいコンテナとか、
アンマウントしたけど運用データが入っているため残しておきたいボリュームなど、
運用によってゴミではないものもあります。

そのため、どのゴミ掃除コマンドでどこまで掃除されるか、をきちんと理解して使用する必要があります。

# ゴミ掃除コマンド

dockerのコマンドでpruneオプションが使えるものがいくつかあり、それらをゴミ掃除コマンドと呼んでいます。

いろいろありますが、基本的には以下があれば私は大丈夫だと思います。

- 【コマンド1】 docker system prune [-f]
- 【コマンド2】 docker image prune -a [-f]
- 【コマンド3】 docker volume prune [-f]

# シチュエーション

以下に、シチュエーションごとに使うとよいゴミ掃除コマンドを紹介します。
ただし、停止状態のコンテナも消えるため、コンテナでエラーが発生して停止したコンテナを調査する場合などは実行してはいけません。

## a. コンテナ置き換えのあと

とりあえず以下のコマンドを順番に打っとけば大丈夫です。
`-f` を付けると確認なしで実行されます。

- 【コマンド1】 docker system prune [-f]
- 【コマンド2】 docker image prune -a [-f]

これを実行すると以下が削除されます。

- すべての未使用コンテナ(停止状態など)
- すべての未使用ネットワーク(どのコンテナにも接続されていないものなど)
- どのコンテナのベースにもなっていないすべてのイメージ

([docker system prune](https://docs.docker.com/v17.09/engine/reference/commandline/system_prune/)の`Extended description` や [docker image prune](https://docs.docker.com/engine/reference/commandline/image_prune/)の`Extended description` を参照)

![qiita_image_a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432518/6b6f8db9-ca00-df59-488f-c92f0d61da20.png)

ボリュームは削除されないので運用データが消える心配はありません。
使っていないコンテナとかネットワークは、使う時にまた作ればいいので大丈夫。

アプリのバージョンアップなどでイメージが更新されたら、
新イメージでコンテナを作り直します。
すると、旧イメージが残るため、`docker image prune` で消しています。

## b. サービスを停止してDocker上の全ての資材を削除するとき

[a. コンテナ置き換えのあと]のコマンドの後に、`docker volume prune`も実行するとよいです。

- 【コマンド1】 docker system prune [-f]
- 【コマンド2】 docker image prune -a [-f]
- 【コマンド3】 docker volume prune [-f]

これを実行すると以下が削除されます。

- すべての未使用コンテナ(停止状態など)
- すべての未使用ネットワーク(どのコンテナにも接続されていないものなど)
- どのコンテナのベースにもなっていないすべてのイメージ
- マウントされていないすべてのボリューム

([docker volume prune](https://docs.docker.com/engine/reference/commandline/volume_prune/)の`Extended description` を参照)

![qiita_image_b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432518/4846bb24-98c4-a63e-3a07-04b6cf1dc22c.png)



サービス停止時は、ボリュームに入った運用データも不要になります（どこかにバックアップはするかもしれませんが）。
したがって、コンテナ停止削除後、`docker volume prune` でボリュームも削除しています。

以上！
GlassFishでデフォルトポート以外にデプロイしようとするとエラーになる場合の対処法

JenkinsでGlassFishにデプロイしようとすると、エラーとなってしまった。

```
/usr/local/glassfish5/bin/asadmin --user admin --passwordfile /tmp/password-admin.txt  redeploy --name=test /tmp/test.war
```

エラーログ

```
SSH: EXEC: connected
Deprecated syntax, instead use:
asadmin --user admin --passwordfile /tmp/password-admin.txt redeploy [options] ...
No such local command: redeploy.  Unable to access the server to execute the command remotely.  Verify the server is available. 
Command redeploy failed.
Remote server does not listen for requests on [localhost:4848]. Is the server up?
SSH: EXEC: completed after 1,412 ms
SSH: Disconnecting configuration [test] ...
ERROR: Exception when publishing, exception message [Exec exit status not zero. Status [1]]
Build step 'Send build artifacts over SSH' changed build result to UNSTABLE
Finished: UNSTABLE
```

どうやら、asadmin redeployコマンドの実行に失敗しているらしい。

## 原因
asadminコマンドはポートを指定しない場合、デフォルトで 4848 と通信するらしい
https://docs.oracle.com/cd/E18930_01/html/821-2433/asadmin-1m.html

## 解決方法
asadminコマンドのオプションでportが指定できるので、このオプションでポートを指定する。

```
/usr/local/glassfish5/bin/asadmin --port 4849 --user admin --passwordfile /tmp/password-admin.txt  redeploy --name=test /tmp/test.war
```
Zabbix vs. Cloudwatch

#はじめに
AWSのサービスを監視する方法として、「Zabbix」か「Cloudwatch」かを検討する機会があったため、比較メモとしてこの記事を投稿します。
「Zabbix」で監視可能なサービス（EC2、ECS）をメインに比較してみました。
#全体
||Zabbix|Cloudwatch|
|:---|:---|:--|
|形態|OSS|サービス|
|料金|タダ|課金あり|
|監視可能なサービス|EC2, ECS|色々※|
|ダッシュボード|〇|〇|
|マネージャー管理<br>手動スケーリングなど|必要|不要|
※[Cloudwatchで監視できるサービス](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/aws-services-cloudwatch-metrics.html)

#EC2
||Zabbix|Cloudwatch(※エージェントなし)|Cloudwatch(※エージェント利用)|
|:---|:---|:---|:--|
|メトリクスの種類|多※1|少|多※2|
|ログ監視|任意のファイル|×|任意のファイル|
|トリガー・アラーム|〇|△|△|

※1 [Zabbixのメトリクス](https://www.zabbix.com/documentation/4.0/manual/config/items/itemtypes/zabbix_agent)
※2 [EC2 Cloudwatchのメトリクス](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/aws-services-cloudwatch-metrics.html)

ログ監視について補足です。

ファイル名指定は、ZabbixはWebコンソールからファイル名指定で監視できますが、CloudwatchではEC2インスタンス側で出力するログファイルを指定します。
また、文字列パターン等を設定してのアラーム発行はZabbix,Cloudwatchともに可能ですが、Cloudwatchでは対象のログが表示されないというデメリットがあります。

#ECS(Fargate)
||Zabbix|Cloudwatch|
|:---|:---|:--|
|メトリクスの種類|多|少※|
|ログ監視|任意のファイル|標準出力、標準エラーのみ|
|サービス監視|×|〇|
|タスク監視|〇|×|
|コンテナ監視|×|×|
|トリガー・アラーム|〇|〇|

※[ECS Cloudwatchのメトリクス](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/cloudwatch-metrics.html)

コンテナ監視をしたい場合、
EC2起動タイプのタスクであれば、[cAdvisor](https://github.com/google/cadvisor)を利用できます。
Fargateでのコンテナ監視はおそらく不可能…

#まとめ
EC2、ECSでログメインの監視をするのであれば、Webコンソールだけで操作が完結するZabbixを使うと良いでしょう。
Cloudwatchでは、障害時に原因のログが表示されないので使い勝手の点で劣ると思います。

それ以外のサービスも合わせて監視したいのであれば、Cloudwatchを選ぶことになります。
Zabbixには、任意スクリプトのリターン値をメトリクスとして取得できる機能があるので
AWS APIを駆使すれば、EC2、ECS以外のサービスも含めてZabbixで監視も可能です。
Vue-gtmを使う

# 注意：@gtm-support/vue-gtm が最新です。
下記は2019年頃のやり方です。

# Vue-CLI 3でGTMを入れる
プラグインがあった。
https://www.npmjs.com/package/vue-gtm

# どこに書くのか
自分の場合はvue-routerを使うのでそこに書いておきました。

```router.js
import VueGtm from 'vue-gtm'
```

開発用サーバーのアクセスが混ざらないように、分けておきます。
GTMのタグは開発用と、本番用の２つ用意した方が良いです。

```router.js
if(location.hostname != 'www.example.com'){
  Vue.use(VueGtm, {
    id: 'GTM-▲▲▲▲',//開発用
    enabled: true, 
    debug: true,
    // vueRouter: router,
    ignoredViews: ['']
  });
}else{
  Vue.use(VueGtm, {
    id: 'GTM-●●●●',//本番環境
    enabled: true,
    debug: true,
    // vueRouter: router,
    ignoredViews: ['']
  });
}
```
「vueRouter: router」が（私の場合）うまくうごかないように思ったので
コメントアウトしてます。GTM側のトリガーで対応しました。
家族共有のノートPCでPythonはじめてみた

お小遣いが寂しいので、副業プログラマーとしてPythonをはじめようと思う。

【わいスペック】
　43歳　男性　会社員　メタボ　ピエール瀧似（ノンドーピング）
　20年ほど前に、仕事でHTML、PostgreSQL、PHP、Linuxを触った経験あり
　その後、PCに詳しい営業として日々を過ごす。
　既婚　恐妻家　

【よめスペック】
　年上　女性　事務のパート　たまに可愛い
　Word Excelは使えるらしい
　御朱印集めと酒が趣味
　PCの調子が悪くなると不機嫌

【環境】
　ノートPC　1台　（Lavie：Win10Home　64bit）
　wi‐fiでつながっている

【要件】
　Pythonの開発がある程度できる
　妻が怖いのでPCが重くなるのは勘弁。

【試行錯誤（環境編）】
　１　無知なため、何もせずPython(Win10版）をダウンロード
　　　→　pip install で躓く。

　２　dockerで仮想環境を作成。Ubuntu・pythonをダウンロード
　　　→　PCが重くなる予兆が発生。よめにバレたらアウトなので、断念する。

　３　Win10にAnacondaをインストール
　　　→　今のところは無事に作動。

 【結論】
　Win10ならAnacondaを導入するのが一番手早い！
ActiveRecordを例にORMの内部を探った話

# 『なんか簡単にDB操作してくれる』くらいのイメージから脱却しようとするお話。
mysqlのクエリをしっかり把握しながらActiveRecordを利用している案件を通じてDB関係の知識を入れていっている中で、ActiveRecordもなんかよく分からないけど、こう書いておけばOK、くらいの身につき方からそろそろおさらばしようといことで書きます。

## そもORMとは何故生まれるに至ったのか？
　Object Relational Mapping、通称、ORM(O\Rマッパー)です。このライブラリの役割は、RDBとオブジェクト指向言語の橋渡しです。なぜ、橋渡しが必要なのかというと、rubyというのはオブジェクト指向言語であり、オブジェクト指向のパラダイムは、ソフトウェア工学に基づいていますが、DBのリレーショナル技術は数学の原則に基づいているので技術的な根幹部分の設計思想が全く違うのです。（それぞれどんな設計思想なのか具体的なところはここでは割愛します。）そして、このような差異は**インピーダンスミスマッチ**と呼ばれています。このインピーダンスミスマッチによって、各々の技術の連携はシームレスに行うことはできない、つまり何かしらのハブを用意しなければ連携ができないということです。以上の理由から、O\Rマッパーは誕生することになったのです。

### ORMのシステム論理階層における位置付け
ORMがやってくれていることは、システム論理層の中のパーシステンス層（別名データソース層）と呼ばれるデータストアに格納されるデータの永続化を行ってくれる階層部分の役割を担っているようです。インピーダンスミスマッチの解消はもちろん、ORMによってやってくれることは様々になってきます。今回取り上げるActiveRecordは、データアクセスロジックやドメインロジックを含んでいるのでドメイン層も含んでいるようです。

## それではActiveRecordではどんなことをやってくれているか？

- インピーダンスミスマッチの解消
- モデルとデータ型の関連性を明示的にする
- モデル同士のリレーションを明示的にする
- dbへの書き込み前のチェック（バリデーション）

##　仕様（rubyコードにおけるどこがSQLのどこに対応させれているか）
Modelのクラス名がそのままDBのテーブル名と直結するが、そのテーブル名は、Modelのクラス名の複数形になる。そして、作成されるマイグレーションファイル内に定義された中身がカラム名と直結する。作られたModelのオブジェクトが、１レコードになる。

## ActiveRecordのメソッドがどんなクエリを発行しているのか。
触ったものは随時追記していきたいと思います。

#### find
idでの検索オンリーで、そこからデータを取得できる。クエリの処理結果としてのオブジェクトを返す。

```stand.rb
Stand.find(2)

#発行されるクエリ
==> select `stands`.* from `stands` where `stands`.`id` = 100 limit 1
```

#### where
指定した条件に合致するレコードを取得する。クエリを実行する前の検索クエリを返す。これはActiveRecord::Relationと呼ばれている。

```stand.rb
Stand.where(name: 'The World')

# 発行されるクエリ
===> select `stands`.* `stands` from `stands` where `stands`.`name` = 'The World'
```

#### find_by
条件に合致したレコードを１つ取得する。クエリの処理結果としてのオブジェクトを返す。

```stand.rb
Stand.find_by(name: Star Platinum)

#発行されるクエリ
===> select `stands`.* from `stands` where `users`.`id` = 'Star Platinum' limit 1
```

#### pluck
特定のカラムのリストを配列にして返す。つまり、クエリは実行済み。

```stand.rb
Stand.pluck(:id)

#発行されるクエリ
===> select `stands`.`id` from `stands`
```

#### order
指定した条件にカラムを並べ替えます。クエリを実行する前の検索クエリを返す。これはActiveRecord::Relationと呼ばれている。

```stand.rb
Stand.order(:created_at)

#発行されるクエリ
===> select `stands`.* from `stands` order by `stands`.`created_at` asc
``` 

#### 技術用語じゃないんだぞ、私
一番最初にAtiveRecordという名前を聞いた時はDB関係だったので、私は勝手に技術用語だと思ってました。
Webアプリケーションに様々なフレームワークがあり、Vには様々なテンプレートエンジンがあるように、Mにも様々なORMがあるということですね。ORMはライブラリで、ActiveRecordはORMライブラリの一種。いわゆる所の固有名詞。
こういう恥も戒めとして記しておきます。

## 参考文献
[オブジェクト関係マッピング](https://qiita.com/yk-nakamura/items/acd071f16cda844579b9)
[今だからデータアクセスを真剣に考える！](http://otndnld.oracle.co.jp/columns/arai-semi/data_access/2/#o_r)
[O\Rマッピングツールに対する誤解をときたい](https://blog.jnito.com/entry/20100528/1274998429)
[RailsのActiveRecord](https://qiita.com/ogomr/items/1c5844b82daebd0580c2)
[Active Recordの色々なメソッドの返り値](https://qiita.com/komakomako/items/ee266241dd8003a75cb9)
[【Rails5】Active Record のクエリ
](http://cloudcafe.tech/?p=2444)
ログを gzip で圧縮しているなら zstd を導入しよう

## はじめに

zstd コマンド(zstdless, zstdcat, unzstd なども)は gzip にも対応しています。特にデコードは拡張子を見て自動で gzip と zstd を切り替えてくれるので、 gzip 圧縮されたログと zstd 圧縮されたログが混在している環境でも透過的に扱うことができます。

なので gzip から zstd への切り替えは次のように段階的に進めることができます。

1. zstd コマンドツール群のインストール
2. 圧縮されたログを扱うときに zstd を使い始める
3. 圧縮フォーマットを zstd に切り替える


## 性能比較

Debian 9.3 で gzip 1.6 (aptでインストールしたもの) と zstd (1.4.0) を比べてみます。

対象となるファイルは ltsv でゴチャゴチャとアプリの情報を混ぜた重めの apache のアクセスログです。 (5,367,216,897 bytes)


### 圧縮

| 圧縮方法 | 圧縮後サイズ (byte) | 圧縮後サイズ/圧縮前サイズ (%) | 時間 (sec) |
|---------|------------|--------|------|
| gzip | 705635144 | 13.1% | 83 |
| zstd --format=gzip -6 | 700917700 | 13.1% | 75 |
| zstd -T4 | 597267814 | 11.1% | 7.2 |

圧縮形式がgzipのままでも、zstdコマンドを使うことで10%ほど高速化できます。

圧縮方式をzstdにして4スレッドで圧縮すれば、圧縮率を改善しながら10倍以上高速に圧縮することができます。


### 伸長

| 伸長方法 | 時間 (sec) |
|---|---|
| gzファイルをgunzip | 25.1 |
| gzファイルをunzstd | 14.4 |
| zstdファイルをunzstd | 4.5 |

圧縮形式がgzipのままでも、zstdコマンドを使うことで40%ほど高速化できます。
なので圧縮形式を切り替えなくても、調査等のために何度も gunzip するのであれば zstd コマンドをインストールしておいて損はないはずです。

そして圧縮形式を zstd に切り替えた時は、 gunzip 比で5倍以上、 zunstd を使って gzip を伸長するのに比べても3倍以上の高速化ができます。
Vue-Routerのページビュー（GTMを使う）

# 注意：ユニバーサルアナリティクスの時代に書きました

GoogleはVue-routerの遷移をページビューにカウントしないと思う（2019年06月07日現在）
いろいろなやり方があると思うんですけど、GTMが一番デバッグしやすいと思います。
 
# Google Tag Manager
アカウントを発行してもらい、ログインしてください。
https://tagmanager.google.com/

# トリガー
リンクのクリックURLに対して設定する
![trigger.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216132/d4b772e6-33b2-d135-233f-1dd015036475.png)

# タグ
タグはページビューを渡す
![tag.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216132/9557bbed-8a49-340a-6598-ee8cac7610a7.png)

# GTMをプレビューモードにする
プレビューモードにした状態でサイトを見る
![スクリーンショット 2019-06-07 16.31.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216132/5abea22a-df0b-5a08-43f1-f4674610fc88.png)

# サイトのTagManagerを見る
画面にツールが現れるので、ちゃんと動いてるか見る
![スクリーンショット 2019-06-07 16.31.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216132/34bd05b1-08e4-de3c-a072-4cf8a5c06efb.png)

Vue-Routerのリンククリックで１ページビューが渡せる。と思います。
もっと良い方法があれば教えて欲しいです。
REDASH7でクエリが実行出来ない問題の解消

REDASH6からREDASH7へ移行しました。
無事にアップデート出来たと思ったのですが、クエリー作成画面で「Execute」をクリックしたのですが
何も結果が表示されない問題が発生しました。
解消方法までの手順を纏めました。

## Dockerのログを確認
Dockerのログを確認します。
コンテナのログは以下のコマンドで表示出来ます。

```
# docker ps
CONTAINER ID        IMAGE                        COMMAND                  CREATED             STATUS              PORTS                         NAMES
9e306be1ae43        redash/nginx:latest          "nginx -g 'daemon of…"   6 hours ago         Up 6 hours          0.0.0.0:80->80/tcp, 443/tcp   redash_nginx_1
56ede752534b        redash/redash:7.0.0.b18042   "/app/bin/docker-ent…"   6 hours ago         Up 6 hours          0.0.0.0:5000->5000/tcp        redash_server_1
613adc931afc        redis:3.0-alpine             "docker-entrypoint.s…"   6 hours ago         Up 6 hours          6379/tcp                      redash_redis_1
198297742e8c        redash/redash:7.0.0.b18042   "/app/bin/docker-ent…"   6 hours ago         Up 6 hours          5000/tcp                      redash_worker_1
207215d21524        postgres:9.5.6-alpine        "docker-entrypoint.s…"   6 hours ago         Up 6 hours          5432/tcp                      redash_postgres_1
```
workerコンテナで実行されているはずなのでworkerコンテナのログを確認します。

```
# docker logs redash_worker_1
```

「Execute」でSQL実行時に「InvalidToken」の文字列が出力されている事を発見。

どうやらdocker-compose.ymlのworker設定に「REDASH_COOKIE_SECRET」が入っていない事が原因の模様。
workerの設定に以下を追加し、コンテナ再起動。

```xml:docker-compose.yml
    REDASH_COOKIE_SECRET: veryverysecret
```

```
# docker-compose -f docker-compose.yml down
```

```
# docker-compose -f docker-compose.yml up -d
```

これで無事解消されました。
Goスタック模索メモ

# HTTP Server

## Router

gorilla/mux: A powerful URL router and dispatcher for golang.
https://github.com/gorilla/mux

定番。薄い。

go-chi/chi: lightweight, idiomatic and composable router for building Go HTTP services
https://github.com/go-chi/chi

薄い。gorilla/muxよりAPIが直感的。

## JSON Request

小さいので自前で書く人が多いっぽい

以下などに薄い実装

render/decoder.go at master · go-chi/render
https://github.com/go-chi/render/blob/master/decoder.go

## Render

unrolled/render: Go package for easily rendering JSON, XML, binary data, and HTML templates responses.
https://github.com/unrolled/render

人気っぽい

# Job Queue

RichardKnop/machinery: Machinery is an asynchronous task queue/job queue based on distributed message passing.
https://github.com/RichardKnop/machinery

Broker、ストアそれぞれのバックエンドがいろいろ対応してる（ex. AMQP, Redis, SQS, GCP Pub/Sub, Memcache, MongoDB）
DelayもRetryも対応してる

gocraft/work: Process background jobs in Go
https://github.com/gocraft/work

Redisバックエンド。Delayも対応してる。

# RDBMS

jinzhu/gorm: The fantastic ORM library for Golang, aims to be developer friendly
https://github.com/jinzhu/gorm

人気。ORM。

go-gorp/gorp: Go Relational Persistence - an ORM-ish library for Go
https://github.com/go-gorp/gorp

人気。Select文は自分でSQL書いてstructへのマッピングはやってくれる。
クエリをコントロールしたい場合によさそう。

# Development

oxequa/realize: Realize is the #1 Golang Task Runner which enhance your workflow by automating the most common tasks and using the best performing Golang live reloading.
https://github.com/oxequa/realize

ホットリロード
go mod使ってる & cmdディレクトリにmainがあるときに相対モジュールが解決できないエラーが起きる（条件は合っていないかも）が、以下にある設定で一応解決する。

Realize が Go 1.11 の Modules で使えない - Qiita
https://qiita.com/enta0701/items/0d0592abb18a333b3268

# その他

rakyll/statik: Embed files into a Go executable
https://github.com/rakyll/statik
Selenium＋Chrome75で全てのオプションが効かない

表題の件ですが、何故直るのかいまいちはっきりしてませんけど、動かせたので共有しておきます。

参考になったのは[ここ](https://bugs.chromium.org/p/chromium/issues/detail?id=971227&can=1&q=webdriver&colspec=ID%20Pri%20M%20Stars%20ReleaseBlock%20Component%20Status%20Owner%20Summary%20OS%20Modified)です。

> The issue is that Chromedriver 75 now defaults to the webdriver w3c specification compliant mode. W3C does not support browser logs, so neither does the selenium class. You can set w3c to false, or downgrade to chrome 74, but as far as I know there are not plans to add this functionality back in the near future.


「selenium classもサポートしていません」というのがどういう意味なのかはっきりしませんが、こいつのせいでオプションが効いてないようです。


以下のコードを試したら動きました。

```rb
Capybara.register_driver "headless_ios11".to_sym do |app|
  Capybara::Selenium::Driver.new(app, browser: :chrome,
    desired_capabilities: Selenium::WebDriver::Remote::Capabilities.chrome(
      chromeOptions: {
        args: ["--headless", "window-size=375,667", "--incognito", "--user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_1 like Mac OS X) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0 Mobile/15C153 Safari/604.1"],
        w3c: false
      }
    )
  )
end
```

chromeOptionsに`w3c: false`を渡すと渡したオプションが有効になります。困っている人いたら試してみてください。
""で囲まれた文字列にあるスペースを＊に変換する

ポイント：preg_replace_callbackを利用する

変換前文字列："aaa bbb" ccc ddd "eee"
変換後文字列："aaa*bbb" ccc ddd "eee"

```php:sample
php > print(preg_replace_callback('/".+?"/', function ($matches) {return str_replace(' ', '*', $matches[0]);}, '"aaa bbb" ccc ddd "eee"'));
"aaa*bbb" ccc ddd "eee"
```
Ginzaでエラーが出たらランタイムを再起動(Colaboratory)

リクルートと国立国語研究所が共同で日本語の自然言語処理(NLP)ライブラリ「GiNZA」を出しましたが、GoogleColaboratoryで使おうとするとエラーが出たので、同じ状況に陥った人のために解決法を。

## インストールからのエラー
GiNZAを以下でインストールします。

```py:GiNZAインストール
!pip install "https://github.com/megagonlabs/ginza/releases/download/v1.0.2/ja_ginza_nopn-1.0.2.tgz" 
```

以下のようにコンソールから使う場合は問題なく処理できます

```
python -m spacy.lang.ja_ginza.cli
```

が、次のようにPythonで使おうとするとエラーが出ます。

```py:エラー！
import spacy
nlp = spacy.load('ja_ginza_nopn')
doc = nlp('これじゃエラーが出ちゃう。')
for sent in doc.sents:
    for token in sent:
        print(token.i, token.orth_, token.lemma_, token.pos_, token.dep_, token.head.i)
```

## ランタイムを再起動する
GiNZAをインストールしたあと、ランタイムを再起動。これで私の場合は解決しました。
理由はわかりません。知っている方がいらっしゃれば、ご教授いただければ幸いです。
Vue-CLI 3  背景画像の「@」が変換されない

# Webpack 3~4 の話

# @はsrc/のエイリアスになっている、
`vue.config.js` デフォルトはそういう設定になっているので使ってると、
たまに変換されない時があって困る。

```
select {
        background-image: url('@/assets/img/image.svg');
        }
```

↓できた

```
select {
        background-image: url('~@/assets/img/image.svg');
        }
```

In order to resolve an alias (@), as you are using, it is mandatory webpack handles the request as a module request. Using the prefix ~ enforces webpack treat the request as a module request, similar to require('some-module/image.svg').


あなたのような使い方のエイリアス（@）を解決するためには、
webpackがリクエストをモジュールリクエストとして扱う必要があります。

接頭辞 ~ を使用するとwebpackはrequire
（'some-module / image.svg'）のように
リクエストをモジュールリクエストとして扱います。



# 古い時代のハックです。


参考リンク：
https://stackoverflow.com/questions/51812496/vue-cli-3-use-background-image-in-style-tag
LINE botのリッチメニューを一括削除するシェルスクリプト

LINE botのリッチメニューをAPI経由でいろいろ設定していたら、公式ページにこんなことが↓

> 1つのLINE公式アカウントに対して、Messaging APIを使って最大1000件のリッチメニューを作成できますが、この上限を超過すると、ステータスコード400 Bad Requestが返されます。その場合は、新しいリッチメニューを作成する前にリッチメニューを削除する必要があります。 [リッチメニューを使う](https://developers.line.biz/ja/docs/messaging-api/using-rich-menus/)

一括で削除できたり、既存のリッチメニューを更新するAPIはみたところなかったので一括削除スクリプトをつくりました。(需要ないと思うけど一応公開)

```shell
# 変数の設定
ACCESS_TOKEN=...

# 一覧取得
existsMenus=$(
    curl -v -X GET https://api.line.me/v2/bot/richmenu/list \
        -H "Authorization: Bearer ${ACCESS_TOKEN}"
)
existsMenus=$(echo $existsMenus | jq ".richmenus")
existsMenusLen=$(echo $existsMenus | jq length)

# 1つずつ削除する
for i in $( seq 0 $(($existsMenusLen - 1)) ); do
    menu=$(echo $existsMenus | jq .[$i])
    menuId=$(echo $menu | jq ".richMenuId")
    menuId=$(echo ${menuId} | sed 's/"//g')

    curl -v -X DELETE https://api.line.me/v2/bot/richmenu/${menuId} \
        -H "Authorization: Bearer ${ACCESS_TOKEN}"
done
```

ちなみにJSONをあつかうので`jq`コマンドが使える必要があります。(Macなら`brew install jq`)


~~おしり~~おわり
IEでformタグ内にtemplateタグを使う方法

# 概要
IEは\<template\>に対応していないため，\<form\>内に\<input\>を持つような\<template\>を配置してしまうと\<template\>内まで送信されてしまうことを回避する方法を紹介します．

# 状況

```html
<form>
    <input type="text" id="input1">
    <template>
        <input type="text" id="input[_new]">
    </template>
</form>
```

この場合，IEでは\<template\>以下の\<input type="text" id="input[_new]"\>まで送信されてしまいます．

# 回避方法
templateタグにdisabled属性を与える．

### 理由
IEでは，親タグがdisabled属性を持つと，disabled属性が子のタグまで伝搬する仕様を利用した手法です．
例えば

```html
<div>
    <input type="text" value="input1">
    <input type="text" value="input2" disabled>
</div>
<div disabled>
    <input type="text" value="input3">
    <input type="text" value="input4" disabled>
</div> 
```

のようなHTMLを書くと，Chromeなどでは

![input_chrome.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431996/c0633c62-ccad-31a5-9479-e69aabf755af.png)

と，自身のdisabled属性の有無で判定されますが，IEでは

![input_IE.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431996/b25d9caf-48ab-2c1b-e8c0-9dcb3a7e3413.png)

と，親タグのdisabled属性が伝搬してしまいます．したがって\<template\>にdisabled属性を与えれば，\<template\>以下の要素はすべて送信されなくなります．

# まとめ
IEでも動く\<form\>内に\<template\>を置く方法を紹介しました．
この方法を用いると，\<input\>にrequired属性を加えていても動作するようになります．
しかし，この方法はIEの特殊な仕様を用いているため，注意が必要です．
そもそもIEが\<template\>に対応していればよいのですが...
[Python] 日本の現在時刻を取得する

pytzとdatetimeを使用して、日本の現在時刻を取得します。
#pytzのインストール
まず、pytzライブラリをインストールします。


```
pip install putz
```

#日本の現在時刻を取得する

```python
from datetime import datetime
from pytz import timezone

now = datetime.now(timezone('Asia/Tokyo'))
print(now)
```

上記のコードを実行すると、以下のように日本の現在時刻が取得できます！
`2019-06-01 14:30:30.736103+09:00`

#任意の時刻情報を文字列で取得したい時
strftime()メソッドを使うことで、下記のように、任意の時刻情報を文字列で取得することができます。

```python
from datetime import datetime
from pytz import timezone

now = datetime.now(timezone('Asia/Tokyo')).strftime("%m%d %H:%M")
print(now)
```

上記では現在の月、日、時間、分を取得しています。以下のように取得できます！
`0606 21:32`
Redmine > Redmine のチケット更新が遅いとき



メール送信がボトルネックになっている場合がある。


config/configuration.yml の 「delivery_method: :smtp」を 「delivery_method: :async_smtp」に変



#### Windowsの場合

（redmine-3.4.3）
C:\Bitnami\redmine-3.4.3-1\apps\redmine\htdocs\config\configuration.yml


#### linuxの場合
/usr/share/redmine/config/configuration.yml


#### 対応

smtp → async_smtpに変更する。

```yaml:configuration.yml
default:
  email_delivery:
    delivery_method: :smtp
    　　　　　　　　　↓
    delivery_method: :async_smtp
```
C#製APIから取得したJSONのKeyを大文字で揃えるには

.net core C#でwebAPIを作っているときに, GETしてきたjsonのkeyが大文字小文字入り乱れていて困った。

#取得したjson
C#側でこんな感じの構造のデータをDBから取得するAPIを作成した

```
public class DISK_CONFIG_INFO
{
    [Key, Required]
    public string SERIAL_NO { get; set; }
    public string DISK_NAME { get; set; }
    public string MOUNT_POS { get; set; }
    public decimal? MAX_VOLUME { get; set; }
    public decimal? ROTATE { get; set; }
    public DateTime? INS_DATE { get; set; }
    public DateTime? UPD_DATE { get; set; }
}
```
これを実際にGETしてみるとこうなってしまった

```
{
    "Serial_no": "13J0DKSGS",
    "Disk_name": "TOSHIBA DT01ACA300",
    "Mount_pos": "/mnt/sdb",
    "Max_volume": 2793,
    "Rotate": 7200,
    "Ins_date": "2019-04-02T17:02:11",
    "Upd_date": "2019-04-03T15:30:03"
}
```

何故かjsonのkeyが全て大文字始まりの小文字になっている…

#修正方法
結論として, startup.csの中でAddMvc()している箇所でjsonのシリアライズの設定をしてあげればよい

```startup.cs
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
  //省略
  services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
  //省略
}
```

これを

```startup.cs
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
  //省略
  services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
                   .AddJsonOptions(opt =>
                  {
                    opt.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();
                  });
  //省略
}
```
こうしてあげる。

#結果
再度同じGETメソッドを呼んで見る

```
{
    "SERIAL_NO": "13J0DKSGS",
    "DISK_NAME": "TOSHIBA DT01ACA300",
    "MOUNT_POS": "/mnt/sdb",
    "MAX_VOLUME": 2793,
    "ROTATE": 7200,
    "INS_DATE": "2019-04-02T17:02:11",
    "UPD_DATE": "2019-04-03T15:30:03"
}
```

これで大丈夫そうです。
MacにRedisをインストールする

### homebrewでredisをインストールする
```
brew install redis
```

### 起動する
```
redis-server /usr/local/etc/redis.conf
```

### CLIに接続する
```
redis-cli
```

### CLIで値をset

```
1127.0.0.1:6379> set key1 val1
OK
```

### CLIで値をget
```
127.0.0.1:6379> get key1
"val1"
```
小さいミスこそ仕事で必要

#ミスをする事に怯えていませんか？
失敗をすること自体はネガティブでストレスになります。
耐性がある方ですと、解決に向け頭を切り替えられますがそれが中々難しいです。。

今回は、意識するだけでも効果があるのではないかと思い共有します！

##トラブルでも動じない為に必要な事

①冷静に状況を理解し
②客観的に状況を整理・把握し
③取るべき行動を判断・選択する

これは感情を考慮しないでの話なので、実際トラブルでの耐性を
つけるにはどうしたらいいかというと。。

#『小さなトラブル（失敗）を若いうちからたくさん経験する事です』

当然の事で申し訳ないですが、これに尽きるかと思います。

***人生は長い旅路になるので、早くから沢山の失敗や
トラブルを経験すれば人生単位では
ミスが減る、ということにつながる訳です。***

私はチームでマネジメントをしているのですが、あまり余分なアドバイスを
しなかったり具体的なことを敢えて言わず経験させる事があります。

理由としては、小さな失敗から学んで経験してもらいたいという意図があります。

リーダーがメンバーの失敗を怖がると、
メンバーも失敗を怖がる連鎖が起きると思います。

#まとめ
自分で考え行動し、小さな失敗を積み重ねましょう！
失敗は怖いものですが、新しい経験が出来ると考え前向きに考えましょう！
Docker初心者が学ぶならこの順番が分かりやすかった

## はじめに
この記事の内容は以下の方向けです。
・Dockerって何？って人
・学び始めたけどいまいちピンってこない人

あくまでも学習の**取っ掛かりに過ぎない**と思ってください。
それ以外の人にはあまり有益な情報は無いと思いますので、
**回れ右をして私より有能なエンジニア**の記事を探してください。

## 結論
**コンテナ、Docker Compose、Docker Fileの順で学ぶのが分かりやすい！！**

## なぜそうなったのか
資料は探してみたけどDockerの成り立ちとか概念とかばっかり...
そういうものは最終的に書き方のリファレンスなって理解が進まない...
自分はそんなのが知りたいわけじゃない...
といった私の経験から出た結論が

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276998/2a7a3efb-116b-23bb-a1be-5c2b355db4fc.png)

というわけで**重要点**です。
・**コンテナ**
・**Docker Compose**
・**Docker File**

私は上記の3点がDockerを理解するうえで最低限なポイントと感じました。
そしてこの順序で学習していくと今までこんがらがっていたところがするすると紐解けました。

***
以下は上記の重要点をまとめたものとなります。
学習の参考資料としてお使いください。

## コンテナ
OSSであるDocker上で動く環境一つの単位です。
基本はOS、ミドルウェア、アプリケーションで構成された環境のことを指します。

**コンテナのイメージ**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276998/9515792e-48b8-3fa6-cdf5-ee62b6a8aafe.png)

そして、このコンテナをDocker Engine上に複数配置して環境を構築します。

**Dockerによる環境構築のイメージ**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276998/b48054d8-4563-9cdb-9755-165fd795096f.png)

## Docker Compose
Dockerの初期学習をした方の中にはこういった経験をした人はありませんでしたか？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276998/71cff42d-507c-0738-9aee-3eac660fc8e5.png)

これは非常に**めんどくさい！！**
できればボタン一つ、コマンド一つで環境の立ち上げや終了をしてほしいと思うのがエンジニアの心情だと思います。

そこで登場するのが**Docker Compose**です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276998/1afb8f55-282f-ab97-4789-024e87990bb5.png)

Docker Composeはymlファイルという定義ファイルを記述しコマンドを実行すると定義ファイルに書かれた内容（複数のコンテナの作成や作成時の環境変数など）を人の代わりにやってくれる優れものなのです。

## Docker File

Docker FileとはDockerイメージを作るため情報を記載したファイルです。
※Dockerイメージとはコンテナを作る際のレシピみたいなものです。
　コンテナはDockerイメージを元に作成されます。

**DockerFileとコンテナの関係性**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276998/3c36ed4b-b876-721d-f46a-4668df75e73b.png)


既存のDocker Imageにカスタマイズを施すために使用することが主たる使用方法です。
例えば、公開されているLinux系OSのDocker Imageをベースにほかのパッケージやアプリを入れたオリジナルの環境を作る時などに使用します。

## まとめ
今までの開発環境のセッティングが石器時代に感じるぐらい
簡単に環境がセッティングできる素晴らしさ知ったらもう手放せませんね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276998/c8f4c385-1ecb-b7bb-c738-7da2a07ffb72.png)
rangeからリストへの変換

rangeで生成したものはイテラブルなオブジェクトだけどリストじゃない。

~~~Python
>>> range(3)
range(0, 3)
~~~

リストに変換するためによく見るのは以下。

~~~Python
>>> list(range(3))
[0, 1, 2]
~~~

以前、以下が等価なことを教えていただいた。

~~~Python
>>> A = [1,2,3]
>>> list(A)
[1, 2, 3]
>>> [*A]
[1, 2, 3]
~~~

つまりrange(イテレーター)をリストに変換するときも、

~~~Python
>>> [*range(3)]
[0, 1, 2]
~~~

と書ける。  

可読性的にどうなんだろうと思うので、使いどきを選ぶかもしれない。
AppStoreConnectアップロード時、'UIApplicationExitsOnSuspend'の警告が出る件

## 概要

AppStoreConnectアップロード時、iOS13で`UIApplicationExitsOnSuspend`のサポートがなくなるので、非推奨だよというメッセージが出るようになりました。

```
WARING ITEMS-90339 "Deprecated info.plist" Key. The Info.plist contains a key 'UIApplicationExitsOnSuspend' in bundle myapp [myapp.app] that will soon be sunsupported.
```

[ iOS13のリリースノート iOS & iPadOS 13 Beta Release Notes \| Apple Developer Documentation](https://developer.apple.com/documentation/ios_ipados_release_notes/ios_ipados_13_beta_release_notes)

## 問題

`UIApplicationExitsOnSuspend`はアプリのバックグラウンド実行を禁止する機能ですが、デフォルトだとNOだと思うので、大体のアプリは消せばOK。

>Deprecations
The UIApplicationExitsOnSuspend key is no longer supported in iOS & iPadOS 13. Update your apps to handle modern multitasking. (43958234)
※リリースノートから引用

「バックグラウンド実行を無効化出来なくなるのでマルチタスク処理をしていない人はやってね」と言われているので、無効化設定している人はバックグラウンド処理を改修する必要がありますね。

## 解決方法
Waringが出るだけで、アップロード自体は出来るが、警告出てるのも気持ち悪いし、リジェクトされたら嫌なので対応しました。

### 暫定対応
とりあえず、info.plistから`Application does not run in background`の項目をDeleteすればOK。

### 恒久対応
Unityからは現状、自動的に追加されてしまうので、ビルドスクリプト(PostProcessBuildなど)を用いて`UIApplicationExitsOnSuspend`を削除するのが良さそう。フォーラムにサンプルコードが投稿されています。

[Unityフォーラムページ The Info.plist contains a key 'UIApplicationExitsOnSuspend](https://forum.unity.com/threads/the-info-plist-contains-a-key-uiapplicationexitsonsuspend.689200/)

#### 2019/6/25 追記
~~TRACKERが作成されています。現在アルファでレビュー中。
https://issuetracker.unity3d.com/issues/ios-apps-with-uiapplicationexitsonsuspend-in-info-dot-plist-failing-to-pass-apple-store-validation~~
⇨2019.2から実装されました。
EC-CUBE4でuser_dataを変更する

ページ管理で、新規ページを作成すると、/user_data配下にコンテンツが生成されます。
この`user_data`は、任意の値に変更することが可能です。

.envに、`ECCUBE_USER_DATA_ROUTE`パラメータのコメントアウトを外し、任意の値に変更します。


```bash:[ec-cubeのインストールディレクトリ]/.env

#ECCUBE_LOCALE=ja
#ECCUBE_TIMEZONE=Asia/Tokyo
#ECCUBE_CURRENCY=JPY
#ECCUBE_ADMIN_ROUTE=admin
ECCUBE_USER_DATA_ROUTE=contents # user_dataをcontentsに変更
#ECCUBE_ADMIN_ALLOW_HOSTS=[]
#ECCUBE_FORCE_SSL=false
#ECCUBE_TEMPLATE_CODE=default
#ECCUBE_AUTH_MAGIC=<change.me>
#ECCUBE_COOKIE_NAME=eccube
#ECCUBE_COOKIE_PATH=/
#ECCUBE_COOKIE_LIFETIME=0
#ECCUBE_GC_MAXLIFETIME=1440
```
この例では、`contents`に変更してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72858/0ee3a5fa-886d-bf1e-81a1-11252a461865.png)

ページ管理にアクセスしてみると、`contents`が反映されているのがわかります。

`user_data`の変更方法は以上です。

※もし反映されない場合は、キャッシュを削除してみてください。
Magic Leap MagicScript Typings settings.

**Prepare**
magic-script-cli v2.2.1
https://www.npmjs.com/package/magic-script-cli

magic-script-typings v1.4.0
https://www.npmjs.com/package/magic-script-typings

**Create Project**

```sh
magic-script init
? What is the name of your application? my typ
? What is the app ID of your application? org.magicscript.typ
? In which folder do you want to save this project? my-typ
? Do you want a Landscape App? Yes
cd my-typ
```

**Before**
![Capture_000001.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19029/1f420d04-e772-24e4-cb8d-e6ccffe9a401.jpeg)
**build**

```sh
magic-script build
```

**After**
![Capture_000002.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19029/8420c354-ad0b-0ceb-aaee-052ab5171777.jpeg)

Reference

magic-script-typings (Github)
https://github.com/magic-script/magic-script-typings

magicscript
https://www.magicscript.org/

Thanks!