OmniAICreator/Qiita-1.07M huggingface dataset:
Windows+Node.js+gulp で AWS Lambda用zipファイルを作成したよ

タイトルの通り、Windows環境のNode.jsでAWS Lambda用のZIPファイルを作成するタスクを書いたので、gulpfile.jsをさらしておくよ。

```javascript:gulpfile.js
var gulp = require('gulp');
var zip = require('gulp-zip');
var install = require('gulp-install');
var tap = require('gulp-tap');
var rimraf = require('rimraf');
var mkdirp = require('mkdirp');

gulp.task('clean', (cb) => {
	rimraf('./dist', function(error){});
	cb();
});

gulp.task('init', (cb) => {
	mkdirp('./dist/build', function (err) {
			if (err) console.log(err);
	});
	cb();
});

gulp.task('modules', () => {
  return gulp.src("./package.json")
    .pipe(gulp.dest('./dist/build/'))
    .pipe(install({production: true}));
})

gulp.task('sources', () => {
  return gulp.src([
        './scripts/*.js'
        ],{base : './scripts'})
    .pipe(gulp.dest('./dist/build/'));
})

gulp.task('zip', () => {
  return gulp.src([
    './dist/build/**',
	],{base : './dist/build'})
		.pipe(tap(function(file) {
			if (file.isDirectory()) {
				file.stat.mode = parseInt('40777', 8);
			}
		}))
		.pipe(zip('lambda-function.zip'))
		.pipe(gulp.dest('./dist'));
})

gulp.task('default', gulp.series('init', 'modules', 'sources', 'zip'));
```

これで`gulp default`を実行するとdistの下にlambda-function.zipというファイル名でZIPが作成される。実行に必要なnode_modulesを抱き込んでいるので、好きなライブラリが使えます。
あ、JavaScriptのソースファイルは全てscriptsというフォルダにまとめられているのが前提なので、利用する際は適宜書き換えて下さい。

肝は
* gulp 4対応
* Windows上でgulp-zipを使うとAWS Lambdaで実行出来ない問題に対応
と言ったところ。

それぞれの具体的な対応方法は各自で探してみて下さい。
Apple Developer Programライセンスの更新で「ユーザ情報を保留中」！？

以下は、2019年2月19日の状況です。
Appleの対応等により最新の情報とは異なる場合がありますので、あらかじめご了承ください。

# 事象

1) Apple Developer Programライセンスが期限切れになったので、更新を行った。

2) App Store Connect (旧iTunes Connect)「マイ App」ページで、ダウンロード課金のアプリが「契約保留中」になっている。
→アプリが公開されなくなってしまっている。

3) App Store Connect「契約／税金／口座情報」にアクセスし、Agreementについて同意する。
これで終わりかと思いきや、**まだ契約のステータスに「ユーザ情報を保留中」と表示されており、アクティブにならない。**

# 対応

調べたところ、以下の役割について、連絡先情報を指定する必要がある、とのことでした。

- Senior Management
- Financial
- Account Holder
- Marketing

https://help.apple.com/app-store-connect/?lang=ja-jp#/dev4387d3023

ということで、これらを指定したところ、無事アクティブになりました。

前はこんな手順なかったような…
[Apple DeveloperとApp Store Connectのメンバーおよびロールの統合](https://developer.apple.com/support/teams/)の影響でしょうかね…
学習記録（私なりの用語翻訳の跡）「Visual Studio Codeの使い方、基本の「キ」by　ITmedia、（最初のページ、冒頭部分）

元記事：[Visual Studio Codeの使い方、基本の「キ」](https://www.atmarkit.co.jp/ait/articles/1507/10/news028.html)

この記事はプログラミング初心者が自分の勉強のために作っています。
また、Markdown記法の練習を兼ねています。
「そんなの解説しなくてもググらせれば解るだろカス」と言われるかもですが、ご批判は重々承知の上ですので捨て置いて下さい。
この記事を書くに至った経緯について興味のある方は、noteにある下記２記事を御覧ください。

[おっさんのゲームプログラミング事始め(1)](https://note.mu/katayakisoba/n/nfa235ec0cf71)
[おっさんのゲームプログラミング事始め(2)](https://note.mu/katayakisoba/n/n0c428426e847)




>ITmedia該当記事、文中より

>VS CodeはElectronと呼ばれる、Web技術を使用してクロスプラットフォームなデスクトップアプリを開発するためのフレームワーク上に構築されている。VS Codeの特徴としては次のようなことが挙げられる。
> * クロスプラットフォーム
> * 軽量／高速
> * デバッグ機能を内蔵
> * 標準で多数の言語をサポート
> * IntelliSenseサポート
> * Git機能サポート
> * 拡張機能によるVS Code自体の機能や操作性の向上
> * タスク機能


# Electron
読み”エレクトロン”。

[説明動画（英語）What is Electron: The Hard Parts Made Easy](https://youtu.be/8YP_nOCO-4Q)

# フレームワーク
[参考:コードキャンプによる説明記事](https://blog.codecamp.jp/web_framework)
> さまざまなシステム開発を効率化してくれる機能群

と、文中にあるが、文章のニュアンスを読む感じ、「定形機能によるアプリケーション生成装置」という表現がふさわしい気がする。

ならば、「コードジェネレーター」と言い換えたほうが、わかりやすいのではないかと思うのだけど、何故「フレームワーク」？
この認識が合っているかどうかは解らない。
[ASCII.jpデジタル用語辞典の解説](https://kotobank.jp/word/%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%AC%E3%83%BC%E3%82%BF%E3%83%BC-4081)

参考までに、そのコードジェネレーターという用語を使っての批判記事に出会ったので紹介しとく。
[はてなブログ・tailislandの日記 2012-07-20エントリ「もう悪質なコード・ジェネレーターには騙されない！」](http://d.hatena.ne.jp/tailisland/20120720/1342789308)


# クロスプラットフォーム
 「複数の媒体で使える」という趣旨。この場合の「媒体」とは、Windows/Mac/Linux といったOS（オペレーティングシステム）の事を指す。
# デバッグ機能
 IDE(統合開発環境)に含まれる機能の一つ、デバッガー。プログラム言語を使って書いたプログラム文（＝ソースコード）を、機械的に判別して、エラー（誤り）部分を判定し、指摘してくれる機能。  
 あくまで指摘してくれる（＝"エラーを吐く"）だけであり、多くは自分の手で修正しなければならない。また、機械はプログラミング言語の仕様に合致しているかを判定してくれるだけであり、そのソースコードが人間が見て読みやすいかどうか、などの部分は多くの場合指摘してくれない。
# IntelliSenseサポート
 読み”インテリジェンスサポート”。
 「自動補完機能」と訳せばいいだろうか。
 命令文や関数名の一部を入力すると、IDEが瞬時に入力候補を指し示して補完してくれ、選択すると自動入力してくれる。

補完機能の一例として、HTMLタグを例にあげて説明する。
正確に言うとHTMLは「プログラミング言語」では無いのだが、VSCodeの機能としてサポートしており、私のような初学者にとっては一番馴染み易い例であるので。

 例えばHTMLタグは開始タグと終了タグが必要だが、人間の手入力でやると括弧の閉じ忘れや対応するタグの未入力などのエラーが発生する。
 > 失敗例：＜p＞段落＜/p   
 (終了タグが＞で閉じられていない)  
 > 失敗例２：＜p＞段落＜p＞  
 （終了タグに、終了を示す為の/が無い）  
 >
 > 正解：＜p＞段落＜/p＞
 
 このようなエラーを未然に防ぐための機能。

# Git（機能）  

読み”ギット”。
ソースコードなどの変更履歴を記録・追跡するための、分散型バージョン管理システム。  
概念説明としての詳しい記事は、
[Wikipedia>Gitの項](https://ja.wikipedia.org/wiki/Git)を参照。

# 「バージョン」とは？
アプリケーションを作る→プログラミングを行う  
この時に、ソースコードの末尾や冒頭、あるいはアプリケーションの一番最初のページ（ウェルカムページ）に「バージョン情報」というものを付ける場合が多い。  
（私個人は、普通のBLOG記事を書くときにも使ったりもする。）
> 例： ver 1.0  

更新のたびに、このバージョンの数値を足していく。そうする事で、書いた時に変更を加えた点や変更した日時を履歴として残しておけるようになる。  

次のバージョンへの更新の際の参考とする。例えば、
* バグが酷い
* 加えた変更点がプログラムの動作に悪影響を与えている
* 加えた変更点がユーザーのニーズに合わない

 これらのような場合には、履歴をさかのぼって以前の状態（バージョン）に戻すこともできる。  
 この行為を「巻き戻り」とも言う。

#  巻き戻り
「カセットテープ」という記録用の磁気ベルト   (この場合、ベルト＝テープ)を使ったメディア(記録媒体)が、かつて存在した。  
一般的には音楽の録音のために使われる形が有名だが、コンピューターも初期はカセットテープ若しくは類似品によって記録を取っていた時期がある。  

この「巻き戻り」という表現は、カセットテープを使っていた時代の名残。  
[参考：グーグル画像検索「カセットテープ」](https://www.google.com/search?q=%E3%82%AB%E3%82%BB%E3%83%83%E3%83%88%E3%83%86%E3%83%BC%E3%83%97&source=lnms&tbm=isch&sa=X&ved=0ahUKEwjs8c6C5sbgAhV9JaYKHXxnBBMQ_AUIDigB&biw=1280&bih=646)

# タスク機能
[ASCII.jpデジタル用語辞典の解説-タスクの項](https://kotobank.jp/word/%E3%82%BF%E3%82%B9%E3%82%AF-5586)

この項目はググっても最適な記事を見つけられなかった。恐らく上記に挙げたような事では説明不足だろう。追々調べていく・・・
【Swiftめも】言語の理解・導入


# Swiftの勉強

そもそもSwiftがどんな言語かすら知らないので
お勉強。

[Swift4 の基本文法をマスターしよう](http://cloudcafe.tech/?p=1931)

↓SlideShare
[![thumbnail](http://image.slidesharecdn.com/swiftstudy-141004235800-conversion-gate02/95/slide-1-1024.jpg)](https://www.slideshare.net/nagaminehiromasa/swift-study)

[![thumbnail](http://image.slidesharecdn.com/swift-150706105819-lva1-app6892/95/slide-1-1024.jpg)](https://www.slideshare.net/kouheikawamata/swift-50206749)

# 導入

勉強ばかりしていても仕方ないので、、、
実際に環境を整えて触れるようにしていきます

[Swift実践入門 〜 今からはじめるiOSアプリ開発！](https://employment.en-japan.com/engineerhub/entry/2017/05/25/110000)

こちらを参考にしながら、作っていきます
※ほぼ同じことを記録程度に記載していきます

### xcodeにて新規プロジェクト作成する

Xcodeを起動して「Create a new Xcode project」または、メニューから［File］→［New］→［Project］を選択し、新規プロジェクトを作成します。

次の画面で、［iOS］の［Single View Application］を選択して［Next］で進みます。
次に、プロジェクトを保存する任意のフォルダを選択し
［Create Git repository on］のチェックを外して［Create］します。

### gitリポジトリ作成
```shell
$ git init
$ git add .
$ git commit -m "initial commit"

githubにてリポジトリ作成

$ git remote add origin https://github.com/{gitアカウント}/{gitリポジトリ}.git
$ git push -u origin master
```

### swiftライブラリを管理する「cocoapods」のインストール

[初めてのCocoaPods](https://qiita.com/shishimo@github/items/d7f508e2489bcc68050e)

```shell
$ sudo gem install cocoapods
$ pod setup
$ pod --version
1.5.3

$ cd {swiftプロジェクト}
$ pod init
```

Podfileの編集

```ruby
target '{swiftプロジェクト}' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for calculator
  pod 'Expression'
end
```

```shell
pod install
```

あとはxcodeより開発を行っていく
vimはこれだけ覚えていればとりあえず使えると思う

vimと言われると大体の人が、
「移動からもう難しい・・・」とか
「コマンド覚えられない・・・」とか
「わけワカンねぇ！使いにくい！」とか
で、vimを始めることを諦めていたり
途中で諦めてしまう人が多いかと思います

そんなあなたに、
vim歴5年の私が使っているコマンドのご紹介を行い
これさえ覚えておけばvimなんて使えるんだ！
という知識やコマンドをご紹介します

**使わないと覚えられないですからね！！！**
私は無駄に歴だけ積み重ねています！！！

## 前提
まずこの記事の前提として、
vimの持ちうる便利機能の全てを紹介するものではないです
（私本人が知らないから書けないだけなんですが）
今回ご紹介する機能は氷山の一角よりも少ないものです・・・
なので各セクションにて紹介する機能はほんの一部だと思ってください

## モードについて
まず知っておきたいvimの最低限の知識として
`モード`
というものが存在します

この概念が他のエディタと違って入りにくさを助長しているんじゃないかと思っています
モードの詳細に関しては後述しますが、

- ノーマル
- 入力
- コマンド
- ビジュアル

というモードが存在し
このモードを駆使してテキストを入力したりしていくわけです
このモードがあるからこそ**キーボードのみで作業**ができるようになるのですね

キーボードのみで作業を行うことが作業効率を上げる一因となっています
やる前はそのメリットがよくわからないと思いますが
できるようになってくるとものすごく大きなメリットであると感じられますよ！

### ノーマルモード
通常状態ってやつですね

読んで字のごとくvimでファイルを開いた時などはこのモードから始まります
このモードでできることは

- 移動
- 各モードへの移行

って感じですかね

各モードへ移行するのもこのモードからなので
逆に各モードからこのモードへ戻ってくる必要があります
その時に使うのが

```
Esc
```

ですね！
とりあえずこのキーを押しておけばノーマルモードです！
**わけわかんなくなっちゃったらとりあえずEsc**です！

### 入力モード
文字を入力するためのモードですね！

ノーマルモードでカーソルを移動して、入力したいところに合わせたら

```
i もしくは a
```

で入力モードへ入れます

ちなみに

```
i はカーソルの左
a はカーソルの右
```

へ入力を始められる状態になります

正直自分はiキーを使うことがほとんどで
たまにaキーを使うイメージです
**iかa押しときゃ入力モードに入れるって思っておけばおk**

### コマンドラインモード
見た感じはノーマルモードに似ているのですが
コマンドを利用するためのモードです

編集しているファイルを保存したりする時に使います

```
:
```

を押すことで画面下部にて特定コマンドを入力できます

一番使うのが

```
ファイルの保存
:w
```
```
ファイルを閉じる
:q
```

ですかね

他にもvimの設定ができたり、新しいファイルが開けたり
様々なコマンドを利用できますが、
**一旦は上記を覚えておけばファイルを保存して閉じれるのでおk**

### ビジュアルモード
vim以外で言うマウスで文字列をドラッグする選択ってやつができるモードです

ビジュアルモードに入るには

```
v
```
です

ビジュアルモードでカーソルの移動を行えば選択を行うことが出来ます

ちなみに、

```
Ctrl+v
```
で**矩形選択**が可能です！

矩形選択後にテキストを入力する際には、

```
I(大文字のiなのでShift+iですね)
A
```

で入力可能です！
入力される方向は通常の入力と同じく、
Iで左
Aで右
ですね！

## 移動とコピペ
プログラムとかファイルの編集って移動してコピペすりゃどうにかなるでしょう！（投げやり）

### 移動
移動はもうご存知かもしれませんが
`hjkl`で移動します！

```
h : ←
j : ↓
k : ↑
l : →
```

### コピペ
コピペはビジュアルモードで選択した状態で

```
y
```
でコピー（vimではヤンクと言いますね）

任意の場所へ移動して

```
p
```
でペーストできます！

1行丸々コピーする場合は、ノーマルモードで任意の行で

```
yy
```
と入力すれば1行コピーできます！

## プラグインに関して
vimを他のIDEなどと同じように（近しい感じで）使うためには
素の状態では少し厳しいです
ファイルツリーもないですし
そういう時にvimにはプラグインがあります！

いろんな機能を追加していくことができるんですよね！
詳細については別記事にてまとめられればと思いますが
気になる人はググってみればたくさんプラグイン出てくるので
ぜひ検索してみてくださいませ

## .vimrcについて
プラグインの導入時にも触るかと思いますが、
vimの設定をいじることで使いやすく出来ます
ゲームでいうキーコンフィグを好きなように変更したりする感じ

これは他の設定ファイルと変わらずテキストファイルみたいなものなので
vimmerの方はgitに上げておいて、
自分がいつも使っているvimをどこでも利用できるようにしてたり
ちょっと前の設定に戻したいなーって時に活用したりされているみたいです
作り方やオススメの設定などは検索してみてね！！

## まとめ
正直vimの全てを覚える必要はないと思います
ExcelでもWordでも覚えきれないほどの機能が搭載されているにも関わらず
既知の機能のみでも十分利用できているのと同じですね

もちろん前述のソフトウェアでも言えることですが、
搭載されている機能を全て使いこなせばより効率的だったりより素敵な成果物が出せたりするのと同じく
vimに**搭載されている機能を使いこなせば使いこなすほど開発が捗ることは間違いない**です

入りはまずはハードルを下げて使いながら慣れていくことが大切ですので
使いながら新しい機能・コマンドに手を出していきましょう！

使っていて不便に思った場合は対応している機能ないかなーと調べてみると
大体は対応している機能が存在して解決されるでしょう！

最後にもう一度言っておきますが、
vimはもっともっとたくさんの機能があります
使っている間に「こうできないかなー」「こんな機能ないかなー」と思うことがあれば
是非とも検索してみてください！大体あるので！！

何かおすすめの機能や素敵なコマンドなどがあれば私にも教えてくださいませーー！！
Chapter5で手間取ったところ

#### 書籍「Dockerによるアプリケーション開発環境構築ガイド
Dockerを勉強するために購入した書籍「Dockerによるアプリケーション開発環境構築ガイド（櫻井洋一郎、村崎大輔[著] ISBN978-4-8339-6458-0)」に掲載されていた演習をやった。
Chapter5を少しやったところで少し手間取った箇所があったので、メモしておく。おそらく執筆時点からクラウドベンダー(google）の仕様が細かく変わったりしていてなかなか難儀ですね。。。手順間違いなどで自分の環境でだけ発生しているのかもしれないので参考程度に。

#### 1. minikube環境作成 (p287-p289)
(1) minikube ip ( コマンド 5-3-1-3) 
実行してもipアドレスは表示されない。どうやら minikube startしていない段階では表示されない模様。のちのステップでminikube startで起動できた後には ipアドレスが表示されるようになった。

(2) minikubeのVM起動に失敗。
P287記載の通り、仮想マシンをインストールしておく必要があった。
この辺り行間を読んで自身の環境に合わせておくことが期待されている模様。
私は brew cask install virtualboxでvirtualboxをインストール。
一応 minikubeをアンインストールご、もう一度 brew cask install minikubeを実行。
minikube start が正常実行できました。

#### 2. ダッシュボードの表示 (p292,p293) 
どうやら現時点2019/2ではダッシュボードのモジュールは最初はインストールされていないようです。
minikube service listでみても出てきません。
こちらに記載の手順でマニュアルデプロイが必要でした。
https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/
以下のコマンドでダッシュボードをデプロイ
kubectl create -f https://raw.githubusercontent.com/kubernetes/dashboard/master/aio/deploy/recommended/kubernetes-dashboard.yaml
その後、以下のURLでダッシュボードにアクセス
http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/.

ダッシュボードの入り口まで表示されますが、現在のバージョンでは認証が求められます。
こちらのURLを参考に、管理者権限を作り、管理者のTokenを入力してSign Inすることでダッシュボードとご対面できました。:grinning:
https://qiita.com/h-sakano/items/79bb15f7a0661e141c75

#### 3. Kubernetes-dashboardにアクセスできない。(p343) 
localhost:8001でアクセスできませんでした。以下を修正して表示できるようになりました。
(1) クラスターを作成するときに折りたたまれている「詳細オプション」を展開して出てくる「Kubernetesダッシュボードを有効にする」にチェックを入れる。
（GKEにはGKEコンソールというのがあり、GCPとしてはKubernetes-dashboardではなくそちらを使ってほしいという意図があるようですね。。）
(2) p338-p339のSDKのインストールを対話型インストールで実行
　　（https://cloud.google.com/sdk/downloads?hl=ja) 
(3) gcloud auth 完了後に、以下を実行
 　　　gcloud config set project プロジェクトID
(4) 管理画面にアクセスする前に以下のコマンドを実行
　　　kubectl proxy 
    # p343の冒頭に”proxyが起動したら”は"proxyを起動したら”と解釈。
(5) http://localhost:81/ui ではアクセスできなかったので、以下でアクセスして成功
http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/.
(6) アドミンユーザーはこちらの手順に再びお世話になりました。
https://qiita.com/h-sakano/items/79bb15f7a0661e141c75



#### 最後に
本書、なかなかの良書と感じています。掲載されている手順に関しては完成度にまだ改善の余地ありですが、完成度よりも鮮度も大事な世の中なので感謝しています。
QiitaにもKubernetesの投稿が増えて、技術情報が沢山あるんですね。
色々苦労しながらも、おかげさまでなんとかChapter05を完走できました。
初めてGCPとGKEを触ってみましたが便利ですね。最後の方はIngressなどでてきたりして、ちょっとわからないまま進んだところもありましたので、復習していこうと思います。
Treasure Data にて Presto のクエリに NOW() を使う

Presto で NOW() を使いたい場合のメモです。

手元の環境は以下になります。

* Ubuntu 18.04 LTS
* td-agent 1.3.3

以下のように VARCHAR に CAST してから TD_TIME_PARSE でタイムスタンプに変換し、最後に TD_TIME_FORMAT で希望するフォーマットに変換します。

```SQL
SELECT
  TD_TIME_FORMAT(TD_TIME_PARSE(CAST(NOW() AS VARCHAR)), 'yyyy-MM-dd HH:mm:ss', 'JST')
```
pdf2imageで日本語消えちゃって困っている場合

## 困ったこと

神ライブラリ [pdf2image](https://github.com/Belval/pdf2image/blob/master/pdf2image/pdf2image.py)を使っていて、
日本語のテキスト埋め込みなPDFを画像化すると、日本語だけ消えちゃうという現象にハマりました。

## 解決法

```
sudo yum install adobe-source-code-pro-fonts adobe-source-han-sans-cn-fonts adobe-source-han-sans-twhk-fonts adobe-source-sans-pro-fonts
```
※当方AmazonLinux2を使用しております。

[こちら](https://www.lovezawa.com/entry/2014/12/26/poppler&ImageMagick%E3%81%A7PDF%E3%82%92%E7%94%BB%E5%83%8F%E3%81%AB%E5%A4%89%E6%8F%9B%E3%81%99%E3%82%8B%E3%82%82%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%81%8C%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%81%AA)のページを参考に `yum info *adobe*` して出てきたfontを全部入れました。
なお、前提として以下のインストールは完了している想定です。

```
sudo yum install poppler poppler-utils
```

## [補足]フォントのライセンスについて

私は詳しくないのですが、知り合いによると `ユーザーが自由な文字列を打ち込める形でパスを提供する` とフォントの著作権的にほげほげな感じの模様。それ以外は印刷物と同様らしい。
例えば今回のようなケースだと、ユーザーが自由に打ち込んだ内容をPDFにして吐き出す、みたいなときに何かしら考慮しないといけないのかな？と想像しています。
私のケースは既にあるPDFを画像化するだけなので、問題ない認識。
もし詳しい人がいたら教えてください🙇


以上です！
Dockerの上にLXDコンテナを作成する（ことはできない）

Docker in Dockerというものがあるので、LXD in Dockerをやりたくなった。
結局できなかったけれど、その記録として。


## Dockerコンテナを作成する

```
# docker pull ubuntu:16.04
# docker run -ti -d --privileged --name ubuntu ubuntu:16.04
# docker exec -ti ubuntu /bin/bash
```

## パッケージの更新とインストール

コンテナ内に入り、以下のコマンドを実行

```
# apt update && apt upgrade -y && apt install -y bridge-utils iproute2 lxd　ca-certificates cgroup-lite
```

## LXDと関連デーモンの起動

```
# /etc/init.d/lxd start
# /etc/init.d/lxcfs start
```

## LXDコンテナを作成してみる

```
root@6df86d661e89:/# lxc launch ubuntu:18.04 test3
Creating test3
Starting test3
error: Error calling 'lxd forkstart test3 /var/lib/lxd/containers /var/log/lxd/test3/lxc.conf': err='Failed to run: /usr/bin/lxd forkstart test3 /var/lib/lxd/containers /var/log/lxd/test3/lxc.conf: '
  lxc 20190219023055.514 ERROR lxc_cgfsng - cgroups/cgfsng.c:cgfsng_enter:1416 - No space left on device - Failed to enter /sys/fs/cgroup/cpuset/docker/6df86d661e89b500bfb7a30c9c20c4c82182233640ffe687ea202ea23455b19d/lxc/test3/cgroup.procs
  lxc 20190219023055.536 ERROR lxc_start - start.c:__lxc_start:1358 - Failed to spawn container "test3".
  lxc 20190219023056.982 ERROR lxc_conf - conf.c:run_buffer:416 - Script exited with status 1.
  lxc 20190219023056.982 ERROR lxc_start - start.c:lxc_fini:546 - Failed to run lxc.hook.post-stop for container "test3".
```

だめだった。
Swift AVAudioで録音した音声が聞き取れないレベル

忘れないようにメモ。

## 現象
色々なサイトのサンプルソースを元に、録音と再生するアプリを作成したところ、
再生した音声が異常に小さかった

## 環境
xcode: 10.1
swift: 4.2

## 修正前
```
let session = AVAudioSession.sharedInstance()
do {
  //try session.setCategory(AVAudioSessionCategoryPlayAndRecord, with: .defaultToSpeaker)
  try session.setCategory(AVAudioSession.Category.playAndRecord, mode: .default)
  try session.setActive(true)
　　　（省略）
}
catch let error {
  // failed to record!
}
```

## 修正後
```
let session = AVAudioSession.sharedInstance()
do {
  try session.setCategory(AVAudioSession.Category.playAndRecord, mode: .default, options: .defaultToSpeaker)
  try session.setActive(true)
　　　（省略）
}
catch let error {
  // failed to record!
}
```

参考にしたサイトの情報だと、4.2に対応していなかったみたいで、関数の引数を変えたところ必要な引数が漏れてしまったことが原因だった。

## 他のアプローチ
```
session.setInputGain(1.0)
```
と設定するといい、といった情報もあったけれど、
公式の使い方を参照し、isInputGainSettableでチェックしてから使おうねってあったのでやったところ、、、

```
if session.isInputGainSettable {
  try session.setInputGain(1.0)
} else { print("設定できないってどういうことだよ！") } 
```
見事撃沈した。

## 参考
[VoiceRecorder](https://iosrevisited.blogspot.com/2017/11/voice-recorder-swift-4.html)
[[iOS]ボイスレコーダーアプリを作る](https://qiita.com/army_sh/items/946aa15263a6d087a99c)
[マイクにアクセスするとアプリ全体の音量が小さくなります](https://stackoverrun.com/ja/q/10098051)
bitbucket.orgからMercurialリポジトリをクローンする際にSSLエラーが出た時の対処

macOS Mojave(10.14)環境において、bitbucket.orgで管理しているMercurialリポジトリをクローンしようとしたところ、以下のSSLエラーが出てしまいクローンが出来ませんでした。

```
(an attempt was made to load CA certificates but none were loaded; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error)
error fetching bundle: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:726)
abort: error applying bundle
```

bitbucketが利用している最新のルート証明書が、Pythonの参照するルート証明書の一覧に登録されていないことが原因でしたので、
以下のコマンドを実行し、libresslの最新のcert.pemを参照させることで回避ができました。

```
brew install libressl
export SSL_CERT_FILE="/usr/local/etc/libressl/cert.pem"
```

今後の同様の事態に備えて、 `export SSL_CERT_FILE="/usr/local/etc/libressl/cert.pem"` は、 `.bash_profile` あたりに書いておいても良いでしょう。

### 参考
https://www.mercurial-scm.org/wiki/SecureConnections
gulpでpugをコンパイルしたときにリンクの＆がエスケープされるのをやめたい

# 結論：! をつけよう
```ruby:hoge.pug
a(href!="https://hogesite.com&piyo") ほげサイト
```
`a(href!="")`のように、!をつけることで回避できます。

# 現象
```ruby:hoge.pug
a(href="https://hogesite.com&piyo") ほげサイト
```
↑これをコンパイルした際、

```ruby:hoge.html
<a href="https://hogesite.com&amp;piyo">ほげサイト</a>
```
`&`が`&amp;`となってしまったピヨ。
エスケープされることが普通なので、コンパイラは悪くないのですが、クライアントからエスケープしないで欲しいとNGが。

これを回避するには最初に書いたように、

```ruby:hoge.pug
a(href!="https://hogesite.com&piyo") ほげサイト
```
`href`のあとに`!`を付けましょう！
何もしないCircleCIのconfig.yml

CI動かしたくないgh-pagesブランチとかに入れておく。
NO TESTSエラーにならずSKIPPED扱いになる。

必須のフィールドをだけ埋めた最小限の記述にするとこうなる。

```.circleci/config.yml
version: 2
jobs:
  build:
    machine: true
    steps:
      - run: ":"
    branches:
      only:
        - nothing/to/do
```
Gibbs sampling によるクラスター法

```{r}

library(dplyr);library(mvtnorm)

n=200;m=3;dim=m-1

K=2

X=rbind(matrix(rnorm(n,mean=1,sd=1),ncol=m-1),matrix(rnorm(n,mean=5,sd=1),ncol=m-1))

mu0=rep(0,m-1)

sigma0=cov(X)

mu=rmvnorm(K,mean=mu0,sigma=sigma0)

pi0=rep(1/K,K)

times=40

for(k in 1:times){

z_mat=array(0,dim=c(n,K))

for(j in 1:nrow(X)){
  
x=X[j,] 

prob_vec=c()

for(i in 1:K){
  
prob_vec=c(prob_vec,dmvnorm(x,mean=mu[i,]))  
  
}

vec=prob_vec/sum(prob_vec)

z_mat[j,]=rmultinom(1,1,prob=vec)

}

n_vec=apply(z_mat,2,sum)

sign=apply(t(t(z_mat)*c(1:K)),1,sum)

X_data=data.frame(X,sign=sign)

mu_vec=array(0,dim=c(K,dim))

for(i in 1:K){
  
X_sub=X_data %>% filter(sign==i)  

X_sub=as.matrix(X_sub[,1:(ncol(X_sub)-1)])

ave_x=apply(X_sub,2,mean)
  
mu_vec[i,]=rmvnorm(1,mean=(n_vec[i]/(n_vec[i]+1))*ave_x,sigma=diag(1,dim)/(n_vec[i]+1)) 
  
}

mu=mu_vec

print(mu_vec)

}

```

```{r}

library(dplyr);library(mvtnorm)

n=2000;m=7;dim=m-1

K=4

X=rbind(matrix(c(rnorm((n/2)*(m-1),mean=1,sd=1),rnorm((n/2)*(m-1),mean=5,sd=1)),ncol=m-1,nrow=n))

mu0=rep(1,m-1)

sigma0=cov(X)

tau=1;p=1;a=1;b=1

mu=rmvnorm(K,mean=mu0,sigma=sigma0)

pi0=rep(1/K,K)

times=40

for(k in 1:times){

z_mat=array(0,dim=c(n,K))

for(j in 1:nrow(X)){

x=X[j,] 

prob_vec=c()

for(i in 1:K){

prob_vec=c(prob_vec,dmvnorm(x,mean=mu[i,]))  

}

vec=prob_vec/sum(prob_vec)

z_mat[j,]=rmultinom(1,1,prob=vec)

}

n_vec=apply(z_mat,2,sum)

sign=apply(t(t(z_mat)*c(1:K)),1,sum)

X_data=data.frame(X,sign=sign)

mu_vec=array(0,dim=c(K,dim))

ave_x_mat=array(0,dim=c(K,dim))

a=n*dim/2;b=0

for(i in 1:K){

X_sub=X_data %>% filter(sign==i)  

if(nrow(X_sub)>0){

X_sub=as.matrix(X_sub[,1:(ncol(X_sub)-1)])

ave_x=apply(X_sub,2,mean)  

mu_vec[i,]=rmvnorm(1,mean=(ave_x*n_vec[i]/(n_vec[i]+p)+mu0*p/(p+n_vec[i])),sigma=diag(tau,dim)/(n_vec[i]+p)) 

ave_x_mat[i,]=ave_x

b=b+(1/2)*sum((X_sub-ave_x)^2)+(n_vec[i]*p/(2*(n_vec[i]+p)))*sum((ave_x-mu0)^2)

}

}

mu=mu_vec

tau=rgamma(1,a,b)

print(mu_vec);print(tau);print(p)

}

```
Watson DiscoveryのConnectorを使ってみた( ICOS/Webクロール )

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/f1c61a0c-debd-5ea1-7a9c-45cbe8311112.png)

# はじめに
Watson Disocoveryでは従来のJavaベースのクローラーに代わり、Connectorが提供されています。Connectorを使うとUIを使って様々なデータストアへの接続が非常に簡単になります。

ドキュメント :blue_book: [Connecting to Data Sources](https://console.bluemix.net/docs/services/discovery/connect.html#sources)

2019/2月現在で提供されているConnectorは下記です。
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/1ce547a0-42a0-f01a-cb70-6deb19ccc1e4.png)

SalesForceやBoxはエンタープライズ環境が必要なので割愛。今回は手元に手軽な環境がある ①IBM Cloud Object Storage　②WebCrawlをサクッと接続してみました。**結論から申せば、簡単すぎ！**

# 1. IBM Cloud Object Storage(ICOS)
ICOS上のバケットに置いてある文書をクロールします。念のため(＆他のデータストアでも同様)ですが、クロールした結果のコレクションや索引はWatson Discovery上に作られます。Watson Discoveryのコレクション/索引がICOS上に作られるわけではありません

## ICOS側での事前の準備
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/846207e7-9bd8-ee14-fc4c-9b68b159e415.png)

上のようにus-geo上のバケットに日本語pdfを置いておきます
Discoveryから当該バケットにアクセスするために、以下の２つの定義情報が必要です

- S3互換(=hmac付き)のサービス資格情報 - 作り方は[この記事](https://qiita.com/ishida330/items/4d59e4b75cb1645048e2#%E6%AC%A1%E3%81%AFhmac%E3%81%A7%E3%82%84%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F)をご参照ください(要は**{"HMAC":true}**で生成)
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/5afed9cc-824a-e26d-c8e1-413eaf670bb6.png)
- 当該バケットのエンドポイントの名前
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/b9015ac3-75a3-2d30-8a15-8a87a94a3a23.png)

:warning: バケットを作る時の「回復力」と「ロケーション」の指定によって、エンドポイントの名前は異なります。ご利用の環境に準じたエンドポイントを適宜選択してください。

## DiscoveryでのICOS指定
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/f8b3c496-5e96-14d2-d010-e2177833972e.png)
「Coonect to datasource」- 「**IBM Cloud Object Storage**」を選択 

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/5ce4579a-be56-c7c1-eccd-00a4aef7a4c3.png)
前項で準備した**Endpoint/Access key ID/Secret Access Key**を入力して「Connect」ボタン

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/f4f54da4-3b30-0074-4ff6-0ba11817f719.png)

以下を適宜選択して、「Save&Sync Onjects」ボタン

- リフレッシュのサイクル(5分毎、1時間毎、1日毎、など）
- コンテンツの言語
- 照会対象のバケット

以上でクロールが始まり、コレクションが作成されます。コンテンツの量次第ですが、インデックス作成が完了したら照会できます
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/34033241-3416-e06c-6ceb-45892a01f209.png)

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/69a724fb-9cdd-86da-5011-16f7277d6a61.png)


# 2. Webクローラー

## Discovery上での設定
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/acd89d38-6691-89c1-0f51-5fc15df45efd.png)
「Coonect to datasource」- 「**Web Crawl**」を選択 

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/14165f9e-8110-9495-2864-88453e755b7a.png)

以下を適宜選択して、「Save&Sync Onjects」ボタン

- リフレッシュのサイクル(5分毎、1時間毎、1日毎、など）
- コンテンツの言語
- 始点となるURL( ホップ数も指定できます）

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/3af3bf1b-6718-d8c8-2e85-e5345053519a.png)

#### :warning: Liteプランの方はホップ数に注意
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/7af71ff4-848c-330c-2c3a-a3f65e3756f7.png)

私はLiteプランでやってたのですが、クローラーのホップ数のデフォルトが2なので、リンクを辿りに辿ってLiteプランの上限である1000を超えてしまいました。テスト的にやられるならサイトによりホップ数を減らしたほうがいいかもしれません。なお、コレクションを削除したら上限はリセットされました。当月はもう使えない、というわけではなさそうですのでご安心ください。

いずれも非常に簡単にクロール対象にできました。おしまい。
NiFi と 他のコンポネント(Kafka/HDFS/...)の関係LineageをAtlasで表示

### 参考資料：
* [Hortonworks DataFlow (HDF) 3.1 blog series part 5: Introducing Apache NiFi-Atlas integration
](https://blog.cloudera.com/hdf-3-1-blog-series-part-6-introducing-nifi-atlas-integration/#respond)
* [Cross Component Lineage with Apache Atlas across Apache Sqoop, Hive, Kafka & Storm](https://www.cloudera.com/tutorials/cross-component-lineage-with-apache-atlas-across-apache-sqoop-hive-kafka-storm/.html)


### NiFi 構成：
![image.png](https://qiita-image-store.s3.amazonaws.com/0/133516/8abb678a-6020-ba4c-bda5-44cdb1e5748b.png)

Template
https://qiita.com/zz22394/items/120060f91ef407f5e492


Controller Service 追加：
![image.png](https://qiita-image-store.s3.amazonaws.com/0/133516/aaf1f4fb-0662-1e1f-c861-f8571dead91f.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/133516/e4d6b783-ffd5-d8eb-2203-fee638083064.png)

Controllerサービス設定：
![image.png](https://qiita-image-store.s3.amazonaws.com/0/133516/c8cfec90-2114-a997-cbde-b09b9059e3e8.png)

### Atlas

Lineage
![image.png](https://qiita-image-store.s3.amazonaws.com/0/133516/187eb296-9f12-5e51-1d41-a4f8ccdda95f.png)

詳細：
![image.png](https://qiita-image-store.s3.amazonaws.com/0/133516/f7de54d7-b3b2-3941-abf4-176851628d26.png)
#簡潔 propsの値を自身のイベントで変更させる方法 #忙しい人のためのシリーズ


### ユースケース

- ダイアログの開閉
  - ダイアログを open={true} で開いたが、ダイアログ自身が持つ×ボタンを押したら open: false にしたい

### 以下で実現

```jsx
export default class extends React.Component {

	constructor(props) {
		super(props);
		this.state = {
			open: this.props.open
		};
	}

	componentWillReceiveProps(nextProps) {
		this.setState({ open: nextProps.open });
	}

	render() {
		return (
			<Dialog
				open={this.state.open}
				onClose={this.props.onClose}
			>
				{this.props.children}
				<div className="close" onClick={()=> {
					this.setState({ open: false });
					this.props.onClose();
				}}>×</div>
			</Dialog>
		);
	}
}
```

### ポイント

- `componentWillReceiveProps` でMount後のpropsの変化にも対応
  - これで "一度しか開かない" なんてことが起こらない
- `this.props.onClose();` を呼ぶ
  - これでこのコンポーネントのonClose属性が実行される
UiPath -Close Aplication でExcelが閉じれない-

UiPath でExcelを閉じる場合、Close Application を利用して閉じていた。
複数のExcelを開いていても一発で閉じれていたので重宝していた。

閉じるのに使用したClose Application のセレクタは以下
![image.png](https://qiita-image-store.s3.amazonaws.com/0/158953/4b9c4723-71ab-f304-0798-1aa0be64ff42.png)

## しかし、複数のExcelファイルが閉じれない事象が発生した。

閉じれなかった時の動作を目で追っていると、以下のポップアップが表示されていた
![image.png](https://qiita-image-store.s3.amazonaws.com/0/158953/794ba99f-6b43-7a3d-68fe-ea285f4d7c0d.png)

変更が入っているExcelファイルを閉じようとした際に、上記ポップアップが表示され、
該当ファイル(Book1)はColse Application のTimeOut時間がきたら、閉じられたが、
それ以外に開いていたExcelファイルが閉じられずにUiPathは終了してしまった。

閉じられたファイルを次回開いた際には以下の表示がされていた。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/158953/558e50f9-b0c1-44e0-8e06-b3ed27e688ef.png)

## 複数のExcelファイルを確実に閉じるには
- Kill Process を使う
- Processを取得してExcelプロセスがなくなるまでClose Application を繰り返す  
などをする必要があるのだろうか...

UiPathを利用していて変更が保存されていないような事象を起こすなよという声がごもっともですが...
.NET Core（コンソールアプリ）で、設定ファイルとのやりとりをする(dotnet core 2.2)

## ConfigurationBuilder だけだと、読み込みしか出来ない？

ConfigurationBuilder()を利用して設定を読み込む処理の情報はたくさん見つかるけれど、書き込みをする情報が見つからない。AddJsonFileメソッドの optional: true にすると、もしかして書き込めるのかとも思ったけども、バインディング使うと反映されていないので、ちょっと現在の考え方では使えなさそう。
ConfigurationManagerは、dotnet core では使えないという記事が多いけど、Macで書いてると普通に使えるから、dotnet core(standard) の最新版だと、使えるようにAPI追加されたのだろうと思い、これらを駆使して実装することにしてみたので、記録として残しとく。

## ConfigurationBuilder は読み込み用に。

こちら、パッケージに含まれていない場合があるので、NuGetで手に入れとく。
まだ全容把握してないので、漏れがあるかも...
JSONファイル形式で操作するので、Jsonもいれる。

```
Microsoft.Extensions.Configuration
Microsoft.Extensions.Configuration.Json
```

依存関係があるパッケージは勝手に入るから、それを放り込んでおけばいい。

読み込みしたい場所に、ConfigurationBuilderでの処理を書く

```c#
using System.IO;
using Microsoft.Extensions.Configuration;

var builder = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appsettings.json", optional: true);

var build = config.Build();

// バインディングしたい場合は、そのクラスを作りオブジェクト化してバインディングする
var appSettings = new AppSettings();
build.Bind(appSettings);
```

Microsoft.Extension.Configuration.Json などのパッケージを入れていないと、new ConfigurationBuilder() のあとに . 入れても、SetBasePath() メソッドなどがインテリセンスで見つからないので注意が必要。最近の開発環境だと、コンソールやらASP.NETのプロジェクトを作ると、Microsoft.Extensions.Configurationのパッケージだけは入っているのかもしれない。なので、最初は迷った。

## 書き込み用に ConfigurationManager を使う

読み込みもこちらでしたらいいのでは？と思ったけど、うまくsection 分けが dotnet core ではできなかった（.NET Frameworkと差があるのだろうか）のと、開発用とデプロイ用で設定を分けようとすると上のがやりやすいのと、こちらの方法、保存をするとコメントを吹っ飛ばしてくれるので、分けることにした（sectionが分けられなかったのでしかたなくというか）

```c#
using System.Configuration;

var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var ret = config.AppSettings.Settings["hogehoge"].Value;
config.AppSettings.Settings["hogehoge"].Value = "3";
config.Save();
```

文字列で保存されちゃうので、数値の取り扱いなどだとパースする必要があり面倒だけど、致し方あるまい。

## まとめ

ASP.NET Core でも当然だけど一応使える。とはいえ、WebだとDB使ったりするし、普通に多目的用とだからあまりConfigurationManagerのお世話になることは無いと思うけど。あとは、.NET Core 3.0 からWPFやらUWPやらWindows Forms も採用されるので、ウィンドウの場所とか保存するために設定ファイルに保存する用途なりはあると思うけど、保存処理の実装はあるのかな。バインディングしてるからだめなのかもしれないけど...。
canvasに画像を表示する

やってみたら直感的にできなかったので少し調べました。
メモとして残しておきます。

```index.html
<html>
<body>
Test<br />
<canvas id="canvas"></canvas>
</body>
<script>
    const canvas = document.getElementById("canvas");        
    let imagePath = "image.png";
    draw(canvas,imagePath);
    function draw(canvas,imagePath){
        console.log("draw");
        const image = new Image();
        image.addEventListener("load",function (){
            canvas.width = image.naturalWidth;
            canvas.height = image.naturalHeight;
            const ctx = canvas.getContext("2d");
            ctx.drawImage(image, 0, 0);
            console.log("load!");
        });
        image.src = imagePath;
    }
    </script>
</html>
```
idがcanvasのcanvasタグ内にimage.pngを表示させます。
試す場合は、index.htmlと同じ場所にimage.pngを適当な画像で準備してください。

addEventListenerはonloadでも問題ないですが、個人的にはaddEventListenerの方が馴染みがあるのでaddEventListenerを使っています。
今更ながらVisual Studio 2015を取得する方法（VSの過去バージョンの取得方法）

#きっかけ
過去にC++の開発をしていた時のソースについて質問を受けた時に、ほぼ忘れていたのでもう一度ビルドしてみようとVS2017をインストールしてビルドしようとして失敗。。
ええい！と思って当時の環境と同じVS2015をゲットした方法。

結局ビルドに失敗した原因はこれか・・・的なものは分かってVS2017でもビルドできるだろうけど、過去のVS関連を取得する方法はメモっておこうかなと。
（十中八九すぐに陳腐化するメモだとは思いつつ）

#ポイントは、`Dev Essentialsプログラム`への登録
https://visualstudio.microsoft.com/ja/vs/older-downloads/

上記のURLへは普通にたどり着くけど、普通にサイトを見ている分には最新のVSへの誘導が基本。

ちゃんと読めば、過去のバージョン使いたいなら`Dev Essentialsプログラム`に入りなと。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/57515/48a881bd-2efc-cd57-65fc-82966839c7fc.png)

##登録はまぁ画面のままやる
他にメモることもないかな。

#登録後になんかVSの管理画面が開かれる
https://my.visualstudio.com/Benefits

ダウンロードタブからソフトの検索ができるので、そこからダウンロード。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/57515/1e927870-6555-ed96-0f73-3d6e11065a2c.png)

#最後に
もっと古い2008や2010なんかもあるので、いざ古いソースを触る機会があったら必要になるかも。
OSが合わずに入れられないこともあり得るけど。。。
Ubuntu On Windows上でopen（あるいはxdg-open）みたいなこと

Ubuntu On Windows上でopen（あるいはxdg-open）みたいなこと

Ubuntu on Windowsのシエルで作業しているときに時々エクスプローラでひらきなおしたくなることがあり調べた

以下のコマンドを叩けばカレントデイレクトリをエクスプローラで開くことができる

```bash上で
cmd.exe /c start "" .
```


参考↓
https://qiita.com/pedantryjp/items/564a961f6fe966e6260d
No.037【Python】ディクショナリーのキーの名前変更

![python-logo-master-v3-TM-flattened.png](https://qiita-image-store.s3.amazonaws.com/0/336067/8fb9f6aa-57f7-dc4b-b4bf-a648969d315c.png)

####今回は、ディクショナリーのキーの名前を変更する方法について書いていきます。
I'll write about "key-name change of a dictionary ", in python" on this page.

###■ 古い要素を削除し、新たな要素を追加する
&emsp;Delete old factors and add new factors


```
>>> # delの使用
>>> 
>>> d = {"key1":1, "key2":2, "key3":3}
>>> 
>>> d["key10"] = d["key1"]
>>> 
>>> del d["key1"]
>>> 
>>> print(d)
{'key2': 2, 'key3': 3, 'key10': 1}
```

``` 
>>> # pop()の使用
>>> # pop():要素を削除+そのキーの値取得が可能
>>> 
>>> d = {"key1":1, "key2":2, "key3":3}
>>> 
>>> print(d.pop("key1"))
1
>>> 
>>> print(d)
{'key2': 2, 'key3': 3}
``` 

``` 
>>> # del文よりもシンプルに記載が可能
>>> 
>>> d = {"key1":1, "key2":2, "key3":3}
>>> 
>>> d ["key10"] = d.pop("key1")
>>> 
>>> print(d)
{'key2': 2, 'key3': 3, 'key10': 1}
``` 

```  
>>> # 注意：デフォルトの状態では、第一引数に存在しないキーを指定するとエラーになる
>>> 
>>> d = {"key1":1, "key2":2, "key3":3}
>>> 
>>> print(d.pop("key10"))
Traceback (most recent call last):
  File "<pyshell#36>", line 1, in <module>
    print(d.pop("key10"))
KeyError: 'key10'
``` 

```
>>> # 第二引数の値を指定の場合、エラーにならない
>>> 
>>> print(d.pop('key10', None))
None
>>> 
>>> print(d)
{'key1': 1, 'key2': 2, 'key3': 3}
```

###■ キーの名前を変更する関数の定義
&emsp;Define a function when a key-name is changed


``` 
>>> # pop()により、以下の関数定義ができる
>>> 
>>> def change_dict _key(d, old_key, new_key, default_value=None):
	
SyntaxError: invalid syntax
>>> def change_dict_key(d, old_key, new_key, default_value=None):
	 d[new_key] = d.pop(old_key, default_value)

	 
>>> d = {"key1":1, "key2":2, "key3":3}
>>> change_dict_key(d, "key1", "key10")
>>> 
>>> print(d)
{'key2': 2, 'key3': 3, 'key10': 1}
```

```
>>> # 存在しないキーを指定すると、第三引数に指定の値が追加される
>>> 
>>> d = {"key1":1, "key2":2, "key3":3}
>>> change_dict_key(d, "key10", "key100")
>>> 
>>> print(d)
{'key1': 1, 'key2': 2, 'key3': 3, 'key100': None}
>>> 
>>> 
>>> d = {"key1":1, "key2":2, "key3":3}
>>> change_dict_key(d, "key10", "key100", 100)
>>> 
>>> print(d)
{'key1': 1, 'key2': 2, 'key3': 3, 'key100': 100}
```
``` 
>>> # 補足：既存のキーの値を残す場合、setdefault()を使う
>>> 
>>> def change_dict_key_setdefault(d, old_key, new_key, default_value=None):
	d.setdefault(new_key, d.pop(old_key, default_value))

	
>>> d = {"key1":1, "key2":2, "key3":3}
>>> change_dict_key_setdefault(d, "key1", "key2")
>>> 
>>> print(d)
{'key2': 2, 'key3': 3}
```
``` 
>>> # 新規のキーが既存のキーでない場合
>>> 
>>> d = {"key1":1, "key2":2, "key3":3}
>>> change_dict_key_setdefault(d, 'key1', 'key10')
>>> 
>>> print(d)
{'key2': 2, 'key3': 3, 'key10': 1}
>>> 
>>> d = {"key1":1, "key2":2, "key3":3}
>>> change_dict_key_setdefault(d, "key10", "key100")
>>> 
>>> print(d)
{'key1': 1, 'key2': 2, 'key3': 3, 'key100': None}
```

随時に更新していきますので、<br>定期的な購読をよろしくお願いします。
I'll update my article at all times.
So, please subscribe my articles from now on.

本記事について、<br>何か要望等ありましたら、気軽にメッセージをください！
If you have some requests, please leave some messages! by You-Tarin

また、「Qiita」へ投稿した内容は、随時ブログへ移動して行きたいと思いますので、よろしくお願いします。
cx_Freeze 用の tkinter 設定を動的に実施する

cx_Freeze で tkinter を使うコードをビルドすると, 
1. TK_LIBRARY, TCL_LIBRARY の環境変数がセットされていない
2. tk86t.dll tcl86.dll がコピーされない
といった諸々の面倒に出会います.

いろいろなところで解決策が提示されているのですが, アドホックな話が多く, 例えば venv の中できちんと動かすには? といった事例はあまりないように思えます.

ということで取りあえず cx_Freeze 用の setup.py の中で, 上記の 1, 2 を解決するスケルトンです.
(python 3.7 で動作確認)

参考資料は
- https://stackoverflow.com/questions/34939356/python-pygame-exe-build-with-cx-freeze-tcl-library-error 
- https://stackoverflow.com/questions/43464355/how-to-find-the-path-of-tcl-tk-library-that-tkinter-is-currently-using
- https://qiita.com/sta/items/b360c5fb61ae2d22b321


``` python
import sys
import os
import pathlib

# set {TCL,TK}_LIBRARY environment variable
import tkinter
root = tkinter.Tk()
tcl_library_path = pathlib.Path(root.tk.exprstring('$tcl_library'))
tk_library_path = pathlib.Path(root.tk.exprstring('$tk_library'))
os.environ['TCL_LIBRARY'] = str(tcl_library_path)
os.environ['TK_LIBRARY'] = str(tk_library_path)

# find tk86t.dll and tcl86t.dll
tcltk_search_dll = {'tk86t.dll', 'tcl86t.dll'}
tcltk_found_dll = {}

for p in sys.path:
    p = pathlib.Path(p)
    for f in p.glob('*'):
        if f.is_file():
            f_low = f.name.lower()
            if f_low in tcltk_search_dll:
                tcltk_found_dll[f_low] = str(f)
                tcltk_search_dll.remove(f_low)

                if not tcltk_search_dll:
                    break
    else:
        continue
    break

if tcltk_search_dll:
    raise 'cannot find tcl/tk DLL. ' + str(tcltk_search_dll)
print('tcl/tk DLL:', tcltk_found_dll)

tcltk_include_files = [(v, 'lib/'+k) for k, v in tcltk_found_dll.items()]

from cx_Freeze import setup, Executable

buildOptions = dict(
    packages = [],
    excludes = [],
    include_files = tcltk_include_files)

base = 'Console'

executables = [
    Executable('myprog.py', base=base)
]

setup(name='myproj',
      version = '1.0',
      description = 'my project',
      options = dict(build_exe = buildOptions),
      executables = executables)
 
```
Chapter4で少し工夫が必要だったところ

### 書籍「Dockerによるアプリケーション開発環境構築ガイド
Dockerを勉強するために購入した書籍「Dockerによるアプリケーション開発環境構築ガイド（櫻井洋一郎、村崎大輔[著] ISBN978-4-8339-6458-0)」に掲載されていた演習をやった。
Chapter4のところで少し手間取った箇所があったので、メモしておく。

###(1) P199 バケットのアクセス設定
P234の手順で、写真をアップロードしても保存できずにエラーになってしまう。原因はS3のパブリックアクセス設定。
P199のAWS S3の設定画面では本機能は追加されていないが、現在(2019/2)は「パブリックアクセス設定」というのが加わっている。とりあえず以下のチェックを”外して”うまく動くようになった。（どちらか一方でもOKかは未検討）
-「新規のパブリック ACL と、パブリックオブジェクトのアップロードをブロックする 」 
-「パブリック ACL を通じて付与されたパブリックアクセスを削除する」

###(2) P249 MySQL
a) 4-2-1-2に記載のコマンドを入力してもmysqlに接続できない。
接続権限がない状態でMySQLが稼働している模様で、sampleDbもまだないので、以下を実施してアクセス権限をつけた。
i) mySQLが動いているコンテナにdocker exec -it で入る
ii) コンテナの中で mysqlのクライアントを起動し、以下を投入
- create database sampleDb ;
- GRANT ALL PRIVILEGES ON *.* TO sampleUser@"%" IDENTIFIED BY 'パスワード' WITH GRANT OPTION;

###(3) minio関連
####a) 起動時にSyntax Error 
docker-compose upで上げた時に、「strict mode以外では云々でエラー」というメッセージとともに処理が停止してしまい、コンテナがうまく起動できない。
Dockerfileで指定しているimageがminio/minio:RELEASE.2017-08-05T00-00-53Z であるものの稼働環境の適合性が悪い模様。Dockerfileでのimageをminio/minio:RELEASE.2019-02-14T00-21-45Zにしたら解消した。

#### b) ストレージが足りなくてminioが起動しない
AWSのt2.micro環境でDiskを8GBで稼働させていたためらしい。EBSを拡張したら解消した。自分は100GBに拡張したけど、それ以下でもいいかもしれません。

#### 残課題
P273-275は設定してもうまく動かなかった（画像がブラウザで表示されない）けど、Dockerを学ぶという意味ではとりあえず保留w

#### 最後に
なかなかの良書と思います。掲載されている手順に関しては完成度にまだ改善の余地ありですが、完成度よりも鮮度も大事な世の中なので感謝しています。
spring-batchはreaderとかでリスナー実装すると自動登録

# 背景

> An ItemReader, ItemWriter or ItemProcessor that itself implements one of the StepListener interfaces is registered automatically with the Step if using the namespace <step> element or one of the the *StepFactoryBean factories.
> 
> https://docs.spring.io/spring-batch/4.1.x/reference/html/step.html#interceptingStepExecution より抜粋

<code>ItemReader</code>とかの実装クラスに```StepExecutionListener```とかのリスナーを実装しとくと、（少なくともspring-bootと一緒にspring-batch動かす分には）そのリスナーも自動登録する、とのこと。とりあえずやってみる。

というか、知らなくてちょっとびっくりしたんでメモ書きを残す。

# ソースコード
## pom.xml

```xml:pom.xml
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.2.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-batch</artifactId>
		</dependency>
```

## ItemReader + StepExecutionListener

適当なchunk処理をつくる。

```java:SampleChunk
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.stereotype.Component;

@Component
public class SampleChunk implements ItemReader<String>, ItemWriter<String>, StepExecutionListener {

	@Override
	public void write(List<? extends String> items) throws Exception {
		items.forEach(s -> System.out.println(s));
	}

	int i=0;
	
	@Override
	public String read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
		if (i<5) {
			i++;
			return i + "";
		}
		return null;
	}

	@Override
	public void beforeStep(StepExecution stepExecution) {
		System.out.println("beforeStep");
	}

	@Override
	public ExitStatus afterStep(StepExecution stepExecution) {
		System.out.println("afterStep");
		return stepExecution.getExitStatus();
	}
}
```

## step定義
適当なstep定義をつくる。

```java
	@Autowired
	SampleChunk r2;

	@Bean("chunkstep1")
	public Step step1() {
		StepExecutionListener s = new SampleChunk();
		return stepBuilderFactory
				.get("step1")
				.<String, String>chunk(1)
				.reader(r2)
				.writer(r2)
				.build();//.listener(s)
	}
```

## 実行

```
beforeStep
1
2
3
4
5
afterStep
```

確かにリスナーも登録されている。

## listenerでも登録
以下のように```listener```でもリスナーを登録してみる。

```java
	@Bean("chunkstep1")
	public Step step1() {
		StepExecutionListener s = new SampleChunk();
		return stepBuilderFactory
				.get("step1")
				.<String, String>chunk(1)
				.reader(r2)
				.writer(r2)
				.listener(s)
				.build();
	}
```

```java
beforeStep
beforeStep
1
2
3
4
5
afterStep
afterStep
```

これだと二重に出る。
WebExtensionのpopupやbackgroundでcurrentTabを取得する場合は代わりにqueryを使う

# まとめ

* popupやbacngroundのスクリプトで[tabs.getCurrent()]は利用不可(undefinedが返る)
 * Promiseの失敗には入らず成功としてundefinedが取得できるので注意
* [tabs.query()]は利用可能なので、プロパティの組み合わせでカレントタブを特定することで代用
 * 組み合わせの一例は`{ currentWindow:true, active:true }`や`{ windowId: browser.windows.WINDOW_ID_CURRENT, active:true }`
 * queryなので結果は一件だが常に配列で返るのが少し手間
 * `current`や`currentTab`プロパティがあるわけではないので注意

* おそらくAndroid版のpopupは別タブで開かれるのでcurrentがpopupになる可能性がある…(未調査)
 * よってこの記事はPC版限定とする

# 環境

* Ubuntu
* Firefox 65.0 64bit
* 一時的な拡張機能として読み込み

# 公式に明記されている

[tabs.getCurrent() - Mozilla | MDN]

>You can call this function in contexts where there is a browser tab, such as an options page. If you call it from a background script or a popup, it will return undefined.

Google翻訳

>この機能は、 オプションページなどのブラウザタブがあるコンテキストで呼び出すことができます 。 バックグラウンドスクリプトまたはポップアップからそれを呼び出すと、undefinedが返されます。

# コード

popupで動かすとする。

## `tabs.getCurrent()`を使った失敗例 undefinedが返る

```js
browser.tabs.getCurrent().then(tab => {
  console.log('getCurrent', tab) // undefined
}, error => {
  // ここには入らない
  console.error(error)
})
```

## 代用コード

tabs型には直接Currentプロパティはないが、組み合わせや別プロパティからカレント情報を取得して一意に特定することができる。

どちらも結果は同じ。なはず。

```js
browser.tabs.query({ currentWindow:true, active:true }).then(tabs => {
  for (tab of tabs) {
    console.log('currentWindow', tab)
  }
}, error => {
  console.error(error)
})

browser.tabs.query({ windowId: browser.windows.WINDOW_ID_CURRENT, active:true }).then(tabs => {
  for (tab of tabs) {
    console.log('browser.windows.WINDOW_ID_CURRENT', tab)
  }
}, error => {
  console.error(error)
})
```

# 参考

* [tabs.getCurrent() - Mozilla | MDN]
* [tabs.query() - Mozilla | MDN]
* [tabs.Tab - Mozilla | MDN](https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions/API/tabs/Tab)
 * >The active tab is usually the selected one. However, on Firefox for Android, extension popups open in a new tab. When this popup tab is selected, the active tab will instead be the one in which the popup opened.
 * Androidではポップアップがタブになり選択状態になるようなので、Androidかつpopupページ内での開く前のカレント取得には別アプローチが必要そう
* [windows.WINDOW_ID_CURRENT - Mozilla | MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows/WINDOW_ID_CURRENT)

***

* [javascript - Chrome extension: Get current tab from popup - Stack Overflow](https://stackoverflow.com/questions/13359421/chrome-extension-get-current-tab-from-popup)
* [javascript - tabs.getCurrent() result is undefined? - Stack Overflow](https://stackoverflow.com/questions/43695817/tabs-getcurrent-result-is-undefined)

[tabs.getCurrent()]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/getCurrent
[tabs.getCurrent() - Mozilla | MDN]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/getCurrent
[tabs.query()]: https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query
[tabs.query() - Mozilla | MDN]: https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query
opencv.jsの作法 その8

# 概要

opencv.jsの作法を調べてみた。

# 実行環境

sandboxを用意した。以下のコードは動く。
https://s.codepen.io/ohisama/debug/YBRBed/XxMVwaxzgzyr

# カメラで、直線検出。


```javascript
let video = document.getElementById('videoInput');
let src = new cv.Mat(video.height, video.width, cv.CV_8UC4);
let color = new cv.Scalar(255, 0, 0, 255);
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
let cap = new cv.VideoCapture(video);
const FPS = 30;
function processVideo() {
	try 
	{
		if (!streaming) 
		{
			src.delete();
			dst.delete();
			return;
		}
		let begin = Date.now();
		cap.read(src);
		cv.cvtColor(src, dst, cv.COLOR_RGBA2GRAY);
		cv.Canny(dst, dst, 50, 200, 3);
		let lines = new cv.Mat();
		cv.HoughLinesP(dst, lines, 1, Math.PI / 180, 50, 0, 0);
		for (let i = 0; i < lines.rows; ++i)
		{
			let startPoint = new cv.Point(lines.data32S[i * 4], lines.data32S[i * 4 + 1]);
			let endPoint = new cv.Point(lines.data32S[i * 4 + 2], lines.data32S[i * 4 + 3]);
			cv.line(src, startPoint, endPoint, color);
		}
		cv.imshow('canvasOutput', src);
		let delay = 1000 / FPS - (Date.now() - begin);
		setTimeout(processVideo, delay);
	}
	catch (err)
	{
		utils.printError(err);
	}
};
setTimeout(processVideo, 0);

```

以上。
Linux上のPharoで日本語を入力する方法

# zeroconfの場合

```
./pharo-ui -compositioninput Pharo.image
```

で起動してください。```-compositioninput```がミソです。
これはCogVMのオプションなので、Squeakでも同様です。

# PharoLauncherの場合

現状のPharo LauncherではVMへのオプションを設定できないので、PharoLauncherに手を入れてみました。VMのキャッシュのスリプトを編集する手もありますが、VMが更新されるたびに編集するのは面倒臭いので、とりあえずPharoLauncherに unix系だったら ```-compositioninput```オプションを付けてPharoを起動するようにしました。

gistに[パッチ](https://gist.githubusercontent.com/tomooda/c70abc3efdea398b80137a111e5a919b/raw/64658e381f2ee74008e1abb0b6da8767d115fcf2/PhLImage-launchCommandWithuseSettings.st)を置きました。

```
wget https://gist.githubusercontent.com/tomooda/c70abc3efdea398b80137a111e5a919b/raw/64658e381f2ee74008e1abb0b6da8767d115fcf2/PhLImage-launchCommandWithuseSettings.st
```
をコマンドシェル上で実行して、LinuxをGUIで使っている人は、できたファイルを **既に開いているPharoLauncher** 上にドロップしてください。
すると、メニューが出るので、Install into new change setを選んでください。

<img width="873" alt="PharoLauncherウィンドウ上にドロップ" src="https://qiita-image-store.s3.amazonaws.com/0/59918/ff0c8429-c686-313c-9681-979ed180b456.png">

CUIで使っている人は、[PharoLauncherで日本語を使えるようにする3つの方法](https://qiita.com/tomooda/items/fa60135868df43e7ba78)を参考にして、開発者モードにして、上記ファイルをfileinしてください。

そして右下のQuitボタンで、一旦PharoLauncherを終了してください。

<img width="69" alt="スクリーンショット 2019-02-19 7.52.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/59918/0075d00a-1b39-af10-7888-cb0bb96bd828.png">

ウィンドウマネージャの「閉じる」ボタンで終了すると修正が保存されない場合があったり色々面倒なので、必ず **Pharo Launcherの右下のQuitボタン** を使ってください。

なお、パッチの内容は以下の通りです。決め打ちのハックにすぎないので、そのうち一般化してPharoLauncherにPRします。

```
launchCommandWith: vmCommand useSettings: usePharoSettings
	| imagePath vmDirectoryPath command basicCommand |
	imagePath := file pathString.
	vmDirectoryPath := vmCommand asFileReference parent fullName.
	command := String
		streamContents: [ :cmd | 
			cmd << 'cd ' << file parent pathString surroundedByDoubleQuotes << ' && '.
			Smalltalk os isUnix
				ifTrue: [ cmd << (self exportLDLibraryPathCommandWith: vmDirectoryPath) << ' && export SQUEAK_PLUGINS="" && ' ].
			cmd << vmCommand surroundedByDoubleQuotes.
			Smalltalk os isUnix ifTrue: [ cmd << ' -compositioninput'].
			cmd << ' ' << imagePath surroundedByDoubleQuotes.
			usePharoSettings ifFalse: [ cmd << ' --no-default-preferences End of statement list encountered ->' ] ].
	basicCommand := self class launchInALoginShell
		ifTrue: [ Smalltalk os isWindows
				ifTrue: [ 'cmd /C ' , command ]
				ifFalse: [ 'bash -l -c ''' , command , '''' ] ]
		ifFalse: [ command ].
	^ basicCommand utf8Encoded asString
```
Ruby on Rails, Vue.js で始めるモダン WEB アプリケーション入門（bootstrap編）

# はじめに

[Ruby on Rails, Vue.js で始めるモダン WEB アプリケーション入門](https://qiita.com/tatsurou313/items/4f18c0d4d231e2fb55f4)では ActiveAdmin を導入したためデフォルトの設定のままだとアプリケーション全体で同じ CSS スタイルが適用されていました。

今回、ActiveAdmin のスタイルはアプリケーション全体には適用せずに ActiveAdmin が管理するページのみに留め、アプリケーション全体では bootstrap を利用することにします。

# ActiveAdmin のスタイルを ActiveAdmin 管理ページのみに留める

そもそもアプリケーション全体に ActiveAdmin のスタイルが適用されているのは、 `app/assets/stylesheets/active_admin.scss` が `app/assets/stylesheets/application.scss` の `*= require_tree .` により読み込まれているためです。

回避する方法は ActiveAdmin の[公式ページ](https://github.com/activeadmin/activeadmin/blob/master/docs/14-gotchas.md#css)に書かれているとおり、active_admin.scss を `app/assets/stylesheets/` から `vendor/assets/stylesheets/` へ移動することにします。

これで ActiveAdmin で管理されている employee モデルの管理ページはスタイルそのままに、アプリケーションページ (`http://localhost:3000/` など) は ActiveAdmin のスタイルが当たらなくなります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/206493/b19e43ca-8f38-cffc-a983-de7104f9a7be.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/206493/c02f9054-e5ce-9de9-c612-ab1cdba4c868.png)


# bootstrap をインストールする

次に bootstrap をインストールします。

webpacker を使っているため yarn コマンドを使って bootstrap をインストールします。
また bootstrap で利用している jQuery, popper.js もインストールします。

```bash:bootstrap,jQuery,popper.jsをインストールする
$ yarn add bootstrap jquery popper.js
```

次に bootstrap の読み込みを JS, CSS それぞれ行います。

```app/javascript/packs/application.js
  : <snip>
import 'bootstrap/dist/js/bootstrap'
```

```app/javascript/packs/vue_sample_app.css
@import 'bootstrap/dist/css/bootstrap'
```

また、webpack で jQuery, popper.js をプラグインとして追加します。

```config/webpack/environment.js
const { environment } = require('@rails/webpacker')
  : <snip>
// Use bootstrap (with jquery, popper.js)
const webpack = require('webpack')
environment.plugins.append(
    'Provide',
    new webpack.ProvidePlugin({
        jQuery: 'jquery/dist/jquery',
        Popper: 'popper.js/dist/popper'
    })
)

module.exports = environment
```

これで bootstrap の導入は終わりです。

後は各ページに対して bootstrap を使ってスタイルを適用させていきます。
※ bootstrap を使ったコードは詳細を割愛します。詳細を知りたい場合は [GitHub のページ](https://github.com/ryu-sato/vue-sample-app)を参照してください。

|TOP画面|Deleteボタン押下時|
| --- | --- |
|![image.png](https://qiita-image-store.s3.amazonaws.com/0/206493/bc18ee71-90cc-7439-6635-71955f6c4bba.png)|![image.png](https://qiita-image-store.s3.amazonaws.com/0/206493/4c91f542-f4fa-1542-5de3-dd129e3c9410.png)|

|新規作成画面|詳細画面|
| --- | --- |
|![image.png](https://qiita-image-store.s3.amazonaws.com/0/206493/5010ecfe-6713-a665-8ca0-e5c007a09e17.png)|![image.png](https://qiita-image-store.s3.amazonaws.com/0/206493/cf88f1d0-ae60-b9c4-2db9-69ec43b3431e.png)|

# 本記事に対するコメントを受けて修正した履歴とお礼

* 2019/07/17 yuuna さんより "ActiveAdmin のスタイルを ActiveAdmin 管理ページのみに留める" にて書かれている active_admin.scss の移動先ディレクトリが誤っていると指摘を頂き修正しました。