OmniAICreator/Qiita-1.07M huggingface dataset:
顧客分析の手順 - 分析フォーマットの適用例:クロスセグメント分析 新規獲得顧客の流入経路とプロファイル  

:::note
この本書は2017年4月1日にTeradata Japanのブログに掲載された内容を、再掲載したものです。
掲載内容の正確性・完全性・信頼性・最新性を保証するものではございません。
また、修正が必要な箇所や、ご要望についてはコメントをよろしくお願いします。
:::


著者 山本 泰史 （やまもと やすし）


# 顧客分析の手順

## 第17回： 新規獲得顧客の流入経路とプロファイル

今回からは、クロスセグメント分析を利用した分析例をご紹介していきます。クロスセグメント分析はその名のとおり、セグメントを縦軸横軸に配置してクロスさせ、セグメント間の重複を理解することを可能とします。今回はこの分析を、新規顧客に適用しています。

### 分析の前提
想定する企業として、インターネット販売をしている企業を想定しています。しかしながら幾つかの要素を変更すれば、様々な業界に適用可能なはずです。まずは図26 をご覧いただき、この分析フォーマットの見方について説明します。

<img width="700" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2768546/43be208b-9f86-bf0e-6845-26d1b39c78c2.png">

他の分析と同様、クロスセグメント分析でも分析対象となる母集団を対象セグメントとして規定しています。この分析では 2008年度新規獲得顧客10,000名がその対象です。そしてこれとは別に、幾つかの顧客セグメントを縦軸と横軸に配置しています。この例では縦軸にポータルサイトN、横軸に平均買上点数と性別を元に絞り込んだセグメントを配置しています。

そしてこのセグメントに合致する顧客の関連指標がすぐ近くに配置されています（藍色部分）。これによると平均買上点数 > 5 の顧客は 1,000名、この 1,000名がもたらした買上数量は 14,749、そして顧客あたりの買上点数は 14.75 となります。 さらに真ん中部分のグリッドは、縦横両方のセグメントに合致する顧客群の関連指標を表示しています。ポータルサイトA から流入し、平均買上点数 > 5 の顧客は 500名存在していることを示しています。


### 流入チャネル毎の顧客差異
従ってこの分析は、新規に獲得した顧客群が、それぞれどのポータルサイトから流入しているのか、そして流入経路によって顧客属性と指標値にどのような違いが発生しているのかを見ることが可能となっています。また横軸を基準に見れば、男性を多く獲得できるポータルはいずれか？、買上点数の少ない顧客しか呼び込めないポータルはいずれか（ポータルC ですね）？を把握可能です。

また、この分析を見ていく際に、それぞれの縦横セグメントの選定条件に純粋合致する顧客数を基準とすることが出来ます。例えばここでの対象顧客10,000名のうち、男性と女性の割合は 7 : 3 ですが、ポータルサイトC からの流入顧客はおおよそ 1 : 2 （900名 : 2,100名）に逆転しています。この観点で見ると、男性の流入割合が多いサイトはポータルA、女性の流入割合が多いサイトはポータルC です。

同じように平均買上点数 > 5 の顧客構成比が高いのはポータルA （1,000 : 9,000 vs. 500 : 1,500）、逆に買上点数の低い顧客を多く呼び込んでいるのはポータルC （1,000 : 9,000 vs. 200 : 2,800）です。




### アプローチの方向性
このような知識を得ることによって、今後のポータル（バナーやテキスト広告等）選定にあたって、この結果を活用することが可能となります。ポータルA に掲出すべきバナー広告は男性向けの内容、ポータルC に掲出すべきバナー広告は女性向けの内容と方向付けができます。一押しの入荷商品が女性向けのものなら、この商品をウリにした広告の掲載先として、優先順位が高いのはポータルC です。また、ポータルA は大量購入を期待できる顧客を呼び込めるため、品揃えの豊富さや、大量購入によるインセンティブ（ポイント付与等）がアピールポイントとなるかもしれません。このように、バナー広告の内容と、掲載先の両方についてどうするべきかという理解が得られ、今後獲得したい顧客の属性に応じて広告メッセージと掲載媒体を選定することが容易となります。


### チャネル毎に分解する
ご紹介した分析例では、新規に顧客を獲得するためのマスチャネルということでポータルサイトを例に挙げました。マスチャネルからの流入をデータとして捕捉するためには、何らかの細工をデータエントリーポイントに仕掛けなければなりません。例えば、ポータルサイトA からの流入用にログ採取用のページを置き、ここからのセッションで申込みがあった顧客に対して、「ポータルサイトA からの流入」とフラグ付けされなければなりません。例えば TVCM からの流入を把握する場合にも、TVCM用の WebサイトURL、検索キーワード、コールセンターの電話番号を用意し、入り口で識別できるようにする必要があります。

また、新規顧客、そしてマスチャネルのみならず、既存顧客の、ダイレクトチャネルに関するアクセス経路に関しても分析の対象として価値があります。特にインバウンドチャネルに関しては、顧客の各チャネルに対する好意度を理解するのに最適です。例えば電話、Webサイト、物理葉書を持って来店といった経路を有している企業があるとします。一度もアクセスが無い経路に関しては、その経路を通じた案内をしても効果が期待できません。電子メールを開いて、Webサイトにアクセスしてくれる顧客と、未開封のままメッセージがほおって置かれてしまう顧客、物理葉書を持って来店する顧客と、自社のダイレクトメール案内とは全く無関係に来店する顧客、…これらの違いを認識できれば、もっとも反応率が高いチャネルを「顧客毎に」決定できます。

クロスセグメント分析に話を戻すと、各チャネルを縦軸に、そして顧客属性や定量指標等をもとに特徴づけしたセグメントを横軸に配置すれば、案内チャネルからの流入顧客数が、各セグメントに対してどのように分散、集中しているか、そして相対的にどのセグメントが多く、どのセグメントが少ないかを理解できるようになります。顧客プロファイルを把握できれば、案内するべきメッセージも自ずと明確になります。




#### Teradata Vantageへのお問合せ
[Teradata Vantage へのお問合せ](https://www.teradata.jp/About-Us/Contact)
ffmpegを使って動画や音声を結合する


ffmpegを使って、動画ファイルを結合したり、音声出力を変更したりしたので、
備忘録として記録しておきます。

ffmpeg version 5.0.1 で試しました。

# 1. 複数の動画ファイルを結合する

list.txt には結合対象ファイルを記述する。

```
ffmpeg -safe 0 -f concat -i list.txt -c copy output.mp4
```

```list.txt
file 'video1.mp4'
file 'video2.mp4'
```

無音にする場合は、-map を使う。

```
ffmpeg -safe 0 -f concat -i list.txt -c copy -map 0:v:0 output.mp4
```

指定秒数に切るときは、-t を使う。以下は、30秒にカットする例。

```
ffmpeg -safe 0 -f concat -i list.txt -c copy -t 30 output.mp4
```

音量を調整する場合。1.0 が基準となる。以下は元の音量から2倍にさせる例。

```
ffmpeg -safe 0 -f concat -i list.txt -vcodec copy -af "volume=2.0" output.mp4
```

音声にフェード処理を入れる場合。以下は、開始5秒地点から1秒かけて無音からフェードインさせる例。

```
ffmpeg -safe 0 -f concat -i list.txt -vcodec copy -af "afade=t=in:st=5:d=1" output.mp4
```

# 2. 動画ファイルと音声ファイルを結合する

## 2-1. 両方の音声を出力させる

```
ffmpeg -safe 0 -f concat -i list.txt -i audio.mp3 -filter_complex "amix" output.mp4
```

・動画ファイルの音声：出力あり
・音声ファイルの音声：出力あり

※動画ファイルと音声ファイルを結合する場合、出力ファイルの尺は長い方が優先される。
つまり、動画ファイルの合計時間が音声ファイルよりも長ければ、終盤で無音状態が発生する。

オプション -t を使うと出力ファイルの尺を変更することができる。

```
ffmpeg -safe 0 -f concat -i list.txt -i audio.mp3 -t 30 -filter_complex "amix" output.mp4
```

## 2-2. 音声ファイルの音声のみを出力させる

```
ffmpeg -safe 0 -f concat -i list.txt -i audio.mp3 -map 0:v:0 -map 1:a:0 output.mp4
```

・動画ファイルの音声：出力なし
・音声ファイルの音声：出力あり

## 2-3. 動画ファイルの音声のみを出力させる

```
ffmpeg -safe 0 -f concat -i list.txt -i audio.mp3 -map 0:v:0 -map 0:a:0 output.mp4
```

・動画ファイルの音声：出力あり
・音声ファイルの音声：出力なし

# 3. 動画ファイルと音声ファイルの組み合わせ

## 3-1. 音量の調整
音声ファイルの音量を調整する場合。

```
ffmpeg -safe 0 -f concat -i list.txt -i audio.mp3 -map 0:v:0 -map 1:a:0 \
-filter_complex "[1:a]volume=2.0" output.mp4
```

動画ファイルの音声と音声ファイルの音声の音量をそれぞれ調整する場合。

```
ffmpeg -safe 0 -f concat -i list.txt -i audio.mp3 -filter_complex "\
[0:a]volume=2.0[0a];[1:a]volume=0.5[1a];[0a][1a]amix" output.mp4
```

・[0:a] : 動画ファイルの音声
・[1:a] : 音声ファイルの音声

## 3-2. 音声フェード処理（フェードイン / フェードアウト）

音声ファイルの音声にフェード処理を入れる場合。

```
ffmpeg -safe 0 -f concat -i list.txt -i audio.mp3 -map 0:v:0 -map 1:a:0 \
-filter_complex "[1:a]afade=t=in:st=5:d=1" output.mp4
```

動画ファイルの音声と音声ファイルの音声それぞれにフェード処理を入れる場合。

```
ffmpeg -safe 0 -f concat -i list.txt -i audio.mp3 -filter_complex "\
[0:a]afade=t=in:st=5:d=1,afade=t=out:st=30:d=2[0a]; \
[1:a]afade=t=in:st=5:d=1,afade=t=out:st=30:d=2[1a]; \
[0a][1a]amix" output.mp4
```

## 3-3. 音量の調整 と 音声フェード処理

音量の調整かつ音声フェード処理を、動画ファイルと音声ファイルそれぞれに設定する場合。

```
ffmpeg -safe 0 -f concat -i list.txt -i audio.mp3 -filter_complex "\
[0:a]volume=2.0,afade=t=in:st=5:d=1,afade=t=out:st=30:d=2[0a]; \
[1:a]volume=0.5,afade=t=in:st=5:d=1,afade=t=out:st=30:d=2[1a]; \
[0a][1a]amix" output.mp4
```

# 参考
- https://ffmpeg.org/ffmpeg-filters.html#amix
- https://ffmpeg.org/ffmpeg-filters.html#volume
- https://ffmpeg.org/ffmpeg-filters.html#afade-1
Opencv2-python: fillPoly() jsonのファイルからマスクを作成する方法

# 概念
```python
cv2.fillPoly(img,polygon_coord,fill_val)
```
引数
img: (画像）np.array
polygon_coord: ポリゴンの座標　x,y のnp.array [[x1,y1],[x2,y2].....] intの値
fii_val: 塗りつぶす値 (値と色のarray)

画像内でポリゴンの範囲を塗りつぶします。物体検出やポリゴンのデータからマスクを作成することでよく利用している関数です。
polygon_coordsは (1,p,2)のサイズのnp.arrayです。pはポリゴンのポイントです。画像内で塗りつぶすので、polygon_coords形式はintが必要です。

# jsonからマスク作成

画像セグメンテーションのタスクでは、もとデータはよくjson形式です。モデル内で読み込むために、画像のarrayに変換しなければなりません。このjsonのデータは、xyのarrayに変化して、cv2.fillpollyを利用したら、画像に変換できます。
今回、[cv2.resize()](https://qiita.com/JarvisSan22/items/e335c9c814948e06d1b3)の記事と同じの「かぼすちゃん」の写真を使います。[Makesense.ai](https://www.makesense.ai/)というラベル作成のサイトでカボスちゃんの体、目、鼻のラベルを作ります。(jsonのファイルを[ダウンロードのリンク](https://drive.google.com/file/d/1YHAGJs80AGgaLl0YCflA7umTDrjtmszG/view?usp=sharing))、利用しているファイルはGitrepoで保存しています（[リンク](https://github.com/JarvisSan22/Jinlabs_learn_python_Notebooks)）。ぜひ使ってください

```python
import matplotlib.pyplot as plt
import cv2,json
import numpy as np

#ファイルを読み込む
img=cv2.imread("doge.jpg")[:,:,::-1]
json_data = json.load(open("doge_json.json"))

#マスク作成
label_dic={"Body":1,"Eye":2,"Nose":3}　#ラベルの辞書
img_mask=np.zeros_like(img[:,:,0])
for id_l, items in json_data["doge.jpg"]["regions"].items():
    #XとYを検出
    print(id_l,len(items["shape_attributes"]))
    x_vals=items["shape_attributes"]["all_points_x"]
    y_vals=items["shape_attributes"]["all_points_y"]
    #(1,p,2)のarrayに変換
    coors_xy= np.array([x_vals,y_vals]) 
    pixel_loc_xy = np.floor(coors_xy).T 
    #マスクのファイルに塗りつぶす
    val=label_dic[items["region_attributes"]["label"]]
    img_mask = cv2.fillPoly(img_mask, np.int32([pixel_loc_xy]), val) 

#表示
fig,axs=plt.subplots(1,2,figsize=(12,8))
axs[0].imshow(img)
axs[1].imshow(img_mask)
#保存
cv2.imwrite("doge_mask.png",img_mask)

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999291/f40ac5f7-47b0-e077-098a-216460eed4b1.png)
[Flutter] 今のコードをちょっとよくする（constants編 その3）


![flutter-logo-sharing.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/c1fc9c3f-1a8c-b906-602f-4ff4c8d268a8.png)

こんにちわ。いせきです。

「今のコードをちょっとよくする」のシリーズも第５回になりました。どんどんかけていいなと思っています。
今回もとても細かいことですが、せっかくなので分けてみました。ぜひ、みてもらえると嬉しいです。

前回の記事はこちら


https://qiita.com/iseruuuuu/items/71b2d7310a5cfc1902a7


前回の記事でも書きましたが、こちらでも言及してみようと思います。

定数を定義していこうと思います。

そうすることで

<b>・保守性が上がる。</b>
<b>・重複を減らしコードの可読性が高められる。</b>
<b>・コンパイラが定数値を最適化し、パフォーマンスが向上する</b>
<b>・定数を強く型付けすることができ、コンパイル時のエラーを発見しやすくなる</b>
<b>・メンテナンスが容易になる</b>

どうでしょうか？これだけでもいいコードになりそうですね。

# 使い方

以下の値は、定数なので、static(静的)、constにて定義してあげる。
詳しくは以下のコードを参考にしてください。

今回は、その他のStyleを定数化していこうと思います。もし、これ以外にもあるよ！と思った方はぜひコメントください。

```dart
import 'package:flutter/material.dart';

class StyleConstant {
  //ElevatedButtonの定数化
  static ButtonStyle buttonStyle = ElevatedButton.styleFrom(
    backgroundColor: Colors.red,
    foregroundColor: Colors.yellow,
    fixedSize: const Size(250, 100),
    side: const BorderSide(
      color: Colors.black,
      width: 3,
    ),
  );

  //Padding（余白）の定数化
  static EdgeInsets textPadding = const EdgeInsets.symmetric(
    vertical: 10,
    horizontal: 20,
  );

  //String（テキスト)の定数化
  static String buttonText = 'tap';
}

```

```dart
import 'package:flutter/material.dart';
import 'package:sample_app/constants/color_constants.dart';
import 'package:sample_app/constants/style_constants.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Qiita Flutter',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int counter = 0;

  void _incrementCounter() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Qiita Flutter App')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Padding(
              padding: StyleConstant.textPadding,
              child: Text('$counter'),
            ),
            ElevatedButton(
              onPressed: _incrementCounter,
              style: StyleConstant.buttonStyle,
              child: Text(StyleConstant.buttonText),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}


```


# 最後に
「今のコードをちょっとよくする」のシリーズをまとめたものをZennで載せているので、良かったら見てもらえると嬉しいです。それぞれの記事を要約されていますので、時間がない方におすすめです。ぜひ！！


https://zenn.dev/iseki/scraps/3b995399cd36d7
python: requests.get() ネットからjsonのデータを読み込み

# 概念
```python
requests.get(url,header)
```
引数
url :　ダウンロードしたいファイルの保存先
header: 送信する内容を辞書

requestsとはHTTP通信を扱うモジュールです。ウェブサイトからダウンロードをダウンロードしたいなら、requests内の関数 getを利用します。
requests.get()の結果は「.json()」と加えると、jsonのファイルを直接に読み込みます。とても便利なツールです。

# Sample Code サンプルコード 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999291/0edeeed4-a024-bc33-202c-3d9b9cc97249.png)
コードはすべてGithubで保存しています。自分のpython環境とGoogleColabで使ってみてください　[リンク](https://github.com/JarvisSan22/Jinlabs_learn_python_Notebooks/blob/main/Scappers/request_get.ipynb)。

```python
import requests 
loc="https://galverse.art/api/metadata/"
header= {"content-type": "application/json"}
r=requests.get(loc+"1906.json",headers=headers)
print(r.json())
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999291/4978456c-b89c-e91d-3698-0d32972079ae.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999291/103e2c49-9f87-be6d-785b-dc50b1f0347a.png)

```python
import pandas as pd

loc="https://galverse.art/api/metadata/" 
main_keys=["tokenId","name","description","image_web","external_url"]

galverse_data=[]
for i in tqdm(range(8888),total=8888):
    headers = {"content-type": "application/json"}
    r = requests.get(loc+f"{i+1}.json", headers=headers)
    data = r.json()
    gal_data={}
    for k in main_keys:
        gal_data[k]=data[k]
    #Trait data 
    for att in data["attributes"]: #Attributes
        trait,val=att["trait_type"],att["value"]
        gal_data["trait_"+trait]=val
    galverse_data.append(gal_data)

df=pd.DataFrame(galverse_data)
df.to_csv("gal_data.csv",index=False)

```

データを集まった後で、pandasのモジュールを利用して、csvのファイルに保存しました。後で、このデータを解析したいので、利用しやすい形式で保存したら、すぐ便利です。そして、pandasのDataframeはデータ分析に適したフォーマットです。ぜひギャルバースのデータを調べてみてください。面白い秘密はいっぱいあります。面白いことを見つかったら、twitterで[galberseNFT](https://twitter.com/galversenft)と[僕](https://twitter.com/JarvisSan22)をメッセージしてください ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999291/b76220de-e17a-996e-326d-e1493649b992.png)
AWS SAMのローカル開発でホットリロードを効かせる

# やりたいこと
`sam local start-api`コマンドなどでAWS SAMをローカル環境で動かしている際、ソースコードを変更してもホットリロードで変更が反映されません。

変更を反映するには`sam build`を実行しなければいけません。

`sam local start-api`を実行しているターミナルとは別のターミナルで`sam build`を実行すればビルド後のファイルを自動で読み込んではくれます。

これを利用してVSCodeの拡張機能「[Run on Save](https://marketplace.visualstudio.com/items?itemName=emeraldwalk.RunOnSave)」を使ってファイルを保存したら`sam build`が走るようにすることでホットリロードっぽい挙動を実現してみました。

# やりかた

拡張機能をインストール後
例えばPythonのプロジェクトならこのように設定をしておきます。

```json:.vscode/setting.json
{
    "emeraldwalk.runonsave": {
        "commands": [
            {
                "match": "template.yaml",
                "cmd": "sam build"
            },
            {
                "match": "requirements.txt",
                "cmd": "sam build"
            },
            {
                "match": ".*.py",
                "cmd": "sam build"
            }
        ]
    }
}
```

ファイルを保存してビルドコマンドが走ればOK。
コマンドの結果はここに出力されます。
![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/156f52cf-0441-c9cb-61b0-497d027ada04.png)

ソースを変えながらホットリロードが走るか試してみます。

```python:hello_world/app.py
import json

def lambda_handler(event, context):
    body = json.dumps({
        "message": "hello world",
    })
    print(body)
    return {
        "statusCode": 200,
        "body": body,
    }
```

```
Mounting C:\Users\danishi\sam-app\.aws-sam\build\HelloWorldFunction as /var/task:ro,delegated inside runtime container
START RequestId: ad2c7322-cc1e-4006-a837-ff7019e09d28 Version: $LATEST
{"message": "hello world"}
END RequestId: ad2c7322-cc1e-4006-a837-ff7019e09d28
REPORT RequestId: ad2c7322-cc1e-4006-a837-ff7019e09d28  Init Duration: 0.38 ms  Duration: 199.60 ms     Billed Duration: 200 ms Memory Size: 128 MB     Max Memory Used: 128 MB
No Content-Type given. Defaulting to 'application/json'.
2023-02-10 09:47:01 127.0.0.1 - - [10/Feb/2023 09:47:01] "GET /hello HTTP/1.1" 200 -
2023-02-10 09:47:01 127.0.0.1 - - [10/Feb/2023 09:47:01] "GET /favicon.ico HTTP/1.1" 403 -
Invoking app.lambda_handler (python3.9)
Using local image: public.ecr.aws/lambda/python:3.9-rapid-x86_64.

Mounting C:\Users\danishi\sam-app\.aws-sam\build\HelloWorldFunction as /var/task:ro,delegated inside runtime container
START RequestId: 3876c9bf-c560-47d1-985c-2b4940354661 Version: $LATEST
{"message": "hello world2"}
END RequestId: 3876c9bf-c560-47d1-985c-2b4940354661
REPORT RequestId: 3876c9bf-c560-47d1-985c-2b4940354661  Init Duration: 0.37 ms  Duration: 133.06 ms     Billed Duration: 134 ms Memory Size: 128 MB     Max Memory Used: 128 MB
No Content-Type given. Defaulting to 'application/json'.
2023-02-10 09:48:55 127.0.0.1 - - [10/Feb/2023 09:48:55] "GET /hello HTTP/1.1" 200 -
2023-02-10 09:48:55 127.0.0.1 - - [10/Feb/2023 09:48:55] "GET /favicon.ico HTTP/1.1" 403 -
```

手動で`sam build`しなくてもホットリロードが実行されてるのが確認できます。

今回はサンプルなので軽量でビルド時間が短いから気になりませんが、デバッグしてないときに毎回ビルドが走るのが煩わしい場合はコマンドパレットからオフにしておくとよさそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/a6adc147-82ff-4fac-9d60-185a649b352d.png)
AzureDevOpsにSSH公開鍵を登録して、GitRepositoryにSSH接続する

# はじめに

自分はGitRepositoryにSSHで接続する派です。
Windowsマシンを使ってた頃、複数の接続先を持ちすぎたのか、頻繁にPWを聞かれてうんざりしてからSSH派になりました。

AzureDevOpsのSSH鍵有効期限は「1年」です。(2023/02/10時点)
毎年やらなきゃいけないことをその度に調べ直すのは嫌なので、メモしておきます。

なお、AzureDevOpsへの登録方法を記述しますが、GitHubでもノリは同じです。

# 環境

```text
macOS 13.1
```

# 公開鍵・秘密鍵の作成

## sshフォルダに移動

```terminal
$ cd ~/.ssh
```

## 鍵ペアの生成

```terminal
$ ssh-keygen -t rsa

Generating public/private rsa key pair.
Enter file in which to save the key (/Users/[userName]/.ssh/id_rsa): key_azure_devops
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in key_azure_devops
Your public key has been saved in key_azure_devops.pub
```

`Enter file in which to save the key (/Users/[userName]/.ssh/id_rsa):`で鍵の名前を、
`Enter passphrase (empty for no passphrase):`でパスフレーズを指定できます。

## 鍵が作成されたかの確認

```terminal
$ ls -l
```

- `key_azure_devops`
- `key_azure_devops.pub`

の2ファイルが確認できると思います。
`.pub`拡張子が「公開鍵」となり、拡張子なしファイルが「秘密鍵」となります。
公開鍵をAzureDevOpsに登録することになりますが、秘密鍵は自分以外に知られてはなりません。

# AzureDevOpsに鍵を登録する

※記事で紹介するAzureDevOpsのUIは、2023/02/10時点のものです。

## SSH公開鍵管理ページにアクセス

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647946/3170cc0c-e98c-ed9c-caec-af8c38d28386.png" width="320">

## 公開鍵の登録

「+ New Key」をクリック。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647946/faf8bb18-9164-6f02-dfd9-631a76245ed1.png" width="450">

Name: 公開鍵やマシンの名前
Public Key　Data: 公開鍵データ

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647946/8f3a7961-3cf1-88b6-b2de-3045639077ad.png" width="450">

公開鍵の中身をコピーする時、マウスを使ったドラッグだとミスの元なので、下記コマンドを使用するようにしましょう。

mac

```terminal
$ pbcopy < ~/.ssh/key_azure_devops.pub
```

windows

```terminal
$ clip < ~/.ssh/key_azure_devops.pub
```

## SSH configファイルでどの鍵を使用するか指定

`~/.ssh/config`を開き、下記を追記します。
`IdentityFile`には、自分で作成した鍵のパスを記述してください。

```~/.ssh/config
# Azure DevOps
Host ssh.dev.azure.com
  HostName ssh.dev.azure.com
  IdentityFile ~/.ssh/key_azure_devops
  User git
  Port 22
  TCPKeepAlive yes
  IdentitiesOnly yes
```

### Host名を変えて、複数のAzureDevOpsアカウントを使い分ける

任意の`Host`名と、個別の`IdentityFile`を指定することで、複数のAzureDevOpsアカウント(GitHubも)があっても簡単にSSH接続情報を使い分けられます。

```~/.ssh/config
# Azure DevOps
Host work_devops
  HostName ssh.dev.azure.com
  IdentityFile ~/.ssh/key_azure_devops
  User git
  Port 22
  TCPKeepAlive yes
  IdentitiesOnly yes

# private Azure DevOps
Host private_devops
  HostName ssh.dev.azure.com
  IdentityFile ~/.ssh/key_private_azure_devops
  User git
  Port 22
  TCPKeepAlive yes
  IdentitiesOnly yes
```

ただし、`clone`してくる時や`remote add`する時など、デフォルトのコマンドラインではなく、自分で定義した`Host`名を使用する必要があります。

デフォルト
`git clone git@ssh.dev.azure.com:v3/[Organization]/[Project]/[RepositoryName]`

変更後
`git clone git@[Host名]:v3/[Organization]/[Project]/[RepositoryName]`

上記の`private_devops`を使うなら、
`git clone git@private_devops:v3/[Organization]/[Project]/[RepositoryName]`となります。

# 参照

https://qiita.com/shizuma/items/2b2f873a0034839e47ce

https://qiita.com/wakahara3/items/52094d476774f3a2f619

https://atmarkit.itmedia.co.jp/ait/articles/1908/02/news015.html

https://zenn.dev/taichifukumoto/articles/how-to-use-multiple-github-accounts
No.6 Teamsのアクティビティレポートを作成する

## はじめに
普段の業務でTeamsをどれくらい使っているのか、気になった事はありませんか？
Power BIサービスが提供する標準のレポートで
**・自分が参加した会議の回数はどれくらい？
・送信したチャット数は何通？
・このチームって、盛り上がっているのか？**
などを確認できるので、このセッションではそちらをお伝えします。

## Power BIよりレポートを作成
**1．TeamsからPower BIのアプリを起動**
**2．「新しいレポート」を押下後、「お客様のTeamsのデータを分析」を選択**
![ezgif-2-ba63632eab.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/69988dfc-e0e0-9f93-3c35-480ab87ce052.gif)
初めて選択した場合は、マイワークスペースにデータセットを作成するので少し時間がかかります。
しばらく待って、このような画面が表示されれば成功です。
![スクリーンショット 2023-02-10 8.59.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/a521c112-2641-e2ac-62c1-ab29bfd842b2.png)

### 「My activity」で自分のデータを確認
参加した会議数や、送ったチャット数を確認できます。
また、期間が設定でき、デフォルトは過去31日間ですが最大過去90日間まで遡って確認ができます。
![スクリーンショット 2023-02-10 9.01.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/4141937c-1372-b5c6-2602-150e8fb0a57d.png)

### 「Team activity」で自分が参加しているチームのデータを確認
自分が参加しているチームでのアクティブユーザ数や、ポスト／リプライ数を確認できます。
![スクリーンショット 2023-02-10 9.03.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/f2a1d121-69ac-4bd5-3146-814c47882cdd.png)

### 「Team activity details」で自分のデータを確認
先程の「Team activity」よりも詳しいデータが見れます。リアクションの数やメンションの数などです。
![スクリーンショット 2023-02-10 9.11.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/cc33784e-217f-d34a-b0fd-c2d0537fd523.png)

私がお見せした画面は検証環境のため、それほどデータが溜まっておらず面白くない（笑）ため、ぜひご自身の環境で一度ご確認ください。
なお、詳細に関してはMicrosoft Learnで確認できますので、こちらもご覧ください！
[Teams 用 Power BI アプリで Teams の利用状況を分析する](https://learn.microsoft.com/ja-jp/power-bi/collaborate-share/service-teams-analytics)

こちらのセッションは以上です。
[→ Power BI サービス練習帳に戻る](https://qiita.com/shinyasasaki/items/391d50c2508794e8fcfd)
Docker on WSL2でawesome-composeのnginx-golang-mysqlを立ち上げる

Dockerの勉強を兼ねていろんなサーバを構築して遊んでいるのですが、次のような素晴らしい（awesome!な）リポジトリがあったので、早速試しました。

https://github.com/docker/awesome-compose

基本的には好きなディレクトリに入って ``` docker compose up -d ``` するだけなのですが、自分の環境（WSL2）では少々詰まってしまったところがあったので、備忘録として残しておきます。

この記事では、アプリケーションサーバにGo、プロキシサーバ（Webサーバ）にNginx、データベースサーバにMySQLを使ったアーキテクチャ ``` nginx-golang-mysql ``` を立ち上げてみます。

### git clone & ディレクトリに入る
```
$ git clone https://github.com/docker/awesome-compose.git
$ cd awesome-compose/nginx-golang-mysql/
```

### docker compose実行
``` docker compose up -d ``` すれば起動するはずなのですが、次のようなエラーが出てしまいました。
```
1 error occurred:
        * Error response from daemon: dockerfile parse error line 25: unknown instruction: APK
```

調べていくと、Docker BuildKitが有効になっていないことが原因でした。
[BuildKit によるイメージ構築](https://matsuand.github.io/docs.docker.jp.onthefly/develop/develop-images/build_enhancements/) にあるように、環境変数 ``` DOCKER_BUILDKIT=1 ``` を指定して実行するとうまく動きました。

```
$ DOCKER_BUILDKIT=1 docker compose up -d
```

（BuildKitはデフォルトで有効化されているようなのですが、自分の環境ではなぜか有効化されていなかったようでした・・・）

### 確認
```:Nginxにリクエストを送る
$ curl localhost:80
```

```:出力
["Blog post #0","Blog post #1","Blog post #2","Blog post #3","Blog post #4"]
```
うまくいってますね。
Have a nice awesome-compose life!

### 参考
* Docker Buildxのドキュメント (https://matsuand.github.io/docs.docker.jp.onthefly/buildx/working-with-buildx/)
【TypeScript】anyとunknownの違い

## はじめに

`TypeScript`は一通り学習し業務でも触れていたのですが深く理解しているかというとそうではないので復習のつもりで記事を投稿いたします。 
まずは `any`と `unknown` の違いについて。

## `any`, `unknown` の違い
どちらも型に縛られることなく値を代入可能です。
ただし、`unknown`型の変数については、
**プロパティ参照や関数実行する前に型チェックを行わないとコンパイルは通りません**。
なので、`any`型を利用するより安全なコードを書き、実行時エラーを未然に防ぐことができます。

```sample01.ts
const a: unknown = 'Who am I?';
const b: any = 'I am any.';

console.log(a.toUpperCase());
console.log(b.toUpperCase());

```

```bash
unknown.ts:5:15 - error TS2339: Property 'toUpperCase' does not exist on type 'unknown'.

5 console.log(a.toUpperCase());
                ~~~~~~~~~~~


Found 1 error in unknown.ts:5
```

```sample02.ts
const a: unknown = 'Who am I?';
const b: any = 'I am any.';

// 型安全であることを確保した上で関数実行
if (typeof a === 'string') {  
  console.log(a.toUpperCase());
}

// any型は型のチェックを入れなくてもコンパイルエラーにならない
console.log(b.toUpperCase()); 
```
OpenCV-python:リサイズする方法（cv2.resize)

# 概要
```python
cv2.resize(img, Size,fx=0,fy=0,interpolation=INTER_LINEAR)
```
・img: ndarray 
・Size: (w,h) サイズの大きさ
・fx x方法の倍率
・fy y方法の倍率
・interpolation: リサイズの処理方法

cv2.resizeはリサイズするために二つの方法が含んでいます。最初にSizeです。希望のサイズを設定して (例え、(256,256) )、画像はこのサイズへ変換します。二つ目の方法は、fxとfyの倍率の方法です。最初に SizeはNoneと設定して、fxとfyのfloatの値により、リサイズを行います。

 # Sample Code サンプルコード

```python
import matplotlib.pyplot as plt
import cv2
img=cv2.imread("doge.jpg")[:,:,::-1]
#Resize D Size 
img_ds=cv2.resize(img,(500,300)) # ( X, Y)
#Resize fx fy
img_fs=cv2.resize(img,None,fx=0.5,fy=0.5)

fig,axs=plt.subplots(1,3,figsize=(12,8))
axs[0].imshow(img)
axs[0].set_title("Original")

axs[1].imshow(img_ds)
axs[1].set_title("Resize 300x500")

axs[2].imshow(img_fs)
axs[2].set_title("Resize fx 0.5 fy 0.5")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999291/592ffe78-0140-6c70-4141-e69039047d33.png)

# Interpolationについて
Interpolationは5つの種類があり、標準の設定はcv2.INTER_LINEARです。それぞれは方法や計算時間が異なっています。
・cv2.INTER_NEAREST ：最近傍補間
・cv2.INTER_LINEAR : バイリニア補間（デフォルト）
・cv2.INTER_AREA :ピクセル領域の関係を利用したリサンプリング．画像を大幅に縮小する場合は，モアレを避けることができる良い手法です．
・cv2.INTER_CUBIC : 4x4 の近傍領域を利用するバイキュービック補間
・cv2.INTER_LANCZOS4 : 8x8 の近傍領域を利用する Lanczos法の補間
```python
from datetime import datetime

def plot_resize_test(img_h,resize):
  dim_h=img_h.shape
  #resizeのオプション
  interpolations=["ORIGINAL",cv2.INTER_NEAREST,cv2.INTER_LINEAR,cv2.INTER_AREA,cv2.INTER_CUBIC,cv2.INTER_LANCZOS4]
  interpolation_names=["INTER_NEAREST","INTER_LINEAR","INTER_AREA","INTER_CUBIC","INTER_LANCZOS4"]
  fig,axs=plt.subplots(3,2,figsize=(10,15))
  axs=axs.reshape(-1)
  
  out_dic={}

  for ax,inter in zip(axs,interpolations):

    if inter == "ORIGINAL":
      ax.imshow(img_h)
      ax.set_title("ORIGINAL")
      out_dic["ORIGINAL"]=[1,img_h]
    
    else:
      start=datetime.now()
      img_pl_resize=cv2.resize(img_h,resize,interpolation=inter)
      end=datetime.now()
      print(dim_h,img_pl_resize.shape)
      p_time=end-start
     # p_time=p_time #.strftime('%S.%f')
      print(p_time)

      
      ax.imshow(img_pl_resize)
      ax.set_title(interpolation_names[inter]+ f"\n process_time (s): {str(p_time).split(':')[-1]}")
  
    fig.tight_layout()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999291/0e3e6b66-fb91-ff89-ab89-c63434587c8e.png)

# 機械学習のマスク画像の注意点
画像のセグメンテーションを訓練したいなら、マスクのデータが必要です。画像の中で、物体の範囲は普通に1つの値が割り当てられていますが、リサイズを行うときに、このラベル値を変化できます。ラベル数は少ないときに、あまり影響がありませんが、多いラベル数の場合、問題が発生します。なぜなら、ほとんどのInterpolationは値を変化するからです。INTER_NEARESTのみで値を変化しません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999291/e1df6034-50e5-67d8-9ae1-d65a559bad04.png)

上記に例の人工衛星があり、左にはこの画像のマスクのデータです。画像のサイズは、1479x2149で6種のラベルがあります。下記にリサイズを行い、それぞれのInterplationの唯一のラベル数を計算します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999291/ac745b17-06f6-f37e-0f47-8d1493f13ee9.png)
INTER_NEAREST以外のInterpolationはラベル数を増えてしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999291/bb68f96f-6362-d0f4-f01c-4655b522a47e.png)
Asterisk AGIでGo言語を使う方法

# 1. AGIファイルを用意する

```agi.go
package main

import (
    "log"
)

func main() {
    log.Println("AGI TEST")
}
```

# 2. AGIファイルをビルドする

```
# $ go build agi.go

$ ls
agi.go
agi
```

# 3. extension.confでビルドしたバイナリを指定する
```extensions.conf
same => n,AGI(agi)
```
C#でDataverseのWebリソースを取得してみた

# はじめに
PowerAppsのモデル駆動の設定が面倒なのでC#からDataverseを操作してみたくなった。
今回はdataverseのHTMLのWebリソースを一覧取得するC#のコードを動かしてみる。

# 前提
参照ライブラリやCreateCrmService関数の中身は以前の以下の記事を参考に

C#でDataverseに接続してテーブル一覧を表示してみた
https://qiita.com/akihiroe_/items/2db8e2634d7962ef0df7

# コード
Webリソースはwebresourceテーブル上に保持されています。実際のコンテンツはcontent属性にBASE64エンコードされています。HTMLはテキストですがJPEGなどの画像もありバイナリデータの可能性があります。
個々のコンテンツがはどのようなものかはwebresourcetype属性で確認できます。

```C#
var organizationService = CreateCrmService(user, password, url);

var tableName = "webresource";
var columns = new string[] { "name", "content", "webresourcetype" };
QueryExpression query = new QueryExpression(tableName);
query.ColumnSet.AddColumns(columns);
ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "webresourcetype";
condition.Operator = ConditionOperator.Equal;
condition.Values.Add(1); //	Webpage (HTML)
FilterExpression filter = new FilterExpression();
filter.Conditions.Add(condition);
query.Criteria.AddFilter(filter);

var entities = organizationService.RetrieveMultiple(query);
foreach (var entity in entities.Entities)
{
    var name = entity.GetAttributeValue<string>("name");
    var content = entity.GetAttributeValue<string>("content");
    var contentAsText = Encoding.UTF8.GetString(Convert.FromBase64String(content));

    Console.WriteLine(name);
    Console.WriteLine(contentAsText.Substring(0, Math.Min(100, contentAsText.Length)));
    Console.WriteLine();
}

```
*webresourcetypeの値とコンテンツの種類
|webresourcetype値|コンテンツ種類|
|-|-|
|1|Webpage (HTML)|	
|2|Style Sheet (CSS)|	
|3|Script (JScript)|	
|4|Data (XML)|	
|5|PNG format|	
|6|JPG format|	
|7|GIF format|
|8|Silverlight (XAP)|	
|9|Style Sheet (XSL)|	
|10|ICO format|
|11|Vector format (SVG)|
|12|String (RESX)|
# おわりに
ちょっとした文言の追加などはWebリソースのHTMLを使うことがありますが、コンテンツがBase64にエンコードされているのでリソースを一括検索しにくいんですよね。

# 参照情報
https://learn.microsoft.com/ja-jp/power-apps/developer/data-platform/reference/entities/webresource
【JavaScript】スクロールが終わった時に発生する「新しいイベントScrollend」とは？

## はじめに
みなさんは、JavaScriptでスクロールが終わった時に何か処理を行いたいと思ったことはありますか？
 
「スクロールが終わった時にアニメーションしたい」や「スクロールが終わった時に動画や音楽を再生させたい」など、
そんな頻繁に思いはしないと思いますが、たまにはあると思います。

この記事では、そんな時に使えるスイベント`scrollend`を紹介します。


## スクロールが終わった時に発生する Scrollend
:::note warn
**`Scrollend`は、実験的な機能です。**
Chrome Canary, chrome 112以降, Firefox 109以降のブラウザで対応しています。
*※投稿日2023/2/10時点*
:::

### 今までのやり方
今までは、確実にスクロールが終わったことを検知する方法はありませんでした。
そのため、以下のハックのようなやり方でスクロールが終わったことを検知していました。

```sample.js
document.onscroll = event => {
  clearTimeout(window.scrollEndTimer)
  window.scrollEndTimer = setTimeout(callback, 100)
}
```
この`setTimeout`を使う方法は、 スクロールが100ms間停止しているか検知しているため、
スクロールが終わった時というより、一時停止した時に発生するイベントになります。

この方法では、イベントが発生するのが遅れたり、ユーザーの指が画面上にあるのにイベントが発生したりすることがありました。
そのため、心地よいユーザー体験にならず、バグが発生しやすくありました。

### これからのやり方
Chrome Canaryバージョン, chrome 112以降, Firefox 109以降のブラウザでは、以下のように`scrollend`イベントでスクロール終了時にイベントを発生させることができるようになりました。

```sample.js
// onscrollendを使う方法
document.onscrollend = event => { ... }

// addEventListenerを使う方法
addEventListener("scrollend", (event) => { ... });
```

この方法は以下のようなタイミングで発火します。

+ ブラウザでスクロールのアニメーションやトランディションが終わった時
+ ユーザーの指が離れた時
+ ポインターがスクロールバーを離した時
+ キー入力を終わった時
+ ページ内スクロールが終わった時
+ スクロールスナップが終わった時
+ `scrollTo()`が終わった時
+  visual viewportのスクロールした時

ただ、以下の条件では発火しないので注意が必要です。

+ ユーザーのジェスチャーによって、スクロールの位置が変化しない時
+ `scrollTo()`でトランディションがなかった時


## サンプル

:::note warn
**`Scrollend`は、実験的な機能です。**
Chrome Canary, chrome 112以降, Firefox 109以降のブラウザで対応しています。
*※投稿日2023/2/10時点*
:::

<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="xxJodLR" data-editable="true" data-user="sp_degu" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sp_degu/pen/xxJodLR">
  Scrollend</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


## まとめ
この記事では、、JavaScriptでスクロールが終わった時に発生する`Scrollend`イベントについて書いせるしました。

今までの `setTimeout`を使った方法は、 スクロールが100ms間停止しているか検知しているため、
スクロールが終わった時というより、一時停止した時に発生するイベントのため、正確にスクロールが終わった時に発火させることができませんでした。

これからは、`Scrollend`イベントを使って、JavaScriptでスクロールが終わった時にイベントを発火させましょう。

`Scrollend`イベントは、2023/2/10時点では、Chrome Canary, chrome 112以降, Firefox 109以降のブラウザーでしか使えないので、使えるようになるのを気長に待ちましょう。

---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaに記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510
【Flutter】Map型のソートでデータが消える時の対処方法

先日、Map型のソートをしたときに、データが消える現象に遭遇したので、解決方法をメモ。

## Map型のソートでデータが消える例

```dart
Map<String, int> userAge = {
  'Taro' : 10,
  'Hanako' : 7,
  'Jiro' : 7,
};

SplayTreeMap.from(userAge, (a, b) => userAge[a]!.compareTo(userAge[b]!));
// print結果: {Jiro: 7, Taro: 10}
// ※ Hanako が消えてる！？
```

ちなみに、`SplayTreeMap` の解説は以下参考

https://api.dart.dev/stable/2.16.1/dart-collection/SplayTreeMap-class.html

## なぜMap型のソートでデータが消えるのか？

原因は、`compareToメソッド` にありました。

戻り値は以下の通りです。

- aの値がbの値よりも大きい = 1
- aの値とbの値が同じ      = 0
- aの値がbの値よりも小さい = -1

例えば、以下のように数値を比較した場合の戻り値を見てみましょう。

```dart
// 比較数値 = 戻り値
// 10と7  =  1
// 10と10 =  0
// 7 と10 = -1
```

このように、値が同じ場合に、データが消えてしまっていたんですね。

## Map型のソートでデータを消さない方法

先程の結果から分かる通り、`compareToメソッド` の戻り値が `0` にならないようにしましょう。


// 出力結果： {Ariana: 50, Saw: 50, Ichiro: 80}

```dart
Map<String, int> userAge = {
  'Taro' : 10,
  'Hanako' : 7,
  'Jiro' : 7,
};

userAge = SplayTreeMap.of(userAge, (a, b) {
  int compare = userAge[a]!.compareTo(userAge[b]!);
  // compareが 0（aとbの値が同じ場合）なら1（aがbよりも大きい場合）に置き換え
  return compare == 0 ? 1 : compare;
});
// print結果: {Hanako: 7, Jiro: 7, Taro: 10}
```

[参考：【Dart】Mapのソート](https://zenn.dev/mukkun69n/articles/21c00064bbe870)
初めてのプログラミング

# HTMLの基本的な操作

2月10日からプログラミングを始めたので、忘備録として書いていきます。また自己成長の為に、アウトプットも兼ねて記事を作っていくので宜しくお願いします。

#### 見出しを付ける

```html
<h1>リンゴ</h1>
```
上記のように見出しを作る。また、数字を大きくしていくと、見出しが小さくなる。最大は6まで。

#### 段落を作成する

```html
<h1>リンゴ</h1>
<p>リンゴアメが食べたい</p>
```

pはparagraph（段落）の略になる。h2要素やp要素で囲んだテキストは改行されて表示される。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123154/9b345c6b-7944-50c8-2e08-54da3674c95f.png)

#### コメントの書き方

```
<!--リンゴアメが食べたいと書く-->
```

囲んだテキストのことを「コメント」と呼ぶ。
コメントとして書かれたテキストはブラウザには表示されないので、メモとして使うことができる。
No5_ググったこと投稿(5分)_ネットワーク関連


## 目次
 [1.OSI参照モデル](#1-OSI参照モデル)

 [2.レイヤー説明](#2-レイヤー説明)

# 1. OSI参照モデル
- コンピューターが通信をするために利用するネットワーク機能を7つのレイヤーに分けて、整理したモデルのこと
- OSI
    - Open Systems Interconnection

# 2. レイヤー説明
- 第7層 アプリケーション層
    - *HTTP/HTTPS,*FTP,*Telnetなどのユーザーが操作するアプリケーションが提供する具体的な機能についての仕様や通信手順を定めたもの
- 第6層 プレゼンテーション層
    - データの表現形式を定義するもの。文字コードや*SMTP,*POP3,*IMAP
- 第5層 セッション層
    - 通信プログラム間の開始から終了までの一覧の手順を定義するもの。例えば接続が途切れた場合の接続回復を試みる際の手順などなど。*SSL/TLSなど
- 第4層 トランスポート層
    - 通信の品質をコントロールする層で、信頼性やリアルタイム性を重視など、用途においてプロトコル(*TCP/*UDP)を使い分ける
- 第3層 ネットワーク層
    - ネットワークにおける通信経路の選択（ルーティング）や中継を行う。*IP,*ARPなど
- 第2層 データリンク
    - 直接的に接続された機器同士の通信を実現する。*イーサネットや*PPP,*HDLC,*アークネットなど
- 第1層 物理層層 
    - ケーブルやコネクターにて接続される。そのため、ハードウェアのコネクターの形状やピン数といった物理的な接続の規定をプロトコルとして定めている。第2層でも挙げたイーサネットの物理層を規定する、IEEE 802.3など


### 単語
- HTTP(Hytertext Transfer Protocol)
   - Webサーバーとブラウザ間で情報をやり取りするためのプロトコル
   - ポート番号80番
- HTTPS(Hytertext Transfer Protocol Secure)
   - *SSL/*TLSと呼ばれるプロトコルが作り出す、安全な接続を使ってHTTP通信を行う
   - ポート番号443 
- FTP(File Transfer Protocol)
    - ファイルを転送するためのプロトコル
- Telnet
    - ネットワークに接続された機器を遠隔操作するために使用するアプリケーション層プロトコル
- SMTP(Simple Mail Transfer Protocol)
    - ールを相手のメールサーバーまで届けるプロトコル
- POP3(Post Office Protocol version ３)
    - 自分が使っているメールサーバに届いたメールを自分のパソコンにコピーしてきて見るときに使うお約束事
- IMAP(Internet Message Access Protocol)
    - 自分が使っているメールサーバに届いたメールを自分のパソコンにコピーしてきて見るときに使うお約束事
    - POPとの違い
        - ユーザーのメールはサーバーが管理してくれる
        - POPは数日で削除される
- IP(Internet Protocol)
    - インターネット通信を行いたいコンピュータにデータを送り届けるためのルール
- ARP(Address Resolution Protocol)
    -  IPアドレスからMACアドレスの情報を取得するためのプロトコル
- イーサネット
    - ネットワークやコンピューター間での通信モデル TCP/IPプロトコルのネットワークインターフェース層に対応する有線の規格
    - 同軸ケーブル・・・バス型
    - 光ファイバー・・・スター型
    - LANケーブル・・・スター型
- PPP(Point-to-Point Protocol)
    - ンピューター同士が1対1の通信を行うための規約を定めたプロトコルです。「どのような手順で」「どのようなデータ形式で」通信を行うのかなどを定めています。
- HDLC(High-level Data Link Control)
    - データリンク層（リンク層）の通信規約（プロトコル）の一つ。相手の応答を待たず連続して送信できるなど伝送効率が高く、CRCによる誤り制御などを行うなど信頼性も確保している。
- アークネット(Attached Resource Computer NETwork)
    - イーサネットより昔使われてた
    - https://www.softech.co.jp/mm_160203_pc.htm
- IEEE 802.3
    - IEEEが策定している無線LANの標準規格

参考）
https://eset-info.canon-its.jp/malware_info/special/detail/220712.html
データベースの機能のトランザクション管理ののACIDについて

未経験からエンジニアになりたい人は、プログラミングから始める人が多いと思いますが、
エンジニアの仕事は、プログラミングだけではありません。そして、プログラミングだけでは、エンジニアになれません。同時にプログラミングが苦手でも、システム構成や開発の流れを理解するとエンジニアに近づきます！
今回はデータベースの機能　トランザクション管理のACIDについて更に詳しく調べてみましょう！

![インスタスライド_202302011.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/78511889-20b1-c1ea-8aab-b4a27e86ca40.gif)


# データベースの機能
一番大事なのがトランザクション管理

ある処理単位でデータベースの内容の整合性を保証する。

これはACID特性と言います

# ACID特性とは
## A Atomicity (原子性) 
　
すべてが完全に実行されるか、処理が完結しない場合には元の状態に戻る 

具体的には：
トランザクション管理で2つのテーブルを更新した時に、コミットすると全ての更新が保証される。ロールバックすると全ての更新はもとに戻ります

## C Consistency (一貫性) 

処理の順番に関わらず結果が同じになる 

具体的には：
2つのテーブルを更新した時にAから更新してもBから更新しても同じ結果が保証されます。
口座金額を減算して加算しても、加算して減算しても同じ結果になります。

## I Isolation (独立性) 

他のトランザクションの影響を受けない 

具体的には：
二人のユーザーから更新処理がかかった時に互いに影響を与えない仕組みになってます。
従って、在庫数を減らす時は、Aの処理がコミットするまで、Bの処理から見た在庫数は前のままです。これを排他制御と呼びます

## D Durability (耐久性) 

いったんトランザクションが完結したら障害が発生してもデータの状態が変化しない 

具体的には：
一度、コミットかロールバックが発行された後、ディスクに書き込む前に障害が発生してもログからデータを復旧させる、データを保証されます。

# ACID特性
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/310f1cbd-9cd4-6824-a8dc-37c6c3ad7556.png)

# まとめ
ー大事なのがトランザクション管理

ーACID特性をもつ

ーA Atomicity (原子性) 

ーC Consistency (一貫性) 

ーI Isolation (独立性) 

ーD Durability (耐久性) 

# 最後に
未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
neosでlogix その112

# 概要
neosでlogixやってみる。
logixを、俺コードで表現してみる。
練習問題、やってみた。

# 練習問題
このページを俺コードで表現せよ。

https://www.youtube.com/watch?v=k9UKTzqu1ig&t=197s

# 俺コード

```
a = Sphere.Grabbable
	|> OnGrabableReleased
b = GlobalTransform Sphere.Slot
c = b
	|> Δ
	|> ÷dT
r = |v| c
s = > r 1
{float3a, d, _} = Write t b
{t, _} = If a s
{float3b, e, _} = Write d c
{user, f, _} = Write e LocalUser
{_, _, _, g, h} = Stopwatch f (m | p) (n | q)
i = FireWhileTrue h LocalUser
e = Trajectory float3b 0,-9.8,0 0 g
j = + e float3a
SetGlobalPosition i Sphere.Slot j
k = > g 3
l = FireOnTrue k LocalUser
{m, n} = Suqence l
o = Sphere.Grabbable
	|> OnGrabableGrabed
{p, q} = Suqence o

```

以上。
Vue 3.0 インストール方法 Ubuntu20.04 

VueCLIをubuntu20.04にインストールし，Vue3.0プロジェクトを作成するまでの手順を記載しました．

- VueCLIのインストール

```bash:install_vuecli.sh
curl -sL https://rpm.nodesource.com/setup_8.x | sudo bash -
sudo apt install -y nodejs npm
node -v
npm -v
sudo npm install -g @vue/cli
vue --version
```

(ref) https://houdoukyokucho.com/2021/01/19/post-2913/

上記実施し`vue`を実行したら`nodejs`のバージョンが古いと怒られた

- nodejsのアップデート

```bash:update_nodejs.sh
sudo apt install -y nodejs npm
sudo npm install n -g
sudo n stable
sudo apt purge -y nodejs npm
exec $SHELL -l
node -v # v18.14.0
```

(ref) https://qiita.com/seibe/items/36cef7df85fe2cefa3ea

ここまでの手順で`VueCLI`がインストールできました．

ここからサンプルを実行していきます．

- プロジェクトの作成

プロジェクトの作成は`vue create {プロジェクト名}`で行えるようです．試しに`hello-vue`というプロジェクトを作成してみます．バージョンの選択で,今回はVue3を選択しました

```
vue create hello-vue 
```

プロジェクトが生成できたら,`npm run serve`コマンドでプロジェクトを実行できます．

```
cd hello-vue
npm run serve
```

ビルトが完了したら,表示されたURLにアクセスすることで立ち上がったサーバーを確認できます．
今回URLは http://localhost:8081/ でした．

アクセスすると以下のような画面が表示されます．
![Screenshot from 2023-02-10 05-10-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/32f72fc0-a6cd-557c-5f76-95a254d05455.png)

(ref) https://codelikes.com/vue-cli/

- おまけ

ちなみにメインのプログラムは`src/App.vue`に記載されているみたいで以下のようなプログラムになっています．

```vue:App.vue
<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <HelloWorld msg="Welcome to Your Vue.js App"/>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
```
Vueのロゴファイルパスは`./Assets/logo.png`みたいでこの`png`ファイルを変えてみたらロゴを変えることができました．

![Screenshot from 2023-02-10 05-21-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/26a0e0f3-13c7-caa0-6653-8a9799cd8101.png)

また`<HelloWorld msg="Welcome to Your Vue.js App"/>`がロゴ下の文章を生成しているようです．このタグをコメントアウトしてみました．がエラーが発生．

ろご下の文章`HelloWorldクラス?`を消すには以下の手順が必要でした．

- `HelloWorld`タブのコメントアウト
- `HelloWold` コンポーネントの import コメントアウト
- `componets`設定内の`HelloWorld`をコメントアウト

```vue:App.vue
<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <!--HelloWorld msg="Welcome to Your Vue.js App"/-->
</template>

<script>
// import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
//    HelloWorld
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
```

ロゴだけになった!

![Screenshot from 2023-02-10 05-39-17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/4d1645d2-6f44-31d6-692f-78b8f1ce64fc.png)
iphoneでcharlesをつかう


iphoneの通信をcharlesでのぞき見したいのに http://www.charlesproxy.com/getssl から証明書が取得できないとき～


１．PCでCharlesを開き、Help > SSL Proxying > Save Charles Root Certificateより、FormatとしてBinary certificate (.cer)を選び保存する。

２．↑をメール等でiPhone側に共有し、「ファイルに保存」から保存する（どこでも良さそう）

４．「ファイル」（iphoneのアプリのこと）にて、↑で保存した証明書をタップする
　→「プロファイルがダウンロードされました」というメッセージが表示される

５．「設定」（iphoneのアプリのこと）にて、「プロファイルがダウンロード済み」と表示されているはずなので、それをタップして、インストール

６．設定＞一般＞情報＞証明書信頼設定　で、↑でインストールした証明書の信頼を　ON　にする

７．この状態で、PCと同じネットワークにiPhoneを繋げて、プロキシを構成＞手動（ポート番号はPCのCharlesのProxy＞ProxySettings参照、サーバはPCのCharlesのHelp＞Local IP address参照）でプロキシを設定し、接続
　→PC側のCharlesに「この接続Denyする？Allowする？」というポップアップが表示されるので、Allowを押下

８．完了なはず

# 参考
https://stackoverflow.com/questions/3976728/how-to-configure-ssl-certificates-with-charles-web-proxy-and-the-latest-android
2023/2/10主にITとかセキュリティの記事

米政府、ランサムウェア「ESXiArgs」の復旧ツール - 十分理解して使用を
https://www.security-next.com/143538

ランサムウェア「Cl0p」のLinux亜種が見つかる - 復号ツールが公開
https://www.security-next.com/143501

フィッシングURLが大幅減 - 10カ月ぶりに1万件下回る
https://www.security-next.com/143516

PDF生成ライブラリ「dompdf」に深刻な脆弱性 - 2度にわたり更新
https://www.security-next.com/143504

「OpenSSL」にセキュリティアップデート - 脆弱性9件を解消
https://www.security-next.com/143521

厚労省、医療機関向けにセキュリティ対策のオンラインセミナー(2/15開催)
https://mhlw-training.saj.or.jp/info-20230201/

クレカ会社装うフィッシングサイトの割合が激減 - 5％ほどに
https://www.security-next.com/143393

4つの現状課題からXDRの「理想と現実のギャップ」を埋める鍵を探る　活用事例から見た“有効性”とは
「学習と適応」「ネイティブかつオープン」「専門家と組み込み」(2/8)
https://enterprisezine.jp/article/detail/16734

【勤務先のウイルス対策は万全！？】そう思う方は7割以上いるものの、“本当に大丈夫？”と不安要素を感じている方も…
半数以上の企業が過去にサイバー攻撃を受けた経験あり！(2/8)
https://prtimes.jp/main/html/rd/p/000000003.000104719.html

情報セキュリティ10大脅威2023、「個人：フィッシング」「組織：ランサムウェア」が引き続き1位【IPA調べ】(2/8)
https://webtan.impress.co.jp/n/2023/02/08/44252

サイバー攻撃、大損害備え
英損保大手が世界初の大災害債　補償額増大、リスク再考(2/8)
https://www.nikkei.com/article/DGKKZO68276560X00C23A2EE9000/

防犯カメラを設置する前に気をつけたいこと(2/8)
https://ascii.jp/elem/000/004/123/4123704/?rss

国内企業が有害性を認識しながらもPPAPを使い続ける理由(2/8)
https://security.srad.jp/story/23/02/07/1336240/

スピアフィッシング市場(Spear Phishing Market)に関する調査は、2022年の市場のランドスケープを理解するために実施されました。(2/8)
https://prtimes.jp/main/html/rd/p/000002279.000072515.html

ChatGPTにWordPressプラグインを要求したら数日かかる作業を5分で完了させたという報告(2/8)
https://gigazine.net/news/20230208-chatgpt-wordpress-plugin/

新しいAndroidバンキング型トロイの木馬「PixPirate」発見、注意を(2/8)
https://news.mynavi.jp/techplus/article/20230208-2585736/

バンダイナムコ事件から学校・病院まで、ランサムウェアの脅威を動画で説明(2/8)
https://news.mynavi.jp/techplus/article/20230208-2584264/

人気のファイル転送アプリGoAnywhere MFTにゼロデイ脆弱性、攻撃への活発な悪用確認(2/8)
https://news.mynavi.jp/techplus/article/20230208-2585737/

「Clop」ランサムウェアの「Linux」亜種が発見--まだ実験段階か(2/8)
https://japan.zdnet.com/article/35199732/

カスペルスキー、ダークウェブ上の雇用に関する投稿を分析(2/8)
https://www.nikkei.com/article/DGXZRSP648989_Y3A200C2000000/

MCPPのアカウント悪用したフィッシングを発見、不正なアプリに注意を(2/8)
https://news.mynavi.jp/techplus/article/20230208-2582467/

「メルペイ」アカウント乗っ取り容疑の中国人 指示役の1人か(2/8)
https://www3.nhk.or.jp/news/html/20230208/k10013974691000.html

不正閲覧４万５０００件に拡大　新電力の顧客情報―九州電(2/8)
https://www.jiji.com/jc/article?k=2023020801174&g=eco

九州電力の顧客情報不正閲覧、３倍の４万５２４２件に拡大…関電や中国電でも相次ぐ(2/8)
https://www.yomiuri.co.jp/economy/20230208-OYT1T50189/

過去最高額の暗号資産窃取　北朝鮮、安保理パネル報告(2/8)
https://www.47news.jp/world/8911235.html

東芝や富士通ら日本勢が3年ぶりのNRF本格参戦、「流通改革の伴走者」になれるか(2/8)
https://xtech.nikkei.com/atcl/nxt/column/18/02328/020800009/

未来を創造する技術構想CPS　ソフト調達の改革と協業がカギ(2/9)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020900021/020200131/

製鉄所を5Gでデジタル化する「5G Steel」、エリクソンが運用開始(2/9)
https://xtech.nikkei.com/atcl/nxt/news/18/14618/

個人にも被害が及ぶランサムウエア攻撃、バックアップやファイル共有で防ぐ方法(2/9)
https://xtech.nikkei.com/atcl/nxt/column/18/02353/020800006/

AIで高まる「なりすまし」詐欺の脅威、日本企業は対策に本腰を(2/9)
https://xtech.nikkei.com/atcl/nxt/column/18/00138/020701218/
macOSのPostgreSQL(Postgres.app)のインストール方法

# はじめに
MacでPostgreSQLをGUIのPostgres.appで使用する場合のインストール方法について記載いたします。
インストールだけではなく、メジャーアップデートを行う場合の方法は以下で解説しております。
データの移行等が必要な方は以下をご参照ください。
[macOSでPostgres.appを使用している場合のメジャーアップデート（データ移行有）](https://qiita.com/ngnmsn/items/5f4f827462b10800d0cd)

# 環境
|項目|情報|
| ---- | ---- |
|OS|macOS Ventura 13.1|
|プロセッサ|1.6 GHz デュアルコアIntel Core i5|
|PostgreSQL|15.1|

# インストール手順
### 最新のメジャーアップデートのインストーラーをダウンロード
Postgres.appの公式サイトから最新のメジャーアップデートのインストーラーをダウンロード
[Postgres.app公式のインストーラーダウンロードページ](https://postgresapp.com/downloads.html)
![postgres_download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639284/66d6527d-c88e-366f-1d11-0e7f8b0c3134.png)

### Applicationsフォルダへのドラッグ&ドロップ
ダウンロードしたdmgファイルをダブルクリックし、インストールを開始する。
以下のウィンドウが表示されたら"Postgres.app"を"Applications"にドラッグ&ドロップ
![postgres_15_install_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639284/067be454-0525-f6f4-a785-3b5b5a4f3699.png)

### 「開く」をクリック
新しく配備されたApplicationsフォルダのPostgres.appを開くと以下のウィンドウが表示されるので、「開く」をクリック。
![postgres_install_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639284/b5b1aa8f-912d-fc54-7034-316a5719c6b4.png)

### 「Initialize」をクリック
新しいバージョンのPostgres.appが開かれるので、「Initialize」をクリックして初期化する。
![postgres_install_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639284/76e133d5-c965-81b2-fa14-dd04b48a0fc8.png)
初期化が完了するとサーバが起動する。
![postgres_install_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639284/a3d1faa8-0ad3-72b9-52e2-33b1eb1a6b72.png)

### パスを通す。
付属のコマンドラインツールを使用できるようにするため、ターミナルで以下のコマンドを実行する。
```
$ sudo mkdir -p /etc/paths.d
$ echo /Applications/Postgres.app/Contents/Versions/latest/bin | sudo tee /etc/paths.d/postgresapp
```

### psqlによるバージョン確認
ターミナルを再起動した上で以下のコマンドを実行し、PostgreSQLがインストールされていることを確認する。
```
$ psql --version
psql (PostgreSQL) 15.1
```
以上となります。
macOSのPostgreSQL(Postgres.app)のアンインストール方法

# はじめに
MacでPostgreSQLをGUIのPostgres.appで使用している場合のアンインストール方法について記載いたします。
アンインストールだけではなく、メジャーアップデートを行う場合の方法は以下で解説しております。データの移行等が必要な方は以下をご参照ください。
[macOSでPostgres.appを使用している場合のメジャーアップデート（データ移行有）](https://qiita.com/ngnmsn/items/5f4f827462b10800d0cd)

# 環境
|項目|情報|
| ---- | ---- |
|OS|macOS Ventura 13.1|
|プロセッサ|1.6 GHz デュアルコアIntel Core i5|
|PostgreSQL|14.6|

# アンインストール方法
### 旧バージョンのサーバ停止
Postgres.appを開き、旧バージョンのサーバを停止する。
![postgres_install_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639284/de065a43-ca65-7743-eb02-878587f47afd.png)
![postgres_install_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639284/777db15b-835f-8390-77ae-800e51a6e567.png)

停止したらPostgres.appは閉じる。

### 旧バージョンのPostgres.appの削除
ApplicationsフォルダのPostgres.appをゴミ箱に移動する。

### 旧バージョンのデータディレクトリ削除
ターミナルで以下のコマンドを実行し、旧バージョンのPostgreSQLのデータディレクトリを削除する。
```
$ rm -rf ~/Library/Application\ Support/Postgres
$ ls -ld ~/Library/Application\ Support/Postgres
ls: /Users/ngnmsn/Library/Application Support/Postgres: No such file or directory
```

### 旧バージョンの設定削除
ターミナルで以下のコマンドを実行し、旧バージョンのPostgreSQLの設定を削除する。
```
$ defaults delete com.postgresapp.Postgres2
```

### 旧バージョンの$PATHコマンドラインツールの構成削除
ターミナルで以下のコマンドを実行し、旧バージョンの$PATHコマンドラインツールの構成を削除する。
```
$ sudo rm /etc/paths.d/postgresapp
```

### アンインストールの確認
ターミナルで以下のコマンドを実行し、PostgreSQLがアンインストールされていることを確認する。
```
$ psql --version
fish: Unknown command: psql
```

以上となります。
NextAuthのFirebaseAdapterを使ったら詰まりまくった件

## はじめに
~~2023年2月10日現在、NextAuthのadapterであるFirebaseAdapterを使用するうえで詰まりまくったので備忘録として残しておく。~~
2023年2月27日時点でドキュメントの正常化とfirebase-adapter@2.0.1のリリースによりここに記載されている内容は無事修正されました。

## 何が起こったか
https://authjs.dev/reference/adapter/firebase

ここのドキュメントを参照しながら開発していたのだが、コピペして実行しても上手く動かない…
NextAuth.jsとAuth.jsてドキュメント2つあって実装方法少し違うんだけどなにこれ？？？

## 結論 
ここ見ろ

https://github.com/nextauthjs/next-auth/pull/6225#issue-1514157022

## 流石にこれだけでは怒られそうなので補足

### 1.NextAuth.jsとAuth.jsとは？
元々あったのがNextAuth.jsという名前のライブラリ。
最近はSvelteKitやSolidStartにも対応したからAuth.jsという名前に変更になっただけ。
ただ、ドキュメントがNextAuth.jsとAuth.jsに分かれて少し混乱した。
NextAuth.jsのドキュメントはAuth.jsのドキュメントに順次移行しているらしいがしばらくかかりそう。

### 2.存在しないNode Module
この記事を見ている頃には直っているかもしれないが、
Installationの`npm install next-auth @next-auth/firebase-admin-adapter firebase-admin`という部分は間違い。
正しくは`npm install next-auth @next-auth/firebase-adapter firebase-admin`

これはただただドキュメントがミスっていただけなので割とすぐ気づいた。
npm君から「そんなモジュールねえよ（E404）」と言われて調べてみたら4日前に`@next-auth/firebase-adapter`が`2.0.0`にバージョンアップしていた。インストールしたのはほぼ同時期なのでびっくり。
恐らく何かしらの手違いでfirebase-admin-adapterになっただけ。

#### そもそも何故メジャーバージョンが上がったのか？

Firebaseを使っている人は知っていると思うが、FirebaseのSDKは2つある。
クライアントサイドで動くfirebaseSDK（npm i firebase）とサーバーサイドで動くfirebaseAdminSDK（npm i firebase-admin）である。
それぞれ役割が違うのでインストールする時は注意。

で、どうやらクライアントSDKで実装されていた旧バージョンはFirestore Rulesを開放するとかいうとんでもない欠点があったらしい。
>対象のGitHubスレッド
>https://github.com/nextauthjs/next-auth/pull/5628#issue-1420003540

これを解消するためにAdminSDKを使用した方法に実装し直したのが`2.0.0`というわけである。

### 3.なんか動かない
バージョンアップに対応した実装方法のはずなのに動かない事態が発生。
何故か`ERR_MODULE_NOT_FOUND`を吐く。
これはもしやライブラリのバグではと思いGitHubを確認すると以下のような発言が…

https://github.com/nextauthjs/next-auth/pull/6225#issuecomment-1422744063

**何と昨日回答されていた**
ありがとう海外ニキ…

というわけでひとまず直接node_modulesからfirebase-adapterを参照インポートすることで無事解決。

実際にログインすると自動でデータベースにuserやsessionが作られたのでとりあえずヨシとした。

## まとめ
1. NextAuth.js=Auth.js
ただしドキュメント内容は少し違うので最新のAuth.jsを見る。
2. `@next-auth/firebase-adapter`の`ver1.x`はセキュリティ的な面で問題があるので`ver2.x`を使う。
3. 困ったらGitHubを見てみる(必ず解決するとは言っていない）