OmniAICreator/Qiita-1.07M huggingface dataset:
grypeを使ってSBOMに関連する脆弱性情報を調べる

# はじめに

grypeを使ってSBOMに関連する脆弱性をリストアップしてみます。
grypeはコンテナイメージやファイルシステム向けの脆弱性スキャナーです。
https://github.com/anchore/grype
前回に引き続き、例としてCentOS 7のrpmdbを元に生成したSPDX-JSON形式のSBOMに関連する脆弱性情報を調べてみます。

# 環境情報

macOS上にDockerでCentOS 7のコンテナを立ち上げて、その中で作業をします。
今回の環境情報は以下です。

| コンポーネント | バージョン | 備考 |
|:-:|:-:|:-:|
| PC | M1 MacBook Pro  |   |
| OS | macOS Ventura 13.0.1  |   |
| Docker | 4.15.0 |   |
| CentOS | 7.9.2009  | |
| grype | v0.59.0 | |
| syft | v0.62.3 | |

# 手順

## CentOS 7のコンテナを作成

macOS上での作業です。

dockerイメージをpullし、コンテナを作成します。
```Bash
$ docker pull centos:centos7
$ docker run -it -d --name centos7 centos:centos7
```

ログインして、バージョンを確認します。
```bash
$ docker exec -it centos7 /bin/bash
# cat /etc/redhat-release 
CentOS Linux release 7.9.2009 (AltArch)
```

## grypeをインストール

/usr/local/binにgrypeをインストールします。

```bash
# curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
```

## syftで生成したSBOM(SPDX-JSON形式)を元に脆弱性を調べる

前回の記事に従って、CentOS 7のrpmdbを元にSPDX-JSON形式のSBOMを生成しておきます。
ファイル名はcentos7_rpm.jsonとします。

syftを使ってCentOS 7のrpmdbを元にSPDX-JSON形式のSBOMを生成する
https://qiita.com/ykmchd/items/b28bca1663d957ae1956

SBOMをパイプでgrypeに渡し、リダイレクトでcentos7_rpm_vulnerability.txtというテキストファイルに出力します。

```bash
# cat centos7_rpm.json | grype --distro centos:7 > centos7_rpm_vulnerability.txt
```

出力結果を一部確認すると、openssl-libsパッケージに該当する脆弱性が紐付けされていることがわかります。

```bash
[root@6252d20a0c65 ~]# grep openssl centos7_rpm_vulnerability.txt
openssl-libs                 1:1.0.2k-25.el7_9                                       rpm   CVE-2015-2808     Medium    
openssl-libs                 1:1.0.2k-25.el7_9             (won't fix)               rpm   CVE-2019-1547     Medium    
openssl-libs                 1:1.0.2k-25.el7_9             (won't fix)               rpm   CVE-2019-1551     Low       
openssl-libs                 1:1.0.2k-25.el7_9             (won't fix)               rpm   CVE-2019-1563     Low       
openssl-libs                 1:1.0.2k-25.el7_9             (won't fix)               rpm   CVE-2020-1968     Low       
openssl-libs                 1:1.0.2k-25.el7_9             (won't fix)               rpm   CVE-2022-3358     Low       
openssl-libs                 1:1.0.2k-25.el7_9             (won't fix)               rpm   CVE-2022-4304     Medium    
openssl-libs                 1:1.0.2k-25.el7_9             (won't fix)               rpm   CVE-2022-4450     Medium    
openssl-libs                 1:1.0.2k-25.el7_9             (won't fix)               rpm   CVE-2023-0215     Medium    
openssl-libs                 1:1.0.2k-25.el7_9             (won't fix)               rpm   CVE-2023-0286     Medium    
[root@6252d20a0c65 ~]# 
```

# 最後に

grype(とsyft)を使ってSPDX-JSON形式のSBOMに関連する脆弱性情報を調べることができました。
syftとgrypeをCIに取り入れて、シフトレフトによって早期に脆弱性を検知・対応するDevSecOpsを推進していきたいですね。

# 参考情報

- anchore/grype
    - https://github.com/anchore/grype
- 開発に使える脆弱性スキャンツール
    - https://engineers.ntt.com/entry/2022/12/07/113602
- syftを使ってCentOS 7のrpmdbを元にSPDX-JSON形式のSBOMを生成する
    - https://qiita.com/ykmchd/items/b28bca1663d957ae1956
エンジニア思考を持つ教員を目指して

## 自己紹介
福岡で学校教員をしている。教員歴20年。
ミッションは「学校・教育・教員を社会へ開く」
生徒たちの出ていく未来へ不安を覚え、現在の教育への疑問を
感じていたため新しいことを模索している中でG'sと出会う。

## ジーズアカデミーでの現在地
G’s福岡DEV12期に入学してはや5ヶ月
学んだことはjavascript、html、css、php、laravelなど多岐にわたる。
もちろんこの期間でマスターできるわけではない。

特に最初の頃は学んでも学んでもコードを書けるようにならず、こんなことでいいのか、
自分には特性がないのではないか、と思うことも多かった。
それでも続けたのは、担任である児玉さんの

「まずテクノロジーの楽しさと奥深さを知ること、目的は自走できる力を付けること」

という言葉を信じていたことと、良い同期・チューターさんに恵まれたため。
プログラミングに関しては、山崎校長のお話で

「50％の理解で良い。続けていけば分かるときが来る」

との言葉で吹っ切れた。きっとそうなのだ、と言い聞かせ粘ってみたら、いつの間にか
何をやっているのかは分かるようになったので、スムーズに学習が進むようになった。
とりあえず`信じた人の話は素直に聞き、同時に自分の力を信じること`が重要。

## 卒業制作について
ジーズアカデミーでは最後に卒業制作を行う。
様々な問題を抱え、苦しい状況位にある学校教育・教員・生徒のために少しでも何かできないか、
と飛び込んで学んできた。当然卒業制作も教育に関するものと考えていた。

`自分のWhy meは何だろう`

周りの同期に比べると入学した動機が曖昧すぎるのではないか、と悩み続ける。
児玉さんとの初めての壁打ちでも`Why meはそんなものではない、もっと心の奥底に根源的にあるものだ`
との指摘を受け徹底的に原体験ドリブンを行う。出てきたのは
- 幼少期に自分のために病身をおして診察をしてくれた町の医院の医師の姿
- 教員である父親が生徒へ接する姿

こういった経験から
「自分の身を犠牲にして誰かのためになることをする、そしてそのことに感謝が生まれる、ということは素晴らしいことだ」
という価値観が強く芽生えていることに気づく。それがそのまま
「教育に強い関心がある、教育が好きだ」
という思いにつながっていることに気づく


`Who/What、Howはどうだろう`
対象が教育ではあまりに規模が大きすぎる。
実際教育現場に様々なテクノロジーは入ってきているが、一種特殊な世界に生きている教員には
響きにくくうまく活かせていない現状がある。
そんな中自分に何ができるのか、ほぼ夜な夜な同期とともに壁打ち会。
皆仕事があるのに、夜遅くまでとことん付き合ってくれ感謝しかない。

あるとき、ずっと私のWhy meに違和感がある、と言っていた同期が気づいてくれた。

`「多くの人のWhy meが過去の辛い経験などであるのに比べて、  先生のは尊敬する人の姿のようなプラスのWhy meです。なのに学校のマイナスをなんとかしようという考え方は合わないんじゃないですか」`

この一言で考えが180度変わる。辛い教員を何とかしたい、ではなくシンプルに教員として最も嬉しいことは何だろう。
答えは一瞬で出た

「卒業生が会いにきてくれること」

生徒がその後きちんと生きていることを知ることが教師にとっての最高の幸せ。
これは多くの教員に共通しているのではないか。それを手助けするプロダクトを作りたい。
心からそう思えた。その一晩でWho/What、Howが固まり一気に走り始めた。

大学在学時以来、暫くぶりに出会ったブレイクスルーの爽快感の中今なお走り続けていられる。

## メンターさんとの出会い
G’sではメンターさんについていただける。私はKids Weekendを運営されている田中さんに
メンタリングしていただけることに。
ここでも尊敬できるメンターとの出会いがあった。それだけではなく田中さんとの繋がりの中で、
新しい縁ができ、またコミュニティが広がった。

## 今回のまとめ
正直に言ってジーズアカデミーに入学して良いことしかない。

自分は運のない人間だ、と何となく思っていたが、ジーズに来てから

「自分ほど幸運な人はいないのではないか」

とさえ思うようになった。
教員・同期・チューター・メンター全てに恵まれ、
薦められてQiitaに記事を書けばそれをみて会いに来ていただける人もいた。
全く関わったことのなかった企業の新採教育の勉強に参加できた。

などなどとてもわずか数ヶ月に起こったこととは思えない。

一番大切なことは、ありきたりだが`「自ら動くこと」`簡単に聞こえるが実際に
動けている人は本当に少ない。これに関しては自分をほめて良いと思う。

子供達が自ら動ける人間に育つためには何をすればいいのだろう、
1人でも多くの子供にこの感動を味わってほしい。
それこそが子供達の人生を幸せなものにする最も確かな力になると信じている。

## 最後に
この記事はどんな人に読んでもらえるだろう。
ほとんど気付かれないかもしれないが、この投稿でまた出会いがあるかもしれない。
少なくともマイナスはない。
何が起こるかワクワクしながら書いている。
こんなことをしている未来は予想していなかったな。
出会いのチャンスは逃さないと決めた。
まだまだ自分も変わっていけると信じている。

私のこと、ジーズアカデミーのこと、教育のこと、
何か引っかかった方とご縁があると嬉しく思います。
「FreeCADの球面 (sphere)」を調べてみた。

短くなる方法を教えて下さい。sympyを追加しています。

# FreeCADで

```python
import FreeCAD
import Part
import Draft
import Mesh
#########################################################################################################
# 計算
from sympy import *
##########################################################################################################
### 3D作図
def myXYZ2Txt(A):
    return '(' + str(A.x) + ',' + str(A.y) + ',' + str(A.z) + ')'
def myTxtXYZ(A,myWedgei):
    P5x=float(A.x)
    P5y=float(A.y)
    P5z=float(A.z)
    p5 = FreeCAD.Vector(P5x, P5y, P5z)
    myText = Draft.makeText(myWedgei, p5)
    myText.Label = myWedgei
    FreeCADGui.ActiveDocument.ActiveObject.FontSize = '1.0 mm'
def myTxtXYZ_S(*xy_tx):
    for i in range(1,int(len(xy_tx)/2)+1):
        myTxtXYZ(xy_tx[2*i-2],xy_tx[2*i-1]+myXYZ2Txt(xy_tx[2*i-2]) ) 
    return
def my_Sphere_name(myCenter,myr,myname):
    sphere = doc.addObject("Part::Sphere", myname)
    sphere.Radius = float(myr)
    sphere.Angle1 = -90
    sphere.Angle2 =  90
    sphere.Angle3 = 360
    sphere.Placement = App.Placement(App.Vector(float(myCenter.x),float(myCenter.y),float(myCenter.z)), App.Rotation(0, 90, 0))
    #FreeCADGui.getDocument('Unnamed').getObject(myname).Transparency = 95
    FreeCADGui.getDocument('Unnamed').getObject(myname).Transparency = 80
O=Point3D(0,0,0)
doc = App.activeDocument()
P=Point3D(0+15,0,0)
myTxtXYZ_S    (O,"O",P,"P")
my_Sphere_name(P,6,"en30")
#
App.ActiveDocument.addObject("App::Origin", "Origin")
App.ActiveDocument.getObject('Origin').Visibility = True
App.ActiveDocument.recompute()
Gui.activeDocument().activeView().viewAxonometric()
Gui.SendMsgToActiveView("ViewFit")
```

![1png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/d06bf283-51c2-18e9-80ea-fb79f3aa113c.png)


# 参考

https://www.google.com/search?q=freecad+sphere&rlz=1CAUHAM_enJP1038JP1038&oq=freecad+sphere&aqs=chrome..69i57j0i19i512j0i8i19i30l4j69i61l2.10201j0j7&sourceid=chrome&ie=UTF-8
みんながカレーを作っている

# カレーを作ろう　

### モデルをどう作るか(´・ω・｀)
### 抽象化をどうするか(´・ω・｀)
### それが問題だ(´・ω・｀)

# 一人暮らしのカレー作り
```:学生
1. ニンジンの皮を剥く
2. ジャガイモの皮を剥く
3. タマネギの皮を剥く
4. ニンジンを切る
5. ジャガイモを切る
6. タマネギを切る
7. 豚肉を切る
8. 鍋で煮込む
```
:::note info
特に分ける必要がない。
:::

# レストランのカレー作り
```:皮むき担当
1. ニンジンの皮を剥く
2. ジャガイモの皮を剥く
3. タマネギの皮を剥く
```

```:切る担当
1. ニンジンを切る
2. ジャガイモを切る
3. タマネギを切る
4. 豚肉を切る
```

```:煮込む担当
1. 具材を煮込む
2. ルーを入れる
```


:::note info
新人とベテランなどで作業の難しさで分けている
二人の担当者に言えば材料増えても問題ない
:::

# 工場のカレー作り

```:ニンジン下拵え装置
1. ニンジンの皮を剥く
2. ニンジンを切る
```

```:タマネギ下拵え装置
1. ジャガイモの皮を剥く
2. ジャガイモを切る
```

```:ジャガイモ下拵え装置
1. タマネギの皮を剥く
2. タマネギを切る
```

```:豚肉下拵え装置
1. 豚肉を切る
```

```:煮込み装置
1. 具材を煮込む
2. ルーを入れる
```
:::note info
野菜のむき方って意外と違う
装置の取り換えが楽
装置って別の会社が作ることが多い
:::

### どれもカレーを作ってるけど、モデルは全然ちがうよね(´・ω・｀)？
### どれもカレーを作ってるけど、抽象化が必要なのは工場だけでは(´・ω・｀)？

### あなたが作るモデルはどうですか(´・ω・｀)？
Twitch APIをPythonで利用する（備忘録）

1.自己紹介
--
こんにちは。YoutubeやTwitchで配信しておりますアニメ、漫画、ゲーム、Vtuber大好きオタクのVtuber
久遠楽 (https://twitter.com/kuonraku0210) です。

今回はPythonを利用して配信活動をより便利にすることを目的として学習しようと思いました。
プログラミングに関しては初心者でQitaに投稿をしたことがないので拙い個所もあるかと思いますが暖かい目で見守ってください。

2.チュートリアル
---
実際にAPIを使ってツイッチ上のデータを取得したいと思います。
今回は指定したユーザーのIDを取得します。
**ソースコード**
```python
from twitchAPI.twitch import Twitch
from twitchAPI.helper import first
import asyncio

async def twitch_example():
    #Twitch developersで取得したクライアントIDとシークレットキーを入力する
    twitch = await Twitch('app_id', 'app_secret')
    #自身のTwitchユーザー名を入力
    #ここは表示名ではないことに注意
    user = await first(twitch.get_users(logins='your_twitch_user'))
    #ユーザーidを取得する
    print('あなたのIDは：' + user.id)
    await twitch.close()

#実行
asyncio.run(twitch_example())
```

**結果**
```
あなたのIDは：788638159
```

3.APIを活用する
---
これでTwitchAPIとの連携が出来たので、次は任意ゲームで視聴者数が多い上位の人の名前と視聴者数を取得したいと思います。
**ソースコード**
```python
from twitchAPI.twitch import Twitch
from twitchAPI.helper import first
import asyncio

async def twitch_example():
    #人数を制限する
    count = 0
    #Twitch developersで取得したクライアントIDとシークレットキーを入力する
    twitch = await Twitch('app_id', 'app_secret')
    #今回はvalorantを選択
    #game_idを変えれば好きなゲームにすることが出来る
    async for playerInf in twitch.get_streams(game_id='516575'):
      count+=1
      print(playerInf.user_name,playerInf.viewer_count)
    #上位5人を取得
    if count > 5:
      break
    await twitch.close()

# run this example
asyncio.run(twitch_example())
```
***結果***
```
A 14000
B 13000
C 12000
D 11000
E 10000
```
4.応用
----
画面上に出力するだけではデータの活用が出来ないのでこれをCSV出力し活用できるようにします。
***ソースコード***
```python
from twitchAPI.twitch import Twitch
from twitchAPI.helper import first
import asyncio
import csv

async def twitch_example():
    count = 0
    #CSV用の変数
    csvInf = [['配信者名','視聴者数']]
    twitch = await Twitch('app_id', 'app_secret')

    async for playerInf in twitch.get_streams(game_id='516575'):
        csvInf.append([playerInf.user_name,playerInf.viewer_count])
        count+=1
        if count > 5:
            # CSVファイルにデータを作成
            f = open('output.csv', 'w', newline='')
            writer = csv.writer(f)
            writer.writerows(csvInf)
            f.close()
            break
        print('データの出力を行いました。')
    await twitch.close()

# run this example
asyncio.run(twitch_example())
```
***結果***
```:画面上
データの出力を行いました。
```
```: output.csv
配信者名,視聴者数
A,14000
B,13000
C,12000
D,11000
E,10000
```

4.最後に
---
まだまだプログラミングについては勉強中ですがやっぱり自分のしたい機能を完成させることが出来るととても達成感がありました。
配信者の一覧取得とかなかなかできずにふて寝したんですが次の日にあっさり解決しました・・・笑
拙い文章ですが最後までお付き合いいただきありがとうございます。
こうしたコードの方がいいなどがあればドシドシ送ってください。
また勉強して記事を作成したいと思います。

【宣伝】
APEXやヴァロラントなどのFPSをメインに毎日20時頃から配信をしているのでよければチャンネル登録していただければ嬉しいです。
【 IT用語 】非機能要件とは

## ■はじめに
システム開発において機能要件・非機能要件という観点があることを知ったので備忘録として調べたことを残しておきます。


## ■機能要件
機能要件とは、要件定義で決まった「実装する機能」のことを指す。
発注者側が満たして欲しい事項となるため、要件通り実装できていなければ「失敗」となる。


## ■非能要件
システム開発をする上で、機能面以外の要件を非機能要件という。
非機能要件は専門性が高いため、開発側が率先して定義する必要がある。
また、範囲が広いためQCDを考慮して決めていく必要がある。

非機能要件は、ヒヤリングベースで作成することが難しいため、IPAが提供している「非機能要求グレード2018」に定めている以下6つの大項目に従って定義するらしい。

:::note warn
表は下記リンク先より「「非機能要求グレード」実践セミナー　システム基盤の非機能要件定義を講義と演習で身につける」のPDFより抜粋
:::
※[IPA システム構築の上流工程強化（非機能要求グレード）](https://www.ipa.go.jp/sec/softwareengineering/std/ent03-b.html)

<table>
<caption>非機能要求項目の分類</caption>
  <thead>
    <tr>
      <th>大項目</th> <th>要求例</th>
    </tr>
  </thead>
    <tr>
       <td> 可用性 </td> <td>・運用スケジュール（稼働時間・停止予定など）
                        <br>・障害、災害時における稼動目標</td>
    </tr>
    <tr>
       <td> 性能・拡張性 </td> <td>・業務量および今後の増加見積り
                            <br>・システム化対象業務の特性
                            （ピーク時、通常時、縮退時など）</td>
    </tr>
    <tr>
       <td> 運用・保守性 </td> <td>・運用中に求められるシステム稼動レベル
                            <br>・問題発生時の対応レベル</td>
    </tr>
    <tr>
       <td> 移行性 </td> <td>・新システムへの移行期間および移行方法
                        <br>・移行対象資産の種類および移行量</td>
    </tr>
    <tr>
       <td> セキュリティ </td> <td>・利用制限
                           <br>・不正アクセスの防止</td>
    </tr>
    <tr>
      　<td> システム環境・エコロジー </td> <td>・耐震／免震、重量／空間、温度／湿度、騒音など、システム環境に関する事項
                                    <br>・CO2排出量や消費エネルギーなど、エコロジー
に関する事項</td>
    </tr>
</table>

## ■非機能テストの一部
**①パフォーマンステスト**
想定に近い状態で動作させ、要件を満たした挙動となるかテストを行う。
例）リクエストに対しての応答時間

**②負荷テスト**
過負荷な状態となった時に、システムにどういった症状が出るかテストを行う。
例）データの不整合

**③ユーザビリティテスト**
ツールなどを活用してユーザが使いやすいシステムであるかテストを行う。
例）Google Analyticsを活用してシステム利用者の行動を確認する。
　　実際に複数のユーザに使用してもらい、問題点を聞く。

**④セキュリティテスト**
システムのバグにより発生する、情報セキュリティの欠陥を調べるテスト
例）SQLインジェクション
　　クロスサイトスクリプティング
java Singleton Patternとは

<h2>singleton patternとは</h2>
プロジェクト内にたった1つだけ存在しなければならないインスタンスがある可能性があります。<br>
例えば、学校といえば、学校には多くの生徒がいますが、学校自体は一つだけ存在しなければなりません。
会社も同じ。 <br>
会社には複数の部署が存在しますが、会社は1つの会社しか存在しません。
学校や会社が何度もnew()された時、複数のインスタンス変数を持つようになって問題が発生することを防止するために
singletone patternを使用します。<br>
singleton patternでは、あらかじめ生成されているインスタンスをpublic getMethod()を通じて取得して使用します。

<h2>singleton pattern方法</h2>

```java
package singleton;

import java.util.Calendar;

public class Company {
    // 内部でInstanceを生成
    private static Company instance = new Company();

    // privateな constructor
    private Company() {}

    // 唯一なInstanceをget()
    public static Company getInstance() {
        if ( instance == null) {
            instance = new Company();
        }
        return instance;
    }
}
```
constructorはprivateにします。
private constructoの場合、外部からインスタンスを生成できないため、内部からnewしてインスタンスを生成します。
そして外部で唯一のオブジェクトを参照できるPublic static get Methodを生成！
100度呼んでも同じオブジェクトを返還します。（参照値が全部同じ！）




日付Instanceも何回もnew()されて作成する必要ないinstanceのため、エラーを起こします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3097775/ebefd1f8-ee8f-3a25-97ae-6d2eea84ebc6.png)
C言語でバブルソートの昇順ができた件

# 注意
・AtCoderの [A - Task Scheduling Problem](https://atcoder.jp/contests/abc103/tasks/abc103_a) のネタバレあり。
・読みにくいから頭の中が整理出来次第更新していく。
# ACしたコード
```C
#include <stdio.h>
int	main(void)
{
	int a123[4];

	for (int i = 0; i < 3; i++)
	{
		scanf("%d",&a123[i]);
		// printf("%d ",a123[i]);
	}
	// printf("\n");

	//ここから昇順ソート
	int i;
	int j;
	int tmp = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = i + 1; j < 3; j++)
		{
			if (a123[i] > a123[j])
			{
				tmp = a123[i];
				a123[i] = a123[j];
				a123[j] = tmp;
			}
		}
	}
	//	並べ替え結果の表示
	for ( i= 0 ; i < 3; i++)
	{
		// printf("a123[i]=%d ", a123[i]);
	}
	// printf("\n");
	int sum = 0;
	for (int i = 0; i < 2; i++)
	{
		sum += a123[i + 1] - a123[i];
		// printf("sum=%d\n", sum);
	}
	printf("%d\n", sum);
	return (0);
}
```
<b>実行結果</b>
入力例1:
1_6_3
出力結果1:
5
期待する出力1:
5

入力例2:
11_5_5
出力結果2:
6
期待する出力2:
6

入力例3:
100_100_100
出力結果3:
0
期待する出力2:
0

# 方針(仮)
[1] int型でa1,a2,a3を標準入力から受け取る。
[2] int型で受け取った値を配列、a123[4]に代入する。<font color="Red">
※変数a1の値をa123[4]に代入できたが、変数a2の値を代入した時に、a1の値がa2の値に上書きされている事に気づき、[3]以降に着手できない。</font>
↓↓↓↓↓↓ [1],[2] を変更 ↓↓↓↓↓↓
[1] 標準入力から受け取る変数をa123[4];という配列で受け取る。
[2] a123[4];という配列をバブルソートの昇順にする。
[3] for文でiを1〜3回まで回して、以下のイメージで引き算をする。
```
a123[1] - a123[0]
a123[2] - a123[1]
```
<font color="Red">
※for文で i の範囲を1〜3回にすると(入力例1の場合)

配列a123[i]の値のa123[0]が 0 、a123[1]が 1 、a123[2]が 6 の値が出力されるので[4]以降に着手できない。</font>↓↓↓↓↓↓ [3] を変更 ↓↓↓↓↓↓
[3] for文の i の範囲は、0〜2回までにして上記のイメージで引き算をする。
[4] int sum = 0;の変数に引き算した結果を代入する。
<font color="Red">※代入すると値が上書きされるので以下のイメージの結果をint sum = 0;に足し算していく。</font>
```
a123[1] - a123[0]
a123[2] - a123[1]
```
↓↓↓↓↓↓ [4] を変更 ↓↓↓↓↓↓
[4] int sum = 0;の変数にa123の配列の値の引き算した結果を足し算する。
[5] for文を抜けてint sumの変数に引き算の結果を出力する。

# ACする方針まとめ
[1] 標準入力から受け取る変数をa123[4];という配列で受け取る。
[2] a123[4];という配列をバブルソートの昇順にする。
[3] for文の i の範囲は、0〜2回までにする。
[4] int sum = 0;の変数にa123の配列の値の引き算した結果を足し算する。
[5] for文を抜けてint sumの変数に引き算の結果を出力する。 
# メモ
```C
// 最後のループ
for(int i = 0; i < 3; i++){
    sum += a123[i - 1] a123[i];
}
//にすると、a123[1] - a123[i]が計算されてマイナスの値になる可能性があるので
for(int i = 0; i < 2; i++){
    sum += a123[2] - a123[i]
}
//の計算で終わるようにループで引き算する回数を1回分減らす。
```
・バブルソートを使う事が増えたからバブルソートの関数を昇順と降順バージョンを作ってスニペットにしたい。
catslyst 機器のメモリについて

cisco製品のcatalystスイッチのconfigやOSの保存場所などOSのバージョンアップの際に分からなくなったのでメモ

# ルータ、スイッチのメモリの種類

https://www.infraexpert.com/study/ciscoios0.html#:~:text=%E2%97%86%E3%80%80Cisco%E3%83%AB%E3%83%BC%E3%82%BF%20(%20%E3%83%A1%E3%83%A2%E3%83%AA%E3%81%AE%E7%A8%AE%E9%A1%9E%20)

# ciscoスイッチのOS選定方法

boot変数にflashメモリ内のOSを指定したら任意のOSで起動できる。
boot変数にOSの指定が無くflashメモリの中にOSが複数あった場合はflashメモリ内で上のOSが選ばれる。show flash:とか

https://www.infraexpert.com/study/ciscorouter8.html


:::note info
show verionでレジストリ確認出来る場合あり。
:::
【個人開発】初めての個人開発、自動車整備工場検索アプリ「SMASH（スマッシュ）」を作成しました


# はじめに  
こんにちは、ご覧いただきありがとうございます。
@Hako_2211と申します。
私は、自動車関連や飲食業界で経験を経ております。
DIVE INTO CODEで4ヶ月間、未経験からWeb開発について学んでおり、主に学んだ言語はRubyで、フレームワークはRuby on Railsでした。

卒業制作として、DIVE INTO CODEで4ヶ月間での学びを活かし、初めての個人開発アプリ「SMASH」を作成しました。

「SMASH」とは、自動車の整備工場を検索するアプリです。
「SEARCH MAINTENANCE SHOP」の文字を取り入れて、「SMASH」と言うアプリ名にしました。

# アプリ制作のきっかけ

お車を所有している方の多くは、購入後のメンテナンスをディーラーに依頼しています。
しかしながら、私の前職では、遠方からや軽度な修理でお越しいただいた方々から、
近隣の修理工場を探しているという相談をよく受けました。

問題として
- 地方では交通インフラが整備されていない、
- 車が必需品の方も多く、車がないと生活できない方もいる
- メンテナンスやアフターフォローに関する情報が不足しており、修理工場が遠くなってしまうため、手間やコストがかかり、メンテナンスが軽視されるケースもあります。

また、コスパや評判の良い修理工場があっても知られていないため、ディーラー以外の整備工場は年々少なくなっている状況にあります。これらの課題に対し、誰でも手軽に情報を共有でき、集客・活性化できるアプリが必要であると考え、開発したいと思い制作に至りました。


# 使用環境
ruby 3.0.4
Ruby on Rails 6.1.6


# 実装した機能と使いかた
- 住所から工場の検索
- カテゴリーから工場の検索
![画面収録_2023-03-05_18_30_30_AdobeExpress.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031489/26ecb1eb-5ac5-a57f-8355-908e5a895df0.gif)


- 工場に対しての口コミ投稿![スクリーンショット 2023-03-05 18.26.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031489/a28e6766-8eb7-8036-903f-2107db6451a2.png)

- マイページでお気に入りの工場の管理![スクリーンショット 2023-03-05 18.20.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031489/99c3341e-9b44-d1b2-fc00-3eea2a5a3873.png)



# 今後の展開
- 口コミの評価機能
- 地図から検索実装
- ログイン機能のセキュリティ強化
- 工場側からの実績を投稿できる機能
- デザインを素敵により良く
- etc...


# 最後に
ここまでご覧いただきまして、ありがとうございました。
DIVE INTO CODEでの4ヶ月間は、とても充実した学びの時期でした。メンターの方々や同期生の方々からのサポートに何度も助けられ、本当に感謝しています。
また、現場の課題解決に焦点を当てた卒業制作を通じて、顧客に寄り添い課題を解決できるエンジニアになることを目標としました。
まだまだ未熟者ですが、今後も精進して参ります。
最後に、卒業制作として制作をスタートさせたアプリには、機能を実装するたび愛着が湧いてきました。このアプリはこれからも開発を続け、より便利で使いやすいものにしていきたいと思っています。
最後までお付き合いいただき有難うございます。
Auth0 アクセストークンバリデーションメモ

# 
* Auth0が発行するアクセストークンのバリデーション方法についてメモする。

## バリデーションの流れ

### 1. JWT標準検証

※Auth0が発行するアクセストークンはJWT形式となっている

* アクセストークンの有効期限や署名、issuerなどの妥当性を検証する。
  * ライブラリを使用して実装することを推奨。

### 2. Audienceクレームの検証

* トークンに含まれるオーディエンス(`aud`)クレームを検証する。
  * `aud`値が呼び出し対象API 設定の`Identifier`に設定された値と一致していることを確認する。

### 3. Scope()の検証

* トークンに含まれるスコープ(`scope`)クレームを検証する。
  * `scope`値に指定された値が呼び出し対象API設定の`Permissions`に定義された値と一致していることを確認

## Pythonコード例

* ライブラリ`PyJWT`を使用

```python
# OpenID ConfigurationエンドポイントからJWKSエンドポイントURLを取得
oidc_config_endpoint = {YOUR_TENANT_URL}/.well-known/openid-configuration
oidc_config = requests.get(
    oidc_config_endpoint
).json()
signing_algos = oidc_config["id_token_signing_alg_values_supported"]

jwks_client = jwt.PyJWKClient(oidc_config["jwks_uri"])

# token: 検証対象アクセストークン
# api_identifier: アクセス対象API識別子(API定義に指定したIdentifier値)
# issuer: テナントURL
# api_scope_list: アクセス対象APIスコープ(API定義に指定したPermissions値)
def validate_token(token: str, api_identifier: str, issuer: str, api_scope_list: list):
    # JWKSエンドポイントから公開鍵取得
    signing_key = jwks_client.get_signing_key_from_jwt(token)

    # 1. JWT標準検証
    # 2. Audienceクレーム検証
    payload = jwt.decode(
        token,
        key=signing_key.key,
        algorithms=signing_algos,
        audience=api_identifier,
        issuer=issuer
    )
    
    # 3. Scopeクレーム検証
    # Payloadからスコープを取得
    # 複数指定に対応するため' 'で分割
    # API定義とPayloadに一致があるかを確認するためsetに変換している
    payload_scope_set = set(payload['scope'].split(' '))
    api_scope_set = set(api_scope_list)
    and_scope_list = list(payload_scope_set & api_scope_set)
    # スコープ一致なし
    if len(and_scope_list) == 0:
        return None
    return payload

```



## 参考情報

* [PyJWT](https://pyjwt.readthedocs.io/en/latest/index.html)
* [Validate Access Tokens](https://auth0.com/docs/secure/tokens/access-tokens/validate-access-tokenshttps://auth0.com/docs/secure/tokens/access-tokens/validate-access-tokens)
SlackでChatGPT Botを作るとき詰まったこと

ChatGPTを使ったSlack Botを作ってみました。

流行りのChatGPT APIについては割と素朴で普通に使えたので、残念ながら（？）あまり特筆するような事がありませんでした。ですが、Slackとの連携で色々と詰まったのでポイントをメモしておきます。

## Slack Botの様々な種類から使う技術を決める
まずSlack Botを開発する方法は結構色々あり、物によってはDeprecatedだったりもするようです。選定する前にどういう要件か、そのために何の技術を使うか、はっきりさせておく必要があります。

https://api.slack.com/apis/connections

今回は

- 通常の投稿に対して反応させたい
    - Slash Commandなど特殊な使用方法は、覚えるのも入力するのも避けたい
- 指定のchannelに投稿があったら（ChatGPTで）投稿したい
- 裏側で待ち受けるサーバは用意できるが、常時起動はしない（サーバレスである）

という事にしたので、**Slack Events API**を使うことにしました。

https://api.slack.com/apis/connections/events-api

使う技術が決まれば、ドキュメントを読んだり、ググったり、ChatGPTに聞くなりして開発が進められますが、最初にここが定まっていないと不必要な情報の要否を判断しにくくなり、簡単な開発であっても生産性が落ちます。

### 今回の構成
- 人間の投稿をSlack Events APIでSubscribe
- サーバにはCloud Runを利用
- サーバからBotで投稿するにはIncoming Webhookを利用

```mermaid
graph TD;
  Slack-->|Slack Events API|Cloud_Run;
  Cloud_Run-->|Incoming Webhook|Slack;
  Cloud_Run-->ChatGPT;
  ChatGPT-->Cloud_Run;
```

### サーバサイドアプリケーションの開発
Cloud RunのサーバにはRuby on RailsでAPIを開発しました。

直近数回の会話を保持してChatGPTに与えたかったので会話履歴をDBに保存するようなアプリケーションにしました。SQLiteを本番環境コンテナ内に入れて、起動スクリプトで毎回`db:create`するようにしてデプロイしました。※良い子は真似しないでね
Cloud Runは`max-instances=1`にしました。Cloud Runがスケールインで寝るまでの間は会話のキャッチボールが続きます。

今回ChatGPTのクライアントライブラリなどは使わず、HTTPリクエストを以下のような感じで組み立てました。

```ruby:ChatGPT API呼び出しコード（一部抜粋）
prompt_messages = [{ role: "system", content: SYSTEM_PROMPT }]
messages.each do |message|
  role = message.message_type == "ai" ? "assistant" : "user"
  prompt_messages.push(
    { role: role, content: message.content }
  )
end

request.body = JSON.dump({
  model: "gpt-3.5-turbo",
  messages: prompt_messages,
})
```

予め`Message.order(created_at: :desc).limit(10)`とかで適当に`messages`を取り出しておいて、こんな感じで会話履歴を順番に組み立ててChatGPTに渡しました。実際にはChatGPTに渡せるトークン数に限りがあるので文字数を数えて上限まで過去の会話を渡すのが良いと思います。詳しくは[OpenAI API](https://platform.openai.com/docs/guides/chat)を参考にしてください。


## Botの投稿に反応してしまい無限ループする
Slackアプリを追加したChannelに投稿があると、Slack Events APIからPOSTリクエストがあります。これは人間の投稿も、Botの投稿も、「○○さんがに参加しました。」といったシステムメッセージも全部イベントとして発火します。

人間とBotの会話が交互に続くようにしたいのですが、何もしてないとBotの投稿に対してBotが反応してしまい無限ループします。

無限ループを防ぐには、Botからの投稿を見分ける必要があります。Slack Events APIからのPOSTリクエストには`subtype`というフィールドがあります。ここが`bot_message`となっているのものはBotからの投稿なので、これをキャンセルします。
通常の人間の投稿には`subtype`が設定されないという仕様だったようなので、結局`subtype`キーが有ったらキャンセルするようにしました。

https://api.slack.com/events/message#subtypes

## Events APIがリトライされて重複実行される
Slack Events APIが発火した後、3秒以内にレスが無いとリトライされる仕様のようです。正常に処理できているのに3秒以上かかっていると、リトライされて同じ投稿に何度も反応してしまいます。
今回Cloud Run起動とOpenAI APIのオーバーヘッドがあるので、3秒というのは結構ギリギリで、間に合ったり間に合わなかったりします。再現条件が不安定なので対処が遅れるポイントです。

リトライによるリクエストには`X-Slack-Retry-Num`というヘッダーが付くので、今回はこのヘッダーが付いていたらキャンセルするようにしました。これだと、何らかのエラーでレスポンスが返せなくて本当にリトライしたいような時に正常に機能しませんが、今回はそこまで厳密に対応する必要は無かったのでこれで良しとしました。

ひとつの投稿に対して1回だけ反応するようにちゃんと対応するには、受けたリクエストを保存しておいて同一のリクエストが処理中でないかチェックするような実装が必要だと思います。

https://api.slack.com/apis/connections/events-api#retries

## 参考
- [Slack Botの種類と大まかな作り方 \- Qiita](https://qiita.com/namutaka/items/233a83100c94af033575)
- [slack event api の設定 \- SO Technologies 開発者ブログ](https://developer.so-tech.co.jp/entry/2022/04/05/131934)
css でのスタイルの掛け方 

# はじめに

フロントエンド開発で

> css をどう書いたらどの要素、className に対応するんだっけ？

> 複数の css が被る場合どちらが優先されるんだ？

となったので初心者向けにまとめてみました。

# 実践

下記３つのような書き方があるので確認していきましょう。

ex)
```css
/* html 要素に直接かかる */
h1 {
  color: red;
}

/* html要素がh1 かつ blue のclasssNameにかかる */
h1.blue {
  color: blue;
}

/* classsName が demo の子要素 かつ html 要素が p の場合にかかる */
.demo p {
  color: green;
}
```

## 1. html 要素のみを指定する

一番簡単な css の反映方法です。
html 要素に直接 css を当てることにより、すべての h1 要素を赤くすることができます。
className の設定はhtml側で不要です。
page 全体の フォントや、フォントサイズを指定する時などに便利です。


```css
h1 {
  color: red;
}
```

```html
<!-- かかる -->
<h1>h1h1</h1>
<!-- かからない -->
<h2>h2h2</h2>
```

![スクリーンショット 2023-03-05 18.03.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2841732/d2bdc205-9f3f-a45d-3aad-3dde8eb3ca88.png)


→ **h2要素は黒いままでh1要素だけ赤くなる**


## 2. html要素に続けてクラス名を指定する

html 要素を指定しその中でも該当の className がかかっているものにのみ css を反映させる方法です。
すでにhtml要素に全体的にcssが当てられているが、一部のみ上書きして別のcssを当てたい場合に有効です。

```css
/* html 要素に直接かかる */
h1 {
  color: red;
}

/* html要素がh1 かつ blue のclasssNameにかかる */
h1.blue {
  color: blue;
}
```

```html
    <!-- かからない -->
    <h1>h1 with no className</h1>
    <!-- かかる -->
    <h1 class="blue">h1 with className blue</h1>
    <!-- かからない -->
    <h2 class="blue">h2 with no className</h2>

```

![スクリーンショット 2023-03-05 18.14.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2841732/534e85a6-11d5-12d2-bfdc-5b9cdc7f455e.png)

実行結果から、

`2. html要素に続けてクラス名を指定する` > `1. html 要素のみを指定する` 

という関係で css が上書きされることがわかります。

## 3. 特定のclassの内部にある要素を指定する。

次の例では、demo が指定されたh1要素にのみ、スタイルが適用されることになります。
部分的に style をかけたく、その範囲が明確な場合に有効です。


```css
/* html 要素に直接かかる */
h1 {
  color: red;
}

/* classsName が demo の子要素 かつ html 要素が p の場合にかかる */
.demo h1 {
  color: green;
}
```

```html
<!-- かからない -->
<h1>h1 with no className</h1>
<div class="demo">
  <!-- かかる -->
  <h1>h1 inside of div(class=demo)</h1>
</div>
```

![スクリーンショット 2023-03-05 18.24.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2841732/9caaf8db-b7cf-54e2-7ac7-555cecf878fd.png)

実行結果から、

`3. 特定のclassの内部にある要素を指定する。` > `1. html 要素のみを指定する` 

という関係で css が上書きされることがわかります。

# まとめ


おまけですが、

- `1. html 要素のみを指定する` 
- `2. html要素に続けてクラス名を指定する`
- `3. 特定のclassの内部にある要素を指定する。`

としたときに

cssとしての優先順位は

`2 = 3 > 1`

となっています。

1は、2でも3でも上書きすることが可能ですが、
2, 3 はcss ファイルの中で後半に記述されているもので上書きされます。
Cの基本16 ~動的記憶域確保~　備忘録*

### はじめに
私は初心者である。この備忘録を参考にされようとしている他の初心者の方は、ここに書かれていることを鵜呑みになさらぬようお願いしたい。何か間違いを見つけた方はコメント欄でご報告頂きたい。
___

### 動的確保の基本

記憶領域というものは普通、プログラム内で宣言した変数のための領域として確保される。
その種類は、自動変数、レジスタ変数、外部変数、静的変数であると。
変数のための記憶領域の大きさは、動作させるプラットフォームが決まっていたら、基本的にはプログラムを書いた時点で決まるらしい。今後出てくる可変長配列とやらは除くとのことだが。

しかしプログラムの実行中に、特別な大きさの領域が必要になることがある。Webブラウザが画像をサーバーからダウンロードしてメモリに入れる時など。そんな時に使えるのが動的記憶域確保(動的確保)らしい。

Cでは言語の機能として動的確保が提供されているわけではなく、ここから記録するのはAPIである。

##### 動的確保の使い方

動的確保する関数は複数あるらしい。

まずは`malloc`関数。指定されたバイト数のメモリ領域を確保して、その先頭へのポインタを返す。確保された場合の領域にはゴミの値が入っていて、確保できなかったらナルポインタを返す。
関数`free`は、mallocなどで動的に確保された領域へのポインタを渡すと、その領域を解放するらしい。

これらを使うには`stdlib.h`を取り込む。

*int型の領域が欲しい場合には下記のようにする*
```c
int *p;

p = malloc(sizeof(int));

free(p);
```
*要素を1000個もつdoubleの配列が欲しい場合は以下のように。*
```c
double *p;

p = malloc(sizeof(double)*1000);    // p[0]からp[999]]まで使える

free(p);
```
コード例として20要素をもつintの配列が入る領域をmallocで確保し、フィボナッチ数列を表示させようってのがあったので一応貼っとく（がこれじゃないだろう感を感じる）
```c
#include <stdio.h>
#include <stdlib.h>

enum {
    N = 20,
};

int main(void){
    int *p;
    int i;

    if ((p = malloc(sizeof(int) * N)) == NULL){    // エラー処理
        printf("cannot allocate memory\n");
        return 1;
    }

    p[0] = p[1] = 1;

    for (i=2; i<N; i++)
        p[i] = p[i-1] + p[i-2];

    for (i=0; i<N; i++)
        printf("%d ", p[i]);

    printf("\n");
    free(p);
    return 0;
}    
```
`if ((p = malloc(sizeof(int) * N)) == NULL){~}`のあたりはmallocを使う際のエラー処理の常套句らしい。

##### 動的に確保された領域の生存期間
mallocなどで確保されてからfreeで解放されるまで！
(プログラムの終了時には、その時点でそのプログラムが使っているすべての領域が解放される。動的確保された領域も同じ。)

___

### 伸びる配列を作る

##### realloc関数
`realloc`関数は、mallocなどで確保済みの領域の大きさを、メモリ内容を保持したまま変えるAPIだと。

少々今時間がないので名前だけで割愛！知るべき時が来たらやる(新しいC言語の教科書 P486)

___

> 今回の内容は富永和人氏の[新しいC言語の教科書](https://www.amazon.co.jp/%E6%96%B0%E3%81%97%E3%81%84C%E8%A8%80%E8%AA%9E%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E5%86%A8%E6%B0%B8%E5%92%8C%E4%BA%BA-ebook/dp/B07P1TC98P)を参考に書き留めてます。
Linux コマンド系　復習


現場でリリース時に必要になった基本的な知識
今更だけど復習


$ su 
「su」コマンドは使用するユーザーを切り替えるときに使用します。


スーパーユーザー（root権限）とは、Linuxにおける管理者権限のことでLinuxにおけるすべての操作が可能となります。

「su」と「su -」の違い

「su」コマンドを実行すると、環境変数は変更する前のユーザーが設定した内容が引き継がれますが、「-」を付けると環境変数が引き継がれません。

そのため、スーパーユーザーに変更して環境変数の内容を引き継ぐ場合には「su」、引き継がない場合は「su -」を使用するようにしましょう。
L5-Swaggerを本番環境で無効にする

LaravelでSwagger UIをホスティングしたりOpenAPIファイルを生成してくれるようになるL5-Swaggerですが、公開環境ではSwagger UIのホスティングを無効にしておきたい。
ドキュメントを読んでもやり方が書いてなかったので、ソースコードを読んで調べた方法をメモ。

https://github.com/DarkaOnLine/L5-Swagger

## 環境

- PHP: 8.1.3
- Laravel: 9.47.0
- darkaonline/l5-swagger: 8.4.1


## 方法

L5-Swaggerのコンフィグで`routes`を`null`にする。
以下の例では`APP_DEBUG`の値に応じて切り替えるようにしてます。

```php:config/l5-swagger.php
<?php

return [
    'default' => 'default',
    'documentations' => [
        'default' => [
            'api' => [
                'title' => 'L5 Swagger UI',
            ],

            'routes' => env('APP_DEBUG') ? [
                /*
                 * Route for accessing api documentation interface
                */
                'api' => 'api/documentation',
            ] : null,
            'paths' => [

// **** 省略 ****
```

## 解説

L5-Swaggerでルーティングしているコードは`vendor/darkaonline/l5-swagger/src/routes.php`にあります。`routes`が`isset`で評価されているので、`null`を入れてあげればルーティングをスキップできます。ミドルウェアなどで制御する必要もありませんでした。


https://github.com/DarkaOnLine/L5-Swagger/blob/master/src/routes.php

```php:routes.php
<?php

use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Route;
use L5Swagger\ConfigFactory;
use L5Swagger\Http\Middleware\Config as L5SwaggerConfig;

Route::group(['namespace' => 'L5Swagger'], function (Router $router) {
    $configFactory = resolve(ConfigFactory::class);

    $documentations = config('l5-swagger.documentations', []);

    foreach (array_keys($documentations) as $name) {
        $config = $configFactory->documentationConfig($name);

        if (! isset($config['routes'])) {
            continue;
        }

        $groupOptions = $config['routes']['group_options'] ?? [];

// **** 省略 ****
```
Cisco 891F設定(メモ)

# はじめに
公式のは見辛くて，個人ブログなどは欲しいところがなかったり...
最低限だけどなんとか設定できたから，とりあえず忘れないようにメモ．
ずっと書こう思って今やっと書く:thinking:

# 使用機材
Cisco 891Fルータ
PC(MacBook Pro 2018, Monterey)
コンソールケーブル
電源アダプタ(自作)

# 設定していく
## 構成
オクで買ったら電源がなかったので，12V出力ACアダプタ買って，それにATX電源からとったCPUコネクタを繋いで，簡易的な電源を作った．コネクタが挿さったのは偶然笑．未使用コードの末端はカプトンテープで絶縁．48V電源欲しいな...(純正アダプタ買え)
<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113099/13a1d65c-3b0b-cb5f-7242-2d6066510895.jpeg">

NW構成
二重ルータ...まあ仕方ない．サーバ公開するわけでもないし．

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113099/65a831ca-e7e9-c8ac-79a9-45b46ade6831.jpeg">

## 設定コマンド
ホストネームとかその辺は色々出てるので割愛．
インターフェース設定だけ書く．

グローバルコンフィギュレーションモードに入る．
```
Router>enable
Router#configure terminal
```

vlanを作ってipを割り当てる．
```
Router(config)#vlan 10
Router(config-if)#name ClientSeg
Router(config-if)#exit
Router(config)#interface vlan 10
Router(config-if)#ip address 192.168.10.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#exit
```

ポート0から7にさっき作ったvlanをつける．
```
Router(config)#interface range gigabitethernet 0-7
Router(config-if)#switchport mode access
Router(config-if)#switchport access vlan 10
Router(config-if)#exit
```

vlan1を無効化する．
```
Router(config)#interface vlan 1
Router(config-if)#shutdown
Router(config-if)#exit
```

DHCPを作る．DNS鯖アドレスは適当．
```
Router(config)#ip dhcp pool dhcpPool1
Router(config-if)#network 192.168.10.1 255.255.255.0
Router(config-if)#default-router 192.168.10.1
Router(config-if)#dns-server 8.8.8.8
Router(config-if)#exit
```

WAN側の設定．
```
Router(config)#interface gigabitethernet 8
Router(config-if)#ip address 192.168.116.200 255.255.255.0
Router(config-if)#ip nat outside
Router(config-if)#exit
```

動的NATのためのリスト．
```
Router(config)#access-list 1 permit 192.168.10.0 0.0.0.255
Router(config)#ip nat inside source list 1 interface gigabitethernet 8 overload
Router(config)#ip route 0.0.0.0 0.0.0.0 192.168.116.254
```

## おまけ?
SFP使う設定．
```
Router(config)#interface GigabitEthernet 8
Router(config-if)#media-type sfp
Router(config-if)#speed 1000
```
未サポートトランシーバは，まだ使えない．ものによっては未サポートでもこの設定だけで使えるらしい(わからん)．
なので上記の設定でまだ使えなかったら，下記のコマンドによって使えるようになる．
```
Router(config)#service unsupported-transceiver
```

# 最後に
完全に理解したの領域なので間違っているかもしれない．
もっと勉強するぞ〜!

# 参考文献
https://maeda577.github.io/2021/07/31/c891fj.html

https://nwengblog.com/cisco-nat/

https://beginners-network.com/cisco_ios_interface.html

https://nozawana44.hatenablog.com/entry/2020/05/03/133019
【SwiftUI】外観モードを固定する

# はじめに
iPhoneにはライトモードやダークモードに二種類が存在します。
アプリによってはダークモードにさせたくない場合などあると思います。
そんな時に使えるモディファイアを紹介します

# ライトモード固定
```diff_swift
struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
        }
+       .preferredColorScheme(.light)
    }
}
```

# ダークモード固定
```diff_swift
struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
        }
+       .preferredColorScheme(.dark)
    }
}
```

# おわり
私はこの機能を使用して、アプリ内で外観モードを変更できる機能を提供しています。
Salesforce　SFDXチート集

自分用ですが、よく使うsfdxコマンド、便利なコマンド。
随時追加していきま～す(=^・^=)

※最近はsfdxより便利なsfコマンドが出ているので今後更新します。

### 前提条件
①VSCodeを使用
②VSCodeに以下の拡張機能がはいっていること
・Salesforce CLI Integration
 ・Salesforce Package.xml Generator Extension for VS Code
③メタデータは./mdapi配下に置く

### 組織認証
##### ◆本番
```html
sfdx force:auth:web:login -a <alias>
```
##### ◆Sandbox
```html
sfdx force:auth:web:login -a <alias> -r https://test.salesforce.com
```


### gitから取得
```html
git clone https://github.com/*********/*****.git
```

### リトリーブ（組織からメタデータを取得）
※「Package.xml Generator」より、manifest配下にpackage.xmlを作成しておくこと
※\<alias>には、認証した組織のAliasまたは、ユーザ名のどちらでも指定可能
```html
sfdx force:mdapi:retrieve -u <alias> -r ./mdapi/<取得したメタを格納するフォルダ名> -k ./manifest/package.xml
```


### コンバート（メタデータをソース形式に変換）
※リトリーブした後のフォルダを解凍しておくこと
```html
sfdx force:mdapi:convert -r ./mdapi/<コンバートしたいメタデータが入っているフォルダ> 
```
▶force-app/main/default配下のソースに対して直接修正＆デプロイができるようになる。「--outputdir」を指定した場合、指定したディレクトリにコンバートしたソースを保存できる


### リリース検証
```html
sfdx force:mdapi:deploy -d ./mdapi/<リリース資源が格納されているフォルダ名> -u <alias>  -c
```

### リリース
※「-w」は待機時間の秒数指定。省略可能
```html
sfdx force:mdapi:deploy -d ./mdapi/<リリース資源が格納されているフォルダ名> -u <alias> -w 10
```

※一部のテストのみ実行する場合は、「-l」を指定
```html
sfdx force:mdapi:deploy -d ./mdapi/<リリース資源が格納されているフォルダ名> -u <alias> 
-l RunSpecifiedTests -r <テストクラス名１>,<テストクラス名２> -w 10
```
### ガバナ確認
```html
sfdx force:limits:api:display -u <alias>
```

### データをエクスポート
```html
sfdx force:data:tree:export -q "<SOQLクエリ>" -u <alias>
```

### データをインポート
```html
sfdx force:data:tree:import -f ./<インポートしたいJSONファイル名>.json -u <alias>
```
【M5Stick】勉強時間をスプレッドシートに記録するシステムを作った

## 目的
スマホで勉強時間を記録していたが、記録するたびにスマホいじりで時間ロスが発生していた。
記録機能のみのIoTで時間を計測すればスマホの使用時間を減らせるのでは考え作成した。

## 必要なもの
- [M5StickC Plus](ssci.to/6470)
- [GoogleSpreadSheet](http://sheets.google.com/)

## 使い方
電源を入れ、wifiに接続ができたら、Standbyと表示される。
![standby.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125452/e8c5162f-fef8-4499-8dc0-d92e9491f615.jpeg)

M5ボタンでタイマー開始
![now.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125452/8694cf86-b6c5-f370-8f33-caa8273971d4.jpeg)

もう一度M5ボタンを押すとタイマーが止まり、内部に保存される。もう一度図ると、送信するまで加算される。
![1stend.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125452/2b8825e4-485a-9f4c-dcca-62c3a42b227a.jpeg)

サイドボタンを2秒押すとGoogleSheetに送信される。
![timesend.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125452/76537509-882a-eabd-bb36-cfe811104e46.jpeg)

最初の状態に戻り、また、計測ができるようになる。

## 工夫ポイント
時間計測中に再度ボタンを押すと時間表示のみが消えます。時間を気にして勉強に集中出来ない時に有効な機能です。

↓実際の動作
<iframe width="402" height="400" src="https://www.youtube.com/embed/UFyNzcZr9SM" title="【M5Stick】勉強時間をスプレッドシートに記録するシステム" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>


### 参考にさせていただいた記事
- [M5stickCを使用したセンサーの値をGoogleスプレッドシートに](https://make-iot.com/2020/12/19/m5stickcを使用したセンサーの値をgoogleスプレッドシート/)(sheet側の設定など)

使用したコードは[こちら](https://github.com/11104/CodeeTime)
Font Awesome　アイコン　備忘録

# FontAwesome　備忘録（2023/3版）

FontAwesome には、2つ導入方法がある。
1．ダウンロード
2．インターネットを介した、CDNを使う方法


今回は、**2のCDN** を採用します。

## 使い方

#### ステップ1

https://fontawesome.com/　

に入り、アカウント作成、またはログイン

#### ステップ2
Kits の画面から、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2101809/f89488f6-2351-bef3-c3de-f3eee83a193a.png)

**Add New Kit** で、新しいKitを作成する。

すると、以下のように、新しいKitが作成される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2101809/6a662c80-0d42-36af-d913-0e079ffa3a44.png)

さらに下にスクロールをすると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2101809/45748518-a846-7179-e266-c4cf03e5636e.png)

このようなJavascriptのコードが出るので、これをそのままコピーし、
お手持ちの編集ファイルの
```<head>```内にはっつけましょう!
迷ったら、```</head>```の前で良いでしょう。

これで準備完了です！
あとは、好きなアイコンのコードをコピーするだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2101809/dc23a2a3-bb22-5d4b-82a9-f0e1537f75d6.png)

の```<i class="fa-solid fa-tricycle"></i>```をつけたい場所に、コピペして完了です！
MajinAIを使って、プロンプトの参考を得よう

# MajinAIって？
有志の人が画像とプロンプトを挙げてくれているサイト。自分が探していたプロンプトを示すサイトの中では
結構クオリティが高い方だと思う。リンクは以下。

https://majinai.art/ja/

# 基本の使い方

とっても簡単。適当にスクロールして、好きな画像を探してみよう。
![スクリーンショット 2023-03-05 16.49.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/65a7e8dd-89be-546d-a3f4-82258254ffdf.png)

今回は以下の画像をクリックしてみる。
![スクリーンショット 2023-03-05 16.51.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/d976fa95-20ee-b9b8-5997-5322e83a9de1.png)

すると、詳細な情報を確認することができる。
![スクリーンショット 2023-03-05 16.52.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/7fc793f6-61e3-14fa-0328-4d638fe093eb.png)

- プロンプト
- ネガティブプロンプト
- サイズ
- モデル
- 解像度
- シード値
など、必要な情報を得ることができる。

infoの横の別タブボタンから、写真の個別ページのリンクを得ることもできる。

https://majinai.art/ja/i/yX4Yli2

また、png,webpの先のリンクを押せば、画像のみのリンクにアクセスできる。これにより、すぐに画像を共有することが可能。
![スクリーンショット 2023-03-05 16.58.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/26d8d73a-a605-a073-c6e6-07efbc456349.png)

ためしに、ここのプロンプトをコピーして、自前のStablediffusionで試してみる。モデルは違うが、やってみよう。

実行すると、以下のような形で画像が出てきた。ほぼ一緒なのがいいね。
![スクリーンショット 2023-03-05 17.00.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/96672f21-5be6-9e86-51e6-d8de164a2c97.png)


また、最初の検索の部分では、モデルでソートしたり、
![スクリーンショット 2023-03-05 17.04.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/9931b93f-c5e0-0687-22cf-41d7d1698491.png)


並び替え順を変更することができる。（最初はランダム。）
表示、閲覧回数の降順でソートすると、良い絵が出てくる率が上がる気がする。（あくまで個人的な感想）
![スクリーンショット 2023-03-05 17.06.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/09d72308-c6ab-3177-5664-0bdc842dc9b1.png)

また、年齢制限を変更することも可能
![スクリーンショット 2023-03-05 17.06.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/2da475da-08e3-45bd-92b3-b55c6cbb0040.png)


最後にもう一度試しに作ってみる。
モデルはないのだが、
- sampler
- seed
は二つとも指定できるので、試してみる。
すると、こんな感じで出てきた。雰囲気は似てる。
![スクリーンショット 2023-03-05 17.28.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/047a3734-e89e-47c8-b768-a47e35417e5b.png)


https://majinai.art/ja/i/tGc6iaw
MySQLで ERROR 1064 (42000) のエラーが出てユーザーが削除できないときの対処法

MySQLでユーザーを削除しようとしたところ 「ERROR 1064 (42000)」が出ました。
原因は、ユーザー名にハイフンがあったからです。
 **シングルクォーテーションでユーザー名を囲むと削除できます。**
これはデータベースなどを削除するときも同じようです。
([こちらの記事](https://qiita.com/niwa1903/items/c8d9eaff46fcd08dacc5)では「バッククォートで囲む」とありますが、シングルクォーテーションでもできました)

```
mysql> SELECT user, host FROM mysql.user;
+------------------+-----------+
| user             | host      |
+------------------+-----------+
| dev-user         | %         |
| mysql.infoschema | localhost |
| mysql.session    | localhost |
| mysql.sys        | localhost |
| root             | localhost |
+------------------+-----------+
5 rows in set (0.03 sec)

mysql> DROP USER dev-user;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-user' at line 1
mysql> DROP USER 'dev-user';
Query OK, 0 rows affected (0.08 sec)

mysql> 
```
Unity公式が公開しているプログラミングパターンを読み取ってみた！～その11. Observer～

# はじめに
Unity公式がプログラミングパターンのデモを説明書と共に全12種公開していたので、1つずつ読み取っていきたいと思います！
英語の説明書でしたので間違った解釈をしているかもしれませんが、ご了承下さい！
最初の5種は、SOLID原則に沿ったデモとなっており、コードのみが公開されています。
残り7種は、Scene付きのデモが入っていますので、ZIPファイルをダウンロードして試してみてください。
今回は、11個目のObserverについてです。

https://github.com/Unity-Technologies/game-programming-patterns-demo

https://resources.unity.com/games/level-up-your-code-with-game-programming-patterns

# 環境
OS : Windows10
Unity バージョン : 2021.3.8f1

# Observerパターンとは
ある1つのオブジェクト(=Subject)の状態が変化すると、それを観察しているオブジェクト(=Observer)が、登録してあった処理を実行するというデザインパターンです。一般的に、1つのSubjectに対し複数のObserverが存在するときに疎結合にしてくれてコードが見やすくなるという特性があります。

# デモ
デモでは、Subjectボタンを押すと、Observerのスピーカーからパーティクルとサウンドが流れるようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368729/2f9cb8d0-d521-ea57-bcef-32d786eff43f.png)

Subjectボタンには、ButtonSubjectクラスがアタッチされています。
ボタンがクリックされると、Clickedに登録してある処理が着火するようになっています。
```C#
public class ButtonSubject: MonoBehaviour
{
    // これがSubject
    public event Action Clicked;

    private Collider collider;

    void Start()
    {
        collider = GetComponent<Collider>();
    }
    // ボタンがクリックされた時の処理
    public void ClickButton()
    {
        // Clickedに登録されてある処理が走る
        Clicked?.Invoke();
    }

    void Update()
    {
        CheckCollider();
    }

    private void CheckCollider()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hitInfo;

            if (Physics.Raycast(ray, out hitInfo, 100f))
            {
                if (hitInfo.collider == this.collider)
                {
                    ClickButton();
                }
            }
        }
    }
}
```
今回は、パーティクルを表示させているParticleSystemObserverしか記載しませんが、サウンドも同様の処理になっています。
```C#
public class ParticleSystemObserver : MonoBehaviour
{
    [SerializeField] ButtonSubject subjectToObserve;
    [SerializeField] ParticleSystem particleSystem;

    private void Awake()
    {
        if (subjectToObserve != null)
        {
            // Subjectが変化するとOnThingHappenedが走るように登録。ここがObserver
            subjectToObserve.Clicked += OnThingHappened;
        }
    }

    private void OnThingHappened()
    {
        if (particleSystem != null)
        {
            particleSystem.Stop();
            particleSystem.Play();
        }
    }

    private void OnDestroy()
    {
        if (subjectToObserve != null)
        {
            // 登録した処理は、オブジェクトが破棄されるときに登録解除する
            subjectToObserve.Clicked -= OnThingHappened;
        }
    }
}
```
このようにButtonSubjectからParticleSystemObserver内のメソッドを呼び出すことはなく、Clickedを公開しているだけなので、疎結合になっているといえます。

# まとめ
Observerパターンとは、観察される側(=Subject)が変化したときに、観察している側(=Observer)に登録してあった処理が走るデザインパターンです。
後に書くMVPデザインパターンとも親和性が高いらしいので是非チェックしてみてください！
CakePHP2のページネーションで検索条件が反映されないときの解決法

CakePHP2初心者です。
詰まったことを解決したとき、備忘も兼ねて書き留めておきます。

■問題
条件を指定して絞り込み検索をしたとき、1ページ目には絞り込まれた結果が表示されるが、2ページ目以降では絞り込みが外れた結果が表示されてしまった。
(A条件で絞り込み検索したとき、1ページ目はA条件で絞り込まれた結果が表示されて、2ページ目以降はA条件に該当しないレコードも表示される。)

■原因
検索文言を取得する箇所はPOST処理で値が取得されるのに対し、ページ遷移はGET処理なので、ページネーションした際に検索文言が保持できていなかった。

■解決策
POST処理時に検索条件をセッションに保持し、GET処理時にセッションを読み込むことで解決。



参考：
公式ドキュメント：PaginatorHelper
https://book.cakephp.org/2/ja/core-libraries/helpers/paginator.html
セッション
https://book.cakephp.org/2/ja/core-libraries/components/sessions.html
Qiita記事
https://qiita.com/BRSF/items/4b1017be88a8b8a03744
paiza.ioでelixir その207

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

# 練習問題
qiita apiを叩いて、記事を投稿せよ。

# サンプルコード

```
:inets.start
:ssl.start

token = "***"
json = """
{
  "body": "# テスト", 
  "private": true,
  "title": "テスト",
  "tags":[{
	  "name": "hoge",
	  "versions": []
	}]
}
"""
{:ok, {{_, _, _}, _, body}} = :httpc.request(:post, {
	'https://qiita.com/api/v2/items', 
	[{'Authorization', 'Bearer #{token}'}], 
	'application/json', 
	json
}, [], [])
IO.puts(body)



```

# 成果物

https://paiza.io/projects/JI62k7mkzymIVeQXt4cIUQ


以上。
Github Actionsの自分用メモ


## hello world

使ってるtokenの権限にworkflowを入れる必要がある。


Github → Settings → Developer Settings → Personal Access Tokens
→ Generate new token




```:helloworld.yml
name: Hello World

on: 
  workflow_dispatch:

jobs:
  say_hello:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Hello World!"
```

https://qiita.com/daytwist/items/f9eac0df2933e2f0169c


https://qiita.com/Teach/items/d2c4d7bec98228df1807

## EC2デプロイ



https://qiita.com/kaino5454/items/bae4bca47e6f409e072f

## herokuへpushする時

マーケットプレイスに雛形が載ってる。
https://github.com/marketplace/actions/heroku-action


ソース全体
https://github.com/miyamotok0105/docker_sample/tree/master/01docker/Flask-Basic-CICD-GithubActions-Heroku


```yml:.github/workflows/main.yml
# ワークフロー名
name: CI

# Controls when the workflow will run
on:
  # push masterブランチのタイミングで実行
  push:
    branches: [master]

  # workflow_dispatchを指定しておくとGitHubのコンソールから実行可能になる
  workflow_dispatch:

# ワークフローの実行処理
jobs:
  # This workflow contains a single job called "build"
  build:
    # ubuntuで実行
    runs-on: ubuntu-latest

    # ジョブのステップ
    steps:
      # ブランチをチェックアウト
      - uses: actions/checkout@v2

      # アクションの一覧
      # https://github.com/marketplace?type=actions
      # uses: アカウント/アクション-リポジトリ-名前@vバージョン
      - uses: akhileshns/heroku-deploy@v3.12.12 #
        with:
          heroku_api_key: ${{secrets.HEROKU_API_KEY}}
          heroku_app_name: ${{secrets.HEROKU_APP_NAME}}
          heroku_email: ${{secrets.HEROKU_EMAIL}}
```
Googleデジタルマーケティング＆Eコマース：検討ステージの基礎

# はじめに

”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/77505f22-0d8f-b3af-4f9c-ed148bcefd65.png" width="800">

[以前、マーケティングファネル][funnel]を紹介しました。今回、検討ステージについて、もう少し詳しく説明します。

[funnel]: https://qiita.com/mapami/items/56f851127a0880d3c97e

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/65ce701b-3a0b-d904-a484-d9d4bf70e7b0.png" width="300">

# 検討ステージの目標

検討とは、あなたのことを知るための段階です。このステージでは、あなたのビジネスについて調べ、競合他社と何が違うのかを見つけてもらいます。

このステージでは、

***<font color="MediumVioletRed">『潜在顧客が最終的に購買に至る可能性を高めること』</font>***　

が目標です。

この時期には、オンライン・レビューを読んだり、ウェブサイトを積極的に閲覧したりしている可能性があるので、そのような人たちに、このサイトに留まる理由、あるいはすでに離れてしまった人たちが再び戻ってくる理由を与える必要があります。

# リードを増やす戦略

このステージで、一部の潜在顧客はリードになります。

***<font color="MediumVioletRed">『リードとは、ブランドと交流し、Eメールアドレスなどの個人情報を共有した潜在顧客のこと』</font>***

冷蔵庫の例で考えてみましょう。

顧客は、あなたのWebサイトにアクセスして、いくつかのモデルをチェックしますが、すぐに決断するわけではありません。考える時間が必要なのか、さまざまなブランドを比較したいのか、あるいはただ気が散ってしまっただけなのかもしれません。

戦略として、お客様が訪れた製品やページに基づいて広告を配信することで、その人を再び惹きつけることができます。そうすれば、購入のために再訪問してくれる可能性が高まります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/f50ccfb2-6f6b-b7bc-3af4-4bb3a38d863d.png" width="600">

潜在顧客がサイトにアクセスしたら、自社の製品について説明し、特定の製品やサービスがどのように顧客の悩みを解決するかを説明する必要があります。

- これは、ブログ記事・ニュースレターなど、魅力的で有益なコンテンツを提供することを意味します。
- また、無料サンプル・トライアルメンバーシップを提供することで、潜在顧客にサービスを試してもらうことができます。

目標は、製品の品質に対する信頼を築き始め、顧客が十分な情報を得た上で選択するのに必要なものを提供することです。

この検討ステージでは、何を提供し、どのように顧客のニーズを満たすことができるかを明確にする必要があります。

# 検討の測定

検討ステージでは、成功を測定するさまざまな方法がありますが、それらはすべて1つの考えに帰結します。それは、エンゲージメントです。

***<font color="MediumVioletRed">『エンゲージメントは、潜在顧客がどれだけ、頻繁に、どれだけの時間、あなたのコンテンツに関与しているかどうか』</font>***

測定基準には、次のものがあります。

- 顧客がオンラインであなたのビジネスを検索する頻度
- サイトへの初回訪問者数
- 訪問者あたりのページ数
- 訪問者が1ページに費やす時間
- メールやニュースレターへの登録数

顧客の連絡先情報を得ることで、企業の存在を思い出してもらい、後々価値を実証することが容易になります。

エンゲージメントが高ければ高いほど良いように思われるかもしれませんが、必ずしもそうとは限りません。顧客が必要なものを素早く見つけることが目標なのに、顧客がタスクを完了するのに長い時間を費やしている場合、Webサイトのレイアウトを見直す必要があるかもしれません。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/9f3126b2-735c-d080-fab5-f989b3902091.png" width="600">

Webサイトのインタラクションを測定することで、多くの知見を得ることができます。そのため、どの数字が重要で、目標に対してどのような意味を持つのかを知ることは非常に重要です。
Notion AIで表や表計算を使う

# 概要
Notion AI
https://www.notion.so/ja-jp/product/ai

文章作成は色々記事がありますが、表に関する記事をあまり見かけないので色々試してみました。

## アイデアを表にまとめてもらう
「〜〜を表にまとめて」と伝えるとまとめてくれます。
考えの整理に良さそう。
![テーブル化.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217321/6b8483c0-931b-ebe1-3f3b-7787be00125f.gif)

## 表計算①：掛け算・足し算
はじめ間違ってる（？）けど計算方法聞くと直してくれた。
![表計算.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217321/d97fd153-39cc-7280-11f6-695e2284a5a1.gif)

## 表計算②：予測
予測の計算方法伝えると計算してくれる。
![予測.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217321/5fb12272-e48a-f586-217a-e6f5cfcda610.gif)

## （番外）数式で計算
![計算.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217321/f7ef6f0a-bf2e-e3c5-00ed-64cbf70f49c4.gif)

## 感想
- パワポに使う表の作成くらいなら捗りそう
- がっつりした表計算ならエクセルが確実だが、意外な計算方法とか教えてくれそう
- そのうちオフィスにAI投入されそう・・でも個人的にNotion好きなので頑張って欲しい