OmniAICreator/Qiita-1.07M huggingface dataset:
[Go]文字コードのUTF-8変換を行う - autodetect

文字コードが分からない際にautodetectする場合、自前でゴリゴリ書いていたのですが
ICU実装をgoで書いた[saintfish/chardet](https://github.com/saintfish/chardet)という便利libraryがありました。

# 実装

```Go
package main

import (
	"errors"
	"fmt"
	"github.com/saintfish/chardet"
	"golang.org/x/net/html/charset"
	"golang.org/x/text/transform"
)

// Converts to UTF-8.
// Charset automatically detected.
func DecodeAutoDetect(src []byte) (string, error) {
	d := chardet.NewHtmlDetector()
	r, err := d.DetectBest(src)
	if err != nil {
		return string(src), err
	}
	e, _ := charset.Lookup(r.Charset)
	if e == nil {
		return string(src), errors.New(fmt.Sprintf("invalid charset [%s]", r.Charset))
	}
	decodeStr, _, err := transform.Bytes(
		e.NewDecoder(),
		src,
	)
	if err != nil {
		return string(src), err
	}
	return string(decodeStr), nil
}
```

車輪の再発明はしないに越したことはないです。

# 確認

とはいえ[saintfish/chardet](https://github.com/saintfish/chardet)って更新だいぶ昔に止まっているし、本当に判別できるのか心配になったので`Shift-JIS` `EUC-JP` `ISO-2022-JP` `UTF-8`の以下サイトを突っ込んでテストを回してみる。

http://charset.7jp.net/sjis.html
http://charset.7jp.net/jis.html
http://charset.7jp.net/euc.html
https://www.unicode.org/reports/tr51/tr51-18.html

```Go
package chardet_test

import (
	"github.com/saintfish/chardet"
	"io"
	"os"
	"path/filepath"
	"testing"
)

func TestDetector(t *testing.T) {
	type file_charset_language struct {
		File     string
		IsHtml   bool
		Charset  string
		Language string
	}
	var data = []file_charset_language{
		{"utf8.html", true, "UTF-8", ""},
		{"utf8_bom.html", true, "UTF-8", ""},
		{"8859_1_en.html", true, "ISO-8859-1", "en"},
		{"8859_1_da.html", true, "ISO-8859-1", "da"},
		{"8859_1_de.html", true, "ISO-8859-1", "de"},
		{"8859_1_es.html", true, "ISO-8859-1", "es"},
		{"8859_1_fr.html", true, "ISO-8859-1", "fr"},
		{"8859_1_pt.html", true, "ISO-8859-1", "pt"},
		{"8859_1_pt.html", true, "ISO-8859-1", "pt"},
		{"iso-2022-jp.html", true, "ISO-2022-JP", "ja"},
		{"gb18030.html", true, "GB-18030", "zh"},
		{"euc_jp.html", true, "EUC-JP", "ja"},
		{"euc_kr.html", true, "EUC-KR", "ko"},
		{"big5.html", true, "Big5", "zh"},
	}

	textDetector := chardet.NewTextDetector()
	htmlDetector := chardet.NewHtmlDetector()
	buffer := make([]byte, 32<<10)
	for _, d := range data {
		f, err := os.Open(filepath.Join("testdata", d.File))
		if err != nil {
			t.Fatal(err)
		}
		defer f.Close()
		size, _ := io.ReadFull(f, buffer)
		input := buffer[:size]
		var detector = textDetector
		if d.IsHtml {
			detector = htmlDetector
		}
		result, err := detector.DetectBest(input)
		if err != nil {
			t.Fatal(err)
		}
		if result.Charset != d.Charset {
			t.Errorf("[%s] Expected charset %s, actual %s", d.Charset, d.Charset, result.Charset)
		}
		if result.Language != d.Language {
			t.Errorf("[%s] Expected language %s, actual %s", d.Charset, d.Language, result.Language)
		}
	}
}
```

```
=== RUN   TestDetector
--- FAIL: TestDetector (0.07s)
    detector_test.go:58: [ISO-2022-JP] Expected language ja, actual 
FAIL
```

あら、`ISO-2022-JP`の場合はlanguageの判定が出来ないようです。
ただし、charsetの判定は出来ているので問題はなさそう。
画像、マルチメディアデータの表現方法、CPUとコンピュータの5大装置,ノイマン型コンピュータ

#画像、マルチメディアデータの表現方法
　あらかじめ数がきまっている文字とは違って、画像、音声、動画等のデータは定型ではなので
　文字のように、**「番号を割り当てる」**ことはできないので、それぞれの形式にあった
　ディジタル化**(マルチメディア)**処理を施すことで、データを数値として表現
**画像**
 　・画像データはドットの情報を集めたもの
　 ・１ビットにつき色数によって異なる
　![図32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/ba62dd18-e8f8-ecf3-25d4-b2b5eb8d788d.png)

また、画像を表すために必要なデータサイズの計算方法は以下の通り
　![図33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/66f2e829-ef14-d689-7c0f-ed7926ae4f66.png)

**音声データ**
アナログの波刑データをディジタル化して数値表現する体表格は<font color="#cc0000">PCM(Pulse Code Modulation）</font>方式
音声を微小な時間単位に区切り、その単位ごとの音程を数値化することで表現、再現方法以下の２種類となっています。
 **標本化(サンプリング)**
 ![図34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/b6f86aad-82aa-9ba1-aefe-fbda7c2a55db.png)

**量子化**
 信号レベルを何段階で表現するか定め、サンプリングしたデータをその段階数にあてはめて整数値に置き換える処理が**量子化**
 標本を何ビットのデータで表すかで粒子かの段階数が決まる。
　![図35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/c036beb6-b09c-03d6-1deb-cbfe262fd396.png)

#CPUとコンピュータの5大装置
コンピュータのハードウェアは大きく分けると５つの装置で構成されています。
![図36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/c1e2358f-3a55-8157-935a-1c9bd2b275ae.png)

装置間の制御やデータ、プログラムの流れは次のようになります。
<font color="#cc0000">※CPUと各装置を結ぶ回線をバスと呼ぶ</font>
![図37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/db405da3-b984-7bdb-ee92-94e9ae40bbca.png)

#ノイマン型コンピュータ
　以下の２種類の方式があるコンピュータのことを呼ぶ
　**プログラム内蔵方式(または、プログラム記憶方式)**
　プログラムを実行時にはあらかじめ主記憶装置上に読み込んでおく方式
　
　**随次制御方**
　プログラムの命令を１つずつ取り出して順番に実行していく方式

#以上
一番かんたんにasync/awaitを理解する

近頃ようやくasync/awaitを理解した。巷の例はむやみに複雑なので、極力単純化して説明する。

## 同期関数

以下のプログラムは標準入力の内容を ``** start **`` と ``*** end ***`` に挟んで出すだけの処理である。**同期関数** の ``readFileSync()`` を使っている。

```echo0.js
const fs = require('fs');

console.log('** start **');
console.log(fs.readFileSync(0, 'utf-8'));
console.log('*** end ***');
```

```
$ echo -n Hello | node echo0.js
** start **
Hello
*** end ***
```

## コールバック

``readFileSync()`` の代わりに非同期の ``readFile()`` を使わざるを得ないと仮定する。**コールバック** で処理すると以下のプログラムになる。

```echo1.js
const fs = require('fs');

function getstdin(callback) {
    fs.readFile(0, 'utf-8', (err, data)=>callback(data))
}

console.log('** start **');
getstdin(console.log);
console.log('*** end ***');
```
当然ながら期待した結果にはならない。

```
$ echo -n Hello | node echo1.js
** start **
*** end ***
Hello
```

## Promise

コールバックを **Promise** に置き換える。

```echo2.js
const fs = require('fs');

function getstdin() {
    return new Promise(resolve=>{
        fs.readFile(0, 'utf-8', (err, data)=>resolve(data))
    });
}

console.log('** start **');
getstdin().then(data=>console.log(data));
console.log('*** end ***');
```
やはり結果は同じだ。

```
$ echo -n Hello | node echo2.js
** start **
*** end ***
Hello
```

## async/await

**async/await** を使うと以下になる。

```echo3.js
const fs = require('fs');

function getstdin() {
    return new Promise(resolve=>{
        fs.readFile(0, 'utf-8', (err, data)=>resolve(data))
    });
}

(async ()=>{
    console.log('** start **');
    console.log(await getstdin());
    console.log('*** end ***');
})();
```

 - Promise を await つきで呼び出すと同期処理となり、.then() で受け取るべき値を戻り値として受け取れるようになる。
 - await は async 宣言された関数内でしか使うことはできない。

上記の例では await を使うためだけに async 宣言した無名即時関数で囲っている。

結果は期待通り。OK!

```
$ echo -n Hello | node echo3.js
** start **
Hello
*** end ***
```
## まとめ

 1. Promise で記述された非同期処理を同期的に扱いたい場合は、その呼び出しに **await** をつけることで .then() で非同期に受け取るべき値を返り値として同期的に受け取れるようになる。
 2. その代償として await を囲む関数は非同期となる。そのことを明示的に示すために宣言に **async** をつけなければならない。
 3. async 宣言された関数は非同期となるので return で値は返せなくなる。return を使っている場合は呼出し元ではその関数が Promise であるかのごとく .then() で受け取らなくてはならない。
SIM Free iphoneの設定でつまづいた話

##au iphone5sからSIM FREEのiphoneSEへ
知り合いから中華系のアクションカメラを譲ってもらったので、
このタイミングで背面がバキバキで使っていたiphone5sをSEへ切り替えることとなった。
auは十数年来使っていたが、HTC10から、つなぎの意味で中古iphone5sを持ち込みでSIM交換してもらい利用。
過去に家族のau iphone6をau iphoneSEへSIMを入れ替えただけで使えた経緯もあり、
今回も差し替えるだけで使えるものと思っていた。
###でも、うまくいかない。SMSが使えない。
あれ？SMSが使えない。
かれこれ2時間調べたり、SIMを抜き差しして、
判明した原因をここにメモとして後人のために記す。

##差し替えても、SMSが使えなかった。
macやipadでも受送信できる利点が良かったので、
iOS系スマホにしたのにうまくいかないのは不思議だった。

[キャリアのサイト](https://www.au.com/iphone/support/guide/)を見たり、
[appleのサイト](https://support.apple.com/ja-jp/HT204065)を見たり、
いろいろ試した。
しかも、wi-fiを切って、safariを開くとデータ通信はできてるっぽい。

###どうやら、通話ができなかった。
携帯電話には通話テストの番号というものがある。([こちら](https://novlog.me/nw/tel-test-111/)を参照されたし。)
"111"という番号。
かけてもたら、つながらない。

###通話できないことについて調べた。
appleのサイトでも発信/受信ができないことについては[掲載され](https://support.apple.com/ja-jp/HT204027)ていた。
他にもいろんなサイトが出てきた。
まとめると以下のような原因が書かれていた。たぶん。
- キャリアごとの周波数が違うんじゃない？
- SIMロックされてないんじゃない？
- そもそも、モバイル通信がOFFになってない？
- 機内モードになってない？
- SIMがちゃんと刺さってる？
- iOS APNがされている？
そんなところだった。

今回、購入したのはSIM FREEだから、キャリアの違いとか、
SIMロック解除は関係ないはず。
他にも、[設定] > [電話]で自分の番号が出てる？とか。
[設定] > [メッセージ] > [iMESSAGE]や[SMSで送信]が正しくチェックされている？などがあった。

確かに、私の事象だと、[iMessage]のグループにある[送受信]で、
[新規チャットの発信元]から電話番号が無かった。

これは怪しい。
そして、キャリアごとのアップデートとかもあるとかで、
[設定] > [一般] > [情報]にある[ネットワーク]のグループなども見たが、
特にアップデートのお知らせもなく、詰まっていた。

##モバイル通信に答えがあった。
困ったので、原因として考えられる設定を見返していたところ、
[設定] > [モバイル通信] > [通信のオプション]を開いたときに手が止まった。
そこの値は「ローミングオン」となっているけど、
中身を見ると、
音声通話とデータが「**4G, VoLTEオン**」になっていた。
前に、HTC10からiphone5sへ切り替えたときに、VoLTEが使えないとかなんとか言っていたことを思い出す。
ここか？と「**3G**」にし直して、「111」へかけたところ、
**つながった!!**

##結論：回線規格でつながらなかった
結果、「**4G, VoLTEオフ**」にしたら、
通話も、SMSも使えました。
なんともお粗末なつまずきでしたが、
今後もあると思ったのでメモとして残します。

技術的なお話はまた今度。
##余談
最近、仕事でコンポーネント的なコーディングを行っているのですが、
displayを、flexか、gridか、はたまたtableかで迷うことがある。
デザイナーがアレなので、伸び縮みしたときや要素が押し広げたときのことを
考慮していない形でよこしてきたときに、どれが良いか悩む。
かつ、IE11だと、flexだと、テキストが飛び出す(word-breakが効かない)こともあり、
いっそのことtableでやってしまってもよいかと思う。
gridの場合、行が膨らむと面倒になってしまうし、
うーむどうしたらいいか。
AWS の ALB 配下の apache にてアクセス元IP（Client IP）を X-Forwarded-For ヘッダの一番右の値で上書きする

# 概要

AWS の ALB 配下に apache を置いた場合、apache へのアクセス元 IP は ALB のアドレスになります。多くの場合、これは嬉しくなく、ALB へのアクセス元の IP が欲しくなります。

ALB はアクセス元 IP を X-Forwared-For ヘッダに設定してくれるので、ここからアクセス元 IP を抽出し、apache 側でアクセス元 IP として利用することができます。それには mod_remoteip を使用します。

この通り、ただそれだけの簡単な話なのですが、意外と設定に手間どってしまったので、設定方法を書いておきます。もちろん、[mod_remoteip](http://httpd.apache.org/docs/current/mod/mod_remoteip.html) のドキュメントに記載してあるわけですが・・・少なくとも私には分かり辛かったです。

ここで解説するのは internet 向けの ALB での設定方法です。LAN 内で使用する ALB の場合は別の設定になりますので注意ください。

# 設定方法

httpd.conf にて mod_remoteip を読み込むようにします。

```conf/httpd.conf
LoadModule remoteip_module modules/mod_remoteip.so
```

X-Forwarded-For ヘッダの値でアクセス元IP を上書くように設定します。

```conf/httpd.conf
# Overwrite remoteip with X-Forwarded-For header value
<IfModule remoteip_module>
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxyList conf/trusted-proxies.lst
</IfModule>
```

RemoteIPTrustedProxyList を以下のように設定します。

```conf/trusted-proxies.lst
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
```

これにて設定完了です。＃反映には apache を restart する必要があります。

apache のアクセスログに "%a" で出力設定できる client ip が ALB の IP でなく、ALB へのアクセス元の IP になります。やったね！

# ポイント解説

`RemoteIPTrustedProxyList conf/trusted-proxies.lst` をちゃんと設定するのが肝要です。
信頼できる proxy ということですが、これを理解するには X-Forwarded-For が信頼できるのか、ということを考えると良いと思います。

X-Forwarded-For はただの HTTP header です。これは送信者が自由に設定することができます。
例えば、あなたのブラウザからリクエストを送信する際、`X-Forwarded-For: XXX.XXX.XXX.XXX` みたいな感じに header を設定しておけば、受信サーバ側に XXX.XXX.XXX.XXX からアクセスが来たと思わせることができます。これでは受信サーバは騙されホーダイなので、RemoteIPTrustedProxyList を設定して、そこにない IP によって設定された X-Forwarded-For を信頼しない（辿るのをやめる）ようにします。

例えば、`X-Forwarded-For: XXX.XXX.XXX.XXX, YYY.YYY.YYY.YYY, ZZZ.ZZZ.ZZZ.ZZZ` が送られて来たとします。RemoteIPTrustedProxyList を設定していない場合、アクセス元 IP として XXX.XXX.XXX.XXX が利用されます。右から順に走査して、一番左の IP まで辿り着いた、ということです。RemoteIPTrustedProxyList を設定している場合（かつ、それが X-Forwarded-For に設定している IP を含まない場合）、アクセス元 IP として ZZZ.ZZZ.ZZZ.ZZZ が利用されます。

internet 向けの ALB のアクセス元 IP が欲しい場合、通常、X-Forwarded-For header の最後に付与された値（＝最も右の値）が欲しいと思うので、上で記載したように、trusted-proxies.lst に private IP を指定すれば良いと思います。＃ALB と apache が同一の LAN 内に存在している（ALB → apache の通信のアクセス元 IP はALB の private IP になる）ことを仮定しています。

ちなみにですが、ローカル開発環境などで、本設定の動作確認をする際の注意点があります。X-Forwarded-For に private IP を設定していると、うまくいかない可能性があります。なぜなら、X-Forwarded-For を右から順に走査していって private IP に行き当たると、mod_remoteip は X-Forwarded-For header を丸ごと無視してしまうからです。internet 向けの LB の場合、このようなケースは存在しない（ことが期待される）からだと思います。＃mod_remoteip は internet 向けと internal 向けで設定内容が異なりますので、internal 向けの場合は本記事は参考にできません。

# 終わりに

やりたいことは単純でも、設定に手間取ることってありますよねー。
JuliaをMacにインストールしてpathを通すまで

1. macOS用のJuliaのpackagesをダウンロードする
https://julialang.org/downloads/

2. GUI上でApplications(/Applications)にドラッグアンドドロップ

3. symbolic linkをはる (インストールしたバージョンに応じて1.5の部分を修正)
`sudo ln -s /Applications/Julia-1.5.app/Contents/Resources/julia/bin/julia /usr/local/bin/julia`

4. juliaを起動し、Pathが通っていることを確認する
`julia`
Lodash.includesの第一引数に文字列を入れると、部分一致比較になる

# なぜ書いたか

仕事で書いていたコードがおかしな動きしたので調べていたら、
意図せず部分一致判定になっていてバグったから。

# 結論

```javascript
import _ from 'lodash';

_.includes('sora-riku', 'sora'); // Return: true; ☆部分一致判定になる

_.includes(['sora-riku'], 'sora'); // Return: false; ☆完全一致判定になる
```

# なぜこうなる

lodashの仕様です。

https://lodash.com/docs/4.17.15#includes
カラム名を変更したのに変更前のカラムに対してUndefined methodと言われた

## バージョン
・ruby 2.5.7
・Rails 5.2.4.3

## カラム名を変えて、新しくレコードを保存しようとするがエラー
Undefined method script_idと言われる。
<img width="695" alt="スクリーンショット 2020-08-13 17 11 14" src="https://user-images.githubusercontent.com/63037931/90110840-cba37780-dd88-11ea-92e9-8f344a719d3c.png">

しかし、schema.rb見たら(変更前：script_id → 変更後：joke_book_id)変わってるしなぁ、、。

```ruby:schema.rb
t.integer "joke_book_id"
t.integer "user_id"
t.text "introduction"

```

では、このscript_idはどこから？

##結論：モデルを変更していなかった
色々調べて、モデルが怪しい事に気付く。
モデルを見ると、
validates :script_id, {presence: true}と変更前のままだった。ここを新しいカラムに変更。
validates :joke_book_id, {presence: true}

```ruby:users_joke.rb
#validates :script_id, {presence: true} #変更前

validates :joke_book_id, {presence: true} #変更後
```
これで動いた！！！
定量発注方式、定期発注方式

平成31年春期 午前問題75

定量発注方式における経済的発注量を計算したところ，600個であった。発注から納入までの調達期間は5日であり，安全在庫量が30個である場合，この購買品目の発注点は何個か。ここで，1日の平均消費量は50個であるとする。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/3e4c97d6-3b8e-7756-36a1-5deb735fd264.png)


１、定量発注方式とは、
発注時期をあらかじめ決めずに、在庫が基準数を下回った時点で最適発注量(経済的発注量)ずつを発注する方式です。定量発注方式における適切な発注点とは、常時保管している在庫数をできるだけ少なくし、かつ、安全在庫を下回らないような時点のことです。

保管在庫を最も少なくするためには、納入日の前日終業後に安全在庫である30個が最低限残っていればよいため、それと発注から納入までの5日間に消費する(50×5=)250個を足した280個が発注点になります。

定量発注方式では、商品の在庫がある一定の量まで減った際にあらかじめ決められた量を発注します。この時の「発注が必要な在庫量」を「発注点」と呼び、「あらかじめ決められた発注の量」を「発注量」と呼びます。

定量発注方式は発注量に変化がないため、急な需要変化や製品生産が安定していない商品には不向きです。常備品や安価な小物類など、需要と供給が安定している製品に用い、在庫量を一定に保つのに適しています。

２、定期発注方式では
1週間に1度、もしくは1か月に1度など、「時期が発注の目安」となります。
定量発注方式では発注量が一定なのに対し、定期発注方式は在庫や需要によって発注量を変えることが可能です。

定期発注方式は単価も高く売り上げ率もよい主力製品に用いるのが一般的です。




ーーーーーーーーーーーーーーーーーーーーーーー
補足

定量発注方式の特徴はどれか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/bba51ae2-6401-c8e6-94d8-d890c7e0fde0.png)

１、定量発注方式
発注時期は決まっておらず、在庫が基準数を下回った時点であらかじめ決まっている最適発注量(経済的発注量)を発注する方式。
・ABC分析の結果でBランクとされた、
・調達期間が短い品目、
・消費量が安定している品目
などを対象とすることが多い。

２、定期発注方式
同じ間隔で定期的に行う方式で、発注日の度に在庫数、予想需要量、安全在庫などを考えて最適な発注量を計算する。
・需要量の変化が大きい品目や、
・ABC分析の結果でAランクとされた
重要在庫を対象とすることが多い。


・定量発注方式では発注時期が決まっておらず、在庫が基準を下回った時点で発注するため、在庫量を常に把握しておく必要があります。
・需要量の変化が大きい品目には定期発注方式が適しています。
・定量発注方式は、需要の安定している品目を対象とするので、発注時の需要予測は行いません。
・発注量には経済的発注量を用いると効果的である。

・経済的発注量とは、
　　　定量発注方式において発注費用と在庫費用の総額を最小化できる1回当たりの発注量のことです。
　　　定量発注方式では、発注量にあらかじめ算出した経済的発注量を用いると効果的です。



参照：


https://www.rakurakuhanbai.jp/column/2020/0604.php

https://www.ap-siken.com/kakomon/29_haru/q75.html

https://www.ap-siken.com/kakomon/31_haru/q75.html
Outlook および Gmail と Salesforce との統合⇒Outlook Integration⇒Learn the Benefits of Integrating Salesforce with Microsoft Outlook

１．Sales reps rely on Outlook for:
２．What's true about the Outlook integration?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/ef5a3c8f-f0f1-cb73-9dc9-b66de29a5153.png)
nokogiriでスクレイピングした情報をCSVファイルに書き出す

# 概要
nokogiriでスクレイピングした情報をCSVファイルに書き出しています。
アプリケーションフォルダ直下にcsvが保存されます。
（勉強がてら遊んでいたコードを備忘に残しています。お手柔らかに）

# サンプルコード

```ruby
require 'open-uri' # URLにアクセスするためのライブラリの読み込み
require 'csv' # CSV出力をできるようにするためのライブラリ

namespace :scrape do
  desc 'アサインナビhintのinterviewページから、各記事のタイトルやURLを取得し、CSVで書き出し'
  task :anavihint_title_url => :environment do
    # スクレイピング先のURL
    url = ''
    charset = nil
    begin
      html = open(url) do |f|
        charset = f.charset # 文字種別を取得
        f.read # htmlを読み込んで変数htmlに渡す
      end
    rescue => e
      puts e # 例外メッセージ表示
    end

    # htmlをパース(解析)してオブジェクトを作成後、csvデータを生成
    header = ['title', 'URL', 'Post_Date']
    rows = []
    rows << header
    doc = Nokogiri::HTML.parse(html, nil, charset)
    doc.xpath("/html/body/div[2]/div/main/div/article[contains(@class, 'col-item-interview')]").each do |node|
      # タイトルとURLの取得
      title = node.css('h2').inner_text
      url = node.css('a').attribute('href').value
      post_date = node.css('time').attribute('datetime').value
      rows << [title, url, post_date]
    end

    # csv書き出し
    CSV.open("anavihint_interview_list.csv","w",:force_quotes=>true) do |csv|
      rows.each do |row|
        csv << row
      end
    end
  end
end

```

# 参考文献
■require 'open-uri'
https://qiita.com/tearoom6/items/8d3cb67a1bc4e454e989
https://qiita.com/kumamonmaster/items/9bb2aadde56c956fdc9f

■require 'csv'
https://docs.ruby-lang.org/ja/latest/class/CSV.html

■xpathの書き方
https://qiita.com/rllllho/items/cb1187cec0fb17fc650a

■gem 'nokogiri'
・Nokogiriの検索・参照系メソッド
https://qiita.com/Kenya/items/d1a2325a552d11814111

・WebスクレイピングのためのCSSセレクタの基本
https://gammasoft.jp/support/css-selector-for-python-web-scraping/

・任意の情報を抜き出す
TBD
【node.js】ルーティング設定ホーム画面表示させる。

##【ゴール】

###node.jsを使用して、対象のviewを表示させる。

##【メリット】
■node.jsの理解度向上
■JavaScriptの理解度向上


##【開発環境】
■ Mac OS catalina
■ Homebrew 2.4.9
■ mysql Ver 8.0.21

##【実装】


###作業環境作成
＊nodebrewをPC内にインストールしてください
＊npm をPC内にインストールしてください。

```mac.terminal
$ mkdir js
$ cd js
$ npm init -y
$ npm install express
$ npm install ejs
$ touch server.js
$ touch app.ejs
```

##ルーティング作成

```js:server.js

// for using express
const express = require('express');
const app = express();

// for path of view
function views() {
  app.set ('views', 'views'),
  app.set('view engine', 'ejs') 
}

// for routing
app.get('/', (req, res) => {
  views();
  res.render('app');
})

// for using 3000 port 
app.listen(3000, (req, res) => {
  console.log('success');
})
```


##view作成
＊***テンプレートエンジンは「ejs」なので、HTMLの宣言は不要です。***

```js:app.ejs
<h2>成功</h2>
```


###確認
*サーバー立ち上げ。

```mac.terminal
$ node server.js
success
```

以上


##【合わせて読みたい】

■ 【node.js】 node.jsインストール 芋っていたけど、簡単だった件...
https://qiita.com/tanaka-yu3/items/739db5ffed24a8d9ae4b

■【HOMEBREW】 Mac OSのパッケージマネージャーについて node.jsやってたら学んだ事
https://qiita.com/tanaka-yu3/items/65dac47443cc08914a86

■ 【comandLine】　一言で　コマンドライン　各種コマンド　ターミナル
https://qiita.com/tanaka-yu3/items/b32e353bd6d7c9ebd4fb
npm token createの結果をjsonで取得する

# TL; DR

`npm token create --json`

# 経緯

記事のタイトルとは関係ないけど、Node.jsのプログラム中からnpmアカウントのAuth Tokenを生成する方法で困ってた。

https://docs.npmjs.com/creating-and-viewing-authentication-tokens

ここにある`npm token create`以外にAPIが見つからないけど、`npm token create`はCLI上でインタラクティブにパスワードの入力を求めてくる。

これについては下記の方法で可能だということがわかった。
意外とお手軽で良かった。

```javascript:main.js
const child = require('child_process')
child.spawn("npm", ["token", "create"], { stdio: 'inherit' })
```

ということで実行してみたところ、パスワードも問題なく親プロセスから対話的に入力でき、トークンが生成できた。（トークン部分は隠してあります）

```
node main.js

npm password: 
┌────────────────┬──────────────────────────────────────┐
│ token          │ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx │
├────────────────┼──────────────────────────────────────┤
│ cidr_whitelist │                                      │
├────────────────┼──────────────────────────────────────┤
│ readonly       │ false                                │
├────────────────┼──────────────────────────────────────┤
│ created        │ 2020-08-13T07:53:39.394Z             │
└────────────────┴──────────────────────────────────────┘
```

しかし実際にはこのトークンをは次の処理への入力にする必要があり、（これパースするのか・・・面倒だな・・・）と思って、ダメ元で`--json`オプションを渡してみたらJSONで取得できた。
感謝感謝。

```javascript:main.js
const child = require('child_process')
child.spawn("npm", ["token", "create", "--json"], { stdio: 'inherit' })
```

```
node main.js 

npm password: 
{"token":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","cidr_whitelist":[],"readonly":false,"created":"2020-08-13T08:04:16.531Z"}
```

これならあとはstdoutへの出力を親プロセスで受け取るだけなのでいけそう。

---

(2020.08.14追記)
あとは簡単だと思ってたらめちゃくちゃ時間を食った上、腹落ちしない結果になったことを報告します。
https://qiita.com/nariakiiwatani/items/0ef81f31ca9d1d071076
MySqlプロシージャ/ファンクションを使ってみた

# はじめに
お勉強がてらにプロシージャ/ファンクションの作り方、使い方を纏めてみた。

## プロシージャとファンクションを用いるケースとは
WebアプリケーションでできることとDatabaseに制御させることを分離させることができる。

### メリット

- sql文をプログラム側で調整しなくてもよくなるため、セキュリティレベルが向上する。


## プロシージャとファンクションの違い

||戻り値の有無|
|:-:|:-:|
|プロシージャ|なし|
|ファンクション|あり|

# DBを照会するプロシージャを作ってみる

```sql:テーブル名をPHPから受け取ってSELECT文を実行するプロシージャを作る
DELIMITER //
CREATE PROCEDURE プロシージャ名(IN TableNameA CHAR(15),TableNameB CHAR(15))
BEGIN
set "@sql_query = CONCAT('SELECT * FROM ',TableName);
PREPARE stmt FROM @sql_query;
EXECUTE stmt;
END;
//
```

## ※注意
プロシージャの登録ができたらデリミタを;に戻してください

```sql:
DELIMITER ;
```

# 使い方

## phpからprocedureをcallする

```php5:
$pdo = new PDO ( 'mysql:host={$server};dbname={$database};charset=utf8','{$user}', '{$password}');
$sql = $pdo->prepare( 'call プロシージャ名(?)');
$t1 = 'テーブル名';
$sql->bindParam(1, $t1, PDO::PARAM_STR);
$sql->execute();
```

<font color="red">※PDOとの接続判定などに用いるtry~catch文を除いた書き方になっています。</font>

# 参考
https://proengineer.internous.co.jp/content/columnfeature/7078
https://blog.janjan.net/2018/11/01/php-call-mysql-storedprocedure/
https://www.php.net/manual/ja/pdo.constants.php
https://qiita.com/chihiro/items/5d438549b5869900abdd
https://teratail.com/questions/157257
https://dev.mysql.com/doc/refman/5.6/ja/sql-syntax-prepared-statements.html
パレート図、特性要因図、連関図、マトリックス図

平成31年春期 午前問題74

発生した故障について，発生要因ごとの件数の記録を基に，故障発生件数で上位を占める主な要因を明確に表現するのに適している図法はどれか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/add0fc98-d526-a829-4fe9-254435edffba.png)

１、パレート図は、
分析対象の項目値を大きい順に並べた棒グラフと、累積構成比を表す折れ線グラフを組み合わせた複合グラフで、主に複数の分析対象の中から重要である要素を識別するために使用します。

パレート図の棒グラフは、項目値の大小を基準に各要因が並ぶので、上位を占める要因を明確に表現するのに適しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/2f7276f8-c93a-7a44-e1a7-421556c9a1c7.png)

２、特性要因図は、（＝フィッシュボーン図）
特性(結果)とそれに影響を及ぼしたと思われる要因(原因)の関係を体系的に表わした図です。直接的な原因と間接的な原因に分別したり、真の問題点を明確にしたりする効果があります。

例：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/a4e950c3-ccec-ba3f-9e64-03042bc125e2.png)


特性要因図の 4M とは
特性要因図の要因をあぶり出す際に意識されるのが、4M と呼ばれる要素です。すべて M から始まる英単語で表現され、その内訳は以下の通りです。

 Man ＝ 人
 Machine ＝ 機械、設備
 Method ＝ 方法
 Material ＝ 材料


３、マトリックス図は、
表の縦軸と横軸にいくつかの項目を設定し、交点に各項目同士の関連性・関連度合いなどを文字列や数値または記号などで表した分析図です。

４、連関図は、
複雑な要因の絡み合う事象について、その事象間の因果関係・相互関係を明らかにして問題や原因を特定し、目的達成のための手段を発見する手法です。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/487f0c70-1ee3-9624-3c77-0d80c5bb3afa.png)


参照：

https://www.ap-siken.com/kakomon/31_haru/q74.html


https://www.fe-siken.com/kakomon/20_haru/q76.html

統計的な考え方「QC７つ道具：パレート図」とは？
https://happymakeproject.com/6585/

特性要因図
https://navi.dropbox.jp/fishbone-diagram

連関図
https://www.i-juse.co.jp/statistics/product/func/nqc/rdiag.html
WebdriverIO + TypeScript でE2Eテスト

[もろもろ事情あってseleniumを使い始めました](https://qiita.com/atchy@github/items/7f21d77d54dac623917c)

その過程で「これぜったいもっとべんりななにかがあるはず」と全部ひらがなで思い浮かべたところ、やっぱりありました。

[WebdriverIO](https://webdriver.io/)
[cypress](https://www.cypress.io/)

他にもあるんでしょうか、とりまロボットのロゴがかわいい```WebdriverIO```でいこうかな、と。
あと、使えるんであればなるべく使いたい、```TypeScript```を使いたいところ。

#### 環境
macOS Mojave 10.14.6（いろいろあって少し古い）
node.js 12.16.1

#### できあがったものがこちらです

[app-wdio](https://github.com/atchy/app-wdio)

#### セットアップ

```
git clone https://github.com/atchy/app-wdio.git
npm install
```

実行

```
npx wdio
```

[テスト対象サイト](https://the-internet.herokuapp.com/)に感謝。

ちなみに、モジュールをインストールするコマンドは以下です。

```
npm i --save-dev @wdio/cli typescript ts-node tsconfig-paths @types/jasmine @types/webdriverio && npx wdio config
```

#### Page Object Pttern
wdioのボイラーテンプレートからプロジェクトを作成するときに、ページオブジェクトパターンの雛形を生成することができます。```npx wdio config```で選択した項目を以下に示します。

```
=========================
WDIO Configuration Helper
=========================

? Where is your automation backend located? On my local machine
? Which framework do you want to use? jasmine
? Do you want to run WebdriverIO commands synchronous or asynchronous? sync
? Where are your test specs located? ./test/specs/**/*.js
? Do you want WebdriverIO to autogenerate some test files? Yes
? Do you want to use page objects (https://martinfowler.com/bliki/PageObject.html)? Yes
? Where are your page objects located? ./test/pageobjects/**/*.js
? Are you using a compiler? TypeScript (https://www.typescriptlang.org/)
? Which reporter do you want to use? spec
? Do you want to add a service to your test setup? chromedriver
? What is the base url? http://localhost
```

[ページオブジェクトパターン](https://webdriver.io/docs/pageobjects.html)

テスト対象サイトの操作を抽象化しておくことにより、テストする際に細々とした制約（アカウントをのテキストフィールドの#idは、とか、ログインボタンの名前はなんだっけ、とか）をページオブジェクトが吸収してくれるので、テストコードはテストだけに集中することができる、と。
そのためには、対象Webサイトがテストに易しい設計であることも同時に求められるかと思います。

#### とはいえ

最近では[cypress](https://www.cypress.io/)のほうが強いらしいです、次回はそのあたりを・・・
batファイルでディレクトリのファイル一覧を取り出して他のexeに処理させる

batファイルで

- ディレクトリのファイル一覧を取り出す
- 他のexe(またはbat)に処理させる  
- 処理結果ファイルなどは指定フォルダに出力する  
 
なんて処理はよくありますが、都度調べるのでメモ

```bat
@echo off
rem フォルダのファイル一覧を取得し、exeを実行してresultに結果を出力する例

SET DIR=C:\tmp\*.txt
SET EXE=shori.exe
SET RESULT=.\result

for %%A in (%DIR%) do (
	CALL %EXE% %%A %RESULT%
)
pause
```

※shori.exeは処理を行って、対象のフォルダに結果の出力(ファイルなど)を返す機能を持っているとします。

出力が無い場合は`SET RESULT=`, `%RESULT%`を除けばいいかと。

```bat
@echo off
rem フォルダのファイル一覧を取得し、exeを実行

SET DIR=C:\tmp\*.txt
SET EXE=shori.exe

for %%A in (%DIR%) do (
	CALL %EXE% %%A
)
pause
```
GitHubのREADME.mdに画像を表示させる

#プログラミングの勉強日記
2020年8月13日　Progate Lv.226
GitHubのREADME.mdにわかりやすいように画像を表示させたかった。（メモ）

#目標
　下の画像のように好きなところに画像を表示させるようにしたい。

<img width="340" alt="0813.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/1077116f-c673-c48c-491e-42923916c600.png">


#方法

##1. issueを作成
<img width="470" alt="0813-1.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/691f45f2-7050-2df2-8d4c-4536671a2c1a.png">

<img width="479" alt="0813-2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/9b7efa13-1619-b786-f8d9-03c2db99170f.png">

##2. 表示したい画像をエクスプローラーからドロップする
<img width="479" alt="0813-3.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/e2a80db2-3972-ef57-5aa3-076f7e9cc384.png">

##3. 生成された画像のURLコピーする
<img width="478" alt="0813-4.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/576b12bd-e01c-bcd8-43e9-bcac788d478b.png">
　issueは閉じて大丈夫！

##4. README.mdにペーストする
<img width="466" alt="0813-5.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/f5ffe247-10e9-f84e-9f44-272e294ecc14.png">
<img width="471" alt="0813-6.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/c8c3e024-0184-d988-18bc-2c6d4a47b863.png">

#参考文献
[GitHubでREADME.mdに画像を使用したい](https://qiita.com/lowg/items/06dd096e7ed1acce4b1e)
AWS ECRにAWS CLI v2でログインエラーになったときの対処法

# Docker ImageをAWS ECRにPush
ローカルでDockerを使って開発をして、いざ、AWS ECRにイメージをプッシュする際、AWS CLIでECRのリポジトリにログインする必要があります。

その方法を調べると以下のコマンドがよく紹介されています。

```
$ aws ecr get-login --no-include-email
```
しかし、これを実行すると、以下のようなエラーとなってしまいます。

```
usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]         
To see help text, you can run:                                                                                                                  
                                                                                                                                                
  aws help                                                                                                                                      
  aws <command> help                                                                                                                            
  aws <command> <subcommand> help                                                                                                               
aws: error: argument operation: Invalid choice, valid choices are:                                                                              
```

# AWS CLI v2で仕様が変わった
AWS CLIの仕様がv2から変わり、上記のコマンドの代わりに以下のコマンドを実行することでログインができるようになりました。

```
$ aws ecr get-login-password | docker login --username AWS --password-stdin <MY-REGISTRY-URL>
```

`<MY-REGISTRY-URL` には、`<AWSアカウントID>.dkr.ecr.us-west-2.amazonaws.com` を入れてやります。
また、`--username` として `AWS` が指定されていますが、ここはこのままでOKです。
これを実行してやると…

```
Login Succeeded
```
無事にログイン成功しました。

もし、これでだめでしたら、AWS CLIのConfig設定が済んでいない可能性があります。
こちらのリンクの方法でConfigが設定できているか確認しましょう。
[【参考】AWS CLI設定の基本](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-quickstart.html)
コマンドラインからMayaをレンダーする

Mayaのプロジェクトファイルをコマンドラインからレンダリングします。

openssl-devのインストール

````
sudo apt install openssl-dev
````

maya のpython 2.7に認識させる

````
cd /usr/autodesk/maya2020/lib/python2.7/lib-dynload
sudo mv _hashlib.so rhel_hashlib.so
sudo cp -v /usr/lib/python2.7/lib-dynload/_hashlib.x86_64-linux-gnu.so _hashlib.so
sudo chmod o+r _hashlib.so
sudo ln -s /usr/lib/x86_64-linux-gnu/libssl.so.1.1 /usr/autodesk/maya2020/lib/libssl.so.10

# sudo ln -s /usr/lib/libaudiofile.so.0 /usr/autodesk/maya2020/lib/libaudiofile.so
````

Nvidiaのグラボを使用しない場合は下記コマンドでファイルを削除（ファイル名変更によるバックアップがいいと思う）

````
sudo mv /usr/autodesk/maya2020/bin/../lib/libOGSDeviceOGL4-16.so /usr/autodesk/maya2020/bin/../lib/libOGSDeviceOGL4-16.so.org
````

コマンドラインからレンダリング

````
Render -r sw pokeball-1.0.ma
````

レンダーされた画像の表示

````
eog ~/maya/projects/default/images/pokeball-1.0.jpg
````

参考リンク

コマンド ラインからレンダーする | Maya 2019 | Autodesk Knowledge Network 
https://knowledge.autodesk.com/ja/support/maya/troubleshooting/caas/CloudHelp/cloudhelp/2019/JPN/Maya-Rendering/files/GUID-EB558BC0-5C2B-439C-9B00-F97BCB9688E4-htm.html

CGTalk | Maya 2020 on Linux 
https://forums.cgsociety.org/t/maya-2020-on-linux/2057341/4

amd graphics - Autodesk Maya symbol lookup error on start after installing AMD proprietary driver on Ubuntu 18.04 - Ask Ubuntu 
https://askubuntu.com/questions/1061236/autodesk-maya-symbol-lookup-error-on-start-after-installing-amd-proprietary-driv

Maya 2017 Installation on Ubuntu 16.04 · GitHub
https://gist.github.com/borgfriend/b83467639cb8039dc79974bf780a4994#gistcomment-1929229
Windowsフォームアプリケーションにアイコンを追加した

# はじめに
Visual Studioに付属するビットマップエディターでアイコンを作るのが大変だったのでMicrosoft Paintを使ってアイコンを作るやり方をまとめてみた。

## 注意1
visual studioに標準で用意されているイメージエディタでは32bitアイコンやPNGを編集することができない。別途ペイントツールが必要。

## 注意2
icoファイルはwindowsシステム互換機能を用いて表示できるbmpとはファイルフォーマットが異なります。＠icon変換などのアプリを使って、ICOファイルフォーマットに変換しましょう。
もし、正しくフォーマット変更できていないとアイコン追加の時に警告が表示されます。
![x15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184939/5f44c02a-b670-9447-20d0-beac030893c4.png)



# アイコンに使えるファイル形式

| サイズ | 色数 | ファイル形式 |
|:-:|:-:|:-:|
| 256 x 256 | 32bit | PNG |
| 48 x 48 | 8bit | BMP |
| 32 x 32 | 8bit | BMP |
| 16 x 16 | 8bit | BMP |
| 256 x 256 | 32bit | PNG |
| 64 x 64 | 32bit | BMP |
| 48 x 48 | 32bit | BMP |
| 32 x 32 | 32bit | BMP |
| 16 x 16 | 32bit | BMP |

# アイコン登録手順

1.mspaintなどのペイントツールでbmpファイルを作成。＠iconなどでフォーマット変換する。

2.visualstudioにてiconを追加したいプロジェックトを作成(もしくは開く)。

3.プロジェクトのプロパティを開く。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184939/3b622d26-1f24-4b47-3f19-67458e5d7f62.png)

4.アイコンの[参照]ボタンをクリック。

5.Windowsエクスプローラーからicoファイルを選択。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184939/fb8044f9-1ae8-9b92-6070-4c329f0647ed.png)

6.アイコンが読み込まれたことを確認。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184939/eb176f1e-8bfa-c95d-3687-f344b71643b0.png)

7.プロジェクトをビルドする(もしくはデバッグ込みビルド)と、実行ファイルにicoが埋め込まれていることが確認できる。

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184939/5b1c11f5-68c5-94bb-f9a9-c6007831134c.png)


## 参考

- Visual Studio 操作編　アイコンの作り方 via 孤独なコンピュータさん
http://ulalablog.jugem.jp/?eid=106
- https://docs.microsoft.com/ja-jp/visualstudio/extensibility/ux-guidelines/images-and-icons-for-visual-studio?view=vs-2019
- https://docs.microsoft.com/ja-jp/visualstudio/ide/how-to-specify-an-application-icon-visual-basic-csharp?view=vs-2019

# icon変換に使用したアプリ
- ＠icon変換 https://www.vector.co.jp/soft/win95/amuse/se201729.html
pythonで線形代数のイメージをとらえる(転置、逆行列、行列の積)

#前回の投稿について
前回初歩の初歩すぎたので次はある程度行列の種類を挙げていきたいと思います。方向性がずれると思いますが、途中で軌道修正をしていきます。頑張るぞー。
てか、この記事は前回と比べると知らないワードとか出てくるので、じぶんでお願いします。説明加えていないのは、ほかの記事を見てください。

#転置行列
具体例として2×2の行列

```math
\begin{pmatrix}
1 & 1 \\
0 & 3 
\end{pmatrix}

```
が対角線で成分を折り返したような行列を転置行列といいます

```math
\begin{pmatrix}
1 & 0 \\
1& 3 
\end{pmatrix}

```
こんな感じですね。イメージは。今

```python
import numpy as np
A = np.array([1, 1],
             [0,3])

C = A.T
print(C)

```

こんな感じですかね。
##転置行列の特徴
任意のベクトルA、B、に対して

```math
(A+B)^T=A^T+B^T\\
(AB)^T=B^TA^T\\(A^T)^T=A
```
となっております。実際に計算してみてください。まだ公式はありますが。。
#行列の積
行列の積は説明してなかったですね。任意の２つの行列A,Bに対して

```math
\vec{A}=\begin{pmatrix}
a& b \\
c& d 
\end{pmatrix}

```
```math
\vec{B}=\begin{pmatrix}
e& f \\
g& h 
\end{pmatrix}

```
があったとすると行列の積は


```math

\vec{AB}=\begin{pmatrix}
a& b \\
c& d 
\end{pmatrix}\begin{pmatrix}
e& f \\
g& h 
\end{pmatrix}=\begin{pmatrix}
ae+bg& af+bh \\
ce+dg& cf+hd 
\end{pmatrix}

```
となります。こんな感じです。縦×横を四回やる感じです。言葉で言ってもわかりずらいと思われるので、このサイトを見てください。
https://mathwords.net/gyouretsuseki

```python

import numpy as np
 
#行列Aを定義
A=np.matrix([
    [1,1],
    [0,3]
        
])
 
#行列Bを定義
B=np.matrix([ 
    [1,0],
    [1,3]
])
 
#行列の積（AとBの積）
C=np.dot(A,B)
 
print("行列の積C")
print(C)
```


#逆行列
逆行列の求め方はサラスか余因子展開か掃き出し法があったような。今回は２×２の余因子展開を紹介していきます。

```math
\vec{A}=\begin{pmatrix}
1 & 1 \\
0 & 3 
\end{pmatrix}

```
の行列があったとする。
行列式を求める方法はサラスの公式を用いる

```math
\begin{vmatrix}
1 & 1 \\
0 & 3
\end{vmatrix}=(1×3)-(1×0)=3=det(A)

```
となる。この行列式から、余因子展開後Aを転置させて、その行列式の値を割ると逆行列の値になる。実際に計算してみると

```math

A^{-1}=\frac{1}{det(A)}A^{\sim}


```


```math
A^{\sim}=\begin{pmatrix}
3 & 1 \\
0 &-1 
\end{pmatrix}\\

A^{-1}=\frac{1}{3}\begin{pmatrix}
3 & 1 \\
0 &-1 
\end{pmatrix}


```
#逆行列のコード
```python
import numpy as np
 
#行列Aを定義
A=np.matrix([
    [1,1],
    [0,3]
        
])
 
#行列Bを定義
B=np.matrix([ 
    [1,0],
    [1,3]
])
 
#行列の積（AとBの積）
C=np.dot(A,B)
D=np.linalg.inv(A)
print("行列の積C")
print(C)
print(D)
```
となる。
余因子展開の説明はまた後にします。中途半端になってしまった。次回は線形独立、線形従属、余因子、掃き出し法あたりを大雑把に説明していきたいと思います。

#感想
線形代数は極めると面白い科目になりそうだなあ。実際にやり方は知っているけど証明は全く理解していない状態というか、計算問題で単位取れてきたようなもんだからなあ。実際には大学１年のころには何も身についていなかったのが悲しい。記事書いていくうちにこんなやり方だったんだ!って思い出すのが新鮮。余因子展開のやり方完全に忘れてた。これじゃあまずいのでもっと続けていきます。

話しは変えるけどなぜ偏微分の記事がこんなに人気なのだろう。
あの記事作るのに５倍ぐらい時間かけているブロック崩しの記事にも見てほしいなあ。
#追記
全ての記事が中途半端すぎて、何やっているかわからないかもしれません。ここで、今までの記事を修正してからまた新しい記事を投稿してきたいと思います。例えば余因子展開の説明、行列とは何か、もっと根本的な説明を加えておらず、自分の知識不足がかなり露呈していると思います。修正しても間違えると思うので、冷たい目でご指摘ください。
Codeceptionでセンシティブな情報を.envから取得する

## テストコードにパスワードを直書きしたくない
```php:AdminLoginCept.php
$I = new AcceptanceTester($scenario);
$I->wantToTest('管理画面にログイン');

$I->amOnPage('/admin/');
$I->seeCurrentURLEquals('/admin/login');
$I->fillField('login_id', 'hideki');
$I->fillField('password', 'hidekisuteki'); // 👎
$I->click('ログイン');
$I->seeCurrentURLEquals('/admin/');
```
- 直書きせずに、環境変数ファイルから取得する方法があるはずと思って調べたのですが、思ったより面倒だったので書き残しておきます。

## Codeception Config Module をインストール

- [JustBlackBird/codeception-config-module](https://github.com/JustBlackBird/codeception-config-module)

> Loads params from Codeception config and pass them to test scenarios.

```bash
composer require-dev justblackbird/codeception-config-module
```

```json:composer.json
"require-dev": {
    "codeception/codeception": "^4.1",
    "justblackbird/codeception-config-module": "^1.0",
}
```

## `codeception.yml`にパラメーター設定を追加
```:.env
ADMIN_PASSWORD=hidekisuteki
```

```yaml:codeception.yml
paths:
    tests: tests
    output: tests/_output
    data: tests/_data
    support: tests/_support
    envs: tests/_envs
actor_suffix: Tester
extensions:
    enabled:
        - Codeception\Extension\RunFailed
params:
    - .env # 👈
```
- これで、`.env`ファイル内の環境変数を**設定ファイルの中で**使えるようになります(テストコード内ではまだです)。

## `acceptance.suite.yml`にモジュール設定を追加
```yaml:acceptance.suite.yml
actor: AcceptanceTester
modules:
    enabled:
        - PhpBrowser:
            url: http://localhost/
        - \Helper\Acceptance
        - Config:
            password: "%ADMIN_PASSWORD%" # 👈
```
- `.env`内の使いたいパラメーターの名前を、`%`で囲って記述します。

## テストコード内でモジュールを使用
```php:AdminLoginCept.php
$I = new AcceptanceTester($scenario);
$I->wantToTest('管理画面にログイン');

$I->amOnPage('/admin/');
$I->seeCurrentURLEquals('/admin/login');
$I->fillField('login_id', 'hideki');
$I->fillField('password', $I->grabFromConfig('password')); // 👍
$I->click('ログイン');
$I->seeCurrentURLEquals('/admin/');
```
【Python】データサイエンス100本ノック（構造化データ加工編） 026 解説

- データサイエンス100本ノックをやりきる会を作りました🎉
- こちらの[Slack招待URL](https://join.slack.com/t/data-science-100nocks/shared_invite/zt-gfncg9vm-8W8b3UrDg8R~TKaqUkQpgw)からご参加ください！！
- ぜひ一緒に励まし合いながら、データサイエンス100本ノックをやり切りたいと思っています！

##Youtube
[動画解説](https://youtu.be/2kzeWsbMFco)もしています。

##問題
P-026: レシート明細データフレーム（df_receipt）に対し、顧客ID（customer_id）ごとに最も新しい売上日（sales_ymd）と古い売上日を求め、両者が異なるデータを10件表示せよ。

##解答
```:コード
df_sales_ymd = df_receipt.groupby('customer_id').agg({'sales_ymd':['max','min']}).reset_index()

df_sales_ymd.columns = ['customer_id','sales_ymd_max','sales_ymd_min']

df_sales_ymd.query('sales_ymd_max != sales_ymd_min').head(10)
```

##出力
|  | customer_id | sales_ymd_max | sales_ymd_min |
|--:|:--|--:|--:|
| 1 | CS001114000005 | 20190731 | 20180503 |
| 2 | CS001115000010 | 20190405 | 20171228 |
| 3 | CS001205000004 | 20190625 | 20170914 |
| 4 | CS001205000006 | 20190224 | 20180207 |
| 13 | CS001214000009 | 20190902 | 20170306 |
| 14 | CS001214000017 | 20191006 | 20180828 |
| 16 | CS001214000048 | 20190929 | 20171109 |
| 17 | CS001214000052 | 20190617 | 20180208 |
| 20 | CS001215000005 | 20181021 | 20170206 |
| 21 | CS001215000040 | 20171022 | 20170214 |

##解説
・PandasのDataFrame/Seriesにて、同じ値を持つデータをまとめて処理し、同じ値を持つデータの合計や平均などを確認したい時に使用します。
・**'groupby'は、同じ値や文字列を持つデータをまとめて、それぞれの同じ値や文字列に対して、共通の操作（合計や平均など）を行いたい時に使います。**
・**'.agg({'sales_ymd':['max','min']})'は、'.sales_ymd'の最大値（=最も新しい売上日）と最小値（=最も古い売上日）を表示させます。**
・**'.reset_index()'は、'groupby'によってバラバラになったインデックス番号を0始まりの連番に振り直す操作を行いたい時に使います。**
・2行目、3行目は、既出のコードになりますが、'.columns'で列名を指定し、'.query'で条件を指定しています**

※2行目は、以下のコードでも、同じ結果を出力します
　ただし、'customer_id'が'customer_id_'になってしまいます

```:コード
df_sales_ymd.columns = ["_".join(pair) for pair in df_sales_ymd.columns]
```
米国の日付形式からYYYY-MM-DDに変換する

# 日付形式の変換

文字列として取得した米国の日付形式(`mm/dd/yy`)から `yyyy-mm-dd` に変換したい。

いろんなパッケージやパースがあるみたいなんだけど、ドンピシャのが見つからなかったので↓のようにして対応した。

```
package main

import (
	"fmt"
	"strings"
)

func main()  {
    usDate := "8/9/20"
    // => "8/9/20"

    slice := strings.Split(usDate, "/")
    // => [8 9 20]

    date := fmt.Sprintf("20%s-%02s-%02s", slice[2], slice[1], slice[0])
    // => "2020-08-09"

    fmt.Println("yyyy-mm-dd:", date)
    // => yyyy-mm-dd: 2020-09-08
}
```

他にいい方法を知ってたらおしえてください（切実）

# 参考

- https://qiita.com/tez/items/1fdcbd9e2b6b575b6725
- https://qiita.com/icbmuma/items/5617f3fc5bc0215aade2
- https://qiita.com/unbabel/items/c8782420391c108e3cac
- [日付 - Wikipedia](https://ja.wikipedia.org/wiki/%E6%97%A5%E4%BB%98)
1.44 インチ TFT液晶に画像を表示する

前回
1.44 インチ TFT液晶 128 x 128 ST7735 動作確認メモ
https://qiita.com/santarou6/items/7f2946ae918245049440
の続き

---

画像を表示したい。
※ソースは、後ほど、アップします

---

結果から示すと、以下のように出せた。
<img width="413" alt="スクリーンショット 2020-08-13 15.48.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107418/f42d2c73-3c8f-cab6-60cf-0e7b528366ea.png">


手順は、
１）　表示する画像ファイルから、書き込み用のデータを作成する
２）　データをEEPROMに書き込む
３）　EEPROMのデータを読み込みながら、TFT液晶に描画する

---

もう少し細かく書くと、

１）　表示する画像ファイルから、書き込み用のデータを作成する

１−１）　１２８×１２８ピクセルのｂitmap（bmp）画像を用意する
１−２）　bmpから、各ｘｙ座標のRGBデータを取り出す
１−３）　２４bitのRGBデータを、1６bitのRGBデータに変換し、１６進表記し、テキスト化する

２４bitのとき、R=1byte（8bit）、G=1byte（8bit）、B=1byte（8bit）
(3byte:RRRRRRRRGGGGGGGGBBBBBBBB)
１６bitのとき、R=（５bit）、G=（６bit）、B=（５bit）
(2byte:RRRRRGGGGGGBBBBB)
この変換は、
　RとBは、0〜255を、0〜31に変換。（例:r1=r0/256*32)
　Gは、0〜255を、0〜63に変換。（例:g1=g0/256*64)

---

２）　データをEEPROMに書き込む

書き込みは、ここを参考にしました

https://www.petitmonte.com/robot/howto_eeprom_i2c.html
http://radiopench.blog96.fc2.com/blog-entry-574.html

メモリは、これ
ＥＥＰＲＯＭ　２４ＦＣ１０２５
http://akizukidenshi.com/catalog/g/gI-03570/

1024Kbitなので、128Kbyte書き込める。
（１画面あたり、128 x 128 x 2byte = 32Kbyteなので、４枚分入る。）

※抜粋

```c:write_eeprom.ino
for (i=( (m_x * stp)); i<((m_x * (stp+1))); i++){  
  Wire.beginTransmission(DEVICE_ADDRESS);    
  Wire.write(i >> 8);     // Address(High Byte)   
  Wire.write(i & 0x00FF); // Address(Low Byte)
  int id1;
  id1 = pgm_read_byte(IMAGE_DATA1 + id_ad);
  Wire.write(id1); 
  id_ad ++;
  Wire.endTransmission();
  delay(5);
}
```


---

３）　EEPROMのデータを読み込みながら、TFT液晶に描画する



※抜粋

```c:tft_drawPixel.ino
 for (int16_t y=0; y < tft.height(); y+=1) {
  for (int16_t x=0; x < tft.width(); x+=1) {

  int16_t ad1 = (y * 256) + (x * 2);
  int16_t ad2 = (y * 256) + (x * 2) + 1;

    Wire.beginTransmission(DEVICE_ADDRESS);
    Wire.write(ad1 >> 8);     // Address(High Byte)   
    Wire.write(ad1 & 0x00FF); // Address(Low Byte)
    Wire.endTransmission();
    Wire.requestFrom(DEVICE_ADDRESS, 1); 
    while (Wire.available() == 0 ){}
    unsigned char a1 = Wire.read();
  
    Wire.beginTransmission(DEVICE_ADDRESS);
    Wire.write(ad2 >> 8);     // Address(High Byte)   
    Wire.write(ad2 & 0x00FF); // Address(Low Byte)
    Wire.endTransmission();
    Wire.requestFrom(DEVICE_ADDRESS, 1); 
    while (Wire.available() == 0 ){}
    unsigned char a2 = Wire.read();

    unsigned short int c1 = (a1 << 8) + a2;
    tft.drawPixel(x, y, c1);
    delay(0);
  }
 }
```
自動化をしたく無い人に自動通知するBOTを作ったら、話が無限ループした件

# 読み始める前の注意
* 面白おかしく誇張しているので、全てを真に受けないでください。
* 会話は誇張していますが、大筋は本物です。作ったものももちろん本物です。
* 技術的には大したものはなにもないです。
* 社内の情報があるのでコードが出せないので流れで楽しんでくださいｗ


# はじまりはじまり

あるところに、比較的大きなSIerで、冗談みたいな5年計画のウォーターフォールで50以上の超絶大規模なシステムが一斉に開発・移行を行う会社がありました。

主人公のぼくが、担当しているのは、小規模なプロジェクトですが、この営みに巻き込まれ、移行作業を行います。

お話はこの移行作業というよりも、移行時の報告作業です。

# 起：始まる前から終わっている報告作業

## おはなし

きっかけは、ふとした業務中の同僚の一言

同僚：移行リハーサルで、報告が多いんだよね。。。しかもほぼ全部メール。

ぼく：Slackとかのチャットじゃないんだ何回ぐらい？。5回とかかな？

同僚：だいたい30回ぐらいかな。あと2時間おきの定期報告があるから+10かな

ぼく：え。`20時間(移行全体の時間)で40回` も報告するの！

ぼく：えっと。。。移行全体でだよね。。。

同僚：いやいや。自分たちは少ない方で、多いところは50回くらいあるから全体では2000回以上の報告が飛び交うんじゃないかな？

同僚：統制しながらは無理だから、上司にお願いするか・・・

上司：わかったけど、忘れちゃうから少し前になったら教えて。あとメールフォーマットがあると助かるな

同僚(超優しい)：フォーマットは作ったのでこれ送ってください。時間になったらお知らせします。

ぼく：いやいやいやいやいや。そんなの全部自動にすればいいじゃないですか！

上司：でも、前倒しになったりしたら、ずれちゃうし

ぼく：じゃあ、タイミングを知らせる部分は自動化してもいいですよね。

ぼく：30分ほど時間をください。

## つくったもの

* 実装はNode-RED

![pic1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/4576db36-1f7f-0775-57f7-bc43819a8fa2.png)


まず、報告するタイムチャートを一覧化して以下のフォーマットに整理

``` list.csv
項番,ID,会議体/報告概要,宛先,日付,時間

```

* Slackじゃないんですよ。。。社内のMattermostですよ。。。
* 10分に一度起動して、csvファイルを開きパース、日付部分が現在時間+10分以内であればmattermostに通知する

# 承：ちょっと使うと、あれもほしい、これもほしいが始まる

## おはなし

上司：40回もあると、報告したかどうか忘れちゃうねｗ

ぼく：(いや、チェックリスト潰すとか、メールのタグでもつければいいんじゃ)←チキンなので言わない

上司：報告メールも通知されるといいんだけど

ぼく：15分待ってもらっていいですか。。。

## つくったもの
![pic2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/183d1184-df6b-9afa-28cb-e590ecea461a.png)

* 単純にメールノードを社内のメールサーバにつないで、msg.topicでキーワードを拾う
* メールタイトルに【〇〇案件】みたいなものをつけるルールがあるので、キーワードで拾う
* なぜか、Reで余計なやり取りを始める人がいるので、これは無視するためにReでないときに処理を足しておく
* さらに、作業項番A1-1みたいなものもルールにある(list.csvのID)ので、これが含まれているときにmattermostに通知

# 転：天井知らずの追加要望

## おはなし

上司：スケジュールが前倒しになると、報告の後に通知が来て、終わったかどうか心配になるな

上司：このファイルから通知するボットくんとメールを監視するボットちゃんは仲悪いのかなｗ

ぼく：えー。仲良くさせるんですか？？

## つくったもの

![pic7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/d1f75ce7-d6b9-af86-9eb4-30fa9bede0bf.png)


* ファイルを開いて通知するものとメールを監視して通知するものはそれぞれ自分の処理が終わったらフラグを設定する
* そのフラグを確認して、先にメールが出て後から通知が来た場合は、「報告済です」とプラスで通知する
* 3秒waitを入れているのは、「報告済です」が先にでるのを防ぐための簡易アイディアです

* ちなみに、フラグをALLセット/リセットしたり、個別でセットしたりするものもあるのですが省略しています。

# 結：そして世界は流転し、振り出しに戻る

## おはなし

上司：ところでさ。忘れてても教えてくれないんだね。

ぼく：忘れないように通知しているじゃないですか。

上司：通知を見忘れたり、通知見たけどメール送りそびれたら、取りこぼすなっと思って・・・

ぼく：(それを言い始めたら何しても無理じゃないのか。。。)

ぼく：15分もらっていいですか？(フラグを監視して規定時間から一定時間報告メールが送られていないた場合は通知するようにするか・・・)

上司：あ、ちょっと待って。でも。そもそもいろいろな通知が来て、分かりにくくなったから、`一番最初の通知だけで良いかな`

ぼく：はーい。全部消しまーす。

## つくったもの

* 一番最初のフローと同じ

## 要するに：プロジェクトコメディ

![project_comedy_s.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/5038c995-6861-7775-6afb-f8f94e4ee531.gif)


# 結末

* 予想通り、リハーサルはぐだぐだとなり、予定していた試験は終わりませんでしたとさ。おしまい。
* リハーサルと本番が合わせてあと4回あるので、このページは最低でもあと4周します。
Xcode12でcarthageのFrameworkを更新しようとするとTask failed with exit code 1:になる時の対処法

Xcodeのバージョンも上がったのでcarthage updateするか〜と思ってしたところ以下の様なエラーが発生した時の対処。
![スクリーンショット 2020-08-13 15.43.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415441/af192768-1215-f058-77f5-d58a72343095.png)

筆者環境

```
% carthage version
0.35.0
```

```
% sw_vers
ProductName:	Mac OS X
ProductVersion:	10.15.6
```
Xcode12Beta〜Xcode12GM

#手順
まずコマンドラインツールが現在のバージョンとあってるかの確認。
Xcode→Preferences→Locations→CommandLineToolsのXcodeバージョンを合わせる。

exit code 1:出てるなら変更していると思いますが一応の確認。。。![スクリーンショット 2020-08-13 15.48.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415441/9372867d-bf14-4807-3563-d8cdb9436927.png)

その後xcconfigファイルをプロジェクトのルートなどわかりやすい場所に新規作成
![スクリーンショット 2020-08-13 12.00.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415441/8e44f81a-1d67-0a22-6e3e-5c234180c06e.png)


以下二行を作成したファイルに追加

```
EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64=arm64 arm64e armv7 armv7s armv6 armv8
EXCLUDED_ARCHS=$(inherited) $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_$(EFFECTIVE_PLATFORM_SUFFIX)__NATIVE_ARCH_64_BIT_$(NATIVE_ARCH_64_BIT))
```
現在こんな感じ![スクリーンショット 2020-08-13 15.56.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415441/a930025c-7384-c65f-99be-2261c2586b28.png)



ターミナルで以下のコマンドを打つ。

```
% export XCODE_XCCONFIG_FILE=(xcconfigのパス）
```

アップデート

```
% carthage update --platform iOS --no-use-binaries --cache-builds
```

喜ぶ。

以上です。
Railsのproduction環境で500 Internal Server Errorが発生する

**はじめに**
Railsでポートフォリオ作成中に500 Internal Server Errorでめちゃくちゃ悩まされたので、問題解決の方法を皆さんに共有したいと思います。

###環境
- Rails 5.2.4
- macOS 10.15.5
- MySQL 5.7
- ruby 2.5.1

###結論
アセットパイプラインが原因かも

###状況
development環境で開発をずっとしてて、ある程度アプリケーションが完成してきたので、本番環境にproduction環境でデプロイしようとしたら**500 Internal Server Error**がでて三日間解決できず。。

###問題解決のために行ったこと
- webサーバ（Nginx）のconfファイルの設定変更<br>
=>解決に至らず
- pumaソケットの削除などソケット周り<br>
=>解決に至らず
- その他database.ymlやGemfileなど関係がありそうな箇所の見直し<br>
=>解決に至らず
- production.logの中身を確認<br>
=>アセットパイプライン周りでエラーを確認

###自分がやった解決手順
- `rake assets:clobber`でまずアセットパイプラインをクリーンにする
- `bundle exec rake assets:precompile RAILS_ENV=production`でアセットパイプラインのプリコンパイルを実行<br>
=>自分の場合yarnのインストールを求められたのでインストールする
- 再起動などをするとうまく立ち上がった<br>
=>自分の場合[こちら](https://qiita.com/at-946/items/b7d467bf25c40fcfca44)も行いました。

###終わりに
最初は完全にWebサーバ周りの問題と決めつけてしまいましたが、きちんと最初からproduction.logをみてエラーを確認するべきでした。とても勉強になったエラー解決でした。
[Git]画像がコンフリクトした場合の対処

画像がコンフリクトしてしまったみたい。
ブランチごとに別々に入れちゃったら起きるらしい。
この場合は、

```
git checkout --theirs ファイル名
```
とすれば直りました。

--therisともう一つ--oursっていうオプションがあって以下のような違いがあります。

```
--theirs //今のブランチじゃない方を優先したい場合
--ours //今のブランチの方を優先したい場合
```
Biopython Tutorial and Cookbook和訳(4.6)

## 4.6  The format method
[4.5へ](https://qiita.com/chaos44/items/79cabbfe8c006583d038)
The format() method of the SeqRecord class gives a string containing your record formatted using one of the output file formats supported by Bio.SeqIO, such as FASTA:
**SeqRecordのformat()はrecord(配列)をBio.SeqIOにサポートされる文字列に変換できます、たとえばFASTA**

```python
from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord
from Bio.Alphabet import generic_protein

record = SeqRecord(
    Seq(
        "MMYQQGCFAGGTVLRLAKDLAENNRGARVLVVCSEITAVTFRGPSETHLDSMVGQALFGD"
        "GAGAVIVGSDPDLSVERPLYELVWTGATLLPDSEGAIDGHLREVGLTFHLLKDVPGLISK"
        "NIEKSLKEAFTPLGISDWNSTFWIAHPGGPAILDQVEAKLGLKEEKMRATREVLSEYGNM"
        "SSAC",
        generic_protein,
    ),
    id="gi|14150838|gb|AAK54648.1|AF376133_1",
    description="chalcone synthase [Cucumis sativus]",
)

print(record.format("fasta"))

which should give:

>gi|14150838|gb|AAK54648.1|AF376133_1 chalcone synthase [Cucumis sativus]
MMYQQGCFAGGTVLRLAKDLAENNRGARVLVVCSEITAVTFRGPSETHLDSMVGQALFGD
GAGAVIVGSDPDLSVERPLYELVWTGATLLPDSEGAIDGHLREVGLTFHLLKDVPGLISK
NIEKSLKEAFTPLGISDWNSTFWIAHPGGPAILDQVEAKLGLKEEKMRATREVLSEYGNM
SSAC
```

This format method takes a single mandatory argument, a lower case string which is supported by Bio.SeqIO as an output format (see Chapter 5). 
However, some of the file formats Bio.SeqIO can write to require more than one record (typically the case for multiple sequence alignment formats), and thus won’t work via this format() method. 
See also Section 5.5.4.
***formatメソッドは引数が必須です、Bio.SeqIOにサポートされる出力の形式です(小文字文字列)。
しかし複数の配列を保持している場合は、format()メソッドを使えません。
5.5.4を参照してください。***
入力フォームに画像を挿入したり文字のフォントをテキストから変更できるsummernoteの導入方法


## summernoteとは
中央揃え文字の色を変えたりできるなど様々な機能を使うことが出来ます


<img width="1434" alt="スクリーンショット 2020-08-13 15.39.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613591/fca8e6b9-55d8-66f2-5ad2-72671d61ffd0.png">


## summernote導入

headにこちらを追加します
使用環境： HTML5

```html:index.html
  <link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
  <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
  <link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.css" rel="stylesheet">
  <script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.js"></script>    
```
bodyにこちらを追加します

```html:index.html
  <div id="content"></div>
  <script>
    $(document).ready(function() {
        $('#content').summernote();
    });
  </script>
```
これでsummernoteを導入できます

間違った箇所がございましたらご指摘よろしくお願いいたします。

僕のポートフォリオであるメモアプリのソースコードは公開しているので良かったらご覧ください
https://github.com/shou-github/memo.App/

以下のURLからご使用頂けます。
https://memoapps.herokuapp.com/