OmniAICreator/Qiita-1.07M huggingface dataset:
Googleデジタルマーケティング＆Eコマース：Google Adsのダイナミック・リマーケティング

# はじめに

”Googleデジタルマーケティング＆Eコマース プロフェッショナル認定証"　の受講が完了しました(2022/3/3)。私がこのコースから得られた素晴らしい体験を、テーマごとに分割して、わかりやすくご紹介しています。興味を持たれた方は、是非下記を受講してみてください。

https://jp.coursera.org/professional-certificates/google-digital-marketing-ecommerce

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/05f6fefc-adb6-1242-4eb1-528a10511727.png" width="800">

# Google Adsのダイナミック・リマーケティング

***<font color="MediumVioletRed">『以前あなたのサイトで商品を閲覧したことのあるお客様に再度アプローチする方法のこと』</font>***

このような顧客は、あなたのお店をよく知っていて、商品の購入を検討したことがありますが、何らかの理由でまだ購入に至っていないのです。決断するのに時間が必要なのかもしれませんし、製品や取引が見逃せないものであることを再認識してもらう必要があるのかもしれません。

いずれにせよ、ダイナミック・リマーケティングは、オーディエンスに合わせたパーソナライズされたメッセージの広告を表示することで、これらの顧客との再エンゲージメントとロイヤルティの促進を支援します。

このタイプのリマーケティングは、すでに購入を検討している訪問者を巻き込み、再度来店してもらい、購入を完了させるように促します。

ダイナミック・リマーケティングは、

- 顧客が既に閲覧した商品や
- 顧客が興味を持ちそうな類似商品の広告

を表示することで機能します。

Google広告の商品推薦エンジンが、各広告に表示する商品のベストミックスを決定します。その結果、人気度や訪問者がサイトで閲覧した内容に基づいて商品を紹介する、パーソナライズされたエクスペリエンスが実現します。お客様がすでに閲覧した商品と類似した商品を表示することで、他の方法では見つけられないような商品を発見することができます。もしかしたら、以前に閲覧した商品は期待したものではなかったかもしれませんが、似たような商品であれば、ちょうど欲しいものが見つかるかもしれません。

例えば、宝飾品のオンラインショップで、大きな買い物を検討している顧客を想定してみましょう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/5589618c-a379-3519-3f17-8dd5517dd466.png" width="600">

このようなお客様は、決断するまでに時間がかかるかもしれません。また、最高の品質の商品と最良の取引を求めて、あちこちの店を回りたいと思うかもしれません。ダイナミック・リマーケティングを利用することで、宝石店は、顧客が自社サイトで閲覧した商品と、顧客が好むかもしれない類似商品の広告を表示することができます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/21947ab6-f03d-9b66-e614-285aea135504.png" width="600">

このように顧客とつながることで、顧客が購買を決定するまでの間、宝石店は顧客の目の前に自社ブランドを表示し続けることができます。
ESP カード５枚の正答率は？（その２）

## 目的

出された５枚のカードの絵柄を当てようとする場合、

a. 適当な順列組み合わせを想定して答える場合
b. 各カード独立して答える場合（極端な話、全部同じ絵柄を解答すれば必ず一枚は当たる）

という戦略が考えられますが、どちらの戦略がどのていど正答率が高くなるのだろう？
という疑問が頭に浮かびました。

a のパターンについてはすでに正答率を計算したので、今度は b のパターンの正答率を考えたいと思います。

## 計算方法

「[ESP カード５枚の正答率は？（その１）](https://qiita.com/tadashi9e/items/bfd4778b28c5f0c28840)」のプログラムを少しだけ改造します。

`カード５枚を当てる/1` 述語で、

- 正答カードを順列組み合わせで生成
- 解答するカード並びも順列組み合わせで生成

で突き合わせたのですが、これを

- 正答カードを順列組み合わせで生成（前回のまま）
- 解答するカード並びは重複を考慮せず、一枚ずつ、まっさらな気持ちで当てにいくことを５回繰り返す

という形にします。


```prolog
% カードは全部で５種類
カード(a).
カード(b).
カード(c).
カード(d).
カード(e).

カード５枚を当てる(_正答数) :-
    permutation([a,b,c,d,e], _実際のカードの並び),
    カード(_推測1), カード(_推測2), カード(_推測3), カード(_推測4), カード(_推測5),
    _推測したカードの並び = [_推測1, _推測2, _推測3, _推測4, _推測5],
    正答数を数える(_実際のカードの並び, _推測したカードの並び, _正答数).
```

## 結果

[前回](https://qiita.com/tadashi9e/items/bfd4778b28c5f0c28840) 得た、順列組み合わせを考慮して解答した場合の結果はこうでした：

```
0 ...  5280 / 14400 = 36.667%
1 ...  5400 / 14400 = 37.500%
2 ...  2400 / 14400 = 16.667%
3 ...  1200 / 14400 =  8.333%
4 ...     0 / 14400 =  0.000%
5 ...   120 / 14400 =  0.833%
```

今回の、すべてのカードを独立して当てに行く場合の結果はこうなります：

```
0 ... 122880 / 375000 = 32.768%
1 ... 153600 / 375000 = 40.960%
2 ...  76800 / 375000 = 20.480%
3 ...  19200 / 375000 =  5.120%
4 ...   2400 / 375000 =  0.640%
5 ...    120 / 375000 =  0.032%
```

## まとめ

シャッフルされた５枚のカードを当てようとする戦略として、

- 順列組み合わせを考慮して解答を生成する場合（「[ESP カード５枚の正答率は？（その１）](https://qiita.com/tadashi9e/items/bfd4778b28c5f0c28840)」）
- 順列組み合わせを考慮せず解答をランダムに生成する場合（この記事）

を考えました。

ランダムに解答を生成する場合のほうが１枚、２枚正答する確率が上がります。
これは「全カード同じ解答にすれば、どれか１枚だけは必ず当たる」という状況も入ってくるためだと思われます。
その代わり、全カード当たる可能性も下がります。
高齢者にいかにＡＩを浸透させるかを考える（１）

普段と違ったことをすると、意外な気づきと言うものがある。
例えば、先週から少し自分の身に降りかかったことを書いてみる。
# 
* 実家の母親(80代)の様子を見に行き、最近のテレビが詰まらないとか、散々の愚痴の聞き役をしてきた
→　ネットで楽しめるよと何度でもいうが、もう後期高齢者にネットを薦めることは諦めた。しかしながら、今の日本には少なくとも、スマホやネットが使えない、一定層のＩＴ難民が存在することは事実だ。自分は三年前ぐらいに、ようやく自分の母親にスマートフォンを持たせ、LINEで連絡を取ることを唯一教えきったので、少なくとも連絡は取りやすくなった。（こういうにニーズはやはり、子供や孫が居て初めて年寄連中が重い腰を挙げるようだ。ちなみに70代はネットやスマホに抵抗はない様だ）。話の中で気づいたことは、まずスマホと言うものは、やはり年寄りにとって、かなり字が小さいらしい。次に50インチのＴＶを持っている割に、デジタル機器として何も使いこなしていない。ハードディスクレコーダーは唯一使いこなせた電子機器らしく、DVDを突っ込んで再生するというアナログプレーヤー時代の常識は唯一使えるデジタルリソースだ。

* AI動画の収集
→　上記の話も関係するが、母親は水彩画や洋裁が好きだったようだ。年を取ると、体が動かなくなるので、だんだんと遠ざかるが、頭が元気な限り、そういうものに触れていて欲しいと思う。そこで、最近の自分が調べているCHATGPTとMIDJOURNEYのようなＡＩ生成について、何とか年寄と接続するにはどうしたら良いかを考えている。一番良いのは、年寄の後頭部の言語野に、1024BITのデジタルセンサを埋め込んで、何とかPCのスクリプト入力画面に、英語のプロンプトを自動入力！と言いたいが、ここまでできる時代を待っている場合ではない（参考動画）。そこで考えたのは、まずYOUTUBEの動画から入り、まずはデジタル鎖国した状態から、一歩開放するルートを取ることとした。
　
* 推奨する番組
→　いくつか動画があったが、やはりユーチューバー（参考動画）が作ったチャンネルを紹介するのは、内容的にも一般人さえ難色を示すので、まずは公式テレビ番組で、こういう面白いのがあるよと伝える方が良いだろう。今回選んだのは、テレ東BIZの長編動画三本だ。長さにすると８時間程度なので、年寄が半年ぐらいかけて、暇つぶしに見るには良いだろう。ブルーレイ片面に二層のRWに焼いて、盆と正月には顔見世程度に動画配信する。なんかディアゴスティーニのような、ＡＩ写真集とセットで月間マガジンを作ってみても、年寄にバカ受けしそうな気がする。
https://www.youtube.com/@tvtokyobiz

#

　すっかり余談が長くなったが、自分がいま何を何のためにいつまでにやるのか？　こういう思考は頭の中からすぐに取り出して、さっとノートにメモして、忘れないようにしなくてはならない。特にこれからのＡＩ開発においては、あまりにも急激な変化に対して、実社会はますます乖離していき、世の中が二極分化してしまうだろう。自分はいま、最新のＡＩ開発をウォッチングしつつ、これからの日本の課題である、少子高齢化の未来の両方に接している状況である。おそらく、いま役立つと思える行動や気づきは、自分が何とかするのも大変であり、少なくともこういう技術者界隈の方々の身に触れる場所に書くことだけでも価値があるように思える。
　YOUTUBEの収集で意外に役に立ったことは、自分も言うほどYOUTUBEを見ていなかったので、けっこうためになったのも事実だ。特にOPEN-AIのシェイングウさんや、サムアルトマンさんらが、ＡＩと日本はコラボできると言っていたのが印象的である（参考動画）。自分は今、かなりの雑なＩＴ案を持っているのであるが、これらの案をＡＩで解決できるのであれば、ＤＭを送ってみたいところである。例えば、[日本語ルビ](https://qiita.com/EasyCording/items/96b19930ac7a5a250ce1)、[ミスチルの歌詞を外国語で音読できないかの検討](https://qiita.com/EasyCording/items/3b220201fb661cb35e69)のＡＩを開発すれば、言語学習のハードルを一気に下げることができて、世界平和にも貢献できると信じている（教師データ作成に時間がかかり、タスクが止まっているが。。。）

# 参考
【未公開】「日本ができることはいっぱいある」ChatGPT技術幹部のシェイン・グウ氏が語るAIと日本の可能性（2023年3月26日）　https://www.youtube.com/watch?v=jdCYKe9W8dI&t=588s

松田語録：脳活動画像化～脳信号からStable Diffusionで絵を再構成するという阪大・NICTの研究について
https://www.youtube.com/watch?v=8DH-NErn4p0

【画像生成AI】今日から貴方もAI絵師！無料で継続利用出来る画像生成AIサービス7選！プロンプト入力のコツもご紹介！
https://www.youtube.com/watch?v=VFHKxGnK2Rk&t=170s
paiza.ioでelixir その217

# 概要
paiza.ioでelixirやってみた。
練習問題、やってみた。

# 練習問題
円周率を求めよ。

# 参考にしたページ。

https://qiita.com/tatsuya6502/items/52c2817b5ccae6d51197

# サンプルコード

```
defmodule Main do
    def pi(n) do
        w = 1.0 / n
        t = Enum.reduce(0..(n - 1), 0, fn i, s ->
                x = i * w
                s + :math.sqrt(1.0 - x * x)
            end)
        u = 4.0 * w * t
        {:ok, u}
    end
    def main do
        pi(1000_000)
        |> IO.inspect
    end
end

Main.main


```

# 実行結果


```
{:ok, 3.141594652413976}
```

# 成果物

https://paiza.io/projects/yB_QQh9L4cLe2X20u84DnQ

以上。
Raspberry Pi (Ubuntu Server) でOpenSSLをビルドする

## OpenSSLのビルドが落ちる

手持ちのRaspberry Pi 3B+ (Ubuntu Server 22.04) でOpenSSL (v3.1.0) のビルドを実行したところ、以下のエラーが発生しビルドできないという事態が発生しました。

```
cc1: error: '-mfloat-abi=hard': selected architecture lacks an FPU 
```

## 解決法

`config`時に、`-march=armv7-a+fp` を引数に含める（gccのオプションを上書きする）

## エラーの原因

`selected architecture lacks an FPU` というエラーの通り、FPU (Floating-Point Unit, 浮動小数点演算装置) がないと認識されているため発生するようです。

`gcc`には`march`というオプションがあり、ターゲットとなるシステムのCPUアーキテクチャを設定できます。Raspberry Pi 3B+でのOpenSSLのビルド時にはこれがデフォルトで`armv7-a`に設定されています。このままだとFPUが搭載されていても認識されず、上記のエラーを吐きます。

FPUが搭載されているCPUの場合、`march`オプションを変更することでFPUを認識させることができます。オプションで使える変数の一覧は[ここ](https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html)にあります。今回の場合は`armv7-a+fp`を設定することで、FPUを認識させることができるようになりました。
Java String.replace()についての勘違い

# immutable
String 型はイミュータブルである。

```java
String message = "hello world";
message.replace("hello","goodnight");
System.out.println(message);
---
> hello world
```
なので上記のようになる。
message の中身を変更したくば、再代入しよう。

```java
String message = "hello world";
message = message.replace("hello","goodnight");
System.out.println(message);
---
> goodnight world
```
css

## @mediaについて

比較演算子を使用して記述することが可能

```css
@media (100px <= width <= 1900px) {
    //style
}
```
他にorやandを使って条件を設定することが可能


## image-set()
background-imageで使用する
srcset属性と同様の処理をCSS上で行える
```css
.sample {
    background-iamge: image-set(url(hoge) 1x, url(fuga) 2x);
}
```

## clamp(),max(),min()

### clamp()
clamp()関数は3つの引数（値）を受け取り、その中間の値を計算して返す関数
第1引数は最小値、第2引数は推奨値、第3引数は最大値となる
```css
.hoge {
    font-size: clamp(16px, 2.5vw, 24px);
}
```
例では16px以上24px以下で2.5vwのfont-sizeとなる

### min()
min()関数は指定された複数の値のうち最小値を返す関数

```css
.hoge {
    width: min(50%, 400px);
}
```
min()関数では1つ以上の複数の値を設定可能

### max()
max()関数は指定された複数の値のうち最大値を返す関数
```css
.hoge {
    width: max(200px, 50%);
}
```
max()関数では1つ以上の複数の値を設定可能


## background-blend-mode
mix-blend-modeと同様の内容を背景に適用するもの

## repeating-linear-gradient,repeating-radial-gradient
gradient各種を繰り返しで使用するもの

## caret-color
input、textareaで文字入力位置のマーカーの色を設定

## justify-content
justify-content: space-evenly;について
space-betweenでは両サイドの要素が両端に密着する
space-aroundでは両サイドの要素が両端から余白を持つ。その余白の2倍の量を並ぶコンテンツ同士の余白となる
space-evenlyではspace-aroundと同様に余白を持つが全ての余白が均等となる

align-contentでも同様

## place-content
place-contentはalign-contentとjustify-contentのショートハンド
place-content: align-content justify-content;となる

## place-items
place-itemsはalign-itemsとjustify-itemsのショートハンド
place-items: align-items justify-items;となる


## inset
insetは要素の位置や余白を指定するために使用
親要素の左上隅からの距離と右下隅からの距離を指定する
positionと組み合わせることで少ない行数で画面中央配置を実現する

```css
.hoge{
    position: absolute;
    inset: 0;
    margin: auto;
}
```

## background-clip:text
文字によるclip。グラデーション表現

```css
.hoge{
    background: linear-gradient(-45deg, #2af598, #009efd);
    background-clip: text;
    color: transparent;
}
```

## scroll-snap
コンテンツの始まりに吸着させるなど
```css
.hoge {
  scroll-snap-type: y mandatory;
}
.hoge .fuga {
  scroll-snap-align: start;
}
```

## scroll-behavior
スムーススクロール
```css
html {
  scroll-behavior: smooth;
}
```
バイヤー今どこで何してる？どこでもバイヤーのスケジュールが確認できるLINEBot



私はスーパーマーケットの商品部で仕事をしています。

本社にいるとよくあるのが**店舗からの電話**の問い合わせ。
「〇〇バイヤーお願いします」
あれ今日はいない・・・少し前までいたような・・・
出勤？？休み？？外出？？商談？？と、いつも部門でまとめている
紙ベースのスケジュール表のところまで歩いて行き確認。

本社にいても意外に知らないバイヤーのスケジュール。
お店の人はもっと知らないはず・・・
電話する前にスケジュールがわかれば対応もかわり、無駄がなくなる。

そこで、バイヤーのスケジュールを**使いやすいツール**で簡単に確認できないか。
日付とバイヤー名の入力でスケジュールが確認できるLINEBotを作成してみました！

使用するもの
-

・Make
・LINE　Developers
・Googleスプレッドシート

作り方
-
1、スプレッドシートに日付とバイヤー名を合わせたもの、シフトを記入
2、LINEで確認したい日付とバイヤー名を入力
3、確認したいバイヤーのスケジュールが返信

**スプレッドシートの設定**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3291625/b79248d9-b7b0-1d72-470e-72af98bf8ca7.png)
1、Ｄ列に日付と氏名（バイヤー名）を合わせた情報、E列にシフト情報を入力
2、Ａ2セルにLINEから知りたい日付と氏名（バイヤー名）が入力される
3、Ｃ2列にＡ2セルを検索値としてＶＬＯＯＫＵＰ関数を使用しシフト情報を抽出

**Makeの全体図**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3291625/5d42ddb1-af21-7ae9-d0a9-00a64ee1c84f.png)
Google SheetsのUpdate a CellとGoogle SheetsのGet a Cellを使用しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3291625/9d2589e9-2a66-b0b9-46a1-379643f49dc2.png)

1、Google SheetsのUpdate a CellのChoose a DriveをMy Driveに設定
2、Spredseet IDに自身で作成したシート名を選択
3、CellにLINEから知りたいバイヤー名が入力されるA2セルを選択
4、valueにEvent message textを選択
5、Google SheetsのGet a Cellも同様にシート名まで選択
6、CellにA2セルを検索値としてVLOOKUPで情報を抽出するC2セルを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3291625/bd4a3681-8ae6-db2d-0bfa-d48b58700430.png)

LINE Send a Reply Messageを設定

実装
-
動きました！！
<blockquote class="twitter-tweet"><p lang="zxx" dir="ltr"><a href="https://t.co/e1WQqC5I6c">pic.twitter.com/e1WQqC5I6c</a></p>&mdash; 勝又慎司 (@KatsumataS80528) <a href="https://twitter.com/KatsumataS80528/status/1641843042213822464?ref_src=twsrc%5Etfw">March 31, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>



あとがき
-

以上、LINEBotを使用しバイヤーのスケジュールを確認できるようにしてみました。
失敗が多かったので動いた時の感動は大きかったです。
当日のスケジュール変更などに対応できるよう改善すればさらに便利になると思います。

最後まで読んでいただきありがとうございました。
Mulesoft: DataWeaveのjoin句で2つのjsonを結合する

# Mule APIでは2つのjsonを結合することができる
Mule APIの最大の利点は複数のデータベースからデータを取得し、Mule上で一つのjsonにまとめ、APIのレスポンスとして返せることです。以下のように二つのデータベースからの取得結果を一つのjsonにまとめるTransform Messageコンポーネントをこの記事で紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259482/17f7be42-78e7-4d15-3cc1-09a408530e39.png)

Transform MessageコンポーネントのDataweaveを以下のように記述します。

```
%dw 2.0
output application/json
import every,join from dw::core::Arrays
var oracleData= 
[
    {
      "id": "456",
      "depositdate": "2023/4/1",
      "clntNameKana": "鈴木太郎"
    },
    {
      "id": "457",
      "depositdate": "2023/4/2",
      "clntNameKana": "佐藤太郎"
    }
]
var mysqlData= 
[
    {
      "id": "456",
      "transferamount": "10000",
      "accountname": "89998"
    },
    {
      "id": "457",
      "transferamount": "20000",
      "accountname": "90000"
    }
]
var result = join(oracleData, mysqlData, (oracleData) -> oracleData.'id', (mysqlData) -> mysqlData.'id') default []          
fun transformFunction(data): Array =
	{	
		id: data."l"."id",
		depositdate: data."l"."depositdate",
		transferamount: data."r"."transferamount",
		accountname: data."r"."accountname",
		clntNameKana: data."l"."clntNameKana"
	}
---
result map ((item, index) -> transformFunction(item))

```
上記のDataWeave記述の説明です。
mysqlData変数にmysqlデータベースからの取得結果となるjson、oracleData変数にoracleデータベースからの取得結果となるjsonが格納されています。

Dataweaveのjoin関数を使ってoracleDataとmysqlDataをid項目で結合します。<a href="https://docs.mulesoft.com/dataweave/2.4/dw-arrays-functions-join">join</a>を使うと二つのjsonを、指定の同じ項目で内部結合することができます。join すると以下のネストされたjsonがresult変数に格納されます。
```
[
  {
    "l": {
      "id": "456",
      "depositdate": "2023/4/1",
      "clntNameKana": "鈴木太郎"
    },
    "r": {
      "id": "456",
      "transferamount": "10000",
      "accountname": "89998"
    }
  },
  {
    "l": {
      "id": "457",
      "depositdate": "2023/4/2",
      "clntNameKana": "佐藤太郎"
    },
    "r": {
      "id": "457",
      "transferamount": "20000",
      "accountname": "90000"
    }
  }
]
```
result変数はネストされたjsonになっているため、こちらをtransformFunction関数を定義し一つのjsonにします。駆動jsonとなる"l"からはidを取得し、結合されたjsonとなる"r"からはaccountnameを取得して一つのマップ(json)を定義しています。transformFunction関数にresult変数のjsonを渡すと以下のように一つのjsonが返されます。

```
[
  {
    "id": "456",
    "depositdate": "2023/4/1",
    "transferamount": "10000",
    "accountname": "89998",
    "clntNameKana": "鈴木太郎"
  },
  {
    "id": "457",
    "depositdate": "2023/4/2",
    "transferamount": "20000",
    "accountname": "90000",
    "clntNameKana": "佐藤太郎"
  }
]
```

簡単にDataWeaveを実行しシミュレーションしたい場合　https://dataweave.mulesoft.com/learn/dataweave　
が便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259482/1ea7d5b9-aa71-4afb-953e-ad23f9629561.png)
Linuc　第三回　コンテナ

# コンテナ
### コンテナとは
アプリケーションを仮想的環境ごと独立させて管理するもの。
コンテナエンジンというソフトを用いて、コンテナの作成や管理をする。
仮想マシンとは違い、OS（カーネル）やハードウェアの基本設定は共有する。
[cgroups]というシステムがコンテナごとのリソースを管理する
[namespace]というシステムがコンテナごとのユーザー権限を管理する

### コンテナのメリット

それぞれのコンテナはお互い独立していて干渉しない、複製が簡単に行える。
アプリケーションに必要な環境ごとコンテナを複製できる。
別のPCにコンテナを移しても安定的。

### コンテナの操作
#### docker
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3293109/6d56cec3-943d-73b4-a345-e3d98d9e938c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3293109/5649b9c9-d354-facd-fd05-35233ebdb2ac.png)
##### コマンド
systemstl start docker   　dockerサービスを起動
systemstl　status docker 　dockerが起動していることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3293109/a951723a-511c-c099-805e-1aea03206538.png)
docker pull debian(debianイメージをダウンロード)
docker images(イメージ一覧確認)
cat /etc/debian_version (Debian環境に存在するバージョンファイル確認)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3293109/dc0ccec6-4665-2745-0321-d8277d13bdd3.png)
docker run -it --name debian debian bash
　→Debianイメージを元にコンテナを起動。さらにコンテナ上でbashを起動して端末に接続
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3293109/8861f1fe-d20d-4a53-1a50-96ff90738744.png)

docker ps 　　　コンテナ一覧表示
docker ps a　　停止中のコンテナも表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3293109/6d8ade4e-d5e3-ba2a-f93c-cc9cef60d258.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3293109/22f5a52d-f2f1-da3d-0c92-8233b3758470.png)

docker run -it --name debian debian bash
docker run -it --name debian debian 
docker run -it --name debian debian /bin/bash
これら3つのDockerコマンドは、すべて "debian"という名前のコンテナを起動し、対話型モードでbashコマンドまたはデフォルトの起動コマンドを実行します。微妙な違いは、コンテナに渡されるコマンドの形式にあります。

docker run -it --name debian debian bash: このコマンドは、コンテナの起動コマンドとして "bash" コマンドを使用します。つまり、コンテナが起動されると、bashターミナルがすぐに実行され、対話的なシェルがターミナル内で提供されます。

docker run -it --name debian debian: このコマンドは、コンテナの起動コマンドを指定していないため、Dockerはデフォルトの起動コマンドを使用します。"debian"イメージのデフォルトのコマンドは "/bin/bash"です。したがって、このコマンドは実際には最初のコマンドと同じです。

docker run -it --name debian debian /bin/bash: このコマンドは、コンテナの起動コマンドとして "/bin/bash"コマンドを使用します。これは、最初のコマンドと同じですが、実行するコマンドのパスを明示的に指定している点が異なります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3293109/64b7dfdb-0e7a-21db-3862-893afb8e6bef.png)

一度作ったコンテナを実行したいときは、コンテナIDを実行すればいい。
docker start ID
【Django】テンプレート内のfor文で困ったので調べたら簡単に解決した話

## 困ったので調べてみた。

忘れないうちに。鉄は熱いうちに打て。

djangoのテンプレート内で、
もし1回目だけ結果を出力したい！
となった場合

```HTML
{% for review in reviews %}
    {% if forloop.first %}
    <p>{{ review.review }}</p>
    {% endif %}
{% endfor %}
```

最後だけ出力したい(一番直近のデータだけ)場合　　
```HTML
{% for review in reviews %}
    {% if forloop.last %}
    <p>{{ review.review }}</p>
    {% endif %}
{% endfor %}
```




参考


https://office54.net/python/django/template-for-loop




ちなみにChatAPI先生に聞いたところ
```HAML
{% load humanize %}
```
を追加しろと言われました。。

![スクリーンショット 2023-04-01 015203.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2854762/36230fbc-f56c-4a60-6f80-5ef17faafb96.png)

幸せならOKです！を思い出しました。

読んでいただきありがとうございました！
社会人になってから振り返るIT系専門学校の良かったこと悪かったこと


# この記事を書こうと思ったキッカケ
知り合いは皆大学に進学してるのに自分だけ専門学校に行っている状況に、漠然と不安を抱いていた。
社会人になり転職も経験してみると、気にするほどのものではないと感じた。
考えをまとめるついでに悩めるIT専門学生にエールを送りたい。

# 要約
専門学生がんばえ〜


# 略歴
- 普通科高校卒業
- IT系の専門学校にゲーム系専攻で入学
- 2年生からIT系専攻にコース変更
- 計4年間専門学校に在籍し卒業
- 新卒でSESの会社に入社
- 転職して別のSESしてる会社に入社

# 専門学校に入学してよかったこと
1. 資格を取れた
行っていた学校は資格取得支援制度が充実していたので、在学中に基本情報技術者試験と応用情報技術者試験などに合格することができました。
これらの資格のおかげか就活・転職は凄く楽でした。
あと、副産物で自主的に勉強する癖がついた。

2. IT業界に関するアレコレを知れた
これは直接的な学校(授業)のおかげではなく、学校に集まった同級生や講師のおかげでした。
フリーランスの講師や情報系高校卒の友人などのおかげで、ただ社会人をしてるだけでも学べなかった知識を学べていました。

3. 就職できた
専門学校は就職率ほぼ100%と掲げているだけあって就活のサポートは手厚かったです。
学校が案内してくれる求人は周囲の声を聞いても内定率が高かったと思います。
(ただし私は学校に来ている求人に就職した結果、薄給賞与無し残業当たり前の会社に当たってしまったので、もしかすると人手不足のブラック会社に無理やり就職させていたりするのかも知れませんね。)

4. その他良かったこと
- 大学と比べ学費が安い
- 自分と似た属性(オタク)が多数派だったので人間関係で拗れることがなかった

# 悪かったこと
1. やる気がない人が多すぎる
大学に行けるほどの学もないが、就職もしたくないので受験勉強をせずに行ける進学先としてIT系専門学生にくる人が多かった印象です。
4年間授業を受けているにも関わらず、ほとんどプログラミングができない人は普通にいました。
やる気ない他人がいる分には特に問題にならないのですが、チーム開発になると無限に足を引っ張られてまともな開発が出来なくなります。私はこの事が原因でゲーム専攻を止めてIT専攻に変更せざるをえませんでした。

２．華々しい学生生活は送れない
イメチェンして専門学生デビューをしても残念ながら華々しいイケイケなデビュー先はありません。もちろんオタクデビューなら可能です。



# 最後に
専門学生はFラン大学生よりは就職率が高いと思います。もしブラック企業に当たっても、転職すればどうとでも出来ると思います。
ですので、あまり将来を不安に思うことなく専門学生生活がんばってください！

まず専門学生でこんな記事を見つけるくらいQiitaを漁っているレベルのあなたなら何も心配することはないでしょう。


初めて記事を書いたので問題があったらコメントしてほしいです
対処法 : Could not resolve dependencies for project *: The following artifacts could not be resolved: com.google.guava:guava:bundle:31.1-jre

# 状況
Mavenを使用した開発をVSCodeで行っていた。VSCodeの拡張機能 Maven for Java を使って"Guava"を依存先として追加したところ、`pom.xml`に以下のように追記された。

```xml:pom.xml
    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>31.1-jre</version>
      <type>bundle</type>
    </dependency>
```

すると以下のようなエラーが発生した。
```
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.093 s
[INFO] Finished at: 2023-04-01T00:31:50+09:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal on project demo: Could not resolve dependencies for project [プロジェクト名]: The following artifacts could not be resolved: com.google.guava:guava:bundle:31.1-jre (absent): com.google.guava:guava:bundle:31.1-jre was not found in https://repo.maven.apache.org/maven2 during a previous attempt. This failure was cached in the local repository and resolution is not reattempted until the update interval of central has elapsed or updates are forced -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException
```

# 解決策
`<type>`タグを取る。
```diff_xml:pom.xml
    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>31.1-jre</version>
-      <type>bundle</type>
    </dependency>
```
これだけで動くようになった。

`<type>bundle</type>`という記述が何を意味しているのか調べてみたが、ネット上には[これくらい](https://stackoverflow.com/questions/5389691/what-is-the-meaning-of-type-bundle-in-a-maven-dependency)の記述しかなかった。この記事によると、この記述があると`.jar`ファイルにまとめてバンドルできるとか何とか。でも[ドキュメント](https://maven.apache.org/ref/3.9.1/maven-core/artifact-handlers.html)を見ても`bundle`というタイプはなさそう。何だったのだろうか。

拡張機能を盲信してはならぬ。
【まとめ】Power AutomateでのDataverseのリレーションシップの使い方


DataverseのリレーションをPower Automateで扱う方法をまとめた記事をこちらでご紹介します。
Dataverseのリレーションは少しクセがあるので、つまづきポイントになりやすいです。
こちらで勉強して、マスターになりましょう！

# Power Automateでのリレーションシップの使い方【前編】
こちらの記事では以下のアクションでリレーションを扱う方法についてまとめています。
- [IDで行を取得する](https://qiita.com/skuramoto/items/a4f0c4441f76972a0e98#id%E3%81%A7%E8%A1%8C%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B)
- [行を関連付ける](https://qiita.com/skuramoto/items/a4f0c4441f76972a0e98#%E8%A1%8C%E3%82%92%E9%96%A2%E9%80%A3%E4%BB%98%E3%81%91%E3%82%8B)
- [行の関連付けを解除する](https://qiita.com/skuramoto/items/a4f0c4441f76972a0e98#%E8%A1%8C%E3%81%AE%E9%96%A2%E9%80%A3%E4%BB%98%E3%81%91%E3%82%92%E8%A7%A3%E9%99%A4%E3%81%99%E3%82%8B)

https://qiita.com/skuramoto/items/a4f0c4441f76972a0e98

# Power Automateでのリレーションシップの使い方【後編】
こちらの記事では主にOdataクエリやFetchXMLを使用した処理での、関連レコードの扱いについてまとめています。
より高度な処理をします。

- [検索列への値の挿入](https://qiita.com/skuramoto/items/11f1111a8eba7673714c#%E6%A4%9C%E7%B4%A2%E5%88%97%E3%81%B8%E3%81%AE%E5%80%A4%E3%81%AE%E6%8C%BF%E5%85%A5)
- [行のフィルター](https://qiita.com/skuramoto/items/11f1111a8eba7673714c#%E8%A1%8C%E3%81%AE%E3%83%95%E3%82%A3%E3%83%AB%E3%82%BF%E3%83%BC)
- [クエリの展開](https://qiita.com/skuramoto/items/11f1111a8eba7673714c#%E3%82%AF%E3%82%A8%E3%83%AA%E3%81%AE%E5%B1%95%E9%96%8B)
- [FetchXML](https://qiita.com/skuramoto/items/11f1111a8eba7673714c#fetchxml)

https://qiita.com/skuramoto/items/11f1111a8eba7673714c

# 【参考】Dataverseのトリガーとアクション
### トリガー一覧
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/b4516264-ee06-b22e-7c79-8b1190002743.png" width=70%>

### アクション一覧
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/48eb6452-338d-db64-ef68-f65eceb5323c.png" width=40%>
Springの基礎知識

## Spring Framework 
__概要__
・springプロジェクトが提供する様々なライブラリやフレームワークを手っ取り早く使用ができるオープンソースのフレームワーク
・Java エンタープライズアプリケーションを簡単に作成が出来る

__Spring Framework歴史__
| バージョン| リリース年 |主なリリース   |
|:-----------------|------------------:|:------------------:|
| 1.0 |2004 | 
| 2.0 |2006 | Spring Security、Spring Web Flow
| 2.5 |2007 | Spring MVC、Spring Integration、Spring Batch、アノテーションベースDI 
| 3.0 |2009 | Javaコンフィグ、JPA2.0、Bean Validation 
| 4.0 |2013 | WebSocket、Webメッセージングのサポート、Java SE8、JavaEE7対応	 
| 5.0 |2017 | WebFlux(リアクティブWeb)、Kotlinサポート 
| 6.0 |2022 | Java 17およびJakarta EE 9対応	


## Spring boot
__概要__
・先に挙げた「Spring Frameworkの機能の使い分けが困難」という欠点を解消するために作られたフレームワーク
・Javaプラットフォーム向けのアプリケーションフレームワークであるSpring FrameworkをWebアプリケーション開発向けに特化させたもの

__Spring FrameworkとSpring bootの違いとは__
●Spring Framework：Java言語のアプリケーション開発のために作られたフレームワークの集合体
●Spring boot：Spring Frameworkの機能を使いやすくするためのフレームワーク

__「Sprig Framework」の全体像__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609668/4b0124c7-bfbd-2636-ff25-e1707ba3459a.png)

●Spring Boot
 Springアプリケーションを煩雑な設定をせず迅速に作成する機能を提供
●Spring プロジェクト
├・Spring MVC 　Webアプリケーションを簡単に作成する機能を提供
├・Spring Data  データアクセスに対する機能を提供
├・Spring Batch　バッチ処理を提供
└・Spring Security　認証/許可を提供
●Spring　コア
├・Spring DI　依存性注入の機能を提供
└・Spirng AOP　アスペクト指向プログラミングの機能を提供

# Springのプロジェクト作成
作成されたプロジェクトのフォルダの中には「src」フォルダと「pom.xml」というファイルが作成されている

```:「src」フォルダ
　├「main」フォルダ-プログラムで使用するファイル類がまとめられている
　└「test」フォルダ-プログラムで使うユニットテストのソースコードがまとめられている
```
```:「pom.xml」
<groupId>　――グループID
<artifactId>　――アーティファクトID
<version>　――バージョンを示すテキスト
<packaging>　――パッケージの種類
<name>　――プロジェクト名
<url>　――URL

<properties>　――各種のプロパティが記述される
　　　　　　　　 プロジェクトのデフォルトエンコーディングを指定するもの
<dependencies>　――この中に<dependency>というタグを使って、必要なライブラリの情報を記述
```


### 引用
【WebSocket API】
https://developer.mozilla.org/ja/docs/Web/API/WebSocket/close
https://kanda-it-school-kensyu.com/java-spring-contents/sb_ch02/sb_0203/
ChatGPTには英語で喋ってもらった方がいい。

### はじめに
文字通りタイトル通りです。
別にエイプリルフールネタでもないです。
ChatGPTくんは、英語のほうが饒舌ですし何より出力がはやい。
下手すると翻訳サイト使ってでも、英語で出力してもらったほうがいいレベルです。

### やりかた
方法論は色々あるのでしょうが
シンプルに以下のプロンプトでいけました。
```
あなたに変わったお願いをします。
私は常に日本語で会話します。
あなたは常に英語で発言します。
可能ですか？
Can you understand my instructions？
```

>回答:
>Yes, I understand your instructions. You will speak in Japanese, and I will reply in English. If you have any questions or concerns, please feel free to ask.

こころよく聞き入れてくれました。

結構個人的に読みやすかったので
日本語訛りで出力してるか聞いたら
そうかも？ぐらいの回答でした。

>ChatGPT:
>My primary goal is to provide clear and understandable responses to users, regardless of their language or cultural background. While I am not intentionally producing "Japanese-accented English," my responses may be influenced by the language and phrasing used in your questions. If you find that my responses are reminiscent of Japanese-accented English, it could be because I am trying to communicate with you effectively based on the linguistic patterns present in your questions. If you have any preferences or suggestions for how I should communicate, please let me know, and I will do my best to accommodate your needs.

Google翻訳:
>私の主な目標は、ユーザーの言語や文化的背景に関係なく、ユーザーに明確でわかりやすい応答を提供することです。 意図的に「日本語アクセントの英語」を作成しているわけではありませんが、私の回答は、質問で使用されている言語や言い回しに影響される場合があります。 私の回答が日本語訛りの英語に似ていると思われる場合は、質問に含まれる言語パターンに基づいて効果的にコミュニケーションを取ろうとしている可能性があります。 コミュニケーション方法についてご希望やご提案がございましたら、お知らせください。お客様のニーズに対応できるよう最善を尽くします。

### おわりに
少なくとも、出力はすごく早くなるのでオススメです。
賢くなってるかはよくわかりません。
基本的な思考回路は変わってない気がします。
でもすごく早くなります。
chatGPTをjyupiter notebookでお手軽にお試ししてみた

# はじめに
2022年11月に公開されたOpen AIのChatGPT3.5を体験するために、Jupiter notebookを利用してお手軽にチャットボットアプリのサンプルを作成してみました。

## 1.環境
windows 11 home 64bit
Jupiter notebook - python
(Google Colaboratory)
＋[chat GPT](https://chat.openai.com/)


## 2.結果
コード
~~~
import openai
openai.api_key = "YOUR_API_KEY_HERE"

# GPT-3エンジンに接続する
model_engine = "text-davinci-002"
prompt = "こんにちは、私はチャットボットです。あなたのお名前は何ですか？"

# GPT-3での応答を取得する関数
def generate_response(prompt):
    response = openai.Completion.create(
        engine=model_engine,
        prompt=prompt,
        max_tokens=1024,
        n=1,
        stop=None,
        temperature=0.7,
    )

    message = response.choices[0].text
    return message.strip()

# ユーザー入力を受け取る関数
def get_input():
    user_input = input("あなた： ")
    return user_input

# メイン関数
def main():
    user_input = ""
    while user_input != "終了":
        user_input = get_input()
        prompt = f"あなた： {user_input}\nチャットボット："
        response = generate_response(prompt)
        print(f"チャットボット：{response}")

if __name__ == "__main__":
~~~

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411736/44feb2fe-747f-3685-5b5c-6f10c6fcca6b.png)


１．chatGPTに「GPT3を利用したチャットボットの作り方を教えてください」と入力します。
２．OpenAPIのAPIキーを利用した上記のサンプルコードが返ってきます。
　　※関数化されていない回答が返ってきた時は「関数化してください」とリクエストすると関数化もしてくれます。
３．Open AIサイトからAPIキーを取得して"openai.api_key"にキーを入れればチャットボットの挙動が確認できます。
[Open AI API key](https://platform.openai.com/account/api-keys)

# 3.所感
本当に日本語（自然言語）の理解度＆回答精度が桁違いでした。
回答は最適な回答を推測して回答しているだけなので、毎回微妙に違った言葉選びだったりコードだったりします。
一方、利用シーンによると思いますが、回答が返った時の情報を鵜呑みせず、これが正しい（だろう）と判断できる知見も併せ持っておく必要があると感じました。
また、モデルによって特性が異なるようなので、目的にあったものに変更してみるとよさそうです。

いずれにせよ、すごい。。


## 引用
https://note.com/npaka/n/nef372ec2e33a#bde2d2d8-4eef-4e83-b416-276af7f6280f
Storybookのtest-storybook実行の際のアクセシビリティテストの無効化

## 概要
一部のコンポーネントである特定のルールを無効化したいケースが発生した。無効にする方法については、以下のページにルールの設定方法が載っており、設定することでプレビューではエラーが出なくなった。
https://storybook.js.org/docs/react/writing-tests/accessibility-testing

```javascript
export const Primary = Template.bind({})
Primary.args = {
  children: 'Primary Button',
}
Primary.parameters = {
  a11y: {
    config: {
      rules: [{ id: 'color-contrast', enabled: false }],
    },
  },
}

```

ただ、　test-storybookの実行では、無効化したはずのルールがチェックされてしまいエラーになってしまった。上記のページでは特に言及がされておらず、調べていたところ以下のGitHubイシューのコメントが見つかった。
https://github.com/storybookjs/storybook/issues/19896#issuecomment-1320771727

このコメントから辿っていったところ以下のページで、test-runnerのほうで設定を見て処理する必要があることがわかった。
https://github.com/storybookjs/test-runner#utility-functions

## 対応方法
以下の通り、preRenderで、ストーリの方の設定を見て、チェックをするかしないかなどを制御すれば、設定が反映される。

```javascript
// .storybook/test-runner.js
const { injectAxe, checkA11y, configureAxe } = require('axe-playwright')
const { getStoryContext } = require('@storybook/test-runner')

module.exports = {
  async preRender(page, context) {
    await injectAxe(page)
  },
  async postRender(page, context) {
    const storyContext = await getStoryContext(page, context)
    if (storyContext.parameters?.a11y?.disable) {
      return
    }

    await configureAxe(page, {
      rules: storyContext.parameters?.a11y?.config?.rules,
    })

    await checkA11y(page, '#root', {
      detailedReport: true,
      detailedReportOptions: {
        html: true,
      },
      axeOptions: storyContext.parameters?.a11y?.options,
    })
  },
}
```
ArduBlock のソースを日本語デコード済みにする(UTF-8 エスケープシーケンスのデコード)

Arduino のブロックプログラム環境である Ardublock。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/70cc94c6-c778-9bde-7a96-6148dfaa9bf6.png)

ArduBlock は各国語に対応しているが、それの記述は 
`src/main/resources/com/ardublock/block`
にある。


```
$ ls
LCD16by2.png             ardublock_de.properties     ardublock_pl.properties     arduino                   linksprite
LCD20by4.png             ardublock_el.properties     ardublock_pt_BR.properties  block-mapping.properties  littlebits
SG90.png                 ardublock_es_ES.properties  ardublock_pt_PT.properties  bulk                      makeblock
Skins                    ardublock_fi.properties     ardublock_ro.properties     dfrobot                   motor.jpg
adafruit                 ardublock_fr.properties     ardublock_ru.properties     esplora                   network
ardublock.properties     ardublock_he.properties     ardublock_sr.properties     i18n.rb                   save_format.dtd
ardublock.xml            ardublock_hu.properties     ardublock_sv_SE.properties  i18n.sh                   seeedstudio
ardublock_af.properties  ardublock_it.properties     ardublock_tr.properties     jerusalab                 trash.png
ardublock_ar.properties  ardublock_ja.properties     ardublock_uk.properties     keenlon                   trash_open.png
ardublock_ca.properties  ardublock_ko.properties     ardublock_vi.properties     keyboard.png              ultrasonic.jpg
ardublock_cs.properties  ardublock_nl.properties     ardublock_zh_CN.properties  keypad_12_button.png      ultrasonic.png
ardublock_da.properties  ardublock_no.properties     ardublock_zh_TW.properties  lang_def.dtd              workshop
```

`ardublock_ja.properties` が日本語用のファイルなのだが
```
$ head ardublock_ja.properties 
#X-Generator: crowdin.com
bc.start=\u30b9\u30bf\u30fc\u30c8
bc.end=\u30b9\u30c8\u30c3\u30d7
bg.constrain=\u5236\u9650
bc.low=\u304b\u3089
bc.high=\u307e\u3067
bg.sd_write2=SD\u30ab\u30fc\u30c9\u3078\u306e\u66f8\u304d\u8fbc\u3080
bg.sd_write=SD \u30d5\u30e9\u30c3\u30b7\u30e5\u66f8\u304d\u8fbc\u307f
bg.sd_return=\u623b\u308b
bd.storage=\u30b9\u30c8\u30ec\u30fc\u30b8
```

このようにエスケープシーケンスになっているのでたいへん編集しづらい。
以前は UTF-8 で日本語を記述するとエラーになったようだが、今だと問題ないようなのでファイルをデコードして扱うことにした。

# 環境

- Ubuntu 22.04
- openjdk 11.0.17 2022-10-18

「Ardublock を Docker でビルドする」
https://qiita.com/nanbuwks/items/1a576859987e463264c3
で構築した環境上で行った。

# 準備

```
$ sudo apt install nkf
```

# 作業

「コマンドライン上でのunicode escape sequenceのデコード | IR.0-4の日記 | スラド」
https://srad.jp/~IR.0-4/journal/575464/

を参考にして、

```
$ FILE=ardublock_ja.properties ; cp $FILE $FILE.back ; cat $FILE.back  | sed -e 's/\\u\(....\)/\&#x\1;/g' | nkf --numchar-input | head

```
とすると
```
#X-Generator: crowdin.com
bc.start=スタート
bc.end=ストップ
bg.constrain=制限
bc.low=から
bc.high=まで
bg.sd_write2=SDカードへの書き込む
bg.sd_write=SD フラッシュ書き込み
bg.sd_return=戻る
bd.storage=ストレージ
```

となって良さそうだったので、
```
$ FILE=ardublock_ja.properties ; cp $FILE $FILE.back ; cat $FILE.back  | sed -e 's/\\u\(....\)/\&#x\1;/g' | nkf --numchar-input > $FILE
```

とします。動かしてみて問題なければ`ardublock_ja.properties.back` は削除します。
【5分で設定完了】OpenSearchを取りあえず触ってみる手順（1.環境構築編）

# はじめに
OpenSearchを、難しいことは置いといて、取りあえず触ってみたい人向けの手順メモ。
基本的には、[Amazon OpenSearch Service の開始方法](https://docs.aws.amazon.com/ja_jp/opensearch-service/latest/developerguide/gsg.html)に沿って進めます。

今回構築する環境は、触ってみる事が目的なので最小構成で作成します。
それでも、社内のちょっとした台帳検索サービスみたいな用途に使うには問題ないかと思います。ただ、本気のログ分析とかで使うとキツイかもしれません。

また、今回は最小構成と言えど、**1ヶ月動かし続ければ普通に5000円以上費用がかかる**ので、試した後は環境を削除しましょう。

# ドメイン作成の手順

ドメインは、RDBで言うところのデータベースのようなものです。

Amazon OpenSearch Service のトップページで、「マネージド型クラスター」を選択して、[ドメインの作成]ボタンをクリックします。

![スクリーンショット 2023-03-31 15.17.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/a6a1e56d-2ddb-572a-87ab-146df811833c.png)

ドメイン作成画面が表示されます。
今回は、まずは触れる環境を作る事が目的なので、最低限の簡易的な設定で進めます。
基本的にはデフォルト値のままで、変更する部分のみを以降に記載します。

### 名前
任意のドメイン名を入力します。
![スクリーンショット 2023-03-31 15.21.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/778e1b59-9755-4357-7b6e-900bf92d271f.png)

### デプロイタイプ
デプロイタイプは、「開発およびテスト」を選択します。
![スクリーンショット 2023-03-31 15.21.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/e21d655d-333a-ceea-6b9e-0881be0f6f9c.png)

### データノード
アベイラビリティーゾーンは最小の「1-AZ」を選択します。
インスタンスタイプは一番下にある「t3.small.search」を選択します。
ノードの数は最小の「1」を選択します。
![スクリーンショット 2023-03-31 15.22.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/c0c15564-8954-032c-705b-08ebd1a7dd33.png)

### ネットワーク
作成する環境へのアクセスを楽にするため、ネットワークは「パブリックアクセス」を選択します。
![スクリーンショット 2023-03-31 23.29.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/089fb914-4cef-1b25-1b32-9b0e7b29d109.png)

### きめ細かなアクセスコントロール
「マスターユーザーの作成」を選択して、併せて「マスターユーザー名」と「マスターパスワード」を設定します。
このユーザー名とパスワードで、ダッシュボードにログインしたり、OpenSearchのAPIを利用する時のBasic認証で使用したりします。
![スクリーンショット 2023-03-31 23.30.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/1f2c22c5-b35e-54bf-2cdf-47a541a3eb60.png)


### アクセスポリシー

ドメインアクセスポリシーで、「きめ細かなアクセスコントロールのみを使用」を設定します。
![スクリーンショット 2023-03-31 23.31.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/af7f996c-a645-a0e4-bdd0-fc677706e47f.png)

設定は以上です。
画面の右下にある[作成]ボタンをクリックして、環境構築を開始します。

# 環境構築処理

[作成]ボタンをクリックして、以下の画面が表示された後、構築完了まで10数分かかります。
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f33383039392f31663631353436612d343166652d623635352d633436622d3738336365393030626162322e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/cfeefc9a-6eda-408e-61a5-fddef92ec461.png)


以下の画面に変わったら、構築完了です。
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f33383039392f38333832323863362d363661632d643161652d626366352d3938643462636464396238622e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/43688ea4-b5a3-6506-e854-0373cc170edd.png)
非MLエンジニアがAWS資格の AWS MLSに合格した話

# はじめに
非ML（機械学習）エンジニアである私が、AWS Certified Machine Learning - Specialty(MLS)に合格したので、その合格記として書いていきたいと思います。

# 生い立ち
私は、エンジニア歴6年目で、AWS資格の12個目として本資格に挑戦をしました。(アルゴリズムなどは勉強したことが無い状態で臨みました。)
本試験は、DASを受けた後であれば比較的簡単だという記事をうのみにし、試験に臨んだ結果、1回目は無様な敗北をいたしました。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252895/fc7d803d-57b2-822c-e5cd-d85c413049ce.png)


2度目にして、793点で無事合格でできました。
その際に実際に勉強した方法などを本記事では書いていきたいと思います。

![スコア1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252895/ab2f1c6a-f128-06d6-f97e-97d63485c798.png)




# 勉強しててよかったと感じた箇所

**前提条件**

まず大前提となるのが、DASを受験し、AWSの分析サービスを基礎が身についていることが理想です。
AWS Gule、EBR、Kinessis、Redshiftの問題は多く出るので、ここの知識の基礎が前提となります。
次項以降は、どのようにアルゴリズムを勉強していったのかについて書いていきます。

**実際におこなった勉強方法①**

下記の動画で、様々なアルゴリズムの基礎的な知識を学習しました。
「教師あり学習、教師無し学習」「欠損値の対応方針」「分析手法のベストプラクティス」「過学習における対応方針」など

https://www.youtube.com/playlist?list=PLwSThH9xkGeqsjNpaptdP98-ttFPTWabq

**実際におこなった勉強方法②**

下記の問題集をひたすら解く。

https://techstock.jp/

**実際におこなった勉強方法③**

AmazonのKindleの無料問題集を解く。
※ここの試験問題集は、無料なのですが、ほんと優秀なのでおすすめです。

https://amzn.asia/d/3mYpQBE

**実際におこなった勉強方法④**

ChatGPT先生に教えを乞う。
問題文を解くだけでは本質が分からないので、ChatGPT先生に教えていただきました。
下記が実際に教えていただいた際の内容です。
こういう風に丁寧に教えてくれるので、これから勉強する方はぜひ活用いただきたい一品です。

![混合行列.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252895/50e8dc1e-4a57-e8d7-1368-74ca5deedf2b.png)

![混合行列_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252895/197f6742-b4c8-a821-b504-2d9af0d06207.jpeg)

![混合行列_2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252895/9e7c5606-aff0-8f7c-9e96-5e23e2c0e676.png)


# 最後に
MLSは、対策をしっかりして無いと確実に落ちる資格なので、入念に勉強することをおすすめします。
欠損値の対処法、適切な分類方法、適切なアルゴリズムを選択できるか、などが試験では重要視されているので、ポイントはしっかりと抑えてから、試験に臨みましょう。
以上です。
ポンコツエンジニアが、AWS資格最難関のAWS ANS-C01に合格した話

# はじめに
自他共にポンコツエンジニアであると認めている私が、先日、AWSで最も難易度が高いと言われる資格「**AWS Certified Advanced Networking - Specialty 認定**」に合格したので、勉強した際の実施内容について記載していこうと思います。
※本記載内容は、私がこの内容で勉強したら、合格したというものであって、必ず合格することを保証するものではありません。

ちなみに点数は、下記です。
ピッタリ賞があったら、受賞ができてしまいますね(笑)
![スコアボード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252895/f7d1be6b-55b0-f70e-6b23-75059fa89968.png)


# AWS Certified Advanced Networking - Specialty(ANS-C01) 認定とは

**本資格**
AWS Certified Advanced Networking - Specialty は、複雑なネットワークタスクを実行し、ネットワークソリューションのアーキテクチャの設計と実装に 5 年間の実践的な経験がある個人を対象としています。
※AWS公式ドキュメントを抜粋

要約すると、めっちゃ難易度の高い資格です。
ものすごく難易度が高い資格なので、1度目の試験で、1発で合格できるかたは非常に少ないです。
現に私も、初めの1回目は見事に敗北でした。敗北した際の記録は下記となります。

https://qiita.com/yes_dog/items/b35d6ddf8f26a0018686

では、そんな私が、何故AWSの最難関の資格に太刀打ちできたのかを、次項以降で記載していきたいと思います。

# 勉強方法

**①hands-onの実施**

はずは、手を動かさないと始まらないです。
本試験で、特に理解しなきゃいけないAWSサービス「**AWS Network Firewall**」を実際に触ってみるところから私は始めました。
実際に手を動かす時に参考にしたものは、下記です。

https://networkfirewall.workshop.aws/

これで実際に触っていたおかげで解けた問題もあるので、実際に触ってから試験に臨むことをお勧めいたします。

**②AWS Black Belt**
ANS-C01で出るAWSサービスをAWS Black Beltの動画をサラッと見る。


**③練習問題をひたすら解く**

あとは、練習問題をひたすら解くだけです。
ただ、AWS ANS-C01は新しい資格なので、日本語に対応したものがほとんどないのが現状です。
その為、英語の練習問題をひたすら解く必要があります。
そこで、私が実際に活用した英語の問題集を下記に記載いたします。
※下記の問題集は、ブラウザをchromeを使用し、Google翻訳のアプリをインストールしておけば、ほぼ日本語で問題を解くことができます。

- whizlabs

https://www.whizlabs.com/aws-advanced-networking-speciality/

- digitalcloud training

※この問題集がほんと優秀で、本試験の問題がそのまんま出てくることがあったので、まじで優秀です。

https://digitalcloud.training/aws-ans-c01-aws-certified-advanced-networking-specialty-exam/


# 最後に

ANS-C01は、生半可な覚悟で受けたら落ちる資格だと思っていた方がいいです。
まじで鬼強い資格なので、それ相応の覚悟をもって受けることをお勧めします。
【Git】git diff の使用方法

## リモートとの差分

```
$ git diff HEAD..リモート名/ブランチ名
```
```
$ git diff リモート名/ブランチ名..HEAD
```

## 直近のコミットの差分

```bash
git diff HEAD^..HEAD
```

## ブランチ間の差分

```bash
git diff ブランチA..ブランチB
```

## コミット間の差分

```bash
git diff 変更前のSHA..変更後のSHA
```

## 特定のファイルの差分
```bash
git diff -- ファイルパス
```
```bash
git diff ブランチA..ブランチB -- 対象のファイルパス
```


## ファイル名のみ出力

```bash
git diff --name-only
```
クレデンシャルのパスワードをPowerShellスクリプトに平文で書かない方法

# スクリプトの例
- 下記スクリプトを例にして説明します。
- Microsoftの各種サービスに接続するスクリプトです。

```powershell: ConnectServices.ps1
param([Parameter(Mandatory = $true)][string]$PWordPlain)

cd (Convert-Path $PSScriptRoot)

$User = "UPN001@contoso.com"
$PWord = ConvertTo-SecureString -String $PWordPlain -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $PWord

Connect-AzureAD -Credential $Credential
Connect-ExchangeOnline -Credential $Credential
Connect-SPOService -Url https://contoso-admin.sharepoint.com -Credential $Credential
Connect-MicrosoftTeams -Credential $Credential
Connect-MsolService -Credential $Credential
```

# 実行例
- 引数を指定せずにps1を実行すると必須の引数 `$PWordPlain` を要求されるので、パスワードを入力します。
- 入力時はパスワードが表示されますが、実行履歴には残りません。
```powershell
PS C:\...> .\ConnectServices.ps1; cls
コマンド パイプライン位置 1 のコマンドレット ConnectServices.ps1
次のパラメーターに値を指定してください:
PWordPlain: 

...

PS C:/...> h
  Id CommandLine
  -- -----------
   1 .\ConnectServices.ps1; cls
```
【PHP】君は max_input_vars を知っているか

# max_input_vars は入力変数の上限

PHP プログラマーの皆さま、 `max_input_vars` をご存知でしょうか。

PHP では、受け取れる入力変数の数に上限があり、それが設定されているのが、
設定変数 `max_input_vars` です。

`max_input_vars` はデフォルトで 1000 に設定されています。
つまり、とくに設定を変えなければ、最大 1,000 個のパラメーターしか受け取れないということです。パラメーターを配列にしたとしても、配列の個数もカウントされます。

https://www.php.net/manual/ja/info.configuration.php#ini.max-input-vars

上記 PHP のマニュアルから `max_input_vars` についての説明を引用します。

> 入力変数 を最大で何個まで受け付けるかを指定します (この制限は、スーパーグローバル `$_GET`　、 `$_POST` そして `$_COOKIE` にそれぞれ個別に適用されます)。 
> このディレクティブを使うと、ハッシュの衝突を悪用したサービス不能攻撃を受ける可能性を軽減できます。

なるほど、セキュリティのためにパラメーターの数を制限しているんですね。
ハッシュの衝突を悪用した攻撃については以下の記事が詳しいです。

https://scan.netsecurity.ne.jp/article/2012/01/18/28135.html

# 上限値を超えてもプログラムは止まらない

さきのマニュアルには、パラメーターの数が設定値を超えた場合の挙動についても説明されています。

> このディレクティブで設定した数を超える入力変数があった場合は `E_WARNING` が発生し、 それ以降の入力変数はリクエストから削除されます。

ということで、パラメーター数が上限を超えたとしても、プログラムが止まるわけではないんです。
Warning に気づかなければ、そのまま実行されるけど後ろの方のパラメーターは処理されない、というハンパな状況も起こり得ます。ご注意ください。

なお、具体的な Warning のメッセージは以下のような感じです。

```
PHP Warning:  Unknown: Input variables exceeded 1000. To increase the limit change max_input_vars in php.ini. in Unknown on line 0, referer:
```

# 設定できる場所

マニュアルを見ると、 `max_input_vars` の変更可能モードは `PHP_INI_PERDIR` となっています。 これは、 `php.ini` や `.htaccess` 、 `httpd.conf` などの設定ファイルで設定可能で、 `ini_set()` 関数を使ってプログラム中で上限を増やすことはできないということです。
まあ、プログラムに入ってくる変数の制限値なので、入ってきたあとのプログラムで設定変更できないのは当たり前といえば当たり前です。

具体的な設定方法ですが、 php.ini では以下のように、

```
max_input_vars = 2000
```

Apache の httpd.conf や .htaccess では以下のように設定してください。

```
php_value max_input_vars 2000
```

# 回避方法とか

max_input_vars の値を変えずに上限値を回避する方法ですが、以下のように入力変数の数を構造的に減らすような策が考えられます。

* 配列であれば、カンマなどの区切り文字でつないで一つの変数に入れて、プログラム側で [explode](https://www.php.net/manual/ja/function.explode.php) する。
* パラメーターを JSONに加工して、body として受け渡し、プログラム側で [json_decode](https://www.php.net/manual/ja/function.json-decode.php) する。

大量のパラメーターを扱う場合は、入力変数に上限があることに注意してシステムを設計していただければと思います。
ルーティングとHTTPメソッドの設定

# HTTPメソッド

HTTPメソッドには、GET、POST、PATCH、DELETEがあります。
HTTPのリクエスト対象をリソースと呼ぶが、HTTPメソッドはそのリソースに対する操作の種類を表す名前です。

#### ルーティングとHTTPメソッドの対応表

| HTTP   | 操作 |      path       | コントローラ#アクション名 | 目的                                |
|:-------|-----|:----------------|:----------------------|:-----------------------------------|
| GET    | 取得 | /photos         | photos#index         | すべての写真の一覧を表示                |
| GET    | 取得 | /photos/new     | photos#new           | 写真を１つ作成するためのHTMLフォームを返す|
| POST   | 追加 | /photos         | photos#create         | 写真を１つ作成する                    |
| GET	 | 取得 | /photos/:id     | photos#show	         | 特定の写真を表示する                   |
| GET	 | 取得 | /photos/:id/edit| photos#edit	         | 写真編集用のHTMLフォームを1つ返す       |
| PATCH  | 更新 | /photos/:id     | photos#update         | 特定の写真を更新する                  |
| DELETE | 削除 | /photos/:id     | photos#destroy        | 特定の写真を削除する                  |

※理由のない限り、基本のアクション名から選ぶ方が良い。
　記述量が減り、ソースコードの意図が明確になるため

## ログイン・ログアウト機能のルーティング実装例
### ルーティング設計
| アクション内容           | HTTP  | URLパス         | コントローラ名   | アクション名 |
|:-----------------------|:------|:---------------|:---------------|:-----------|
| ログインフォームを表示する | GET    | /staff/login   | staff/sessions | new        |
| ログインする             | POST   | /staff/session | staff/sessions | create     |
| ログアウトする           | DELETE | /staff/session | staff/sessions | new        |

### 実装例
```rb:config/routes.rb
Rails.application.routes.draw do
  namespace :staff do
    root "top#index"
    get "login" => "sessions#new", as: :login
    post "session" => "sessions#create", as: :session
    delete "session" => "sessions#destroy"
  end
```

4行目〜5行目の末尾にあるasオプションは、ルーティングに名前を付けるためのものです。
こうしておくと、ERBテンプレートの中で :staff_login や :staffsession といったように
シンボルを用いてURLパスを参照できるようになります。
TypeScriptで配列からユニオン型を生成する

# この記事の目的
配列からユニオン型（共用体型）を生成する方法の一つを紹介します。

そもそもユニオン型の一般的な使い方は、以下のように二つ以上の型が入る可能性がある変数などに用いられます。
```
const exampleFunction = (id: number | string) => {
    console.log(`ID: ${id}`);
}
```
この例では、引数idにはnumber型またはstring型のいづれかの値が入り、コンソールに出力されます。
このように複数の型を許容することができるのがユニオン型です。（anyとは違い、列挙したものに限定することができる）

他にも以下のように、値がない（null）ことが想定される場合にはこのように使用することもできます。
```
const exampleFunc = (id: string | null) => {
    if(!id) {
        console.log("IDはありません")
    } else {
        console.log(`ID: ${id}`)
    }
}
```
この例では、idはnullである可能性もあるため、その場合には「IDがありません」とコンソールに出力しています。

## 本題
では本題に入ります。
例えば、アレルギー（allergies）という変数を定義したときに、その変数には以下の五つの値しか入らないようにしたいとします。
["金属", "卵", "ゴム", "乳", "ハウスダスト"]
それなのに、
```
type UserData = {
    allergies: string;
}
```
のように定義してしまうと、誤った値でも文字列であれば許容してしまいます。
そのため、以下のようにユニオン型にするのが正しいでしょう。
```
type UserData = {
    allergies: "金属"| "卵"| "ゴム"| "乳"| "ハウスダスト";
}
```
しかし、この型を他でも使い回したい場合には、都度定義しなければなりません。それでは変更があった場合に工数が増えてしまうので何とか使いまわせるようにしたい。
そこで今回はこのように解決してみました。
```
export const allergiesArr = ["金属", "卵", "ゴム", "乳", "ハウスダスト"];
export const Allegies = typeof allergiesArr[number];

type UserData = {
    allegies: Allergies;
}
```
これで他の場所でも使用可能になり、保守性が高まったのではないでしょうか？
わざわざ配列から変換している理由としては、他の場所で（例えば画面に描画するときなど）使いたい時に便利だからです！

今回は以上です。
最後まで読んでいただきありがとうございました！
何かこの記事についてのご意見やアドバイスなどがあれば是非コメントください！
ChatGPTにGithub Actions の実行履歴を削除方法を聞いたら存在しない機能を答えてきたが…

# 背景
1. Github Actions のワークフローをテストして何回も実行していた
1. 失敗の実行履歴が溜まってきたので削除したい
1. ブラウザからだと1件ずつで面倒だったので検索したところ Github CLI が使えるらしい
1. 折角なので ChatGPT にも聞いてみた

# ChatGPT(GPT-3.5) に聞いてみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517184/fd8376ae-660f-9300-4ba8-7b2c18f55a09.png)
- それっぽい回答を返してきた
- 実行結果を取得する `gh run list` は存在する機能だが、`gh run delete` が存在しなかった。
    - https://cli.github.com/manual/gh_run

# 思ったこと
- 「正しい結果を返さない!使えない!!」ではなく、機能を提供していない CLI 側がよろしくないのでは?とも考えられる。
- インターネットを凝縮した結果の一般的な回答であれば、仕様や機能を ChatGPT 側に合わせていく必要があるのかもしれない。

# おまけ
GPT-4 だと、より正確な回答でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517184/90fc6385-f0e4-dbc9-54cb-7410c333d421.png)
【MSAL SwiftUI】MSALでのAuthenticator認証を可能にする

[公式チュートリアル](https://learn.microsoft.com/ja-jp/azure/active-directory/develop/tutorial-v2-ios#for-ios-only-configure-url-schemes)に沿って
SwiftUIで作ったiOSアプリにMSALを導入し、
AzureADのユーザー名とパスワードでの認証が可能になったが
`Authenticator`での認証が上手くいかなくてハマった時の備忘録

## Authenticatorでの認証を許可する設定（許可するだけ）
iPhoneに`Microsoft Authenticator`がインストールされていると
ログイン処理時に自動でAuthenticatorを開き認証できるよう
チュートリアルに沿って下記のように```Info.plist```を設定した

``` swift
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>msauth.[BUNDLE_ID]</string>
        </array>
    </dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>msauthv2</string>
    <string>msauthv3</string>
</array>
```

↓この部分がそれに該当する
``` swift
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>msauthv2</string>
    <string>msauthv3</string>
</array>
```
こうするとログイン処理時にAuthenticatorが自動で開きはするが
これだけではあくまでを「**Authenticatorを自動で開くように許可しただけ**」であり
「**Authenticator認証のレスポンス**」を受け取る処理を別で実装する必要がある

## Authenticator認証のレスポンスを受け取る実装

レスポンスを受け取るには、`AppDelegate`と`SceneDelegate`を実装する

``` swift
// AppDelegate.swift
import UIKit

class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        configurationForConnecting connectingSceneSession: UISceneSession,
        options: UIScene.ConnectionOptions
    ) -> UISceneConfiguration {

        let config = UISceneConfiguration(name: nil, sessionRole: connectingSceneSession.role)
        config.delegateClass = SceneDelegate.self
        return config
    }
    
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil
    ) -> Bool {
        sleep(UInt32(1))
        return true
    }
}
```

``` swift
// SceneDelegate.swift
import UIKit
import MSAL

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        guard let urlContext = URLContexts.first else { return }
        
        let url = urlContext.url
        let sourceApp = urlContext.options.sourceApplication
        
        MSALPublicClientApplication.handleMSALResponse( url, sourceApplication: sourceApp)
    }
}
```
そして、SwiftUIで`AppDelegate`を読み込めるように`App.swift`を実装する
``` swift
// HogeApp.swift
import SwiftUI

@main
struct HogeApp: App {
    @UIApplicationDelegateAdaptor (AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView(viewModel: .init())
        }
    }
}
```

`@UIApplicationDelegateAdaptor`は
UIKitのDelegateをSwiftUIで使用するためのプロパティラッパー。
アプリのデリゲートが`@UIApplicationDelegateAdaptor`に準拠している場合
SwiftUIは作成したデリゲートをプロパティ ラッパーを使用して
アプリの任意のSceneまたはViewからデリゲートにアクセス可能になる。
```　swift
@UIApplicationDelegateAdaptor (AppDelegate.self) var appDelegate
```


このように実装することで
デバイスに`Microsoft Authenticator`がインストールされていれば
ログイン処理時に自動でAuthenticatorを開き
そのレスポンスをアプリが受け取り、認証できるようになる



*※ご参考*

https://learn.microsoft.com/ja-jp/azure/active-directory/develop/tutorial-v2-ios

https://developer.apple.com/documentation/swiftui/uiapplicationdelegateadaptor