OmniAICreator/Qiita-1.07M huggingface dataset:
ky を Deno から使う

Deno (ディーノ) <img src="https://raw.githubusercontent.com/kt3k/drafts/master/assets/deno.png" width="20"> Advent Calendar 21日目の記事です.

今日は [ky][] というライブラリを Deno から使う話です.

# [ky][] とは

<img src="https://raw.githubusercontent.com/kt3k/drafts/master/assets/ky-in-deno/ky.png" width="300" />

[ky][] は HTTP client ライブラリです. HTTP client というと [axios](https://github.com/axios/axios) が有名ですが, Deno は XHR (XMLHttpRequest) オブジェクトを持たないため axios を使うことは出来ません. XHR ベースではなく fetch ベースの手軽な HTTP Client が ky です.

Deno から ky を使うには以下のように使います.

```js
import ky from 'https://deno.land/x/ky/index.js';

const parsed = await ky.post('https://postman-echo.com/post', { json: { foo: true } }).json();

console.log(JSON.stringify(parsed, null, 2));
// => JSON output
```

(`deno eval "上のコード"` で実行できます.)

上の ky の例と同じ内容のリクエストを fetch で実行すると以下のようになります.

```js
class HTTPError extends Error {}

const response = await fetch('https://example.com', {
  method: 'POST',
  body: JSON.stringify({ foo: true }),
  headers: {
    'content-type': 'application/json'
  }
});

if (!response.ok) {
  throw new HTTPError('Fetch error:', response.statusText);
}

const parsed = await response.json();

console.log(JSON.stringify(parsed, null, 2));
// => JSON output
```

promise を2回 await している点 (HTTP ヘッダーが帰ってきた時点と, レスポンス全体が帰ってきた時点で分けて promise を待っています) や, body が JSON であることを明示的に設定している点などが煩雑ですね. このような煩雑さを回避して, JSON を送って JSON を受け取るリクエストを自然に実行できる所に ky の手軽さがあります.

## ts で使う場合の注意点

現在 ky はまだ ts に対応できていません. ts から使う場合は import した ky を一旦 any にキャストするか, 各自で適切に型付けする必要があります.

# ky の Deno サポート

ky の Deno サポートはオフィシャルなものです. [date-fns のケース](https://qiita.com/kt3k/private/4ed644e7a1359ab2552e)と同様に Deno サポートをすることにほとんど労力はかけられていません. ky は Web 標準の fetch に依存していますが, Deno の fetch も Web 標準に準拠しているため, ky がそのまま Deno で動いたのでした.

# Recap

今日は ky を Deno から使う方法を紹介しました. 明日は @nana4gonta さんの記事です.

[ky]: https://github.com/sindresorhus/ky
LogisticRegressionのsolverはデフォルト値がlbfgsに変わったので注意

## はじめに

scikit-learnライブラリの[ロジスティック回帰](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html)（LogisticRegression）は、バージョン0.22において`solver`のデフォルト値が`liblinear`から`lbfgs`に変更されました。

この変更により、同じコードでも過去とは実行結果が異なる、あるいはエラーが出力されることが想定されるのでメモ。

## たとえばこんな事象

L1正規化を行うような、下記のコードでエラーが発生します。

```python
lr_l1 = LogisticRegression(C=C, penalty='l1').fit(X_train, y_train)
```

以下はエラー内容。

```console
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~/devp/linear_model.py in 
      1 for C, marker in zip([0.001, 1, 100], ['o', '^', 'v']):
----> 2     lr_l1 = LogisticRegression(C=C, penalty='l1').fit(X_train, y_train)
      3     print('Training accuracy of l1 logreg with C={:.f3}: {:.2f}'.format(C, lr_l1.score(X_train, y_train)))
      4     print('Test accuracy of l1 logreg with C={:.f3}: {:.2f}'.format(C, lr_l1.score(X_test, y_test)))
      5     plt.plot(lr_l1.coef_.T, marker, label='C={:.3f}'.format(C))

/usr/local/lib/python3.7/site-packages/sklearn/linear_model/_logistic.py in fit(self, X, y, sample_weight)
   1484         The SAGA solver supports both float64 and float32 bit arrays.
   1485         """
-> 1486         solver = _check_solver(self.solver, self.penalty, self.dual)
   1487 
   1488         if not isinstance(self.C, numbers.Number) or self.C < 0:

/usr/local/lib/python3.7/site-packages/sklearn/linear_model/_logistic.py in _check_solver(solver, penalty, dual)
    443     if solver not in ['liblinear', 'saga'] and penalty not in ('l2', 'none'):
    444         raise ValueError("Solver %s supports only 'l2' or 'none' penalties, "
--> 445                          "got %s penalty." % (solver, penalty))
    446     if solver != 'liblinear' and dual:
    447         raise ValueError("Solver %s supports only "

ValueError: Solver lbfgs supports only 'l2' or 'none' penalties, got l1 penalty.
```

`solver`の`lbfgs`は`l2`か`none`しかサポートしてないよ、っていうエラーです。

## エラー解消のためには`solver`を記述

下記のように記述します。

```python
lr_l1 = LogisticRegression(C=C, penalty='l1', solver='liblinear').fit(X_train, y_train)
```

## 原因についてちょっとだけ詳細

[ここ](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html)に書いてある通り、`LogisticRegression`の`solver`のデフォルト値がアップデートにより変更されたせいです。

> Changed in version 0.22: The default solver changed from ‘liblinear’ to ‘lbfgs’ in 0.22.

これにより本来`solver`のデフォルト値を`liblinear`だと想定して、L1正規化を行いつつ`solver`の設定を省略しているソースコードが軒並み影響を受けてエラーを吐くと思われます。

その他にも、`solver`を省略したせいで「デフォルト値が`liblinear`だと思って実行したら、`lbfgs`で実行されちゃった」ケースなんかは、エラーにはならなくても出力結果が過去とは異なる、という事象になります。

## ベタな結論

こういう「ライブラリ側が原因で動作が変わる、あるいは動作しなくなる」ケースって界隈あるあるなので、よく利用するライブラリのバージョンアップは欠かさずチェックしておこうね、という話。
AWSでGitBucketを使う（構築編）

### AWSでGitBucketやってみた。

AWSが流行りに流行っている＆タスク管理を
本格的にチームに導入するために、いじってみました。


#### やったこと
以下を参照してみたら、出来ました。

- ベース
  <https://ky-yk-d.hatenablog.com/entry/2018/11/29/012851>

- Amazon Linuxにログインどうやるの？ｗ
  <https://dev.classmethod.jp/cloud/aws/first-login-to-ec2-linux/>

- Tomactはとりま最新をインストール
  http://ftp.tsukuba.wide.ad.jp/software/apache/tomcat/tomcat-9/v9.0.30/bin/apache-tomcat-9.0.30.tar.gz
- Tomcatへアクセスできない。。
  セキュリティグループの設定をしっかりやってなかった。
  カスタムTCPルールで8080を追加。→ 無事アクセス。
- chmod コマンド…だー！エラー
  sudo chmod webapps 755ではなく、sudo chmod 755 webapps
  権限を先に記載するのね。。。忘れた。
- GitBucketもとりま最新
  ```wget https://github.com/gitbucket/gitbucket/releases/download/4.32.0/gitbucket.war```

なるほど…Trello的なKanbanいい。

   
#### やりたいこと → 終わり
- High
  - ~~期限設定を簡単にしたい（マイルストンではなく）~~：【不要】
     → これはない？マイルストンをいくつか用意してあげればいいだけか。
     　 マイルストン設定や人の設定も「Kanban」からどらっぐ＆ドロップできるから、楽ちんかも。
  - ~~Issueのテンプレを作成する。（作成する方法から調査）~~：【完了】
    → ブランチ作成する時に、空作成していた（デフォルト設定）ため、コマンド別途発行する必要ありっぽい。よく分からないので、ブランチ再作成して以下を選択して、マネっこしてみたら出来た。
  ```Initialize this repository with a README```
  - ~~「PullRequest」を理解する。~~：【完了】
   → ブランチ管理者へ提案時＆レポジトリ利用する時くらいしか利用しなさそうなため、不要。
     https://qiita.com/suzuki-hoge/items/3a568dff36fd981082ba
  
- Mid
  - ~~コメント内とかに関連チケットを記入し、すぐに飛んでいけるようにしたい。~~：【無理】
    → これは出来ないみたい…。
    <https://yoshinorin.net/2016/07/16/gitlab-impression/
  - クローズするとKanbanから見えなくなる問題
  → 見えるようにしたい理由はどれをクローズしたか、分からなくなるため。
    　 が、クローズしないとマイルストンのOPEN数が正しくカウントされない。。
  - ~~プラグインを色々見てみる。~~：【完了】
     - ガントチャート  
       <https://takezoe.hatenablog.com/entry/2018/10/14/125638>
  
- Low
  - ~~日本語化~~：⇒慣れの問題：【不要】
  - ラベルのNoneを非表示にしたい：邪魔



#### 今後
リポジトリとかなら、こいつ一択なのかしらん？
リポやらないのなら、Redmine強そう。GitbucketはISSUEの前後関係と、紐づけが特に…。

- GitLabでタスク管理してみた感想（主にRedmineとの比較）
  https://yoshinorin.net/2016/07/16/gitlab-impression/

WebHookくらいかな、自分の利用する範囲での利点は。
※とはいえ、プラグインでRedmineも出来そう。

どっち採用するか、迷う。
『Machine Learning: a Probabilistic Perspective』Murphy著を読み始めたので紹介する

『Machine Learning: a Probabilistic Perspective』という本があります。
以下ではMLaPPと略します。
日本語版は2019年12月15日現在、出版されていないです。

著者のページ：
http://people.cs.ubc.ca/~murphyk/MLbook/

amazon.co.jp：
https://www.amazon.co.jp/gp/product/0262018020/

# 他の本との比較
MLaPPは、Bishopの『パターン認識と機械学習』、Hastieらの『統計的学習の基礎』と以下の様な違いがあるとMurphyは述べています。

- 学部生にとってアクセスしやすい。
確率、線形代数、微積分、プログラミングの背景を前提としている。ただし、数学的なレベルは徐々に上昇し、より難しいセクションは難しいと明示されている。

- より実用的。
本で説明されているほぼすべての図を再現し、ほぼすべてのアルゴリズムを実装するMatlabのコードが付属している。

- 他の本では説明されていない様々な重要なトピックをカバー。
条件付きランダムフィールド、深層学習など。

# 日本語で書かれている評判

「英語しかありませんが，今熱い教科書がMLaPPです． 
 出版は2012年で，PRML・ESLよりかなり新しいです．
 1000ページ以上あり，通読するというより，リファレンスとして使うのが適当かもしれません．」

http://blog.livedoor.jp/idres/archives/1027540915.html

「機械学習系の新著が出る度思うんですけど、みんな新しい本に飛びつくよりもMurphy本なりPRMLなり何でもいいから基礎的な教科書を一通り読んだ方が力つくんじゃないかという気がしている。アカデミアの人は知らんけど、企業の人はこれをやってない人が多いように自分には見える。」

https://twitter.com/csstudyabroad/status/1165595343930580993

# コメント
- 学部レベルの知識で読める内容になっているのは嬉しいですね。
- 現在はPythonのコードも作製中ながら公開されています。 https://github.com/probml/pyprobml
- まだ第2章の途中までしか読むことができていませんが、続きが楽しみです。
- 最近話題の『Mathematics for Machine Learning』 https://mml-book.github.io/ も気になっています。
- 他にも機械学習に関する良い洋書があれば教えていただけると嬉しいです。
（C#）赤色のみ、除外する画像処理　（特定色だけ操作する処理）

（C#）
赤色のみ、除外する画像処理
（特定色だけ操作する処理）

ーーー画像加工ソフトに同等の機能はあるが、色を操作するソースコードを自作すれば、自身の意図に合わせて、自由度の高い処理が可能になる。


```C#:iro2iro.cs
//c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /target:winexe iro2iro.cs

using System.Drawing;

public class iro2iro
{
 public static void Main(string[] args)
 {
	if(args.Length==2){
	string path1;//in file name
	string path2;//out file name

	path1 = @".\" + args[0];
	path2 = @".\" + args[1];

	Bitmap image1;
	image1 = new Bitmap(path1, true);

	Bitmap canvas = new Bitmap((int)image1.Width, (int)image1.Height);
	Graphics g = Graphics.FromImage(canvas);
	Color pClr;
	SolidBrush b;
	int x;
	int y;

	int r1;
	int g1;
	int b1;

	for(x=1;x<(int)image1.Width;x+=1){
		for(y=1;y<(int)image1.Height;y+=1){
		r1=0;g1=0;b1=0;
		pClr = image1.GetPixel(x , y);

		r1 = (int)pClr.R;
		g1 = (int)pClr.G;
		b1 = (int)pClr.B;

		//ここで抽出する色の条件を決める
		//一例。赤要素が１６０以上でかつ、
		//青緑の平均より、2割上回る部分（これがないと単に白色が抽出される）
		//if (r1 > 160 )
		if (r1 > 160 && r1 > ((g1+b1)/2*1.2))
		{
			//pClr = Color.FromArgb(255,255,255);
			pClr = Color.FromArgb(200,200,200);
			//単に白色に置き換えると返って浮く場合は色を調整
		}

		b = new SolidBrush(pClr);
		g.FillRectangle(b, x, y, 1, 1);

		}
	}

	canvas.Save(path2, System.Drawing.Imaging.ImageFormat.Jpeg);
	}
 }

}
```
・変換後
![3q3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107418/816510fd-a593-c12e-c994-552a478ec598.jpeg)

・変換前
![3sample.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107418/87df5768-8437-261b-9a0c-3f405e154670.jpeg)
JupyterLabでログを可視化

## やりたいこと

- WebSphere Libertyのアクセス・ログから応答時間をグラフ化する
- アクセス・ログが複数に分割されていても読み込む
- パーセンタイル

## Jupyter Labで作った結果

```python
import pandas as pd
from datetime import datetime, tzinfo
import matplotlib.pyplot as plt
import glob
%matplotlib inline

# 指定したディレクトリ以下の複数のファイルを読み込む
path = r'.'
all_files = glob.glob(path + "/access*.log")
li = []

# 各ファイルからDataFrameを作る
for filename in all_files:
    df = pd.read_csv(filename, names=['start_time','remote_host','method','url','user_agent','status_code','response_byte','elapsed_time'])
    li.append(df)

# DataFrameを結合する
df = pd.concat(li, axis=0, ignore_index=True)

# Timezone部分を削除してTimestamp型へ変換する関数
def to_timestamp(str):
    # タイムゾーン(+0900)の部分が%zではうまくパースできなかったのでとりあえず消す
    str=str.replace(' +0900', '')
    return pd.Timestamp(datetime.strptime(str, '[%d/%b/%Y:%H:%M:%S]'))

# Timestamp型へ変換
df['start_time']=df['start_time'].map(to_timestamp)


# 応答時間部分の統計情報
print(df['elapsed_time'].describe())
print(df['elapsed_time'].quantile(0.9))

# グラフ化
df = df.set_index('start_time')
plt.scatter(df.index, df['elapsed_time']/1000)

# 自動で計算してくれるはずだが、うまく動かない場合に指定
# 最大値・最小値を取得する
start_time_max = df['start_time'].max()
start_time_min = df['start_time'].min()
#plt.xlim(start_time_min,start_time_max)

plt.xticks(rotation=70)
plt.xlabel('start time')
plt.ylabel('elapsed time[ms]')
plt.show()
```
300回プログラムじゃんけんでを戦わせるWebアプリを作った

#作ったアプリ
https://janken-programmer.web.app/


#遊び方
これはじゃんけんの出す"手"をプログラミングして戦わせるアプリです。

例えばグーだけを出すA君のプログラムと
グーとパーを交互に出すB君のプログラム
を300回戦わせると

B君が勝ちます


こんな感じでじゃんけんのアルゴリズムを考えて戦わせるアプリです

## 例
A君のプログラム

```python
HAND = 0
```

B君のプログラム

```python
HAND = 1
if COUNT % 2 == 0:
	HAND = 0
```

戦わせると・・・
<img width="633" alt="スクリーンショット 2019-12-10 12.36.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292260/564f57b6-e0a2-b870-cb41-04bc43aa3e0f.png">
こんな結果になります。

これをWebで遊べるアプリです。

#システム構成
今回使ったものは以下の通りになりました。

+ Vue.js
+ Buefy
+ AWS
+ serverless framework
+ dynamodb
+ firebase
+ circleCI

フロントエンドの部分はVueとBeufyを使いました。
同じような画面を作ることが多かったのでサクサク作れました。

バックエンドではAWSのサービスをserverless frameworkで構築しました。
アクセスが不安定なサービスになりそうなのでこちらのフレームワークを使いました。

ホスティングと認証にはfirebaseを使用しました。
本当はAWSなのですべてまとめたほうがいいのかもしれませんが
firebaseは無料で結構使えるのでこちらを採用しました。

無料枠などもあり、すべて無料でできました。
本当はRDBを使いたかったのですが、お金がないので無理やりdynamodbで作りました（反省）

# 機能
## じゃんけんプログラム
じゃんけんのアルゴリズムを実装するにあたり、システム変数的なものを用意することにしました。

| 変数名 | 型 | 概要 |
|:-----------|------------:|:------------:|
| HAND      | Intger | 0~2 の数値を代入することでグーチョキパーを出せる |
| WIN       | Intger | 勝った数 |
| LOSE      | Intger | 負けた数 |
| DROW      | Intger | あいこの数|
| P      | List | 自分が出した手の履歴 |
| E      | List | 相手が出した手の履歴 |
| COUNT      | Intger | 対戦数 |

これを実装したことにより100回負けたらグーを出すみたいなプログラムを書けます

```python
HAND = 1
if LOSE >= 100:
    HAND = 0
```

### コーディング画面
ハイライトやインデントの機能が欲しかったため今回は「Codemirror」を使用させていただきました。

Vueで使用する場合は「vue-codemirror」を使うと単一コンポーネントで使用できるため、気持ちよく作れました。


## ランキング機能
ランキングの実装には「イロレーティング」を使いました。

イロレーティングは対戦型の競技に使用されており、相対的な強さを評価します。

そのため、今回のランキングではこちらを使用し投稿されたプログラムを総当たりさせて順位を決定しました。

引用:イロレーティング
https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%AD%E3%83%AC%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0

## 認証機能
今回は一人が複数のプログラムを投稿できないように認証機能を追加しました。

Firebase Authenticationを使用しGithubで認証できるようにしました。



#感想
自分の想定しているものが一通りできたので、だいぶ満足しています。

ただセキュリティやじゃんけんのプログラムに不備があるかもしれないのでこれからも運営、開発をしていきたいと思います。
GCPでLinuxサーバを動かす

今まで手元にあるLinuxマシンで行っていたことをGCP(google cloud platform)のサーバで行いたいと思い、GCPにVMとしてLinuxマシンを作り、プログラムを動かすところまで行いました。最低限のところまでできたので、メモです。

### 備忘録

基本的にblogの記事
- [これから始めるGCP（GCE）　安全に無料枠を使い倒せ](https://qiita.com/Brutus/items/22dfd31a681b67837a74)
- [GCP Compute Engineを使ってLinuxサーバを始める](https://qiita.com/ariaki/items/1d4dbfeb41a4080a3f66)

などに従うことで、慣れている人なら大丈夫だと思います。私はこれを読んでからフォローしたのですが、project を新規に作成していたのにローカルのgcloud を使うところで新規プロジェクトにset していなかったので、作成したＶＭにログインできませんでした。また料金のことがよく分からず。という状態でのメモです。

### プロジェクトの確認方法と設定

現在のプロジェクトを見る。

```
> gcloud config list
[core]
account = xxxxxxxxxx@gmail.com
disable_usage_reporting = True
project = myproject-000000

Your active configuration is: [default]
```

作成したプロジェクトに切り替え。

```
> gcloud auth login
> gcloud config set project myproject-000000
```

作成したインスタンスがあるか確認する。最初、ここで作成したはずのＶＭがインスタンスとしてなかったので、project の設定がおかしいと気が付いた。

```
 > gcloud compute instances list
 NAME         ZONE        MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
 myinstance  us-west1-b  n1-standard-1               10.11.0.2   12.123.123.123  RUNNING
```

インスタンスがあれば、gcloud ssh でログインする。ＶＭのアカウントを何も作っていないのに大丈夫かな？と思いましたが、このコマンドを打つと、Puttyが立ち上がり、pass phrase の設定を聞かれてリターンキー（設定なし）を押したら、そのままログインしたターミナルに入りました。

```
> gcloud compute ssh myinstance --zone=us-west1-b
```

ログイン後は普通に使える感じだったので、今のところトラブルはありません。多謝。

## LinuxマシンをVMのインスタンスとして作成

順番は逆になりますが、仮想マシンを作成するまでのメモです。こちらは、console.cloud.google.com での作業で済みました。あるプロジェクトにあるとします。

(1) Compute Engine から VMインスタンスを選択します。

![20191215-VM.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/82e8dcf4-bede-3d4b-fa32-f02bd3ed154a.png)


(2) VMインスタンスについて「作成」を選択します。

![20191215-VM2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/e3536d81-5087-86be-9bae-11080ff28d83.png)

あとはいろいろ記事に書かれていますが、リージョンの選択、ＯＳの選択などを行います。私がどれが良いのか分からず、blog に書かれていたものを選びました。結局、それが無料になったのか今のところ分かりません。（費用は月額２４ドルと表示されちましたが、１年間はデポジット？があり無料なのかもしれない。が、よく分からないので、私の記事のこの部分は無視してください。）Ubuntu19、30G、USオレゴンを選択しました。結果、インスタンスができました。

![20191215-VM4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/497bc698-5457-9a41-c292-b10c68e5434f.png)
とは、先に書いた通り、gcloud でログインしました。

### そもそもの目的（メモ）

これは以前に書いた[室内の湿度のログ](https://qiita.com/xtkd/items/4497c74fcd955bfbeed7)を残すためのものです。
MQTT client として受信してファイルに保存するpython スクリプトを動かすマシンを今回、仮想マシンに移動しました。もっとスマートな解があるのは分るのですが、少しずつ改善していきたいと思います。

これからは公開鍵を向こうに置いて、こちらから普通にＳＳＨできるようにしたいと思います。というか、そもそも、Google のpub/sub を使って直接Container に保存したい。。。
JavaScriptのprototype宣言・使用

##prototype？
・継承を実現できる
・すべてのオブジェクト（複数の値をひとまとめにした値）がプロトタイプをベースに作られている。
・メモリの無駄消費を防げる

##使用方法

###宣言とオブジェクト構造

```
const Dog = function(name){
    this.name = name;
}

const poti = new Dog('ポチ');
console.log(poti);
```

```:結果
Dog {name: "ポチ"}
```

###メソッド定義

```:prototype使用
const Dog = function(name){
    this.name = name;
}
Dog.prototype.getName = function(){
    return this.name;
}
```

```:prototype未使用
const Dog = function(name){
    this.name = name;
    
    this.getName = function(){
        return this.name;
    }
}
```

prototypeを使用した場合と使用しない場合では、new されて違うインスタンスを生成した場合、使用した場合はプロトタイプを使って宣言したメソッドを参照するが、使わない場合だとgetNameがインスタンスの数分コピーされるので、無駄にメモリを消費する。

ただ、上記のプロトタイプを使った書き方をすると、ほかのプロトタイプなども作りたい場合まとまりがなくなっていってしまう。そこで違う書き方ができる。

```
const Dog = function(name){
    this.name = name;
}

Dog.prototype = {
    getName : function(){
        return this.name;
    }
};
```

こうすることで、対象のオブジェクトごとにまとめることができる。（プロトタイプを使用しながら）

##参考にさせていただいたサイト
https://www.sejuku.net/blog/47722
railsでhas_secure_passwordを使うための準備

####has_secure_passwordを使うための準備について書いています。

Userモデルを例にしています。

まず、モデルでhas_secure_passwordメソッドを呼び出します。

```user.rb
class User < ApplicationRecord
 has_secure_password
end
```

次に、メソッドを使うため、モデル内にpassword_digest属性を加えます。
コンソールに以下のコードを打ちます。

```
rails g migration add_password_digest_to_users password_digest:string
```

データベースでマイグレーションを実行することを忘れてはいけません。

```
rails db:migrate
```

続いて、gemfileにbcrypt fileを追加します。

```Gemfile
source 'https://rubygems.org'

gem 'rails',          '5.1.6'
gem 'bcrypt',         '3.1.12'
```

Gemfileにfileを追加したならbundle installを行いましょう。

```
bundle install
```
以上です。
>rails チュートリアル6章　https://railstutorial.jp/chapters/modeling_users?version=5.1#sec-creating_user_objects
AIでゴッホの絵柄を真似するツールを試してみた

## ゴッホ×AI
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546792/97d59c14-5eb5-7401-cf5f-a1ccdba0f6c0.png)
普通の画像をゴッホの絵柄に変換する、このマシンラーニングツールは
多分AIボームで一番流行ってたアプリの中でも有名なやつだろう。
これを試してみた。

## モデル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546792/a213de02-2bcc-690d-5b15-3fe10227956a.png)
スタイル画像style imageと内容画像content imageを
INPUTとしてマシンラーニングを通って合成する。

### 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546792/93049aac-bbd5-ccf8-6101-ef199545758e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546792/2013ebd9-d570-ea11-d678-e3832dea9d2b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546792/2ac631d9-6ffc-8ace-107b-b49dece3f997.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546792/2f88f70c-73c4-1559-3ec3-2175bf5e32af.png)
特定の日付との差が何年何か月かを表示

社内システムである特定の日付と現在の日付との差を何年何か月で表示する必要があったので、調べてみた。

- Java

あまり使ってこなかった java.time を使用。
今回は時間までは必要ないため、LocalDateTimeではなく、LocalDateを使用。

```Java
LocalDate sampleDate = LocalDate.parse("2019/12/09", DateTimeFormatter.ofPattern("yyyy/MM/dd"));
LocalDate currentDate = LocalDate.now();
// 特定の日付と本日の差を年形式で取得
//long year = ChronoUnit.YEARS.between(sampleDate , currentDate); 
// 特定の日付と本日の差を月形式で取得 ※間違い。トータル月数が取得される
//long month = ChronoUnit.MONTHS.between(sampleDate , currentDate);

// コメントいただいた方法で修正
Period period = Period.between(sampleDate , currentDate);
// 特定の日付と本日の差を年形式で取得
long year = period.getYears();
// 特定の日付と本日の差を月形式で取得
long month = period.getMonths();
```

上記で取得した年と月を文字列にして画面に表示。


- PHP

ついでにPHPも最近使ったので覚書。
PHPは独学なのでやり方間違っているかも。

```PHP
$sampleDate = new DateTime('2019/12/09');
$currentDate = new DateTime('now');
$diffDate = $currentDate ->diff($sampleDate);
$year = $diffDate->format('%y');
$month = $diffDate->format('%m');
```

終わり！
AWS環境構築（用語編）~VPC~

# AWSの基本サービスVPC
以下に自分用のメモもかねてAWSの基本的なサービスの一つであるVPCについてまとめてみた。
##VPC(Virtual Private Cloud)
[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/what-is-amazon-vpc.html)を参考に簡単にまとめました。

Amazon VPCとはAWSリソースを起動するための仮想的なネットワークです。（そもそもネットワークとはなんぞやという方は[TCP/IP](https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%8D%E3%83%83%E3%83%88%E3%83%BB%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB%E3%83%BB%E3%82%B9%E3%82%A4%E3%83%BC%E3%83%88)あたりの知識を身に着けることをお勧めします。）

VPCでIPアドレス範囲を設定できます。このIPアドレスは大まかにいうと、入出国審査での分類みたいなものです。君は入れる、入れない的な。
さらにサブネットというものを追加することで、より細かい設定が可能です。（空港でも日本人とその他の国籍の方で審査別れますよね。）

各サブネットではさらにそれぞれセキュリティの設定をすることができますが、ここでは詳細は省きます。

ちなみにVPCの設定で出てくる用語について簡単に説明すると以下の通りです。
主にアルファベットの略語についてです（覚えられない...）。

-AZ
アベイラビリティーゾーンの略。実際にデータが保存されているデータセンターの集まりです。
最近日本でスマホゲームなどがプレイできなくなったのは物理的にAZ障害が起きたからです。
[AWSのAZ(アベイラビリティーゾーン)とは？AZ障害が起きたときどうすればよいのか](https://developers.cyberagent.co.jp/blog/archives/22732/)ここの記事は面白いです。

-CIDR
Classless Inter-Domain Routingの略(サイダー)。IPアドレスのブロックを任意単位で区切ることができる。従来より柔軟性があった便利だよねという感じ。
[図](https://www.nic.ad.jp/ja/basics/terms/cidr.html)わかりやすい。

-tenancy
インスタンスをどこで実行するかを決める。

-Internet Gateway([公式](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/VPC_Internet_Gateway.html))
その名の通り。役割は公式の[和文](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/VPC_Internet_Gateway.html)から引用しますが
"1 つは、インターネットでルーティング可能なトラフィックの送信先を VPC のルートテーブルに追加することです。もう 1 つは、パブリック IPv4 アドレスが割り当てられているインスタンスに対してネットワークアドレス変換 (NAT) を行うことです。"
とあります。要は入出国における実際のcheckみたいなイメージ。

##その他の関連記事
[AWS環境構築（実装編）~VPC~](https://qiita.com/ryuryu52868475/items/e9600c1050051f407cf2)
[AWS環境構築（用語編）~EC2~](https://qiita.com/ryuryu52868475/items/4940ea4a99146721a094)
Rubyのdefの基本について

勉強していて分からなくなったからRubyのdefについて、自分の振り返り用。

def はメソッドを定義するためにある。

```
def メソッド名
　puts "hello"
end

hello
```

メソッド名を書くだけでhelloが出力される.
簡単に言うとトンカツ定食を注文すると、ご飯、味噌汁、トンカツ、サラダ、小鉢が付いてくる様な感じ。
Nuxt with TypeScriptのセットアップ方法

タイトルをするのに、de factoがわかりにくかったので、調査してまとめてみました。

## 歴史
nuxtのTSサポートissueこちら：
https://github.com/nuxt/create-nuxt-app/issues/23

issueの番号を見てもわかるように、create-nuxt-appが作成された当時からあったissueで、セットアップをするタイミングによって一番イケてる方法が違う様子がわかります。

## セットアップ方法
今取れる方針は、概ね以下の3つに大別できます。

1. [vue-cli](https://cli.vuejs.org/)から使用できるtemplateを使用。いくつかありそう。([Typescript starter with Nuxt.js](https://github.com/nuxt-community/typescript-template))
1. [create-nuxt-app](https://github.com/nuxt/create-nuxt-app)でscaffoldして、@nuxt/typesなどなどでsetupする([setup-guide](https://typescript.nuxtjs.org/guide/))
1. [create-nuxt-app-ts](https://www.npmjs.com/package/create-nuxt-app-ts)でscaffoldする

## 結論
頑張るならどれでもいいです。気合い入れて、どうぞ。

予めセットアップされてるとやりづらいなら、2. がもっともpre-installのライブラリが少ないのでおすすめできそうです。

ts移行は軽く、axiosやexpressなどのライブラリのセットアップが重いと見るなら1が良さそうです。uiライブラリで使いたいやつがリストにある場合もこれが楽ですね。

vuetify, prettier, pug, eslintで十分だと思うなら3.がもっとも楽です。


ちなみに、nextjsはzero-config ts supportをしているらしいので、初心者向けかもしれない。。
https://nextjs.org/blog/next-9#built-in-zero-config-typescript-support


## 最後に
Reactの方が難しい、という宗教の方がいますが、個人的にはむしろvue/nuxtの方が難しい印象を持ちました…
特に、仕組みを理解してセットアップするのは骨が折れそう、かも？
S3で署名Verを4にしたらエラー



AWS SDK for PHP v2を使ってるもんで、署名Verを2から4にする必要があった
そしたらファイルのアップロードで以下の様なエラーが出てアップロードできない

```
The request signature we calculated does not match the signature you provided. Check your key and signing method.
```

修正自体はfactoryするときに'signature' =＞ 'v4'を渡すくらいで大した作業でもなく。
キーが間違ってるから確認して的なエラーメッセージだけど、ファイル一覧は正常に動くしそもそも今まで動いてたのでACCESS_KEYとSECRET_KEYが間違ってる訳でもなさそう。

ファイルアップのソースはこんな感じ

```
    // S3バケット名
    $backet = 'backet_name';
    // アップするS3のパス
    $s3dir = '/hoge/fuga';
    // アップ時のファイル名
    $file = 'aaa.txt';

    // アップするローカル側のファイルフルパス
    $upfilepath = ’/tmp/tmp.txt';

    $s3->upload(
        $backet.'/'.$s3dir,
        $file,
        fopen($upfilepath, 'rb'),
        'public-read'
    );
```

uploadメソッドの第一引数は本来バケット名を渡すはずがバケット名 + ファイルパスになってる・・・
正しい引数に修正することでエラーは出なくなった

```
    $s3->upload(
        $backet,
        $s3dir.'/'.$file,
        fopen($upfilepath, 'rb'),
        'public-read'
    );
```

署名Ver2は第一引数と第二引数はただのファイルパスの情報だったので、バケット名とファイルパスをどこで区切って渡してもアップロードできた。多分
署名Ver4はこれらの引数を元にハッシュ値を作成するので、バケットとファイルパスをちゃんと渡さないとハッシュ値が変わっちゃってアップロードに失敗する。多分

解決したものの、署名Ver2が使えなくなるのは延期になったし、以前に作ったバケットはずっとVer2使えるみたいな話もあるので対応する必要なかったかも？
Notes/Dominoの役立つリンク集

# Notes/Dominoの役立つリンク集

　売却後、存在しているリンクを確認してまとめ。

## 初心者向け

### 公式
- [「超・初級講座!!」IBM Notes/Domino をこれからはじめる人のための【最初の一手】](https://www.ibm.com/developerworks/jp/lotus/ldd_tech/pdf/connectjapan2016_c-4.pdf)
- [IBM developerWorks 日本語版 : IBM developerWorks: Notes 小ワザ集: IBM Notes/Domino \- Japan](https://www.ibm.com/developerworks/jp/lotus/ldd_tips/)


### 協賛団体
- [Dominoサーバー管理者講座](https://www.notescons.gr.jp/home.nsf/blogs.xsp?cat=Domino%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E7%AE%A1%E7%90%86%E8%80%85%E8%AC%9B%E5%BA%A7)
   - →全10回。初めての人向け。- [ノーツコンソーシアム](https://www.notescons.gr.jp/home.nsf/blogs.xsp)は、日本アイ・ビー・エム株式会社・ICS公認のノーツドミノユーザの為の団体です。

### 個人
- [おっちーのLotus Notes入門](http://notesmoe.web.fc2.com/)
    - 更新が止まっているが、初心者向けとしてはよさそう。


## 中～上級者向け

### 個人
- [ノーツってヤッぁ\.\.二児の父の苦悩つ](http://harunakano.blogspot.com/)
    - 2019年時点で精力的に更新が続いているブログの１つ。
- [Lotus Notes/Domino \(R\) をこよなく愛して。。。。](https://ameblo.jp/iwama)
    - Notes/Dominoの技術者である岩間さんのブログ。2005年からの蓄積があるため、困ったらこのブログの検索で多くのことが見つかります。
- [Notes サポートのつぶやき](http://hnagasim.blog8.fc2.com/)
    - 売却前からNotes/Dominoのサポートをされていた方々のブログ。こちらも技術情報多し。ここ1年更新止まっているのが…。
- [のおつ \-Notes/Dominoに関すること\-](https://guylocke.blogspot.com/)
    - ガンガン新しい技術情報が集まってくるブログ。実戦に即した内容が多いです。

　以下更新止まっていますが参考になる記事：

- [なにぬねのーつ](http://www.niji.or.jp/home/toru/notes/index.html)
    - 小技集がとても便利。2009年で更新が止まっているが、役立つ情報が多いです。
- [Dominoのクラス表](http://3.bp.blogspot.com/_56nqSDeeYcM/SZzuiA_UaXI/AAAAAAAAAJM/Sz501IBdQZU/s1600-h/DominoDesigner8.jpg)
    - デザイナーでこれが表示されなくなったので…。



## イベントなど

- [のの会 \-notes knows community\- \- ホーム](https://www.facebook.com/notesknows/)
    - Facebookのコミュニティ。活発に勉強会など開催され提案す。
- [~~テクてくLotus~~](https://www.ibm.com/developerworks/community/groups/service/html/communitystart?communityUuid=b9fc1613-1e5e-4fe7-9a9b-fabd0b5195f1)
- [テクてく Lotus 技術者夜会](https://www.ibm.com/developerworks/jp/offers/events/techtech/index.html)
    - どちらもDeveloperWorks（IBMのサイト）にあるため、いつなくなるかわかりませんが…。
結婚式でPlayCanvas使った

#TL;DR
私事で恐縮ですが、今年の12/8に結婚式を挙げさせていただきました。
結婚披露宴では何本かムービーを流すのですが、最後のゲストに感謝を伝える「エンドロールムービー」をPlayCanvasを使って作ってみました。
自分にしかできない独自性あふれるいい感じの演出になったんじゃないかなーとなかなか満足しています。

# 背景
結婚式ではオープニングムービー，プロフィールムービー，エンドロールムービーとほとんどのひとがだいたい3本程度の動画を作成し流すのですが、外注すると高額になるうえ、あまり独自性はでないです。
自分が動画クリエーターとかなら全然何本でも作るのですが、動画ソフトよりもゲームエンジンの方が慣れているので、動画風ゲームを一本作ってそれをキャプチャすることにしました
また、終了後は誰でも体験できるようにWeb上にホストして体験可能な状態にしました


# つくったもの
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148084/379fe330-8e95-d51a-b5d9-b45d49a1e242.png)
横スクロールゲームにしてみました
横からゲストの思い出写真とメッセージが流れてきて、申し訳程度ですが流れてきた星をキャッチしていくちょっとしたゲーム要素を入れてみました。

権利の関係でBGMは入っていませんが、こちらから体験できます
https://utautattaro.com/endroll/


# 結果
結構盛り上がったので良かったかなーと思います。
最後に引き出物に実行リンクをQRで貼ったのですが、「全クリしました」などいろいろメッセージも受け取れたのがうれしかったです。
![IMG20191215151010.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148084/0bcf2ebe-999e-2323-537d-5bb62f953180.jpeg)

これから流行るかな、エンドロールゲーム
【GitHub Actions】 actionを自作して動かしてみる

# はじめに

今回は最近何かとよく聞くGitHub Actionsを
少し仕事で触る機会があったのでソースも含め、まとめてみます。

# GitHub Actions とは
公式では以下のように書かれています。

> GitHub Actions では、カスタムソフトウェア開発のライフサイクル (SDLC) にわたるワークフローを GitHub リポジトリに直接作成することができます。

参考: https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/about-github-actions

今まで外部サービスを利用して行なっていたリリースフローも
GitHubのソースリポジト内に簡単に設定できるような仕組みが提供されています。

また、GitHub Actionsを設定するにあたり理解しておくべき二つの概念についてもまとめておきます。

## workflow
GitHubリポジトリのどの処理（pull request作成時など）にひっかかけて
どういう処理を走らせるかを定義します。

あとで記述しますが`app-path/.github/workflows` に上記の内容を定義したyamlファイルをおきます。

簡単な処理だとworkflowの中で定義することも可能ですが、
複雑な処理やいくつかのworkflowで共通化させたい時処理が出てくる時もあります。
その時に使うのが次です。

## action
ここではaction.ymlというファイルをGitHubのフォーマットに乗っ取って定義すれば
あとはコンテナなどでプログラムを簡単に動かすことができる仕組みが提供されいます。

現在多くのactionがOSS化されており、
様々なことが簡単にできるようになっています。

#作ったもの
pull requestにlabelが貼り付けられた時に設定されたコメントを投げるだけの簡単なリリースフローの作成です。(実際の業務はもう少し複雑ですが、少し簡易化します）

# actionの作成
まずactionを作成します。

`app-path/.github/actions/actions-test`
のディレクトリ以下にactionsを作るのに必要なファイルを作成します。

```yaml:app-path/.github/actions/actions-test/action.yml
name: 'comment-action'
description: 'When a pull request is labeled Create a comment'
inputs:
  msg:
    description: Comment's message
    required: true
runs:
  using: 'docker'
  image: 'Dockerfile'
  args:
    - ${{ inputs.msg }}
```

```dockerfile:app-path/.github/actions/actions-test/Dockerfile
FROM ruby:2.6.0

RUN gem install octokit

ADD entrypoint.sh /entrypoint.sh
RUN chmod 711 /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]
```

```Ruby:app-path/.github/actions/actions-test/entrypoint.sh
#!/usr/bin/env ruby

require "json"
require "octokit"

pr_json = File.read(ENV.fetch("GITHUB_EVENT_PATH"))
pr = JSON.parse(pr_json)

github = Octokit::Client.new(access_token: ENV.fetch["GITHUB_TOKEN"])

repo_name = pr["pull_request"]["head"]["repo"]["full_name"]
pr_num = pr["number"]

msg = ARGV.msg
github.add_comment(repo_name, pr_num, msg)

```

これでworkflowから呼び出された時にDockerfileを元にコンテナを起動して
entrypoint.shに書かれている処理が実行されるようになります。

ちなみにGITHUB_EVENT_PATHにはイベントの起点となったものの情報がいろいろ入っているので
actionを作る時には活用することになると思います。

# workflowの作成
次にworkflowを作成します。

`app-path/.github/workflows`
のディレクトリ以下にworkflowを設定するのに必要なファイルを作成します。

```yml:app-path/.github/workflows/workflow-test
name: workflow-test
on:
  pull_request:
    types: labeled

jobs:
  commented:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - uses: './.github/actions/action-test'
        env:
          GITHUB_TOKEN: ${{ secrets.GH_TKN }}
        with:
          msg: "test comment"

```

これでpull requestにlabelがつけられた時に
action-testが動くように設定できました。

そしてあとは、
GitHubのprojectページから、secret keyを設定することが可能なので
GitHubのaccess tokenを設定すれば完成です。

# まとめ
今回は非常に簡単な処理を行いましたが
GitHubが様々な仕組みを用意してくれているので
簡単にリリースフローが設定しやすくなっていると思います。

ただ、まだ日本語文献が少なく
概念を理解しずらいため簡単にまとめてみてました。

ぜひ一度試してみてください。
Node.jsからSendGridを使ってメールを送る


久しぶりにSendGridを使ってみたのでメモ。

## SendGridの注意点

* ユーザ名はメールアドレスではなく、代理店である構造計画研究所から独自に振られたxxx@kke.comというやつ

>久しぶりですっかりID忘れてました。

## 準備

### API KEYの取得

利用するにはAPI KEYが必要です。到達率を上げるためにはドメイン認証やらいろいろやったほうがいい。
API KEYはSettingsの中にある。

![スクリーンショット 2019-12-15 14.58.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/fdff7b9a-05f1-fa44-0642-111a32d43109.png "スクリーンショット 2019-12-15 14.58.57.png")



### 作業場の準備

```
mkdir sendmail
cd sendmail
touch index.js

npm init -f

npm install --save @sendgrid/mail
```

## 実装

難しくない。本家サイトにユースケースの紹介があるのでそれを見ながら実装する。
まずはSend a sigle email to single recipientを試す。

API_KEYやらその他情報は各自環境に合わせて変更。

```
const sgMail = require('@sendgrid/mail');

const API_KEY = "XX.O1c1v3QNQzed41lkvQKNIw.7DYw-coFLLfoLqEuWADNzKH_xxxxxxxxxxxxxxxxxx";
sgMail.setApiKey(API_KEY);

const msg = {
    to: 'to@mail.com',
    from: 'from@mail.com',
    subject: 'test mail from sg',
    text: 'hoge hoge',
    html: '<p>foo bar</p>'
}

sgMail.send(msg).then(res => {
    console.log(res);
}).catch(e => {
    console.log(e);
});
```

複数人に送る場合はアドレスの配列を作り、sgMail.sendMultiple(msg)としてやるみたい。

## 動作確認

実行してみる。

```bash
node index.js
```

届いたみたい。

##　追記：ファイルを添付する

idnex.jsと同じ階層にtest.pdfがあるとして、下記のような感じ。

```js:index.js
const sgMail = require('@sendgrid/mail');
const fs = require('fs');

//sendgrid
const api_key = "xx.h_2KiszrS9acLRNN8oCs1g.mygHZwKirzSu9FHDR_TVOenruHqjtxxxxxxxxxx";
sgMail.setApiKey(api_key);

//attachment
const pathToAttachment = `${__dirname}/test.pdf`;
const attachment = fs.readFileSync(pathToAttachment).toString("base64");
// console.log(attachment);

const msg = {
    to: "to@test.com",
    from: "from@test.com",
    subject: "test",
    text: "hoge",
    // html: "<p>hoo</p>",
    attachments: [
        {
            content: attachment,
            filename: "test.pdf",
            type: "application/pdf",
            disposition: "attachment",
            contentId: "myPdf"
        }
    ]
}

sgMail.send(msg).catch(e => console.log(e));
```
IBM Notes リンク生成あれこれ

# IBM Notes リンク生成あれこれ

## 文書プロパティから取得する方法&amp;アドレスバーから取得する方法
[Notes 小ワザ集: 第127回 Notes文書リンクのURLをすばやく調べる](https://www.ibm.com/developerworks/jp/lotus/ldd_tips/nd8_127.html)

## @式による生成（文書リンク）

　以下のようなボタンを作ると、ボタンのクリックだけで文書リンク（![image.png](https://qiita-image-store.s3.amazonaws.com/0/151198/29838c54-411d-2223-2434-de03f1b0fe38.png)
）を生成することができます。

```@式:EditMakeDocLinkの例
@Command([EditMakeDocLink]) 
```

## @式による生成（URLリンク（識別子））

　以下のような@式でnotes://から始まるURLリンク（識別子）を生成できます。
　残念ながら@式でビューのユニバーサルIDが取得できないためビューの情報が欠落しますが、一応開くことは可能です。

```@式:識別子取得例１
"Notes://" + @Name([CN]; @Subset(@DbName; 1)) + "/" + @ReplaceSubstring(@ReplicaID; ":"; "") + "/" + "" + "/" + @Text(@DocumentUniqueID)
```

```@式:識別子取得例２（コピペできるポップアップを表示）
@Prompt([OkCancelEdit]; "文書リンク"; ""; "Notes://" + @Name([CN]; @Subset(@DbName; 1)) + "/" + @ReplaceSubstring(@ReplicaID; ":"; "") + "/" + "" + "/" + @Text(@DocumentUniqueID))
```
Notes/Dominoの役立つ@式

# Dominoの役立つ@式


## 各種値の取得

### ユーザーIDの略称を取得（例：Taroh Yamada/Hoge/Fuga)

```
@Name([Abbreviate]; @UserName)
```

### 現在のDBのサーバー名取得

```
@Name([CN]; @Subset(@DbName; 1));
```

### 現在のDBのファイルパス取得

```
@Name([CN]; @Subset(@DbName; -1));
```

### 現在のDBのフォルダ取得

```
@LeftBack(@Subset(@DbName; -1); "\\")
```

### サーバー→ローカルの順でタイムスタンプ取得

```
@SetField("InputDate"; @Date(@Now([ServerTime])));
@SetField("InputTime"; @Now([ServerTime]));	
```

## アクセス制御

### 管理者のみ表示

```
@UserAccess(@DbName; [AccessLevel]) != "6"
```


## 判定

### フィールドが英数字のみかチェック

```
@If(@Matches(@ThisValue; "+{a-zA-Z0-9}"); @Success; @Failure("エラーです"))
```


## 印刷

### 印刷用のフォームで文書を印刷する

各種パラメータはビューから文書を選択したときに使われるものが多いため、「開いている文書をフォーム指定して印刷」の場合は、以下のようなボタンを作って、印刷用フォームに切り替えてから印刷するとよい。

```
@Command([SwitchForm]; "PrintForm")
@Command([FilePrint])
```
【C#, log4net】シングルトンクラスのコンストラクタでロガーを使ったらNullReferenceExceptionが発生して苦闘した話

#追記 2019/12/15
コメント欄にてalbireoさんにシングルトンの実装の仕方などについてご指摘いただきましたので、
そちらも一緒にお読みいただければと思います。


#はじめに
シングルトンクラスを作り、そのインスタンスを外部のクラスから取得しようとしたら、下記の画像のような例外が発生した。
原因はシングルトンクラスに書いていたlog4netのロガーインスタンスを取得するコード(GetLoggerメソッド)にあった。
色々すっ飛ばしてこの話の結論を先に述べると、「ロガーインスタンス取得コードはフィールドの一番最初に書きましょう」。
もし同じ問題ではまっている方がいればとの思いで記事を書いた（いるかな・・・）。
※シングルトンパターンについて正しくない説明があるかもしれませんので、その点はご了承いただいたうえでお読みください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/ea067404-64c9-6b63-bf4d-d5b88b29f9d9.png)



#環境
・IDEはVisual Studio 2017を使用

##問題の発生まで
[このサイト(.NET TIPS：シングルトンパターンを実現するには？［C#／VB］)](https://www.atmarkit.co.jp/ait/articles/1711/29/news029.html)を参考にして、シングルトンクラスを作成し、ログ出力するためロガーインスタンス取得コードを書いた。

下記がそのシングルトンクラス。

```cs:SingletonClass.cs
namespace Hoge
{
    class SingletonClass
    {
        //　自身のクラスのインスタンスを初期化（アプリ実行時にインスタンスはこの1つしか存在しない）
        private static SingletonClass _instance = new SingletonClass();

        // ロガーインスタンス取得コード
        private static readonly log4net.ILog _logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        // 自身のインスタンスを外部から使うための手段を用意してあげる
        // プロパティを使った方法
        public static SingletonClass Instance => _instance;
        // メソッドを使った方法
        public static SingletonClass GetInstance() => _instance;

        
        // 外部から直接呼べないコンストラクタ
        private SingletonClass()
        {
            _logger.Debug("SingletonClassのインスタンスが生成されました");
        }
    }
}

```

　
そして、シングルトンクラスを利用する側のクラスで、シングルトンインスタンス取得コードを書いた。

```cs:UseSingleton.cs
namespace Hoge
{
    class UseSingleton
    {
        // シングルトンインスタンスを保持するフィールド
        private SingletonClass _singletonInstance;

        public void SomeMethod()
        {
            // シングルトンインスタンスを取得
            _singletonInstance = SingletonClass.GetInstance();         
        }
    }
} 
```
　

実行したら、落ちた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/c408ae8b-56d1-9374-5568-7e5ff9095f77.png)

##問題の原因
問題のコードは下図の矢印の順序で処理が行われている。
まずGetInstanceメソッドを呼び出すと、シングルトンクラス内部ではシングルトンインスタンスを取得しようとする。
その際にシングルトンインスタンスがnewされ、したがってシングルトンクラスのコンストラクタに処理が移る。
ここからが問題。
今回はコンストラクタでロガーを使ったログ出力を行おうとした。
しかしこの時点でロガーインスタンスの取得は実行されていないため_loggerはNullの状態だったのだ。
まだ取得してないはずの_loggerを使おうとしたから、「オブジェクト参照がオブジェクトインスタンスに設定されていません」と怒られたのであった・・・。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/1476132d-0af4-2ce1-a113-8ea614873f02.png)


##解決
シングルトンクラスにおいて、ロガーインスタンス取得コードを自身のインスタンス初期化コードより先に書いてあげ、無事に動いた。

```cs:SingletonClass.cs

    class SingletonClass
    {
        // ロガーインスタンス取得コード
        private static readonly log4net.ILog _logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        //　自身のクラスのインスタンスを初期化
        private static SingletonClass _instance = new SingletonClass();


```
firestoreのsetトランザクション処理

# はじめに
firestoreにリレーションを持ってデータを新規作成する際のトランザクションの方法がのっていなかったのでその時の解決策を共有します
# ドキュメント構成
userがたくさんのeventを持つというようなドキュメント構成となっています
user->event(1対n)
<img width="1257" alt="スクリーンショット 2019-12-12 13.05.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281558/9b6fd9f2-e670-2152-d116-59408e50d420.png">
<img width="1259" alt="スクリーンショット 2019-12-12 13.05.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281558/66144955-41f1-9bbd-5a01-91854e8e8cdc.png">


# 解決法
```javascript
// 独自でIDを生成する関数
autoId = model => {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  let autoId = ''
  for (let i = 0; i < 20; i++) {
    autoId += chars.charAt(Math.floor(Math.random() * chars.length))
  }
  return autoId
}


saveNewEvent = async (title, body, uid, navigation) => {
  const db = firebase.firestore()
  const timestamp = firebase.firestore.Timestamp.now()

  const newEventId = autoId('events')
  const eventRef = db.collection('events').doc(newEventId)
  const userRef = db.collection('users').doc(uid)

  // トランザクション開始
  db.runTransaction(async transaction => {
    await Promise.all(transaction.get(userRef), transaction.get(eventRef))
    transaction.set(eventRef, {
      userId: uid,
      title: title,
      body: body,
      createdAt: timestamp,
      updatedAt: timestamp
    })

    transaction.update(userRef, {
      events: firebase.firestore.FieldValue.arrayUnion(newEventId),
      updatedAt: timestamp
    })
  }) // トランザクション完了
    .then(() => {
        // 完了後の処理
    })
    .catch(error => {
      console.log(error)
    })
}

```
# 解説
firestoreでトランザクションを行うときは先に作成コレクション作成前にidを指定する必要があるそうなので今回はautoId()というメソッドを作って独自でIDを生成してそのIDをもとにしてコレクションを作成しています。

# まとめ
トランザクション管理は一貫性を持ったデータを保持するためには絶対に必要なので丁寧にやりたいところですね！
# 参考文献
- トランザクションとバッチ書き込み（firestore公式ドキュメント）
https://firebase.google.com/docs/firestore/manage-data/transactions?hl=ja#transactions

- 【Firestore】ドキュメントの自動生成 ID って被らないの？
https://qiita.com/yukin01/items/dcac3366adcf0fe827a3

- 【Firebase】Firestoreで複数collectionの更新にトランザクションを使う
https://notsleeeping.com/archives/3984
Nuxt.jsでheadにasyncDataの値を入れたい

```hoge.vue
<script>
export default {
  async asyncData({ route, app, store, payload }) {
      return {
        title: payload.title.rendered
      }
    }
  },
  head: {
    title: this.title
  },
```

これでは`TypeError: Cannot read property 'title' of undefined`となり失敗してしまう。

```
  head() {
    return { title: this.title }
  },
```

これで設定できた。headメソッドを使うことでコンポーネント内のデータにthisでアクセスできるようになる。`nuxt.config.js`でメタ情報を設定するときと同じように`head: { ...`と書いてしまったのが失敗した原因のようだった。

参考：[API: head メソッド - NuxtJS](https://ja.nuxtjs.org/api/pages-head/)
テスト項目書作成に気をつける事

##はじめに
開発を行なったら、避けては通れない **テスト**
初心者はテスト工程から入ることが多いと思います。

テストを行うときは、テスト項目書どおりの手順でバグが起こらないことを確認します。
条件があり、確認項目があります。
テストに慣れている人であれば、その他おかしな点(確認項目にない箇所)を確認すると思いますが、新人は確認内容だけを重視してしまう可能性があります。
(僕がそうだっただけです)

#作成時に気をつけること
項目書作成するときは、テストで確認をしたい観点を明確にする必要があります。

- 確認観点を作成
- マトリックスを作成
- 最大桁数、最大表示数、最小値、null・空文字の許容

##確認観点を作成
**一番大切な確認観点の作成**
確認観点さえしっかり仕上げていたら、問題ないと言うのも過言ではないくらいに大事です。
（過言ですが、、、）

観点作成は、テスト項目書１個１個を作成前に認識合わせ、作成中に再確認する為にも必要なものです。

###例
- 新しい画面を追加した場合
    - ボタン制御を確認したい。
    - 画面間の引き継ぎ情報を確認したい。
    - 画面の音声、文言、タイマー設定を確認したい。

上記内容を確認観点に残しておけば、作成する際にテストの項目を考えることができますし、後から画面でバグが見つかった時に、観点として何が足りなかったのかを見つけることができます。

##マトリックスを作成
テスト項目書を作成する時にマトリックスを作成するのが、網羅率を上げる為にも必要です。

###例
ボタン１制御ありボタン２制御あり
ボタン１制御なしボタン２制御なし
ボタン１制御ありボタン２制御なし
ボタン１制御なしボタン２制御あり

マトリックスを言語化したものですが、テスト項目書を作る為に、いくつかのパターンのテストを行います。
有無だけであれば、２パターンですが、二つの有無が発生したら４パターン三つの有無が発生したら８パターンと言葉だけだとわかりにくくなります。

| ボタン１制御| ボタン２制御 |結果|
|:---------|:-----------|:---|
|●|●|二つ表示|
||×|ボタン１のみ表示|
|×|●|ボタン２のみ表示|
||×|ボタン表示なし|

このように表にまとめると、漏れがないかの確認も簡単になります。
表を一から作るのは難しいかもしれませんが、先に苦労を取れば、後から楽できます。

##最大桁数、最大表示数、最小値、null・空文字の許容
確認観点の作成とマトリックスで表を作成しました。
そこでテストを詳細化する為に、最大値最小値確認も必要です。

先ほどのボタンであればbool型の0か1の確認ですが、文言のString型やInt型だと許容範囲外が来た場合に例外処理を起こしてしまいます。

例外処理が正しく行われるか、運用上MAXの値を許容できているか、画面の表示範囲を超えていないのかを確認することは大切です。

#最後に
テスト項目書は仕様書をテスト化したものでもあります。
観点を追加する際には、仕様書を理解する必要がありますので、まずは、どのように動くことが正なのかを理解して各動きを当てはめていきます。
JqueryのinArrayを使う際に、気を付ける。

##動機
phpのin_arrayみたいな関数がJSで使えないかなと思い、調べていると$.inArrayというのがあることを知って、使ってみたが意図しない挙動をしたのでメモ

##解説
```:間違った書き方
const a = 10;
const b = [1,2,3,4,5];
if($.inArray(a, b)){
    alert('');
}
```

この処理を実行すると条件式を満たし、alertが実行される。JqueryのinArrayは、配列に含まれていたらそのインデックスを返し、含まれていなかったら-1を返す。

```
const a = 10;
const b = [1,2,3,4,5];
if($.inArray(a, b) !== -1){
    alert('');
}
```

この処理を実行すると、条件式を満たさずalertは実行されない。含まれていなかったら-1が返ってくると、覚えておく

### 直感的な書き方

```
const a = 10;
const b = [1,2,3,4,5];
if(!b.includes(a)){
    alert('');
}
```

arrayのprototypeにincludesという関数が用意されている。これのほうが直感的に書けて見やすいと思う。
R・RStudio・パッケージのアップデート

# 1. 趣旨
何だかんだよく忘れるので、備忘録として。
必要最低限やればいいことを書いておく。

# 2. まずはRのアップデート

### 2-1. installrの導入

環境が変わった時に入れ忘れてることがあるので。

```R
install.packages("installr") 
```




### 2-2. パッケージの読み込みと実行

`installr`パッケージを読み込み、

```R
library(installr)
```

アップデート用の関数を打ち込むだけ。

```R
updateR()
```

といっても、結局はインストーラーを自動で取得してくれるだけなので、結局はR本家のサイトで最新版をダウンロードしても結果は全く変わらない。




### 2-3. 留意点
`updateR()`は、RStudioとかでは使わないほうがいいらしい。そういう警告が出るので、深く考えずRGuiからやれば問題ない。


# 3. RStudioのアップデート

`Help > Check for Updates`でアップデートの有無をチェックできる。
あとは素直に指示に従えばよろしい。

ちなみにIgnore Updateを押すと、その版のアップデートはスルーされる。
以降、RStudioのアップデートが生じない限り、アップデートチェックを行っても「最新版だぞっ」と応答されるので、「間違って押しちゃったぞ☆」というドジっ子（ぼく）は、公式サイトから最新のインストーラを手動で取得しよう。

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

`update.packages()`でおっけい。論点なし。
ただ、引数を何も設定しないと、ご丁寧にパッケージ毎に「アップデートしますか？」と聞かれるので、「黙らっしゃい！」という方は`ask =false`の引数を設定しましょう。

```R
update.packages(ask = FALSE)
```

# 5. Tips：コピペ用
`installr`がない場合のパッケージ取得、R本体と各パッケージのアップデートを同時にやる`allupdate()`を雑に作っておきました。
R本体のアップデートは通常再起動を要求するので、先にパッケージをアップデートする仕様です。
以下をコピってEnterを押せば、RStudio以外はサクッとアップデートできるはず。

```R:allupdate()
allupdate <- function()
{
  update.packages(ask = FALSE)
  if("installr" %in% rownames(installed.packages())){
  }else{
    install.packages("installr")
  }
  library(installr)
  updateR()
}

allupdate()
```
フォームへSLEEP値を入力してタイムアウトをテストするアプリ

##はじめに
Webフォームへ値を入力し送信ボタンを押すと、その秒数SLEEPして応答を返すという単純なJavaのサンプルコードです。タイムアウト値をテストする際に使ったものです。
##サーブレット配置
```text:servlet
servlet
　＋WEB-INF
　｜　＋classes
　｜　｜　＋RequestSample1.class
　｜　＋web.xml
　＋formsample.html
```
##formsample.html

```html:formsample.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" Content="text/html;charset=Shift_JIS">
<title>sleep_sample</title>
</head>
<body>
<p>sleep_sample</p>
<form action="/sample/RequestSample1" method="get">
<table>
<tr>
<td>SLEEP（秒）</td>
<td><input type="text" size="3" value="" name="sleep"></td>
</tr>
</table>
<input type="submit" name="button1" value="送信">
</form>
</body>
</html>
```
##web.xml
```xml:web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
  version="2.4">
  <servlet>
    <servlet-name>RequestSample1</servlet-name>
    <servlet-class>RequestSample1</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>RequestSample1</servlet-name>
    <url-pattern>/RequestSample1</url-pattern>
  </servlet-mapping>
</web-app>
```
##RequestSample1.java
```java:RequestSample1.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class RequestSample1 extends HttpServlet {
  public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException{
    response.setContentType("text/html;charset=Shift_JIS");
    PrintWriter out = response.getWriter();
    String sleep_sec = request.getParameter("sleep");
    try {
     Thread.sleep(Long.parseLong(sleep_sec) * 1000);
    } catch (InterruptedException e) {
    }
    StringBuffer sb = new StringBuffer();
    sb.append("<html>");
    sb.append("<head>");
    sb.append("<title>sleep_sample</title>");
    sb.append("</head>");
    sb.append("<body>");
    sb.append("<p>");
    sb.append(sleep_sec);
    sb.append("秒SLEEPしました。</p>");
    sb.append("</body>");
    sb.append("</html>");
    out.println(new String(sb));
    out.close();
  }
}
```
RunCat開発に基づく知見

RunCat開発にあたって得た知見について執筆した記事まとめ

# システム情報取得系

- [Swift：macのCPU使用率を取得する](https://qiita.com/Kyome/items/0f640ff03b9018c5369a)
- [Swift：macのディスク使用量を取得する](https://qiita.com/Kyome/items/2d2161a5cf8a1d3a56f0)
- [Swift：macのメモリパフォーマンスを取得する](https://qiita.com/Kyome/items/01cce674f7c9d9092a14)
- [Swift：macのネットワーク上り下りスピードを取得する](https://qiita.com/Kyome/items/e9f56432fa0d1d3f3165)
- [Swift：macのIP Addressを取得する](https://qiita.com/Kyome/items/88d82bd38bf981494f63)

# 画像処理系

- [Swift：再生スピードが変更可能なキーフレームアニメーション](https://qiita.com/Kyome/items/15eb1893c48a64900e12)
- [Swift：左右反転した画像，白黒画像，ネガポジ反転画像を生成する](https://qiita.com/Kyome/items/ff35962f43269e2c4134)
- [Swift：NSImageのドット絵をそのまま拡大(リサイズ)する](https://qiita.com/Kyome/items/4f2233cab95288918e80)
- [Swift：CGImage ←→ NSImage ←→ CIImage【変換Extension】](https://qiita.com/Kyome/items/87b771e13695a6fba99e)
- [Swift/Xcode：Image Assetsの@2x,@3x画像をコードでリサイズするときは注意しろよな☺️](https://qiita.com/Kyome/items/2ecc41aabd8f44b72422)

# そのほか
- [macOS向けアプリでカスタムフォントを扱う方法](https://qiita.com/Kyome/items/c52ebf61384e7d5e8b34)
- [Swift：スクロールバーのギャップを除いたNSScrollViewのサイズを取得する](https://qiita.com/Kyome/items/ce128844117ee13b59e9)
- [Swift：macOSメニューバーの項目の選択可否を動的に変更する](https://qiita.com/Kyome/items/fdd4f666edf2831a3cdb)
- [Swift：macのスリープ/復帰の通知を受ける](https://qiita.com/Kyome/items/c1db350d0b6de0fb89ab)
- [Swift：macOSメニューバーの項目の選択可否を動的に変更する](https://qiita.com/Kyome/items/fdd4f666edf2831a3cdb)
- [Swift：NSCollectionViewの使い方](https://qiita.com/Kyome/items/b18ad1adae8d3dcd54b3)
GitHub ActionsでPRのマージ時に自動的にGAE versionを削除する

# GAE versionには210個制限がある！
HerokuにはReview Appsという便利な仕組みがあり、GitHubでPRが作成される事に検証用の環境を自動的にデプロイすることができます。
参考: https://qiita.com/kon_yu/items/6d2c0ae91d0176ceb167

GAEでもCI上でスクリプトを書けば自動デプロイが実現できるので（こちらは今回触れません）、PR毎にGAEのversionを分けてデプロイをしてReview Appsぽいことをやっています。

しばらく運用していると、↓の様なエラーが出てしまいました...どうやらversion作りすぎで210個制限を超えてしまった様です。

```
Error 400: --- begin server output ---
<ApiError 400, Message: "Your app may not have more than 210 versions. Please delete one of the existing versions before trying to create a new version.">
--- end server output ---
```

# GitHub Actionで不要なversionを消してみる
ちょうど[GitHub Actions](https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/about-github-actions)が使える様になった時期だったので、PRのclose時に自動的に不要になったversionを削除する様にしてみました。
↓インラインコメントで簡単な解説を書いておきます。

```
name: Delete GAE version from staging

on:
  pull_request: # PRのclose時のみ発動させます
    types: [closed]
jobs:

  build:

    runs-on: ubuntu-latest
    container: # GAE SDKの入ったDockerコンテナを使っています
      image: ubiregiinc/jdk8-scala-appengine:latest

    steps:
    - uses: actions/checkout@v1
    - name: delete_version
      run: $APPENGINE_SDK_HOME/bin/appcfg.sh -A YOUR_APPID -V pr${{ github.event.number }} --oauth2_refresh_token=YOUR_TOKEN delete_version src/main/webapp
    # ↑まだgcloudに移行していないので...appcfgを使っています...
    #  `-V`でversion指定ができるので、CIからデプロイしている命名規則と同じversionを指定して`delete_version`します
```

上記の様なymlで記述したworkflowを`.github/workflows/delete_version_on_pr_close.yml`の様な場所に置いておくと該当レポジトリのPRなどのイベントに応じていろいろなことが自動化できて便利です。

## 実行状況を見る
PRの`Checks`タブから実行状況を確認することができます。
<img width="717" alt="スクリーンショット" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9490/980ae775-57f3-179c-211e-f4e9db1da360.png">


# プランによっては使えない...
GitHub ActionsのGAに伴い、レポジトリ数課金の古いプランだと使えなくなってしまいました...
> GitHub Actions is unavailable for per-repository plans, which are legacy billing plans.

こんなエラーが出る場合はプランを確認しましょう。

```
### ERRORED 11:20:00Z

- Workflows can't be executed on this repository. Please check your payment method or billing status.
```