OmniAICreator/Qiita-1.07M huggingface dataset:
アイコンのサイズを調整するカスタムButtonを作ってみた

#アイコンのサイズを調整するカスタムButtonを作ってみた
AndroidでVectorDrawableをアイコンとしてボタンに表示させて使っていたが解像度別にアイコン（画像）を用意するだけだと、端末によっては
大きすぎたり小さすぎたりして今一だったのでボタンサイズに合わせてアイコンサイズを調整するカスタムボタンを作ってみました。

## カスタムViewにした理由
画像のリサイズにViewのサイズを使いたかったがfragmentやactivityでやろうとすると[ViewTreeObserver](https://developer.android.com/reference/android/view/ViewTreeObserver)使わないといけなくてめんどくさかったし、別に作った当時はView内部で完結しててよかったので。

##実装
android.widget.Buttonを継承したCustomButtonクラスを作成しコンストラクタとonLayoutを実装する

        // 1.0(フルサイズ) 〜 0.0
        var mRatio = 0.55

        override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        var drawable: VectorDrawable? = null
        val list = compoundDrawables.toList()

        // アイコンは一つしか設定されていない想定
        list?.forEach {
            if(it != null){
                drawable = it as? VectorDrawable
            }
        }

        // アイコンのサイズ設定
        val scalingSize = (this.height * mRatio)
        drawable?.apply {
            (this as VectorDrawable).setBounds(0,0,(scalingSize).toInt(),(scalingSize).toInt())
            // アイコンの表示位置調整（今回はボタン上部にアイコンを表示）
            setCompoundDrawables(null,this,null,null)

        }
        background = ContextCompat.getDrawable(context, R.drawable.button_round_corners_10dp)
        setTextColor(mColor?: Color.WHITE)
    }

##使い方
layout(xml)なりFramgentなりActivity任意の場所でアイコンを設定しておけばOK
(*言わずもがなアイコンが事前に設定されていないと表示する画像がないのでどうしようもない）
アイコンのサイズ（割合）を変更したい時は mRatioの値を0から1の値を変えればOK

##注意点
・アイコンを表示する箇所を変更したい時はsetCompoundDrawables（）でdrawableの表示位置を変える必要がある
・今回のCutomButtonではonLayout無いでサイズを指定するので問題ないが、
通常のボタンでアイコンを設定する際にsetCompoundDrawables（）を使う時は
使う前にsetBounds（）でサイズ設定しないと描画サイズが縦横ともに０になるのか表示されなくなるので注意が必要になる

----
##参考
[Qita: onMeasureとonLayoutについて理解する](https://qiita.com/naodroid/items/d685a0113342edbb7587)
[stackoverflow : Calling setCompoundDrawables() doesn’t display the Compound Drawable
](https://stackoverflow.com/questions/6590838/calling-setcompounddrawables-doesnt-display-the-compound-drawable)
Amazon LexのバージョンによるLambdaレスポンスの違いについて

2021/04/02からAmazon Lexが遂に日本語対応されました！
https://aws.amazon.com/jp/about-aws/whats-new/2021/04/amazon-lex-launches-support-japanese/

# バージョンの違い
色々触ってAmazon Lexにはv1とv2がある模様です。
Lexの返答にはLambdaを使うことが可能ですが、そのLexを作るバージョンによってレスポンスが異なっているので注意が必要です。

具体的なレスポンスのドキュメントは下記をご確認ください。

■v1
https://docs.aws.amazon.com/ja_jp/lex/latest/dg/lambda-input-response-format.html#using-lambda-response-format

■v2
https://docs.aws.amazon.com/lexv2/latest/dg/lambda.html

## 具体的なソース
v1とv2それぞれ簡単なレスポンスは下記で実装できます。

dialogActionのmessageのcontentに返してほしいテキストを入れるようです。

```javascript:index.js(v1)
exports.handler = async (event) => {
    const response = {
      "dialogAction": {
            "type": "Close",
            "fulfillmentState": "Fulfilled",
            "message": {
                "contentType": "PlainText",
                "content": "これはv1です。"
            }
        }
    };

    return response;
};
```

下記のように応答が返ってきます。
![スクリーンショット 2021-04-02 17.51.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/b3f7de6d-d5ad-c54b-6a03-29bdb7ce3c6c.png)

続いてv2

```javascript:index.js(v2)
exports.handler = async (event) => {
    const response = {
        "sessionState": {
            "dialogAction": {
                "type": "Close",
            },
            "intent": {
                "name": "",
                "state": "Fulfilled"
            }
        },
        "messages": [
            {
                "contentType": "PlainText",
                "content": "これはv2です。"
            }
        ]
    };

    return response;
};
```

下記のように返ってきます。
![スクリーンショット 2021-04-02 17.51.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/b5cc34cf-f5f6-9250-e428-8a65e52f2b83.png)

## v2のLambda指定箇所
v2ではLambdaの指定箇所が奥深すぎて見つけにくいです。。。

まず、左側のメニューからAliases①をクリックして、TestBotAlias②をクリックします。
![step1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/3d3ad846-ff33-3d49-cb5d-bdd81c5c4646.png)

Japanese(Japan)③をクリックします。
![step2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/60728716-b278-7881-5515-e6b8318bf587.png)

ようやくLambdaを指定する画面が表示されます。。。
![step3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/d3953c92-59d8-fddb-9a3d-fbe3ebab9488.png)

## まとめ
個人的にはv1の画面のほうがわかりやすかったです。v2はLambdaを指定する場所が奥深すぎて見つけにくい。。。
Amazon Lexがようやく日本語対応してくれたので、Amazon Connectとの連携が増えるのがとても楽しみですね！

システム化のご検討やご相談は弊社までお問い合わせください。
https://i-enter.co.jp/contact/
ECS で GemNotfound によりコンテナが起動できない


ECS というモダンな技術を扱いながらも、基本を疎かにしないようにするための個人的メモです。

# 前提条件
・ECR にコンテナをプッシュできている。
・タスクのステータスが Running にならない。
・CloudWatch で以下のようなエラーログが確認できる


```
2021-04-02T17:12:42.440+09:00	bundler: failed to load command: rails (/usr/local/bundle/bin/rails)
2021-04-02T17:12:42.440+09:00	Bundler::GemNotFound: Could not find i18n-1.8.9 in any of the sources
2021-04-02T17:12:42.440+09:00	/usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:86:in `block in materialize'
2021-04-02T17:12:42.440+09:00	/usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:80:in `map!'
2021-04-02T17:12:42.440+09:00	/usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:80:in `materialize'
2021-04-02T17:12:42.440+09:00	/usr/local/lib/ruby/2.7.0/bundler/definition.rb:170:in `specs'
2021-04-02T17:12:42.440+09:00	/usr/local/lib/ruby/2.7.0/bundler/definition.rb:237:in `specs_for'
2021-04-02T17:12:42.440+09:00	/usr/local/lib/ruby/2.7.0/bundler/definition.rb:226:in `requested_specs'
2021-04-02T17:12:42.440+09:00	/usr/local/lib/ruby/2.7.0/bundler/runtime.rb:101:in `block in definition_method'
2021-04-02T17:12:42.440+09:00	/usr/local/lib/ruby/2.7.0/bundler/runtime.rb:20:in `setup'
2021-04-02T17:12:42.440+09:00	/usr/local/lib/ruby/2.7.0/bundler.rb:149:in `setup'
2021-04-02T17:12:42.440+09:00	/usr/local/lib/ruby/2.7.0/bundler/setup.rb:20:in `block in <top (required)>'
2021-04-02T17:12:42.440+09:00	/usr/local/lib/ruby/2.7.0/bundler/ui/shell.rb:136:in `with_level'
2021-04-02T17:12:42.440+09:00	/usr/local/lib/ruby/2.7.0/bundler/ui/shell.rb:88:in `silence'
2021-04-02T17:12:42.440+09:00	/usr/local/lib/ruby/2.7.0/bundler/setup.rb:20:in `<top (required)>'
```
![Screen Shot 2021-04-02 at 17.50.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335807/1b81b693-6d76-8a88-1377-bf6a7e436c96.png)


注目は２行目

```
Bundler::GemNotFound: Could not find i18n-1.8.9 in any of the sources
```

この部分。

#解決策
```
gem install i18n
```
ただ Gem がインストールされていなかっただけだった。これで無事に、タスクのステータスが Running になった。基本を大事にしていきたい。
アセンブリ言語　基本用語、実行方法メモ

## アセンブリ言語 【assembly language】

> アセンブリ言語とは、プログラミング言語の類型の一つで、コンピュータのCPU（MPU/マイクロプロセッサ）が直接解釈・実行できる機械語（マシン語）と正確に対応する命令語で構成された言語。

[アセンブリ言語とは - IT用語辞典 e-Words](https://e-words.jp/w/%E3%82%A2%E3%82%BB%E3%83%B3%E3%83%96%E3%83%AA%E8%A8%80%E8%AA%9E.html)

アセンブリ言語は、**機械語**と**命令語**で構成された言語。

用語|意味
--|--
アセンブリ | 言語の呼び名
アセンブラ| アセンブリをコンパイルするプログラム
アセンブル|アセンブリをコンパイルすること

アセンブリを、アセンブルして、アセンブラを作る

## 機械語 【machine language】 マシン語 / machine code

> 機械語とは、コンピュータのマイクロプロセッサ（CPU/MPU）が直接解釈・実行できる命令コードの体系。0と1を並べたビット列として表され、人間が直に読み書きしやすい形式ではない。

[機械語（マシン語）とは - IT用語辞典 e-Words](https://e-words.jp/w/%E6%A9%9F%E6%A2%B0%E8%AA%9E.html)

## オペコード 【opcode】 operation code

> オペコードとは、マイクロプロセッサ（CPU/MPU）に与える機械語の命令の識別番号。そのプロセッサの命令の体系を定義する「命令セットアーキテクチャ」（ISA：Instruction Set Architecture）で定められている。

[オペコードとは - IT用語辞典 e-Words](https://e-words.jp/w/%E3%82%AA%E3%83%9A%E3%82%B3%E3%83%BC%E3%83%89.html)

### オペコードの例

```
00000001 0001 0010
```

[オペコードとは？ - パソコンの選び方と買い方](https://pcinformation.info/computer/about-opecode.html)


## ニーモニック 【mnemonic】

> ニーモニックとは、コンピュータのマイクロプロセッサ（CPU/MPU）に与える命令の種類を表す番号（オペコード）に、人間が分かりやすいように付けられた英数字の短い符号。

[ニーモニックとは - IT用語辞典 e-Words](https://e-words.jp/w/%E3%83%8B%E3%83%BC%E3%83%A2%E3%83%8B%E3%83%83%E3%82%AF.html)

## アセンブラ言語を動かすには for Mac

アセンブリ言語ようのコンパイラ`nasm`を使用して、自分の実行環境に合わせて、コンパイルする。

```
nasm -f macho64 test.s
```

### 自分の実行環境の調べ方

自分のハードウェアの名前を以下コマンドで出力する。

```
uname -m
```

## nasmが対応するフォーマットの一覧

```
$ nasm -h
    -f format     select output file format
       bin                  Flat raw binary (MS-DOS, embedded, ...) [default]
       ith                  Intel Hex encoded flat binary
       srec                 Motorola S-records encoded flat binary
       aout                 Linux a.out
       aoutb                NetBSD/FreeBSD a.out
       coff                 COFF (i386) (DJGPP, some Unix variants)
       elf32                ELF32 (i386) (Linux, most Unix variants)
       elf64                ELF64 (x86-64) (Linux, most Unix variants)
       elfx32               ELFx32 (ELF32 for x86-64) (Linux)
       as86                 as86 (bin86/dev86 toolchain)
       obj                  Intel/Microsoft OMF (MS-DOS, OS/2, Win16)
       win32                Microsoft extended COFF for Win32 (i386)
       win64                Microsoft extended COFF for Win64 (x86-64)
       ieee                 IEEE-695 (LADsoft variant) object file format
       macho32              Mach-O i386 (Mach, including MacOS X and variants)
       macho64              Mach-O x86-64 (Mach, including MacOS X and variants)
       dbg                  Trace of all info passed to output stage
       elf                  Legacy alias for "elf32"
       macho                Legacy alias for "macho32"
       win                  Legacy alias for "win32"
```

## AMD64 【x86-64】 x64

> AMD64とは、米AMD社が開発したマイクロプロセッサ（CPU/MPU）の64ビット命令セットで、32ビットのx86系命令セットとの互換性を維持したまま64ビットコードの実行を可能にしたもの。

[AMD64（x86-64）とは - IT用語辞典 e-Words](https://e-words.jp/w/AMD64.html)
【Rails】あるテーブルからあるテーブルへ、belongs_toを「複数回」使いたい

関連付けアンチだったけど、今は好き。「コロンが付いたら配列を疑え」の意識がまた消えてた。でもモデルに関しての知識が深まったから良し（？）。普通にreferences使わない方が簡単。

####【ページ内リンク】
[０．環境](#０環境)
[１．動機](#１動機)
[２．やった](#２やった)
[３．foreign_key: trueを設定する理由](#３foreign_key-trueを設定する理由)
[４．感想](#４感想)
[５．参考文献](#５参考文献)

#０．環境
・AWS
・heroku/7.48.0 linux-x64 node-v12.16.2
・Rails 5.2.4.5
・ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]
・MySQL 5.7.31
・PostgreSQL 9.2.24

#１．動機
試合のテーブル（**Gameテーブル**）を作っている。試合なのでホームチームとビジターチームの2種類のチーム名が必要。**Teamテーブル**と関連付けしたいが、**Gameテーブル**に`hometeam_id`、`visitorteam_id`を作った場合、`belongs_to`で**Teamテーブル**の`id`とどうやって関連付けすればいいんだ･･･？と思ったため

[ページ内リンクへ戻る](#ページ内リンク)

#２．やった
【やりたいこと】
①カラム名を`hometeam_id`、`visitorteam_id`とする
②外部キー制約
③`game.hometeam.~`で値が取れるようにする
④値がnullでもOKとする

```rb:20210402000000_create_games.rb
class CreateGames < ActiveRecord::Migration[5.2]
  def change
    create_table :games do |t|
      t.references :hometeam, foreign_key: { to_table: :teams }
      t.references :visitorteam, foreign_key: { to_table: :teams }

      t.timestamps
    end
  end
end
```
・`t.references :hometeam`で、`hometeam.id`の値を参照しますよという意味（しかし、そんな物は無い。）　**#①完了**
・`foreign_key: { to_table: :teams }`は、`foreign_key: true`を変形したもの。なぜ`true`だと駄目なのかは、`t.references :hometeam, foreign_key: true`だと`hometeamテーブル`と外部キー制約をするということになる。しかしそんなテーブルは存在せず、`teamテーブル`を参照する必要があるから。　**#②完了**

```rb:game.rb
class Game < ApplicationRecord
  belongs_to :hometeam, class_name: "Team", optional: true
  belongs_to :visitorteam, class_name: "Team", optional: true
end
```
・`optional: true`は下記参照。　**#④完了（？）**
・**【`belongs_to :hometeam`で`game.hometeam`としたときに値が取れるようにし、`class_name: "Team"`で値は`teamテーブル`から取りましょう。という意味。】**　**#③完了**

[ページ内リンクへ戻る](#ページ内リンク)


#３．`foreign_key: true`を設定する理由
外部キー制約をするため。

　`foreign_key: true`が無い場合を考える。`references`クラスとすると、値が親テーブルに無かったりnullの場合にエラーを出す。
　**値がnullでもOKとしたい場合**は`optional: true`を入れるが、これだと親テーブルに無い値の時にもエラーを吐き出さずに通してしまう。
　`foreign_key: true`を入れることで、親テーブルに無い値の時はエラー、nullはOKとなる。

※**値がnullでエラーとするとき**の存在価値は正直分からなかった。`references`と役割が被っているのか、それとも何か別の理由があるのだろうか。もしくは自分がただ勘違いしているのか。

[ページ内リンクへ戻る](#ページ内リンク)

#４．感想
③について思ったこと。
普段は`belongs_to :team`のように関連付けを行っているけど、これって`class_name`を指定しない場合は自動で`class_name: "Team"`となってるだけなのかな。何で`Teamテーブル`を参照しているのに`belongs_to Team`じゃないんだろうと思ってたけど、なるほど合点がいった。Railsすごい（n回目）

[ページ内リンクへ戻る](#ページ内リンク)

#５．参考文献
参考１：[Railsで外部キー制約のついたカラムを作る時のmigrationの書き方](https://qiita.com/publichtml/items/1fba15d8071fab66d043)
参考２：[Active Record の関連付け](https://railsguides.jp/association_basics.html)

[ページ内リンクへ戻る](#ページ内リンク)
さくらの花びらのピンクを浮立たせる補正方法

徳島では、さくらの見どころは土曜までとなる感じです。

さて、実際にみるサクラとスマホで撮った写真のサクラの花びらでは、ピンクの際立ちが異なると思います。

そこで、今回は、photoshopでサクラの花びらがピンクっぽくなるように補正してみたいと思います。

補正前のサクラ
![sakura_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1069454/f4fcd962-1121-c98b-bdac-ccf264268427.jpeg)



1.「塗りつぶしまたは調整レイヤーの新規作成」で、「レンズフィルター」を選択
![saklura_1.1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1069454/2ce05262-9d0a-a467-0cb2-f190e9223329.jpeg)



2.プロパティの「フィルタ」をマゼンタ、適用量を「〜15%」の任意の値に調整
![sakura_1.2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1069454/099e5bc7-d617-bdc0-79c1-03bc92eca28d.jpeg)



3.完成
![sakura2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1069454/63e5248a-dbfc-f450-7eae-308aa64364e0.jpeg)



補正前と見比べて、よりピンクっぽさが際立ったと思います。

背景などを元の状態に保って、サクラの木のみを補正したい場合は、
サクラの木を切り抜いてレイヤーを作成し、そこだけ補正し、背景と合成すれば良いと思います。
【phpbb】エラーをロギング

##はじめに
phpbb3.2を使っています。
`/var/log/httpd/error_log`にエラーが出てこず、phpbbでエラーログ出している人いるかなと思いググっても、困っている人はそれなりにいるにも関わらずACPで見ることのできるログの情報しか出てこなくて、結局以下の方法で対応しました。

##コード

```config.php
@define('PHPBB_ENVIRONMENT', 'production');
```

`config.php`で'development'以外が対象です。

```common.php
if (PHPBB_ENVIRONMENT === 'development')
{
	\phpbb\debug\debug::enable();
}
else
{
	set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');
}
```
`PHPBB_ENVIRONMENT === 'development'`でないときは`set_error_handler()`で`defined('PHPBB_MSG_HANDLER')`がなければ`msg_handler`がセットされます。

`msg_handler`は`includes/functions.php`にあります。

```includes/functions.php
* Error and message handler, call with trigger_error if read
*/
function msg_handler($errno, $msg_text, $errfile, $errline)
{

###略###

    // phpbb does not have logging system so added error_log
    if ($errno == E_ERROR || $errno == E_USER_ERROR) {
        error_log(
            implode(" ", array(
                "errorno:".$errno,
                "msg_text:[".$msg_text."]",
                "errfile:[".$errfile."]",
                "errline:".$errline,
                "phpbb_root_path:[".$phpbb_root_path."]",
                "msg_title:[".$msg_title."]",
                "msg_long_text:[".$msg_long_text."]"
            ))
        )
    }

	switch ($errno)
	{
		case E_NOTICE:
		case E_WARNING:


```
`function msg_handler`に`switch ($errno)`しているところがあります。
今回はそのあたりに`error_log`でロギングするようにしました。
ログの書き方は適宜変えてください。
【Laravel】バルクインサート後にモデルインスタンスを取得する方法

# はじめに
Laravelでバルクインサート後に各モデルインスタンスを取得する方法を解説します。せっかちな人のためにコードだけ最初にのせておきます。

```php
Model::insert($array);
$lastId = DB::getPdo()->lastInsertId();
$ids = [];
for ($i = 0; $i < count($array); $i++) {
    $ids[$i] = $lastId +  $i;
}
$models = Model::find($ids);

```

以降、経緯と解説になります↓


#そもそもバルクインサートって？
バルクインサート（BULK INSERT）という言葉に馴染みがない方に簡単に説明すると、バルクインサートとは複数のデータを一括でテーブルに保存することを意味します。

たとえば、Postモデル、user_idカラムとcontentカラムを持つpostsテーブル、そして以下のような配列があったとします。

```php
$posts = [
    [
        'user_id' => 1,
        'content' => 'エヴァ見たい。'
    ],
    [  
        'user_id' => 2,
        'content' => '記事よんでくれてありがとう！'
    ],
    [
        'user_id' => 3,
        'content' => '最近プロテインの豆乳割りにはまってます。'
    ]
];
```

これをバルクインサートを使わずにDBに保存するとしたら

```php
foreach ($posts as $post) {
    Post::create($post);
}
```
こんな感じの書き方になると思います。（他にも色々あると思います。）

これをバルクインサートを使って書くと、

```php
Post::insert($posts);
```
こうなります。
insertの引数を二次元配列にすることで、データベースに一括で保存しています。

バルクインサートのメリットは、クエリを叩く回数が少なくなるので不可を軽減することができる点です。今回の例では3件だけなので大差ないですが、何万件ものデータがある場合は大きな差になります。

また、デメリットとしては１つでもデータに不備がある場合は全てのデータ保存に失敗する点です。なので、ユーザーが入力するデータの保存などにはバルクインサートは推奨されないようです。

ざっとバルクインサートについて説明しました。

# createとinsertの違い
一旦、バルクインサートのことは忘れて、少しinsertとcreateの違いの話をします。
両者の違いは色々ありますが、今回重要なのは返ってくる値です。

先程の例の続きで、以下のようにすると

```php
$post = Post::create($post);

$post = Post::insert($post);
```
それぞれ`$post`には何が代入されるでしょうか。

実は上記の場合は保存したレコードのモデルインスタンスが、
下記の場合はBoolean型の1(true)が返ってきます。

恥ずかしながら、insertを使ったときBooleanが返ってくるのは最近知りました。

ようやく前おきが終わりました。やっと本題です。

# バルククリエイトしたかった

今回、僕はバルクインサートの後に、各モデルのインスタンスを使って続きの処理をしたかったのですが、なんとcreateを使ってバルクインサートはできない仕様みたいです。

```php
// こう書けない...。
$posts = Post::create($posts);
```

僕の理想では上記のようにして、

```php
[
    {
        "id": 1,
        "user_id": 1,
        "content": "エヴァ見たい。"
    },
    {
        "id": 2,
        "user_id": 2,
        "content": "記事よんでくれてありがとう！"
    },
    {
        "id": 3,
        "user_id": 3,
        "content": "最近プロテインの豆乳割りにはまってます。"
    }
]
```
こんな感じの配列を$postsに格納したかったわけです。

# 解決法
最初にのせたコードを今回の例にあわせて書き換えました。

```php
Post::insert($posts);
$lastId = DB::getPdo()->lastInsertId();
$ids = [];
for ($i = 0; $i < count($posts); $i++) {
    $ids[$i] = $lastId +  $i;
}
$posts = Post::find($ids);
```

こうすることで、少し遠回りですが`$posts`に各インスタンスモデルを取得できます。
今回のコードの肝は

```php
$lastId = DB::getPdo()->lastInsertId();
```
この部分ですね。

`DB::getPdo()->lastInsertId();`は最後にインサートしたデータのIDを取得してくれます。便利です。
しかし、注意してほしい点は、バルクインサートをした場合は複数インサートしたデータの最初のデータのIDが取得される点です。
例えば、３つのデータを一括保存してそれぞれ1,2,3というIDが割り振られたとしたら、`DB::getPdo()->lastInsertId();`は1を返します。

なにはともあれ、無事各モデルのインスタンスを取得することができました。

# 終わりに
今回はバルクインサートを題材に記事を書きました。
データベースやEloquentの理解が浅いと思うので、間違ってる箇所やこうしたほうがいいよ！っていう部分があればご指摘いただけると幸いです。

また、最後まで読んでいただきありがとうございます！

それでは、よいLaravelライフを〜
unameコマンド man翻訳

# unameコマンド

「uname」はカーネルの名前やバージョン、ハードウェア名（x86_64など）などを表示するコマンドです。主に現在ロードされているカーネルのバージョンを確認する際に使用します。

[【 uname 】コマンド――カーネルのバージョンなどの情報を表示する：Linux基本コマンドTips（275） - ＠IT](https://www.atmarkit.co.jp/ait/articles/1901/24/news026.html)

## 主な機能

オペレーティングシステムの名前の表示

## 詳細

unameユーティリティは、1つ以上のシステム特性を表すシンボルを標準出力に書き込みます。

## option

オプション|説明
-|-
-a | すべてのオプション-mnrsvが指定されているかのように動作します。
-m | マシンのハードウェア名を印刷します。
-n | nodenameを印刷する（NodeNameは、システムが通信ネットワークに認識されている名前です）。
-p | マシンプロセッサアーキテクチャ名を印刷します。
-r | オペレーティングシステムのリリースを印刷します。
-s | オペレーティングシステム名を印刷します。
-v | オペレーティングシステムのバージョンを印刷します。

オプションが指定されていない場合は、uname -sオプションが指定されているかのようにオペレーティングシステム名を印刷します。

## 関連のあるコマンド

hostname(1), machine(1), sw_vers(1), uname(3)
Vue.jsのコンポーネント間のデータの受け渡しについてまとめてみた。(props,$emit)

今回はVue.jsのコンポーネント間の通信についてまとめてみました！
![スクリーンショット 2021-04-02 16.00.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185431/033268ff-36bd-72a0-0343-8f24d2a5a754.png)

##propsとは
親コンポーネントから子コンポーネントにデータを渡すことができるもの。
親から子への受け渡し方は単純ですね。

###App.vue（親コンポーネント）
※template内はキャメルケースでも書けますが、HTMLの慣習で属性はケバブケースで書く為、ケバブケースが推奨されてます。

```vuejs
<template>
  <div>
    <LikeHeader />
    <h2>{{ number }}</h2>
    <!--属性のようにつけることで子コンポーネントにnumberを渡す-->
    <LikeNumber :total-number="number" /> 
  </div>
</template>

<script>
import LikeHeader from "./components/LikeHeader.vue";
import LikeNumber from "./components/LikeNumber.vue";

export default {
  data() {
    return {
      number: 10,
    };
  },
  components: {
    LikeHeader,
    LikeNumber,
  },
};
</script>
```
###LikeNumber.vue（子コンポーネント）

```vuejs
<template>
  <div>
    <!--親から受け取った値を表示-->
    <p>いいね({{ totalNumber / 2 }})</p> 
  </div>
</template>

<script>
export default {
  //親からnumberを受け取る
   props: {
    totalNumber: {
      //バリデーションもかけられる！
      type: Number,
      // required: true 必須かどうかの真偽値
      required: true,
    },
  }
};
</script>
```

##$emitとは
子供から親にデータを渡すもの

というよりかは。。

子コンポーネントの好きなタイミングで**親コンポーネントのメソッドを発火できるもの。**
それが結果として**親コンポーネントにデータを受け渡すことができるようになります。**

またpropsで受け取った値は直接更新してはいけないというVueのルールがあるので、子コンポーネントでpropsの値を書き換えても親には反映されません。

####$emitの引数
```
$emit( eventName, […args] )
```
第一引数: カスタムイベント名（好きな名前で良い。**また、第一引数のみでも問題ない**）
第二引数: 渡したい値

つまり**$emitはカスタムイベントを作るものになります！！**
そのカスタムイベントを発火させる時に一緒にデータを渡すこともできます！

###App.vue（親コンポーネント）
```vuejs
<template>
  <div>
    <LikeHeader />
    <h2>{{ number }}</h2>
    <!--@my-clickは子コンポーネントでつけたカスタムイベント名-->
    <LikeNumber :total-number="number" @my-click="incrementNumber" />
  </div>
</template>

<script>
import LikeHeader from "./components/LikeHeader.vue";
import LikeNumber from "./components/LikeNumber.vue";

export default {
  data() {
    return {
      number: 10,
    };
  },
  components: {
    LikeHeader,
    LikeNumber,
  },
  methods: {
    //valueは子コンポーネントに指定した第二引数
    incrementNumber(value) {
      this.number = value;
    },
  },
};
</script>
```

###LikeNumber.vue（子コンポーネント）
```vuejs
<template>
  <div>
    <!--親から受け取った値を表示-->
    <p>いいね({{ totalNumber / 2 }})</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script>
export default {
  //親からnumberを受け取る
  // 型を指定することで
  props: {
    totalNumber: {
      type: Number,
      required: true,
    },
  },
  methods: {
    increment() {
      //第一引数は好きなイベント名、第二引数に親に渡したい値
      this.$emit("my-click", this.totalNumber + 1);
    },
  },
};
</script>
```




###感想
$emitは親コンポーネントにデータを渡すもの、、というより
$emitはカスタムイベントを作るもので、結果として**親コンポーネントにデータを渡すことができるものになります。**
【GCP】GCEについて

64TB
https://cloud.google.com/compute/docs/disks/?&_ga=2.163958847.-1496270841.1601963847#pdspecs

永続ディスクのサイズ変更は、大きくすることのみ可能です。永続ディスクのサイズを小さくすることはできません
実行中の VM にアタッチされているかどうにかかわらず、ディスクのサイズはいつでも変更できます。
https://cloud.google.com/compute/docs/disks/working-with-persistent-disks#resize_pd

128個(ディスクの内容による)
https://cloud.google.com/compute/docs/disks/?&_ga=2.163958847.-1496270841.1601963847#pdperformance
まずは基本の「線形回帰」を理解する（理論編）

## はじめに
**回帰モデルの基本である線形回帰の理論について解説していきます。**特に以下の内容について説明します。サンプルデータを用いたPythonでの実装方法については[こちら](https://qiita.com/oki_kosuke/items/ebb0f7c28f86e72f9224)で解説の記事を書きました。

- 線形とは？（非線形との違い）
- 線形回帰モデルの概念（最小二乗法による係数の決め方やイメージ）

※機械学習やプログラミング関係の内容を他にも投稿していますので、よろしければ[こちら](https://qiita.com/oki_kosuke/items/34b1071224953776c211#%E6%8A%95%E7%A8%BF%E4%B8%80%E8%A6%A7)の一覧から他の投稿も見て頂けますと幸いです。

### 線形とは？
関数の線形・非線形を簡単にまとめますと以下の通りです。

- **線形関数：グラフが直線になる関数**　      （例）y=x, y=-3x
- **非線形関数：グラフが直線にならない関数**　（例）y=x<sup>2</sup>, y=sinx

### 単回帰分析と重回帰分析とは？
少し脱線しますが、たまに聞く単回帰分析・重回帰分析について以下にまとめます。

- **単回帰分析は説明変数（x）が1つ、目的変数（y）が1つの回帰分析**

　→式で表すとy=ax+b

<br>

- **重回帰分析は説明変数（x）が2つ以上、目的変数（y）が1つの回帰分析**

　→式で表すとy=b<sub>0</sub>+b<sub>1</sub>x<sub>1</sub>+b<sub>2</sub>x<sub>2</sub>+…
　　xの前についている定数b<sub>1</sub>, b<sub>2</sub>…を「偏回帰係数」といいます

## 線形回帰とは？
説明変数をx、目的変数をyとした際に線形回帰モデルは以下のように表されます。εはノイズ（擾乱項）を表しますが、係数wを決定していく際には0と仮定して扱われます。 

```math
y = w_0+w_1x_1+w_2x_2+…+w_dx_d+ε
```

ここから係数wを決定して線形回帰モデルを決定します。以下にn個のデータがある際にwを決定する方法について簡単に説明していきます。

```math
\boldsymbol{X}=
\begin{pmatrix}
1&x_{11}&x_{12}&\cdots&x_{1d} \\
1&x_{21}&x_{22}&\cdots&x_{2d} \\
\vdots & \vdots& \vdots&&\vdots& \\
1&x_{n1}&x_{n2}&\cdots&x_{nd} \\
\end{pmatrix}
```

<br>

```math
\boldsymbol{w}=
\begin{pmatrix}
w_0  \\
w_1 \\
w_2 \\
\vdots \\
w_d
\end{pmatrix}
```

とすると、線形回帰モデルによる予測値は以下のように表すことができます。

```math
\boldsymbol{\overline{y}}=\boldsymbol{Xw}
```

実際の目的変数（ターゲット）を**_y_**とすると、モデルの誤差の二乗和*E*は以下のように表すことができます。

```math
E=||\boldsymbol{y-Xw}||^2
```

*E*を最小にするために勾配を計算して、その値を0とすると以下の式が得られます。

```math
\boldsymbol{w}=\boldsymbol{(X^TX)^{-1}}X^Ty
```

ここからの解法は割愛させていただきますが、 [こちら](https://mugichoko.hatenablog.com/entry/2018/04/05/184100)などを参考にしていただければと思います。このように線形回帰モデルを決定していく手法を**「最小二乗法」**といい、係数決定の一般的な手法です。

最小二乗法が何をしているか、以下の図を用いて説明します。青色の線の長さは線形回帰モデルと実際のデータ（赤色のプロット）との誤差を表しています。この誤差の二乗和が最小となるとき、線形回帰モデルはデータを最も精度よく予測できている状態になります。**つまり、最小二乗法は青色の線の長さの総和を最小にして（最も精度の高い回帰モデルを作っている）のです。**

![線形回帰.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1057114/836b6991-402d-1f88-eebe-0b8c97febb87.png)

## まとめ
線形回帰の理論について解説いたしました。

- 線形回帰は説明変数と目的変数を線形関係（直線的な関係）で結びつけた回帰モデルである
- 線形回帰モデルの式は最小二乗法により決定される

pythonでの線形回帰の実装方法については[こちら](https://qiita.com/oki_kosuke/items/ebb0f7c28f86e72f9224)に投稿しています。

### 参考
- [趣味の大学数学](https://math-fun.net/20190619/1715/)
- [Albert社 データ分析基礎知識](https://www.albert2005.co.jp/knowledge/statistics_analysis/multivariate_analysis/multiple_regression#:~:text=%E5%8D%98%E5%9B%9E%E5%B8%B0%E5%88%86%E6%9E%90%E3%81%8C%E3%80%811,%E3%81%8C%E9%87%8D%E5%9B%9E%E5%B8%B0%E5%88%86%E6%9E%90%E3%81%A7%E3%81%99%E3%80%82)
- [Mugichoko's blog](https://mugichoko.hatenablog.com/entry/2018/04/05/184100)
Photoshop レイヤーをアートボードの中心（縦・横）に配置する方法

画像やシェイプ、文章などを、アートボードの縦・横に中心配置する方法です。

1.中心配置したいレイヤーを移動ツールで選択した状態で、Ctr + A（Windows）,command + A（Mac）を押す。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1069454/e85a4438-96e0-32d0-5ec8-587b9b0ffdbe.png)


2.配置をおす（縦中心・横中心ともに）
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1069454/b229b7c2-978d-5174-9bbc-96351aa76604.png)


3.中心配置完了
![スクリーンショット 2021-03-26 14.14.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1069454/8bdbffb5-cce2-7181-fe17-4e155486cd9c.png)
【C#】ModelをJSONシリアライズしたい

##シリアライズ
ModelをJSONにシリアライズしたいとき、あると思います。
`JsonSerializerOptions`をいじると整形したりnull項目を非表示にしたりできます。

```CS:CS
Model model = new Model 
{ 
    TemperatureCelsius = 1,
    Summary = "No.1",
};

var optionsUTF8 = new JsonSerializerOptions
{
    // すべての null 値プロパティを除外
    IgnoreNullValues = true,
    // 文字コードの設定
    Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
    // 整形出力を行う
    WriteIndented = true
};

var serialize = JsonSerializer.Serialize(model, optionsUTF8);
```

```json:出力結果
{
  "TemperatureCelsius": 1,
  "Summary": "No.1"
}
```
##おまけ
拡張メソッドにしておくとちょっと便利。

```CS:CS
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;

public static class JsonUtility
{
    // 拡張メソッドにしておくとちょっと便利
    public static string ToJson<T>(this T model)
    {
        var optionsUTF8 = new JsonSerializerOptions
        {
            // すべての null 値プロパティを除外
            IgnoreNullValues = true,
            // 文字コードの設定
            Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
            // 整形出力を行う
            WriteIndented = true
        };

        return JsonSerializer.Serialize(model, optionsUTF8);
    }
}
```

```CS:呼び出し方
var serialize = model.ToJson();
```
fish-shell + NeoVimでsudoeditしたい

## 環境

* Ubuntu 20.04
* fish(aptでinstall)
* nvim(snapでinstall)

## [問題]fishでsudoeditすると```$EDITOR```, ```$SUDO_EDITOR```, ```$VISUAL```を参照してくれない

Ubuntuでログインシェルをfishにしている場合、
config.fishに```set EDITOR nvim```などを設定していても、
update-alternativesの設定が優先されてしまう。

bashでexportしておいて、fishを起動すると大丈夫なので、
ログインシェルがbashでそこからfishを起動しているとnvimがちゃんと選ばれる。

ログインシェルをfishにしたら、いきなり躓いたので記録しておく。

## TL; DR

config.fishに以下を書いておいて、```se [file]```

```sh
set EDITOR nvim
alias se="export EDITOR=$EDITOR; sudoedit "
```

ここから以下は、試してみたこと備忘録。


## 案1 update-alternativesにnvimを登録する

snapで入れているとなかなか面倒。

/snap/bin/nvimを登録しても
snapへのシンボリックリンクなためか、snapの引数としてファイルが渡されてしまう。

```bash
#!/bin/bash
/snap/bin/nvim $1
```
みたいなファイルを作って登録するとうまくいくかもだけど、
スマートさに欠けるので、このアプローチはここで保留。

おそらくaptでNeoVimを入れていればこのアプローチでもいけそう。

## 案2 bashからやる

ログインシェルがfishの場合、
bash起動して、export EDITOR=nvimして
fishすると大丈夫

つまり、

```sh
bash -c "export EDITOR=nvim; sudoedit /etc/hosts"
```

ならちゃんとnvimが起動する。
でも、このやり方はとても気持ち悪いので却下。

ここで実は、fishでexportして、sudoeditしても大丈夫なことに気づく。

そこで案3へ。

## 案3 aliasを使う

config.fishに以下を書いておく

```sh
set EDITOR nvim
alias se="export EDITOR=$EDITOR; sudoedit "
```

ちなみに、```alias sudoedit="export EDITOR=$EDITOR; sudoedit "```という風にsudoeditを上書きはできない。
また、```set EDITOR nvim```だけではsudoeditに利いてくれないので、exportを使う。
直接config.fishにexportを書くことはできない。

```bash
se /etc/hosts
```

今の所、この案を採用。
PHP cURLの使い方

#curlを使用する一連のコードの流れについて

参考：
[Qiita](https://reffect.co.jp/php/perfect_understanding_curl_in_php)
[Refect](https://reffect.co.jp/php/perfect_understanding_curl_in_php)

##基本

```php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.hogehoge.com/");
//(その他用途に応じてcurl_setopt()を記述)
curl_exec($ch);
curl_close($ch);
```

上記を実行するとhogehoge.comのサイトページの情報を取得し、表示出来る。


###curl_getinfoについて
**curl_getinfoはリクエストに関する情報を配列として返す。**
使用する場所：**curl_exec()とcurl_close()の間**に記述する。

###上記を踏まえてグーグルの情報を取得する例

```php
<?php 


/* curlセッションを初期化する　*/
$ch = curl_init();

/* curlオプションを設定する */
curl_setopt($ch, CURLOPT_URL, "http://www.google.com/");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);


/* curlを実行する */
$result = curl_exec($ch);

$info = curl_getinfo($ch);


var_dump($info);


/* curlセッションを終了する */
curl_close($ch);


//var_dump($info)の結果は以下
/*
array(26) {
  ["url"]=>
  string(22) "http://www.google.com/"
  ["content_type"]=>
  string(29) "text/html; charset=ISO-8859-1"
  ["http_code"]=>
  int(200)
  ["header_size"]=>
  int(732)
  ["request_size"]=>
  int(53)
  ["filetime"]=>
  int(-1)
  ["ssl_verify_result"]=>
  int(0)
  ["redirect_count"]=>
  int(0)
  ["total_time"]=>
  float(0.127532)
  ["namelookup_time"]=>
  float(0.005124)
  ["connect_time"]=>
  float(0.01553)
  ["pretransfer_time"]=>
  float(0.015613)
  ["size_upload"]=>
  float(0)
  ["size_download"]=>
  float(49800)
  ["speed_download"]=>
  float(390490)
  ["speed_upload"]=>
  float(0)
  ["download_content_length"]=>
  float(-1)
  ["upload_content_length"]=>
  float(-1)
  ["starttransfer_time"]=>
  float(0.105488)
  ["redirect_time"]=>
  float(0)
  ["redirect_url"]=>
  string(0) ""
  ["primary_ip"]=>
  string(14) "216.58.197.196"
  ["certinfo"]=>
  array(0) {
  }
  ["primary_port"]=>
  int(80)
  ["local_ip"]=>
  string(13) "192.168.0.101"
  ["local_port"]=>
  int(55635)
  */
  ```
.vscodeのlauch.jsonをgit監視下から外す

開発から離れると毎度忘れるので備忘録。

ワークスペース内でデバック設定するとできる.vscode/launch.jsonをgit監視下から外したい。
.gitignoreに書くとこれをコミットするしないでめんどくさいので
(他の人はデバック設定していなかったりvscodeじゃなかったりする)
他の方法の実行。

ワークスペース配下の隠しフォルダの
.git/info/exclude
に以下記述

```
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
.vscode
```
【Swift初心者】メトロポリタン美術館APIを使ってTinder風アプリを作ってみた！

<h1>アプリ概要</h1>
メトロポリタン美術館の作品を検索でき、好きな作品を保存・シェアすることができるアプリです。


主な機能は以下になります。
・メトロポリタン美術館の作品を検索できる。
・好きな作品はTinder風でカードとして表示される。
・右スワイプでお気に入りリストに保存可能。
・他のユーザーがお気に入りにした作品の閲覧もできる。
・その中から気に入った作品を自分のお気に入りリストへ追加できる。
・お気に入りの作品をツイッター等でシェアできる

![search_Swipe](https://user-images.githubusercontent.com/78245675/112149481-5fdc9380-8c22-11eb-9a02-94b89410cf9a.gif) 


# このアプリを作成した背景
このアプリを作成した背景は2つあります。

1.アートに関心を持つ人を増やしたかったから。 
2.アート作品がみれるアプリが少なかったから。

### 1.アートに関心を持つ人を増やしたかったから。 
自分自身、ZOZOの前澤社長がバスキアの作品を買った時からアートに興味を持ち始めました。
そこからいろいろなアーティストの作品を見ていくと、それぞれの作品に個性が詰まっていて、とても面白かった。
ただ、現状アート自体に関心がある人はかなり少ないと思います。おそらくアートに重いイメージを持っている人も多いからだと思いますが、写真と同じようにもっと気軽に作っても、観賞しても良いものだと自分は思います。

もっと多くの人にアートに関心を持ってもらう機会があれば、と思いこのアプリを作成しました。
また、若い人でも楽しめるように、若い世代に定着しているTinder風のUIを使いました。


### 2.アート作品がみれるアプリが少なかった。
AppStoreで検索してみたところ、あまりアート作品に特化したアプリがあまりなかったので、作成しました。
Pinterestのアート作品特化バージョンをイメージして作りました。
自分が好きな作品を保存・シェアすることができます。




# UIデザイン
・アーティストに詳しくない人でも検索できるように、おすすめのアーティスト一覧を表示。
→気になるアーティストをタップするだけで検索可能に。

・作品を吟味できるように、スワイプで一作品ずつ確認できるようにした。 
→画像が羅列されるよりも、一作品ごとにかける時間が多くなり、じっくり見て頂ける。

![search_Swipe](https://user-images.githubusercontent.com/78245675/112149481-5fdc9380-8c22-11eb-9a02-94b89410cf9a.gif)  

![favolite](https://user-images.githubusercontent.com/78245675/112149794-b4800e80-8c22-11eb-9dcf-546ca6915538.gif) 


・他のユーザーのリストから新しい作品に出会えるようにした。 
→他のユーザーのお気に入りリストから新しい作品に出会える。
![otherListFav](https://user-images.githubusercontent.com/78245675/112150001-f446f600-8c22-11eb-8b99-2215d2d8e68e.gif)

## 機能
匿名ログイン機能
ログアウト機能
作品検索機能
カードスワイプ機能
お気に入り追加機能
お気に入り削除機能
別ユーザーのお気に入り確認機能
別ユーザーの作品保存機能
画像シェア機能


## 作品検索機能
`工夫したこと`
・APIの仕様上、情報を取得するために検索ボタンを押してから2回パースした。
1回目でobjectIDsを取得して、2回目でそれぞれの作品のデータを取得。

・検索数が0の場合、アラートが出るようにした。
検索ヒット数が多いと動作が重くなってしまうので、30件以上ヒットしたら30件のみ表示。

・アーティスト名が書いたボタンを押すだけで、自動で検索できるようにした。
アーティスト名に詳しくない人のためにこのようなUIにした。


## カードスワイプ機能
`工夫したこと`
VerticalCardSwiperを使って表示。
右にスワイプした作品はデータベースに保存。


## 別ユーザーのお気に入り確認/保存機能
`工夫したこと`
・オートID以下（userID,userName）を取得してきて、userNameをリストに表示。
・リストの名前をタップすると、そのuserIDを元に、その人がお気に入りした作品の詳細情報を表示。

## 画像シェア機能
`工夫したこと`
・より多くの方に作品を知っていただけるように、コメントをつけてTwitter等でシェアが可能。


## 追加実装予定
・作品詳細画面で複数枚の写真を表示
・検索ロード時間を短縮
・検索コードの見直し
・現代アートも検索できるよう改善
・匿名ログインの変更/Twitterログインの実装
・アートに関する知識が増えるようなコンテンツの実装


## データベース
Firebase/Database
Firebase/Auth

## API
The Metropolitan Museum of Art Collection API

## 使用ライブラリ
Firebase/Database
Firebase/Auth
VerticalCardSwiper
SDWebImage
PKHUD
Alamofire
SwiftyJSON
ChameleonFramework
EMAlertController
Laravel バリデーションメッセージ日本語化 attribute書くのめんどくさい人向け

# laravelのバリデーションでattributeの設定をするのがめんどくさい
自分はFormRequestを一番使うが、基本的にバリデーションメッセージはメッセージに一貫性がなくなるから`/resource/lang`にぶち込んであるメッセージに乗っかってFormRequestでの独自のメッセージはなるべく書かないようにしている。

その時にリクエストパラメーターのkeyでバリデーションメッセージが生成されれる。当たり前だが、labelなりフォームの見出しなりはリクエストに含まれてないので自分で変換してあげなきゃいけない。

一般的なやり方はFormRequestの場合、attributeメソッドに連想配列で書いて変換する方法だと思う。

modelかどっかに`param名 => ラベル`の連想配列を常に持っておけばそこから参照できる。ただ、ページごとにラベルを変えてフォームを用意すると破綻する。

# 自分がよくやる構成

``` html
@php
  $data = ['name' => 'xxx']; // 初期値配列
  $key = 'name';
  $label = '名前';
@endphp
<label>{{ $label }}</label>
<input name="{{ $key }}" type="text" value="{{ old($key, $data[$key] ?? null) }}">
@error($key)
    {{ str_replace(str_replace('_', ' ', Str::snake($key)), $label, $message) }}
@enderror
```

attributeを毎回書くので疲弊するのは避けられる。

メモがてら
JS~ハートが可愛く回るよ♥④~

今回は、可愛く回ったハートを百個まで増やしたいと思います！！
自分で百個まで作るのはしんどいので、for文を使って行きましょう👌

```index.html
for (let i = 0; i < 1000 ; i ++) {
    const div = document.createElement('div');
    div.classList.add('heart');
    div.addEventListener('click', () => {
      div .classList.toggle('circle');
    });

    document.body.appendChild(div);
  }
    
```
iはカウンターのような役割を担っています👍
今回の場合、値が0から９９９まで繰り返されるといった感じになります！
ちなみにブラウザ上ではこうなります！

![スクリーンショット 2021-04-02 16.56.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/fc688729-92f7-605b-5dd8-5fceab8efeb0.png)
[セキュリティ]DNSに対する攻撃方法と対策まとめ

社内で毎週エンジニアの勉強会を行っており、次回は自分の担当なので発表用の資料をこちらにまとめていこうと思います。

# 教材
教材はIPAが出している安全なウェブサイトの作り方を使っています。
https://www.ipa.go.jp/security/vuln/websecurity.html

2.2~2.4の章が自分の担当なのでこちらの記事では `2.2 DNSに関する対策`についてまとめていきます。


# DNSにおける問合せの流れ
DNSにおける問合せの流れについてはJPRSのサイトの図がわかりやすかったので引用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324032/3c59f464-55b2-0548-08cf-97aa143ba10e.png)

引用: https://jprs.jp/glossary/index.php?ID=0145

`example.jp`というドメインの名前解決をしたい場合、下記の流れでIPアドレスを取得します。

* クライアントはキャッシュDNSサーバーに問合せ
* キャッシュDNSサーバーはルートサーバーに問合せ
* ルートサーバーはjpのDNSサーバーのIPアドレスを応答
* キャッシュDNSサーバーはjpのDNSサーバーに問合せ
* jpのDNSサーバーはexample.jpのIPアドレスを応答


参考: 
権威DNSサーバーってどこにあるの？
http://dnsops.jp/event/20150724/LT-simamura-1.pdf

一般家庭にあるネットにつなげるために設置されたルータの中にあるDNSのプログラムはスタブリゾルバでしょうか。(ter)
https://teratail.com/questions/99195

# DNSの脆弱性の影響

安全なウェブサイトの作り方の資料から引用

> DNS により、ドメイン名を 指定するだけで、該当するウェブサイトへのアクセスやメールの送受信が可能になります。そのため、 DNS に問題が発生すると、ウェブサイトや電子メール等のインターネットを利用するサービス全てに影響 が及びます

# DNSを狙った攻撃
## キャッシュポイズニング攻撃
### 攻撃方法

![スクリーンショット 2021-04-07 17.43.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324032/4d0f73d1-4505-441e-776a-eade26f2c4b9.png)
引用：
https://www.ipa.go.jp/security/vuln/documents/2008/200812_DNS.html

* DNSキャッシュサーバーのキャッシュが切れた時に発生
* 権威DNSサーバーに問い合わせた際に悪意あるユーザーから偽の応答が注入され、偽のIPアドレスがキャッシュされる
* 例えば、example.jpのIPアドレスは192.168.1.23が正解なのに、172.16.3.2とキャッシュされる
* ユーザーがexample.jpをのIPアドレスを取得しようとした時に偽のウェブサイトのIPアドレスの172.16.3.2が応答されてしまう

### キャッシュポイズニング攻撃の対策
#### ソースポートランダマイゼーション  
https://jprs.jp/glossary/index.php?ID=0167

キャッシュDNSサーバーが権威DNSサーバーに問合せを行う際に発信元のポート番号をランダムに変化させる手法。
攻撃者はポートを特定しないと応答を注入できないので攻撃しにくくなる。

#### オープンリゾルバー対策
オープンリゾルバーとは？
https://wa3.i-3-i.info/word12274.html

アクセス元を制限しておらずどこからでもアクセスできるDNSキャッシュサーバーのこと。

DNSキャッシュサーバーへのアクセスを制限することでキャッシュポイズニング攻撃を受ける機会を減らす。

## リフレクター攻撃
### 攻撃方法
JPRSの図を引用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324032/b6a43edf-b70a-d52e-f189-54614394f945.png)
引用:
https://jprs.jp/glossary/index.php?ID=0156

* DNSキャッシュサーバーに送信元を偽った問合せを送る
* DNSサーバーは偽りの送信基に応答を返す
* 上記を問合せを大量に行うことで偽りの送信元(攻撃対象)に大量に応答が返され、サービス不能状態にさせられる

### リフレクター攻撃の対策
#### オープンリゾルバー対策
キャッシュポイズニング攻撃と同様でDNSキャッシュサーバーに問合せできなければ成立しないのでDNSサーバーへのアクセスを制限する

#### 送信元の検証
送信元のアドレスが正しいか事前に検証することで不正な問合せをブロックする
https://www.iij.ad.jp/dev/tech/activities/sav/

## 水責め攻撃
### 攻撃方法
参考： https://jprs.jp/related-info/guide/021.pdf

* `abcdefg.example.jp`みたいに、`example.jp`のランダムなサブドメインに対して問合せを送信
* DNSキャッシュサーバーは指定された文字列のサブドメインに対する応答のキャッシュを持っていないため権威DNSサーバーに問合せ
* ランダムなサブドメインに対する問合せが大量に送られることで問合せを受けるDNSサーバーに大量に問合せが送られサービス不能になる

### 水責め攻撃の対策
#### DNSログの解析
参考：
https://cybersecurity-jp.com/column/34745

こちらの記事ではDNSログを解析して異常な数の不審な問合せをブロックする方法があるとのこと
DXライブラリでマイクラのデバッグ画面みたいなやつを作る

DXライブラリのアドベントカレンダーを一人で埋めていくシリーズです。

今回作りたいのはこんなやつ↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286973/ca49d300-a771-3641-a279-c5b4e5b838c1.png)[画像引用元](https://minecraft.fandom.com/wiki/File:DebugScreen.png)

下のグラフとかはまたやる気があったらやってみます。（多分やらない）
今回は上の数字とか文字がいっぱいあるやつをやります。

# 実装方針
といっても簡単な話で、背景に半透明の矩形を描画したうえに文字列を描画させます。
また、すべての処理箇所で使用したいのでグローバル空間においておきます。
### 補足
フォントは`DxLib_Init()`のあとでしか読み込めませんので、グローバル空間に置く場合、コンストラクタ内ではフォントは読み込めません。

# 実装
```c++:DebugConsole.h
#include<vector>
#include<DxLib.h>

class Debug {
	std::vector<std::string> List; //描画する項目
	int FontHandle; //描画するフォント
public:
	void Init() { //フォントを使用しない場合はいらない
		FontHandle = CreateFontToHandle("ＭＳゴシック", 16, 2);
	}

	void Add(std::string text) { //描画する項目を追加
		List.push_back(text);
	}

	void Add() { //空行を追加
		List.push_back("");
	}

	void Update() {
		int i = 0;
		for (auto& t : List) {
			if (t == "") { //空行処理
				i++;
				continue;
			}
			int x, y, l;
			SetDrawBlendMode(DX_BLENDMODE_ALPHA, 127); //背景の矩形を半透明にする
			GetDrawStringSizeToHandle(&x, &y, &l, t.c_str(), t.length(), FontHandle); //各行の大きさを取得
			DrawBox(0, i * y, x, i * y + y, 0x000000, TRUE); //背景の矩形を描画
			SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0); //半透明から通常に戻す
			DrawStringToHandle(0, i * y, t.c_str(), 0xffffff, FontHandle); //文字列をフォントを使って描画

			i++;
		}
		List.clear(); //すべて描画し終えたら、リストを消去する
	}
};

Debug debug;
```


使用例

```c++:main.cpp
#include <DxLib.h>
#include "DebugConsole.h"

void foo() {
	debug.Add();
	debug.Add("foo");

	if (CheckHitKey(KEY_INPUT_A) != 0) {
		debug.Add("A ia pushed");
	}
	debug.Add();
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR IpCmdLine, int nCmdShow) {
	ChangeWindowMode(TRUE);

	if (DxLib_Init() == -1) {
		return -1;
	}

	SetDrawScreen(DX_SCREEN_BACK);

	SetBackgroundColor(0xbc, 0xe2, 0xe8);//背景を水色に
	
	debug.Init();

	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
		debug.Add("1");
		debug.Add("2");
		foo();
		debug.Add("3");


		debug.Update();
	}
	DxLib_End();

	return 0;
}
```

# 実行結果
## Aキー押してないとき
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286973/35b46ddf-30a3-aac2-3974-77e63aded70e.png)

## Aキー押してるとき
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286973/1a276a94-718e-7f3c-5d73-d417e961db52.png)

このように、実行順に上から描画されます。

# 最後に
何かあったら不備や改善点があればコメントで教えてください
amplify-authenticator for vueのカスタマイズメモ

vueでamplify-authenticatorを使って、ログイン画面をさっくり作る

ほぼこちらの記事を参照した。
https://qiita.com/jre233kei/items/d719159c6b0b44b3980d

# サインアップをNGとする

```
  authConfig = {
    signInConfig: {
      isSignUpDisplayed: false
    }
  };
```

# 日本語化する

https://qiita.com/Akio-1978/items/213a352dbc98578d83aa

# スタイルを変更する

対象画面のstyleタグに記載

https://github.com/aws-amplify/amplify-js/issues/2471

ボタンを赤くする

```
:root {
  --amazonOrange: red;
}
```
ImageJ で画像データの表示と解析するメモ

## 背景

dcraw で TIFF に変換した RAW 画像とか, CG でレンダーした 16bit, 32bit CG 画像の生のピクセル値の確認とか解析とかしたい.

32bit floating point 画像を表示したい.

jupyter-lab + matplotlib とかで表示するめんどい(`display image.tiff` みたいにしたい. 一応 ImageMagic(display) 16bit, 32bit TIFF 読めるっぽいがダイナミックレンジが合わず黒つぶれ, 白飛びしてしまうケースがほとんど) 

ImageJ 使ってみます.

## ImageJ

https://imagej.nih.gov/ij/

https://ja.wikipedia.org/wiki/ImageJ

web サイトしょぼくて開発されているのか不安ですが, 以外とちゃんと開発続いているようです.
医療方面ではよく使われているようです.
UI もしょぼいですが, 慣れればまあ許容できるでしょうか. 

Java ですが, JRE(?)同梱っぽいので Linux でもパッケージダウンロードでそのまま使えました.

## 画像ビューアとして使う

```
$ ImageJ image.tiff
```

などとして開けます. Java なので画像データサイズ大きいとロードに時間かかります.


* '+' , '-' キーで拡大縮小できます.

### 解析する

矩形で画像領域選択し, `Analyze -> Measure` すると領域内の平均値とかがでます.
`shift` + ドラッグで複数矩形つくれますが, 矩形選択モードですと `Measure` では最後の矩形での情報しか表示してくれないようです.

各領域の解析したかったら, 矩形選択 -> `Ctrl + M`(Measure) を繰り返すしかありません.

### multi point 

![Screenshot from 2021-04-02 16-26-07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/f819f453-0252-1bae-57b9-ce5e8a9868b2.png)

各ピクセルを選択して, `Analyze -> Measure` でそれぞれの点の情報がでます.
結果は CSV で吐けて便利です



### 3D plot

`Analyze -> Surface Plot...` か, Plugin -> 3D -> Interactve plot でいい感じに interactrive プロットしてくれます.

![Screenshot from 2021-04-02 16-37-33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/f869b164-8d20-d876-c0be-ea37b15ce19d.png)


### 連番画像ビューア

連番も対応していますが, ややファイル名指定方法がめんどいかもです.
読み込んだい連番画像はスライダーで変えて表示できて便利です.

## autoreload したいができない

ファイルが変わったら自動リロードとかしてほしいですが, 残念ながら標準ではサポートされていません.

手動で `File -> Revert` (`Ctrl + Shift _ R`)するしかありません.

もしくは, 

https://imagej.nih.gov/ij/plugins/watch-dir/index.html

https://katurakuno.xsrv.jp/Linux/LinuxMint/ImageJ/complexMacro.html

あたりを参考にして自前でスクリプト(Plugin)を書くで対応でしょうか.


## その他

たぶんほしい!と思った機能はだいたい実装されているかと思いますので, マニュアルなど確認してみましょう!

Happy image analysis!
react-router-dom(ルーティング)

#react-router-domの導入

```
$ npm i -S react-router-dom
```

`react-router-dom`をインストールします。


```react

import React from 'react'
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import Home from './Home'
import About from './About'
  
  const App = () => {
    return (
      <BrowserRouter>
        <Switch>
          <Route exact path={'/'}>
            <Home />
          </Route>
          <Route exact path={'/about'}>
            <About />
          </Route>
        </Switch>
      </BrowserRouter>
    )
  }
  
  export default App
```

```react
 <Route exact path={'/about'}>
   表示される範囲
 </Route>
```


**` <BrowserRouter>`**
ここの中にルーティングを設定していきます。他にも`HashRouter`などあり、
`HashRouter`の場合は`/#/about`のようなルーティングになります。

**`<Switch>`**
Switchコンポーネントがなくても動きますが
URLにマッチしている全てのものが表示されるため
思いもよらない挙動してしまうためSwitchコンポーネント囲う方が良いです。

**`<Route exact path={'/about'}>`**
path="URL"
表示されるURLです。
`exact`は完全一致していたら表示できます。

```react
  <Link to="/">
    Home
  </Link>
  <Link to="/about">
    About
  </Link>
```
使いたいところで` <Link to="/">`など書けば完成です。
【忙しい人のためのVBA】シート名を変数にしたい

今回、MsgBoxの選択を利用して指定しています。
超初心者向けの説明をコードの下に記述しておきますので、参考にしてください。

## コード

```vb
Sub update_data()

    Dim rtn As Integer
    Dim ws As Worksheet
    rtn = MsgBox("Aの時は「はい」" & vbLf & "Bの時は「いいえ」" & vbLf & "を選択してください", 3, "マクロ実行の確認")
    Application.ScreenUpdating = False '画面更新をしない
    Select Case rtn '押されたボタンの確認
    
        Case vbYes 'はい選択
        Set ws = Sheets("A") 'シートAを引数に
        Call マクロ(ws)
        ws.Select 'シートAを開く
         
        Case vbNo 'いいえ選択
        Set ws = Sheets("B") 'シートBを引数に
        Call マクロ(ws)
        ws.Select 'シートBを開く

        Case vbCancel 'キャンセル選択
        MsgBox ("キャンセルしました")
            
     End Select
    Application.ScreenUpdating = True '画面更新する


End Sub
```

## 超初心者向け説明

### 定義

VBAはDimで変数を宣言します。型宣言はAs の後ろです。
シート名の宣言はWorksheetで行います。（私はここで詰まってました）

### MsgBox
MsfBoxの選択、はい、いいえを利用してデータを反映する先を決定しています。
**MsgBox=(説明など文字,3(はい、いいえ、キャンセルのボックス),タイトル)**
の記述になっています。
ちなみに、**& vbLf &** は改行です。これはオートフィルがされないので半角スペースやLの大文字に注意してください。
`"文" & vbLf & "文"`というコードでは記述をしています。

### 分岐

Caseで分岐です。
vbYesがはい、vbNoがいいえ、vbCancelがキャンセルです。
処理を行うときはその分岐の下に記述します。

シート名の指定には**Set ws = Sheets(シート名)** です。
少し特殊な指定のためSetが必要です。

Callはほかのマクロを呼び出すことができます。
必要に応じたマクロを用意しましょう。
()は引数です。
渡す先は**Sub マクロ(ByVal ws)** としておきます。
ByValはwsの値を変更しない。という指定です。

作業をしたシートを開きたい場合、Selectしておくと開くことができます。

分岐の終わりに**End Select** を入れれば完了です！

### その他

`Application.ScreenUpdating`の指定で作業中の更新を止めることができます。
マクロ実行時、かなりスムーズに終わるのでお勧めです。（私のパソコンはメモリがきつきつなので利用してます）

**'** でコメントアウトです。

## 参考
VBAについてほぼ知りたいことが載ってます。いつもお世話になっています。

https://excel-ubara.com/excelvba1/#sec1-2
じゃんけん

```js
const GU = 1
const CHOKI = 2
const PA = 3

hand = prompt('コンピュータとじゃんけんをします。半角数字を選んでください。\n\n' + '1: グー\n' + '2: チョキ\n' + '3: パー\n')
hand = parseInt(hand, 10) //数値化



com = Math.floor(Math.random() * 3) + 1 //1.2.3

let result = '';
let comHandName = '';

switch (com) {
  case GU:
    comHandName = 'グー'
    break;

  case CHOKI:
    comHandName = 'チョキ'
    break;

  case PA:
    comHandName = 'パー'
    break;
}

if (hand === com) {
  result = 'あいこです。'
}

else if ((hand == 1 && com == 2) || (hand == 2 && com == 3) || (hand == 3 && com == 1)) {
  result = 'あなたの勝ちです。'
}

else {
  result = 'あなたの負けです。'
}


alert(result + 'コンピューターは「' + comHandName + '」を出しました。')
```

エラーパターンを除いた場合は、例えば4を入れるとif文のどれにも当てはまらないので負けが返ってくる。
とても勉強になりました。
【連載】誰でもわかるデバドラ講座

# この講座で学べること
誰でもわかるデバイスドライバ講座は”初心者でもデバイスドライバ開発ができる！！”を目標にした記事を順次投稿していきます。

内容はサイエンスパーク株式会社のWebページで公開されている<a href="https://qiita.com/spc_canbe/items/ac255f279035338f65c4">誰でもわかるデバイスドライバ講座</a>を現在に合わせて再編したものです。デバイスドライバ講座の基礎編から順次投稿させていただきますので、お付き合いいただければと存じます。

# 目次

この講座の構成は、以下の通りです。

第1回　<a href="https://qiita.com/spc_canbe/items/ac255f279035338f65c4">はじめに</a>
第2回　<a href="https://qiita.com/spc_canbe/items/30487b56bfb1f47e8d14">デバイスドライバとは</a>
第3回　<a href="https://qiita.com/spc_canbe/items/4150d52135ef0d16241b">デバイスドライバの種類</a>
第4回　<a href="https://qiita.com/spc_canbe/items/02ec6eb0dffd30d5b2e2">デバイスドライバの開発モデル</a>
第5回　<a href="https://qiita.com/spc_canbe/items/a6653534088823e7eb7b">ドライバサンプルをビルドしてみよう</a>
【連載】Mac講座

# この講座で学べること
この講座は最新MacOS環境MacOSでの開発で役に立つ情報を発信することを目指しています。実際の開発で使用しているフレームワークやツールを解説・紹介してすぐに開発に取り込める情報も共有しますのでぜひご覧ください。

# 目次

この講座の構成は、以下の通りです。

第1回　<a href="https://qiita.com/spc_gmorimoto/items/c3c2f42d9952ca38703e">Appleシリコンについてまとめてみた</a>
第2回　<a href="https://qiita.com/spc_canbe/items/216565049c683bfa5d35">Intel/Appleシリコン対応Universalバイナリーを作ってみた</a>
第3回　<a href="https://qiita.com/spc_gmorimoto/items/b7ba5d69a00e277bb259">MacOSのデーモンをマスターしよう</a>
第4回　<a href="https://qiita.com/spc_gmorimoto/items/cd070354dfa92b38a4d8">MacOSでドライバ開発：DriverKit入門① ～DriverKit用プロジェクトの作成～</a>
第5回　<a href="https://qiita.com/spc_gmorimoto/items/4504034fa8239ae23998">MacOSでドライバ開発：DriverKit入門② ～システム拡張インストールアプリ～</a>
第6回　<a href="https://qiita.com/spc_gmorimoto/items/6b31d82ab28202eff603">新しいApple公証用ツールのnotarytoolを使ってみた</a>
第7回　<a href="https://qiita.com/spc_gmorimoto/items/10ee021303f8b1b05114">pkgutilの便利なコマンドをまとめてみた</a>
新しいPCにインストールしたもの記録

だいたいこんな感じのアプリをインストールする

代替マシンインストール記録

* visual studio 2017
* visual studio 2019
* sqlserver management stuido 18
* docker desktop
* vscode
* a5m2(portable)
* scoop
* concfg
* chrome web browser
* slack
* microsoft teams
* winmerge(portable)
* source tree
* git for windows
* WSL2

scoop, concfg はps ウインドウの色を変える
sqlserverはdockerでインストール
他portable(インストーラーでないもの)はバージョン変えた時のリスク最小化

あとは TortoiseSVN,GIMPぐらいか
JS~可愛くハートが回るよ♥③~

前回の記事でハートが可愛く回ったかなと思います！！
今回の記事ではそのハートを１００個に増やしたいと思います！(うるさいだけやんw)
ではでは、勧めていきましょう😊

html側で百個も作るとめちゃくちゃ大変なので、JS側で作れるように実装していきましょう👍

CSSのみ残し、bodyタグに書いていきます。

```index.html
<body>
  <script>
    'use strict';


    const div = document.createElement('div');
    div.classList.add('heart');

    div.addEventListener('click', () => {
      div .classList.toggle('circle');
    });

    document.body.appendChild(div);

  </script>
</body>
```

document.createElement('div')として、これを定数を指定して定義します。
ここから、処理を書いていきたいと思います。

div要素にheartというクラスを付けたいので、heartを追加します。

次にクリックしたときのイベントを追加したいので、EventListenerを追加し、ここでまたアロー関数を使用します👍

そして、bodyの子要素として処理するために、document.body.appendChild(div)を追加します。

わざわざ、HTMLで書かなくていいのはめちゃくちゃいいですね😊

ではこの子達を増やして行きたいと思います！！
シンプルなkey-valueオブジェクトを、kintoneレコードオブジェクトに一発で変換

こんなオブジェクトを、kintoneにAPI経由で登録したいとします。
各キーがそのままkintoneのフィールドコードになる想定。

```js
﻿const obj = {
  name: 'コーラ',
  price: 120,
  count: 5,
  amount: 600,
};
```

kintoneレコードオブジェクトは、一段`{ value: xxx }`というオブジェクトを内包して、こんな感じにする必要があります。kintoneあるあるの「value面倒くさい問題」。

```js
const record = ﻿{
  name: { value: 'コーラ' },
  price: { value: 120 },
  count: { value: 5 },
  amount: { value: 600 },
};
```

こんなワンライナーで変換できます。
`reduce()`使ってもできますが、ES2019で追加された`Object.fromEntries()`の方が「オブジェクトを新しく作る」という目的がハッキリしてるので、慣れると読みやすくてオススメです。


```js
const record = Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, { value }]));
```

チェックボックス型みたいな配列が交じる場合は、
また色々大変だったりするので今回は割愛。
（Boolean型の1個だけのチェックボックスが欲しいんだよなー）

では、超適当ですが今日はこれにて！
SpyderでOpenCVを使えるようになるまで(Mac)

anaconda Navigatorからspyderを使ってOpenCVが使えるようになるまで。

色々と試した挙句、結局できなかったので
anacondaとPython3をアンインストールして入れ直しました。

まずはanacondaを削除後、再インストール。

こちらを参考に
https://imagingsolution.net/program/python/anaconda/python-multi-version-environment/

通常のanacondaだとPythonのバージョンが3.8で
デフォルトのOpenCVがインストールできなかった。
（バージョンが高すぎるとのエラーが出た）

こちら参照
https://code-graffiti.com/install-opencv-on-mac/

anaconda.navigatorの
右メニューEnvironmentsから
Create からPython3.7をインストール

インストールしたPython3.7を選んでから、openCVをインストール

Homeに戻るとSpyderが install に変わっているのでinstallする。

spyder起動後

spyderで以下を試す。

import cv2
print(cv2.__version__)

でコンソールにバージョンが表示される。

無事に終了。６時間くらいかかった。



追記：
ナビゲータを再起動すると、Pythonがbase(root)に戻るためSpyderが起動しない
EnvironmentsからPython3.7を選択し直してからSpyderを起動する。


---
まとめ
pipとcondaは別らしい
ターミナルからより、ナビゲータを使ったらすんなりできた
思い切ってやり直した方が早い

無事にSpyder起動したらこんなダイアログが
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295432/50c112ab-01ac-eecd-2684-f15f046fc3e4.png" width=60%>

「pip使うな、condoでインストールしてね。」
って、インストール後のダイアログで知らせるのはどうかと思います。