OmniAICreator/Qiita-1.07M huggingface dataset:
root権限を持ったディレクトリの書き込み権限開放方法

# はじめに
この記事ではroot権限を持っており、自身のアカウントでは書き込み権限や移動権限がないためなにも操作できないディレクトリの権限開放の方法を紹介します。
自分が割と困ったのでこれからの人達のためになればと思っています。

# そもそもrootってなんだ？
そもそもrootとは何者なのでしょうか？
rootとは，UNIX系OS（MacOS・Linuxなど）の全ての操作が可能な” 管理ユーザ "という位置づけになっています．文字通り，全ての操作が可能ですので，ファイルの削除などはもちろんのこと他人ユーザのファイルなどの操作もできてしまう，いわば**そのOS内での最高権力者**であるわけです．
逆に言えば他人にroot権限が渡ってしまえばかなり危険な状態になるので慎重に管理しましょう。

# じゃあそのrootに入り込んでみよう
ここまでの情報はこの記事を読む人にとってそこまで必要な情報ではないでしょう（笑）
さっそくroot権限を持つディレクトリの権限開放について説明します。
なお，常時rootとしてPCを使用するのはセキュリティ上お勧めできません．なのでここでは自分のアカウント上からrootに**一時的**にアクセスする方法を紹介します．
## 本記事でのPC環境
以下にこの記事におけるユーザやディレクトリを書いておきます．
ユーザーネーム：students
root権限がかかっているディレクトリ：Documents　
ディレクトリパス：/home/students/Documents
現状はstudentsというユーザーとしてPCを操作しているとします．
## rootに入るコマンド　$ su
一時的にrootに入るコマンドとして，suを紹介します．
```
$ su
```
これは " Super-User "の略でこれを実行するとrootとしてPCに入ることができます
実際に実行してみた画像がこちらです．

root権限に入ることが出来たら，権限を変更したいディレクトリがある上位ディレクトリまで移動します．
```
cd /home/students
```
上位ディレクトリまで来たら，以下のコマンドを実行して所有者を変更します．
```
chown user-name file-name
```
chownというコマンドは所有者を変更してくれるコマンドです．chownの後に新しい所有者を，その後に権限を開放したディレクトリ名を実行します．
この記事の場合は以下のコマンドになります．
```
chowm students Documents
```
これを実行するとターミナル上では何も起こりませんが，ファイルディレクトリまで行くと，先ほどまであったオレンジ色の鍵マークがなくなって書き込みできるようになっているはずです．

# 最後に
今回はroot権限を開放する方法を紹介しました．お困りの方はぜひ試してみてください．
【初学者】malformed module path "command-line-arguments": missing dot in first path elementの解決手順

# はじめに
お疲れさまです！
おおくまです！

https://www.udemy.com/share/103TVa3@4kwnCMQ2PbkgS2i2YK2IF6VPItXbl8tA-PI4XVWjk6Snxsv71ohaHmMYakH42khRcA==/

こちらのコースのセクション13で、``malformed module path "command-line-arguments": missing dot in first path element``というエラーが出ました！
その解決手順の備忘録です！

# 注意点
:::note warn
私はプログラミング学習中で、初学者です。
内容に誤りがある場合があります。
コメント等で教えていただけると幸甚です。
:::

# エラー内容

```:ディレクトリ構成
.
└ workspace
  └ golang_kisonyumon
    └ section13
      ├ foo
      │ └ foo.go
      └ main.go
```

```go:main.go
package main

import (
	"command-line-arguments/Users/ryoyaokuma/workspace/golang_kisonyumon/section13/foo/foo.go"
	"fmt"
)

func main() {
	fmt.Println(foo.Max)
}
```

```go:foo.go
package foo

const (
	Max = 100
	min = 1
)

func ReturnMin() int {
	return min
}
```

```:ターミナル
go run main.go

main.go:4:2: malformed module path "command-line-arguments": missing dot in first path element
```

エラーが出てしまいます！
``main.go``の``"command-line-arguments/Users/ryoyaokuma/workspace/golang_kisonyumon/section13/foo/foo.go"``の部分があやしそうですね！

# 解決方法

```:ターミナル
go mod init example.com/section13
```
このコマンドを打つと``go.mod``ファイルが作成されます！

```mod:go.mod
module example.com/section13

go 1.21.3
```

次に``main.go``ファイルを編集します！

```go:main.go
package main

import (
	"fmt"
	"example.com/section13/foo"
)

func main() {
	fmt.Println(foo.Max)
}
```

```:ターミナル
go run main.go
100
```

無事に表示されればOKです！

<br>

最後まで読んでいただきありがとうございました！
Kuernetesテンプレートエンジンをリストアップしてみた

本記事は個人的な見解であり、筆者の所属するいかなる団体にも関係ございません。

# 0. はじめに

Kubernetesで使うテンプレートエンジンとしてHelm Chartってのがありますが、他にもどんなのがあるかなと思って探してみた誰得な記事です。

紹介している順番に意味はありません。

## 1. Helm Chart
言わずと知れたKubernetesのデファクトテンプレートエンジンです。
嫌われることも多いですが。

Helm
https://helm.sh/ja/

## 2. Kustomize

kubectlにも組み込まれているテンプレート適用ツールです。

Kustomize - Kubernetes native configuration management
https://kustomize.io/

## 3. helmfile

helm chartがDeclarativeになるとい意味でこちらに入れてみました。

helmfile
https://helmfile.readthedocs.io/en/latest/

## 4. ytt

ちょっと前のCloud Native Daysで紹介されていた？ytt
筆者は使ったことはありません。

Carvel - Carvel - ytt
https://carvel.dev/ytt/

## 5. kubes

テンプレートというよりはデプロイツールに近いが、Kustomizeみたいな宣言ができるみたい。

Kubes | The Kubernetes Deployment Tool
https://kubes.guru/

## 6. Kluctl

こちらも、どちらかと言えばデプロイツールですね。
デプロイ操作をテンプレート化できるという事みたいですが、筆者もよく分かっていません。

kluctl.io
https://kluctl.io/

## 7. cue

一見するとYAMLの定義をチェックするツールにも見えますが、定義を書き換えることもできるので入れてみました。

CUE
https://cuelang.org/

## 8. Tanka

正確にはYAMLテンプレートエンジンというよりは、jsonnetを使ったマニフェスト生成ですが、一応入れてみました。

Introduction | Tanka
https://tanka.dev/#highlights

## 9. cdk8s

もう、ここまでくると完全にYAMLじゃないですね。

cdk8s
https://cdk8s.io/

## 10. まとめと参照

ざっくりまとめてみましたが、kustomizeとhelmで生きていくしかなさそうです。
こういうのがあるぜ！とご存じのものが抜けていることがありましたら、コメントでお教えいただければ幸いです。


【参照】
- Alternatives to Helm? : r/kubernetes
https://www.reddit.com/r/kubernetes/comments/11m06lr/alternatives_to_helm/


- 環境ごとにパラメータを変えて、Kubernetesマニフェストを自動生成する #kubernetes - Qiita
https://qiita.com/kentarok/items/d935e5e2a53548aa0c3f

## 11. そのほか

ksonnet → 終了
Podが「ContainerCreating」のまま起動しない

kubernetes環境での作業にも慣れてきたところでぶつかった問題とその解決方法を紹介します。  

# トラブル発生
Kubernetes環境で、3つのPodから構成されるアプリケーションを使用していた際に、  
特定のノードでPodの状態が「ContainerCreating」のまま止まってしまいました。

問題のPodのdescribeを確認してみるとエラーを吐いていました。  
以下は、Eventログの抜粋です。
```
Events:
  Type     Reason                  Age                     From     Message
  ----     ------                  ----                    ----     -------
  Warning  FailedCreatePodSandBox  4m31s                   kubelet  Failed to create pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container "ba883b271864c900c8a75025d117a57649c427f80ea2bc60fc94bde3435186df" network for pod "feature-extraction-0": networkPlugin cni failed to set up pod "feature-extraction-0_edgeai-msa" network: failed to delegate add: failed to set bridge addr: "cni0" already has an IP address different from 10.244.13.1/24
  Warning  FailedCreatePodSandBox  4m30s                   kubelet  Failed to create pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container "5fedc4770e80bbf09c11809d9b81cebb0db10165b2e429ff6a5d67203cc47811" network for pod "feature-extraction-0": networkPlugin cni failed to set up pod "feature-extraction-0_edgeai-msa" network: failed to delegate add: failed to set bridge addr: "cni0" already has an IP address different from 10.244.13.1/24
```
色々と言っていますが、どうやら  
「**"cni0" already has an IP address**　すでにIPアドレスを持っている」  
というエラーが原因のようです。

# 解決方法
結論から言うと、クラスターを抜けるときの手順が不十分だったようです。  
試行錯誤していた中で、クラスターから抜けることがあり、  
抜けるノードでは「kubeadm reset」をすれば良いと思っていましたが、  
インターフェースも削除する必要があるようです。

インターフェースの削除（インターフェース名は環境によります）
``` bash
$ sudo rm /etc/cni/net.d -r
$ sudo ip link delete flannel.1
$ sudo ip link delete cni0
```

削除後に、改めてクラスタにjoinしてみると、無事動きました！
```
$ kubectl get po -n hoge
NAME                               READY   STATUS               RESTARTS       AGE    IP      NODE       NOMINATED NODE   READINESS GATES
pod/test-1                         0/1     Completed            0              30s    XX      node-1     <none>           <none>
pod/test-2                         1/1     Running              0              30s    XX      node-2     <none>           <none>
pod/test-3                         1/1     Running              0              30s    XX      node-3     <none>           <none>
```

# まとめ

kubeadmでresetをすれば大丈夫でしょ、と過信してしまっていました。  
以下にクラスターを抜けるときの手順をまとめたので参考にしてください。

## クラスターを抜けるときの手順

- 特定ノード(node-1)へのスケジュールの停止（マスターノードで実行）
  ```
  kubectl cordon node-1
  ```
- Podの追い出し（マスターノードで実行）
  ```
  kubectl drain node-1 --ignore-daemonsets
  ```
- nodeの削除（マスターノードで実行）
  ```
  kubectl delete node node-1
  ```
- 設定のリセット（抜けるノードで実行）
  ```
  sudo kubeadm reset
  ```
- インターフェースの削除（抜けるノードで実行）
  ```
  sudo rm /etc/cni/net.d -r
  sudo ip link delete flannel.1
  sudo ip link delete cni0
  ```
文字列のHTMLをHTMLの要素に変換する

```js
new DOMParser().parseFromString(a, "text/html").body.firstElementChild;
```
### 出典
https://pote-chil.com/blog/parse-string-to-html-element

# DOMParser()
DOMParserインターフェイスは、```XMLやHTMLソースコードを文字列からDOMのDocumentに解釈```する機能を提供します。

### 出典
https://developer.mozilla.org/ja/docs/Web/API/DOMParser#:~:text=DOMParser%20%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%95%E3%82%A7%E3%82%A4%E3%82%B9%E3%81%AF%E3%80%81%20XML%20%E3%82%84%20HTML%20%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E6%96%87%E5%AD%97%E5%88%97%E3%81%8B%E3%82%89%20DOM%20%E3%81%AE%20Document%20%E3%81%AB%E8%A7%A3%E9%87%88%E3%81%99%E3%82%8B%E6%A9%9F%E8%83%BD%E3%82%92%E6%8F%90%E4%BE%9B%E3%81%97%E3%81%BE%E3%81%99%E3%80%82

新しいDOMParser オブジェクト作成します。

### 出典
https://developer.mozilla.org/ja/docs/Web/API/DOMParser#:~:text=%E6%96%B0%E3%81%97%E3%81%84%20DOMParser%20%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E4%BD%9C%E6%88%90%E3%81%97%E3%81%BE%E3%81%99%E3%80%82

# parseFromString()
このインターフェイスparseFromString()のメソッドはDOMParser、```HTML または XML を含む文字列を解析```し、HTMLDocumentまたは を返しますXMLDocument。

### 出典
https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString#:~:text=%E3%81%93%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%95%E3%82%A7%E3%82%A4%E3%82%B9parseFromString()%E3%81%AE%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AFDOMParser%E3%80%81HTML%20%E3%81%BE%E3%81%9F%E3%81%AF%20XML%20%E3%82%92%E5%90%AB%E3%82%80%E6%96%87%E5%AD%97%E5%88%97%E3%82%92%E8%A7%A3%E6%9E%90%E3%81%97%E3%80%81HTMLDocument%E3%81%BE%E3%81%9F%E3%81%AF%20%E3%82%92%E8%BF%94%E3%81%97%E3%81%BE%E3%81%99XMLDocument%E3%80%82

# parseFromString(string, mimeType)
* string
```解析する文字列```。HTML、xml、XHTML、または svgドキュメントのいずれかを含める必要があります 。

* mimeType
```文字列```。この文字列は、文字列の解析に XML パーサーと HTML パーサーのどちらを使用するかを決定します。有効な値は次のとおりです。

    * text/html
    * text/xml
    * application/xml
    * application/xhtml+xml
    * image/svg+xml

```js
parseFromString(a, "text/html")
```
### 戻り値
引数に応じて HTMLDocument、 または。 XMLDocumentmimeType

### 出典
https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString

### 気づき
aの文字列をHTMLの文字列を解析させるのかな

# .body
Document.body プロパティは、その文書の <body> または <frameset> ノードを表し、そのような要素がなければ null になります。

### 出典
https://developer.mozilla.org/ja/docs/Web/API/Document/body

# 感想
まだまだ調べることがありそうだ。
Volumio3とSpotify Pluginを使いつつ、Pulse Audio Serverにする設定メモ

# 目的
タイトルの通り、Volumio3とSpotify Pluginを使いながらも
Pulse Audioによるリモートスピーカーとして動かしたのでそのメモとなります

# 環境
- Raspberry Pi 3
- Volumio3 (ver 3.546)
- Spotify Plugin 4.0.1

なお、Raspberry Pi 3にDAC-HAT(HiFi Berry DAC+)を搭載しているため
設定途中で各自環境に合わせてPulseのオーディオ出力先を変更してください


# 設定
```bash
sudo su -
apt update
apt install pulseaudio

cat << '_EOL_' > /etc/systemd/system/pulseaudio.service
[Unit]
Description=Pulseaudio Sound Service

[Service]
Type=notify
ExecStart=/usr/bin/pulseaudio --daemonize=no --system --realtime --log-target=journal
Restart=on-failure
User=volumio

[Install]
WantedBy = multi-user.target
_EOL_

cat << '_EOL_' >> /etc/pulse/default.pa
# HiFi Berry DAC+
load-module module-alsa-sink device=hw:2,0
_EOL_

systemctl daemon-reload
systemctl status pulseaudio.service
systemctl enable --now pulseaudio.service
systemctl status pulseaudio.service
```

Spotify Plugin 4.0.1の中身はgo-librespotですが、
ALSAを使おうとしてくるのでasound.confでPulseに向けてやります
```bash
sudo su -
cat << '_EOL_' > /etc/asound.conf
pcm.!default {
        type pulse
}

pcm.volumio {
        type pulse
}
_EOL_

```

# 補足
- mpdを使ってるアプリケーションもPulseを利用するよう変更が必要ですが
私の環境ではSpotfyだけ使えれば十分なので調べきれてないです
- `/etc/asound.conf` はVolumioが生成しているため、再起動すると消える?っぽいです
定時帰る術-Linux 圧縮ファイル確認（zless、zgrepコマンド）

前回、圧縮ファイルの作り方を話だが、基本的は圧縮ファイルを解凍して、ファイル操作する。
圧縮ファイルの中身を見てみたいだけで、解凍するのが面倒くさいからやりたい方もいると思う。
z系コマンドを使って、解凍せずに圧縮ファイルの中身が確認できる
（読み方はわからなく、適当にz系コマンドにした。）

### 適当に圧縮ファイルを作る
```
[root@mgmt tmp]# tar zcvf snow-log.tgz /var/log/vmware-network.1.log
tar: メンバ名から先頭の `/' を取り除きます
/var/log/vmware-network.1.log
[root@mgmt tmp]# file snow-log.tgz
snow-log.tgz: gzip compressed data, last modified: Mon Oct 30 03:57:51 2023, from Unix, original size 10240
```
普通のmoreやcatなどのコマンドで開こうとすると、文字化けになり、開けない
ここでz系コマンドの登場だ

### zless/zmoreで圧縮ファイルの中身を確認できる
**(zcatもできるが、ファイルを丸ごとでメモリに投げてしまうため、川口的にはイヤだ)**
[root@mgmt tmp]# zless snow-log.tgz
```
@^@^@^@^@^@2023年 10月 5日 木曜日 17:01:40 JST : Executing '/etc/vmware-tools/scripts/vmware/network poweroff-vm'
2023年 10月 5日 木曜日 17:01:40 JST : No argument supplied.
2023年 10月 5日 木曜日 17:01:40 JST :
```
### zgrepでgrepもできる
**aを付けないとgrepできない**
(圧縮ファイルの中では複数ファイルが存在する場合が多く、-hを付けると、ファイル名も表示できるのが便利)
```
[root@mgmt tmp]# zgrep -ah 2023 snow-log.tgz
var/log/vmware-network.1.log0000644000000000000000000000043314507466544014776 0ustar  rootroot2023年 10月 5日 木曜日 17:01:40 JST : Executing '/etc/vmware-tools/scripts/vmware/network poweroff-vm'
2023年 10月 5日 木曜日 17:01:40 JST : No argument supplied.
2023年 10月 5日 木曜日 17:01:40 JST : Finished '/etc/vmware-tools/scripts/vmware/network poweroff-vm'
```
### zdiffでdiffすることもできる
(中身も表示できるはずなのに、でない。。。)
```
[root@mgmt tmp]# tar zcvf snow-log-2.tgz /var/log/vmware-network.2.log
tar: メンバ名から先頭の `/' を取り除きます
/var/log/vmware-network.2.log
[root@mgmt tmp]# zdiff snow-log.tgz snow-log-2.tgz
バイナリーファイル /dev/fd/5 と- は異なります
```

以上
Railsプロジェクトをコンテナ化する方法

## 概要

- 既存のRailsのプロジェクトをコンテナ化する方法についてまとめました
- プロジェクト名はrails-dockerとします
- データベースにPostgreSQLも使用します
- ウェブサーバーとデータベースを別のコンテナで起動してdocker-composeで管理します

### 環境
- Ruby 3.2.2
- Rails 7.0.6
- PostgreSQL 12
- Docker 24.0.6
- Docker Compose v2.22.0-desktop.2
- M1 Mac 13.4

### 全体の流れ

- 既存プロジェクトの用意
- 各ファイルの作成
    - Dockerfile
    - docker-compose.yml
    - .env
    - .gitignore
- コンテナ化するためのコマンドを実行

## 手順

#### 既存プロジェクトの用意

- コンテナ化するプロジェクトに対して`git clone`します

#### 各ファイルの作成

リポジトリのルートフォルダに下記のファイルをそれぞれ追加します

```Dockerfile:Dockerfile
# .ruby-viersionと合わせる
FROM ruby:3.2.2

# パッケージ取得(-qqでエラーメッセージのみ表示)
RUN apt-get update -qq && apt-get install -y \
  build-essential \
  libpq-dev \
  nodejs \
  # rails dbを行う場合に必要
  postgresql-client

# 作業フォルダを指定
WORKDIR /rails-docker
# moduleをインストール
COPY Gemfile Gemfile.lock /rails-docker/
RUN bundle install
```

```yml:docker-compose.yml
version: "3"

# 永続化のためのvolume作成
volumes:
  db-data:

services:
  web:
    build: .
    # コンテナ起動時にserver起動。工数削減のためにここで毎回migrateを実行
    command: bash -c "rails db:migrate && rails s -p 3000 -b '0.0.0.0'"
    # railsで使用するportを解放
    ports:
      - 3000:3000
    # ホストとコンテナのファイルシステムの同期（リポジトリトップと/rails-docker)
    volumes:
      - .:/rails-docker
    # 環境変数
    environment:
      # dbにアクセスするpasswordを追加(.envより)。初期ユーザーはpostgresになるのでPOSTGRES_PASSWORDと一致させる
      - DATABASE_PASSWORD=${DATABASE_PASSWORD}
    # dbの後に構築
    depends_on:
      - db
    # webサーバーとdatabaseを接続
    links:
      - db
    # コンテナログイン可能化
    tty: true
    # 標準入力を許可
    stdin_open: true
  # DB側の設定
  db:
    # Dockerfile不要でimage指定
    image: postgres:12
    # 永続化のためのvolume指定
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      # デフォルト値だが記載がないと動かない場合があるので記載
      - POSTGRES_USER=postgres
      # パスワードを変更。web側のDATABASE_PASSWORDと同じ値にする
      - POSTGRES_PASSWORD=${DATABASE_PASSWORD}

```

ご存知の通り、データベースのパスワードをコードに記載するべきではありません。
そこで.envファイルを使用します。
.envが存在するとdocker-composeのビルド時に読み取り環境変数として保存します。
上記のdocker-compose.ymlで`POSTGRES_PASSWORD=${DATABASE_PASSWORD}`とした箇所が該当します。

```sh:.env
DATABASE_PASSWORD=your_secret_password
```

.envは公開するものでもないのでリポジトリの管理対象外にします。

```sh:.gitignore
# 下記を追加
.env
```

#### コンテナ化するためのコマンドを実行

下記のコマンドを実行していきます。

```sh:initialize.sh
# Dokcerのimage作成
docker-compose build --no-cache
# db作成
docker-compose run web rails db:create
# container起動
docker-compose up -d
# ブラウザ起動
open http://localhost:3000/
```

ブラウザが起動してアプリが表示されればセットアップ完了です。
ここで問題なければリポジトリにpushしましょう。
後で他のメンバがcloneした時も上記のコマンドの実行が必要になります。
ちなみに私は途中参加メンバーが環境構築をしやすいよう、initialize.shを一回実行するだけで良いようにまとめています。

#### 開発に使うコマンド

開発時に使用するコマンドを記載します。

|項目|コマンド|
|:--|:--|
|更新したコードの確認|ブラウザをリロードするだけで反映|
|コンテナ停止|docker-compose down|
|コンテナ起動|docker-compose up -d [--build]|
|コンテナ状況確認|docker-compose ps|
|インフラ構成変更|docker-compose build --no-cache|

## おわりに

Dockerを使用した既存のRailsプロジェクトのコンテナ化についてまとめました。
Dockerさえあれば環境構築が不要になる、環境を使いまわせる、チームで同じ環境で実行できる、などのメリットがあります。
もっと良い方法があると思いますので引き続き改良していきたいです。

また、記事作成にあたり下記を参考にさせて頂きました！
- [Docker ドキュメント日本語化プロジェクト](https://docs.docker.jp/compose/rails.html)
勉強を負担だと感じる人がハマっている、タスク管理の罠について。


この記事の内容
- 初心者エンジニアの勉強には、タスク管理ではなく時間管理をおススメします。
- 勉強が負担に感じるのは、日々のノルマが原因です。
- 時間管理によって、勉強を負担なく続けることができます。

<br>

エンジニアの皆さん、『勉強』できていますか？

普段から空き時間を見つけて勉強している方にとっては、それは負担になるものではないかもしれませんが、私のように向上心が低く、仕方なく勉強している人にとっては腰が重たいものですよね。

ただ、その腰の重たさは考え方（やり方）ひとつで変わるかもしれません。この記事では、私が進んで「勉強をしよう！」と思えた『時間管理』の考え方についてご紹介します。

<br>

# 時間管理とは？
時間管理についてざっくり説明すると、「その時間内で、できる限り頑張る」という考え方です。学校の授業などがそうで、1コマ50分など時間が決まっていますよね。

社会人の勉強の場合、『1日1時間勉強する』などの目標がこれにあたります。

<br>

この時点で「え？別にそんなの当たり前の考え方じゃん」と思った人は、Congratulations!!!さようなら。本記事でお伝えすることはありません。

しかし、ほとんどの人は『1日1章やる』のようなタスク管理をしており、例えば、7つの章から成る本を1週間で読破するといった具体的な目標を立てています。なぜなら、タスク管理には作業を進めるうえで時間管理よりも効果的だという、大きなメリットがあるからです。

「時間管理にするとダラダラとサボりそう」「やること決まってないとモチベーションも出なさそう」という意見も実にその通りで、実際、日本の組織の多くもタスク管理で回っています。

<br>

では、なぜ私はあえて時間管理をおススメするのでしょうか。実は、この時間管理という考え方、『継続する』という面で絶大な効果を発揮するのです。

<br>

# 「タスク管理＝ノルマに追われる」ということ
少し昔話をさせてください。私がタスク管理で Twitter の運用に失敗した時の話です。当時、SNSのインフルエンサーに憧れた私は「私もインフルエンサーになりたい」と思い、毎日の作業目標を決めて Twitter アカウントの運用をはじめました。

具体的な1日の目標はこんな感じです。
| アクション | 回数 |
|:-----------|------------:|
| ツイート      | 5回 |
| フォロー     | 30回 |
| いいね       | 100回 |
| リプライ         | 20回 |

<br>
<br>

最初の3日間はモチベーションが高いので、問題なく作業できます。順調にフォロワーも増え、そのときは「なんだ、Twitter 楽勝じゃん」と感じました。

<br>

そんな私が「これ…しんどいな」と気が付き始めたのは、作業開始から1週間後のある日です。その日は特別仕事が忙しく、夜までまったく Twitter にさわれない状況でした。それでも日々の目標をクリアしたいので、罪悪感はありつつも、適当にフォローといいねを連打して済まします。

<br>

さて、ここから目標という名の「ノルマ」に追われる日々がはじまりました。

また別の日、私のツイートにリプライを送ってくれた人への返信を考えてるうちに10分かかりました。私は「こんなことに時間を使ってしまった」と思ってしまいます。そうです、他のタスクができていないことに焦っているのです。

<br>

この時、すでに私はまともではありませんでした。

タスク管理をしていると、想定していた時間を大幅に過ぎると坂道を転げ落ちていくように作業の質が落ちます。どんなかたちでも終わらせようとするからです。そういう状況になると、もうモチベーションも上がりません。「なんでもいいから終わらせよう」と投げやりになります。



悲しいことに、Twitterにおいて質の低いアプローチはほとんどの場合逆効果です。無駄になるか、スパムアカウントを引き寄せるだけだからです。調子が良かったのは最初だけ。徐々にインプレッションとエンゲージメントが減り、フォロワーの増え方が露骨に落ちたとき…私は「あぁ…こんなはずじゃなかったのに」と落胆しました。

そして、「頑張るぞ！」と決意してからたったの1か月で私は Twitter を辞めてしまいました。

<br>

## タスク管理はしんどい
上記の話は、勉強においても同じことです。

7つの章から成る本があったとして、毎日1章を終わらすタスクを想定した時、きっとこんな壁にブチ当たり、勉強を辞めてしまう理由になるでしょう。

・後半になるにつれて、内容が難しくなる。
・時間をかけて学ぶべき、大事な章が存在する。
・実技（プログラミングなど）が発生する章がある。


なぜなら、こんなことが起こるからです。

:::note alert
・3ページに30分もかかってしまった、急がないと…
・今日中に終わらせないといけないから、あまり理解できてないけど先に進もう
・実技までやってる時間ないからここはスキップしよう
:::

※それでも時間をかけて勉強できる人はいるかもしれませんが、本記事では勉強を負担だと考えている人向けなので、こういうことが「起こる」前提で進めます。

<br>


つまり「ところどころ適当にやってしまった…なんか後半になるにつれて分からなくなってきたなぁ…あ～あ、なんか面倒くさくなってなぁ」という悪循環に陥りやすくなります。

<br>

では、これを時間管理にしてみましょう。少々極端ですが、こんな感じに変わります。

:::note info
・3ページに30分もかかったけど、それだけ内容が難しかったってことやな。
・そんなに進まなかったけど、本質みたいなモノが理解できたからいいや。
・今日は実技しかできなかったけど、さらに理解が深まったぞ！
:::

<br>

どうでしょう。控えめに言って最高じゃないですか？

別に本のページ数が進まないのは仕方がない、その分内容は濃いし、理解もしているから気になりません。ノルマじゃないから罪悪感もありません。

<br>

**

<br>

結論が遅くなり申し訳ございません。時間管理の方がいい理由、それは精神的に疲れることがないので、無理なく継続しやすいことです。

こういうと「本1冊読み終わるのに何日かかるか分からないじゃないか」と思われる方がいるかもしれませんが、それでいいのです。理解していないまま先に進む、もしくは辞めてしまうよりマシです。


ノルマに追われることはストレスです。逆に、ノルマに追われないことはストレスフリーです。むしろ、その時間内に思ったより進んだ場合は、自己肯定感が高まることすらあります。

<br>

# あとがきに代えて
この記事では時間管理にするメリットを示しましたが、最終的には自分が向いているなと思った方法を取ればいいと思います。タスク管理の方が性に合っている人もいます。

勉強、キツいですが頑張っていきましょう。また、もうすでに習慣化できている人は尊敬します。勉強を続けるためのコツなどあれば、是非ともコメントで教えてください。

<br>
<br>

以上です。
AWS SSMのフリートマネージャーについて！インスタンスのファイルシステムやパフォーマンス、プロセスなどを管理

# ■概要
SSM（Systems Manager）のフリートマネージャーと機能的にできる事を書いてみます。
機能が多く複雑そうに見えますが、使いこなせればとても便利なものです！

# ■フリートマネージャー
まずフリートマネージャーについてですが、以下はSSMのフリートマネージャーのページです。
ここでマネージドノードとなっているインスタンスは接続やパフォーマンスの確認といった様々なアクションを実行できます。

![フリート1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/f1f8a2a1-e9c7-23cb-3aa0-b6650b4bcd2b.png)

# ■マネージドノードのやり方
EC2インスタンスに対してSSMの機能を活用する為には、
対象インスタンスをマネージドインスタンス、もといSSM管理可能なインスタンスにする前準備が必要です。
以下の３つの条件が必要となります。

1.IAMロールの紐付け（AmazonSSMManagedEC2InstanceDefaultPolicy が必須）
2.SSMエージェントがインストールされている
3.SSMエンドポイントとの通信（パブリックIPかエンドポイントを用意）

前準備が完了すると、SSM内のフリートマネージャーにマネージドインスタンスとして表示されるようになります。

# ■KMSの設定が必要
より詳細にインスタンス内の情報を管理したい場合はKMSの設定が必要になるみたいです。
例えばパフォーマンスカウンターの機能はこちらの設定が必要になります。
手順は簡単です。

1.SSMのSession Managerを開いて「編集」

![KMS1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/e7a767a2-002e-d372-d915-88625b62088f.png)

2.「Enable KMS encryption」をチェックし、keyを選択する

![20231030124535.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/edf93b8c-6578-b2c5-36b8-42489bcf4855.png)

keyがない場合は「新しいキーを作成する」から、デフォルトで大丈夫なので作成しましょう。
（新規作成する場合はリージョンを間違わないように！）

![KMS2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/17585457-5f02-f2e0-72f0-82f6002561b9.png)

3.KMS encryption が Enabled になればOKです！

![KMS3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/c8fbecae-4d06-0eb6-65d5-deeee6f3f471.png)

# ■ツールで出来ること
フリートマネージャーで確認できる事について簡単に見ていきましょう。
ここでの対象のOSはLunux2023です。

### ・ファイルシステム

ここでは中のディレクトリを確認する事ができます。
ファイルの削除やファイル移動する際のコピーなんかも出来るみたいですね。
テキストとかだと中身のプレビューも出来ます。

![ファイルシステム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/32e27e68-86fe-281e-6778-91a857e9d7aa.png)

### ・パフォーマンスカウンター

インスタンスメトリクスの確認が秒単位で観測できます。
CPU、ディスク、メモリ、トラフィックの項目があります。

![パフォーマンスカウンター.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/eb0cae62-01ed-63f0-47d1-f228c34da7f6.png)

### ・プロセス

動いているプロセスの確認が可能です。
TOPコマンドで見れるような内容が確認できそうですね。
後はプロセスを開始ができるみたいですが…？こちらは未検証です…

![プロセス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/1b3510d7-d371-4856-61dd-9bb00d66f05a.png)

### ・ユーザーとグループ

ユーザーとグループの確認が可能なんですが、ユーザーをグループに追加する事も可能になっています。
またユーザーの新規作成や削除といったアクションも実施可能です。

![ユーザーグループ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/9493f8c3-c872-1fd6-9f3c-9c9707adb2d9.png)

### ・実行コマンド

ここは語る事が多いので割愛しますが…、例えばShellScript等のコマンド実行ができて、
それ以外でも他サービスと連携して定期実行が出来たり、多用途で使用可能です。

![コマンド実行20231030121728.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/7336f6b6-48ab-57f9-63fd-c5379c04bb9d.png)

### ・パッチノード

パッチに関する操作です。
必要なパッチのスキャンであったり、インストールまで実施する事も可能です。
実行についてはログを残す事もできます。

![パッチ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/4c9d2539-76cb-d382-1b3d-3c1c518ca319.png)

簡単な内容になりましたが以上です！
Swiperの無限ループが止まるバグでアップデートできなかった人たちへ

# Swiper v9からのバグ

以下のバグを見てSwiperのアップグレードをしていない人は多く、弊社のスタッフのコードにもv8を利用しているものがあった。

> スライダー無限ループ（swiper使用： v9だと無限ループが途中で止まる 30min（swiper-slideの数に対して、slidesPerViewの指定は半分に指定しないと正常に動かない！）→v8だと正常にループする）
https://codepen.io/tera-ono/pen/Podjjmp

## Swiper v11 で loopedSlides が停止された

> `loopedSlides` parameter has been removed. If it breaks your slider loop behavior - try to use new loopAdditionalSlides parameter
https://swiperjs.com/migration-guide-v11#loop-mode


`loopedSlides` は削除されました、動かない場合は `loopAdditionalSlides` を使ってね。
とのこと。

また、 [ChangeLog](https://swiperjs.com/changelog) にも autoplay関係の修正が入っている。

## 差し替えてみる

上記のCodePenのソースを書き換えてみる

1. HTMLタブ
    ```
    - https://cdnjs.cloudflare.com/ajax/libs/Swiper/9.1.0/swiper-bundle.min.js
    + https://cdnjs.cloudflare.com/ajax/libs/Swiper/11.0.3/swiper-bundle.min.js
    ```
1. JSタブ
    `loopedSlides` を `loopAdditionalSlides` に差し替えてコメントを外す（2箇所）

## 結果

問題なく動作します。素敵。

## 備考：実は loopedSlides（loopAdditionalSlides） はそんなに必要ない。

大抵の場合は指定なしでも問題なく動作する。
なにか不都合が発生した場合のみ設定すればよい（v9~10でも）
フリーの開発環境で画面キャプチャーするまでのメモ

なんか前回作ったやつ　VisualStudio2019のライセンス購入しないと駄目だからロハなのでやってーって言われたので泣きながら
javaとか
無料開発ツールの
Code::Blocks
CLion
Qt Creatorなど調査してやってみようとする……

開発環境のライセンスぐらいと思うけどネ(^_^;)
ユニーク制約について



# ユニークとは？
たとえば、ログイン機能を作ります。
emailカラムは他のユーザーと重複することを禁止したいです。

その時！emailにユニーク制約をかけることで
emailカラムは重複値を許容しなくなります。

# Mysql Raw Sqlでユニークをかける方法(usersテーブルを作成する時にかける場合)
```
CREATE TABLE users (
	email varchar(50) UNIQUE,
    ...
)
```

# Mysql Raw Sqlでユニークをかける方法(既にusersテーブルがある場合)
```
ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE (email);
```
⚠️既存のデータに重複が存在する場合、重複削除処理を事前にする必要があります。

# Laravelのマイグレーションでユニーク制約をかける方法(usersテーブルを作成する時にかける場合)
<img width="686" alt="image.png (95.4 kB)" src="https://img.esa.io/uploads/production/attachments/5658/2023/10/30/145821/06cf70bb-bad9-4f6b-a4c1-241ee45b1573.png">

ユニークにしたいカラム`->unique()`を指定すればOK。

# Laravelのマイグレーションでユニーク制約をかける方法(既にusersテーブルがある場合)
<img width="684" alt="스크린샷 2023-10-30 오전 11.20.59.png (74.2 kB)" src="https://img.esa.io/uploads/production/attachments/5658/2023/10/30/145821/f148d69b-1f86-4899-adef-522ddc50f09f.png">

⚠️既存のデータに重複が存在する場合、重複削除処理を事前にする必要があります。

# もっと条件を入れたい場合
たとえば、部署が違う人のであれば、同じemailアドレスを許容したい！
どうすればいいでしょうか。

二つのカラムにそれぞれユニークをかける？
そうなると部署が同じユーザーは作れなくなりますね。


**ユニーク制約には複数のカラムを登録することができます。**
コードで見ると
<img width="391" alt="image.png (6.8 kB)" src="https://img.esa.io/uploads/production/attachments/5658/2023/10/30/145821/5be72346-72f9-4293-9e65-fe292938926a.png">
このようにです。

**このように複数のカラムにユニーク制約をかけることを
複合ユニーク（Composite Unique）と言います。**

今回の例で言うと（部署、メールアドレス）ペアが同じ値だと許容しないことになります。
これで部署が違う場合同じメールアドレスでも会員登録ができるようになります。

３つのカラムで複合ユニークを登録すると、３つの値が全部同じ場合許容しなくなることになります。
【JSTQB ALTM】シラバスまとめ（第4章）

<iframe src="https://www.slideshare.net/slideshow/embed_code/key/AlDUSUuLBLHoNr?hostedIn=slideshare&page=upload" width="476" height="400" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>

:::note warn
筆者（私）独自の解釈・理解をまとめた資料のため、誤りがある可能性があることにご留意ください
:::
【storyboard】StackViewの中身の均等配置

# 目次
[1.StachViewの中身の均等配置とは？](#1-オプショナルバインディングとは？)
[2.実例](#2-シャドーイング)
[3.おわりに](#3-実例)

# 1. StachViewの中身の均等配置とは？
UIStackViewで中身を均等配置＆スペースを開けたいことありませんか？
以下のイメージが今回のゴールです。
![スクリーンショット 2023-10-30 11.08.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534617/359b1656-6e13-0967-7466-9b23790c66b3.png)

# 2. 実践方法
1. UIStackViewを配置
1. Viewを３つStackViewの中に配置
1. Spacingに設定したい間隔の数値を入力
    ![スクリーンショット 2023-10-30 11.14.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534617/1a9e8665-8eb4-5012-f202-15b49bb5d2f7.png)
1. 設置した３つのViewを全て選択してEqualtoWidthをの制約を追加
![スクリーンショット 2023-10-30 11.19.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534617/e0f022df-70d0-4b54-074c-6e6ce48e376a.png)

# 3. おわりに
UI開発に大変便利なUIStackViewのTipでした。
他にもStackViewには色々な設定ができるので、開発現場でも多用させています。
本日も本記事を読んでいただきありがとうございました〜
目指せ脱初学者！
Android Studio: 動画の再生

こちらと同じことを、Kotlin で行いました。
再生する動画の名前は、bigbuckbunny.mp4 です。
[基礎 動画再生](https://yakiimosan.com/android-dev-videoview/)

## 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/73a4432f-f20c-52e6-d436-40f359ddaf08.png)


## 環境

```app/build.gradle.kts
    compileSdk = 34
    minSdk = 26
    targetSdk = 34
```

## データ
raw というフォルダーを作成
Open In でファイルをドラッグ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/7b77a97c-de11-4501-9445-389a469fe09d.png)

## 画面

```xml:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/buttonId"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="145dp"
        android:layout_marginTop="20dp"
        android:layout_marginEnd="145dp"
        android:layout_marginBottom="16dp"
        android:onClick="playMovie"
        android:text="動画再生"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.481"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />

    <VideoView
        android:id="@+id/videoViewId"
        android:layout_width="410dp"
        android:layout_height="652dp"
        android:layout_marginTop="11dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/buttonId" />
</androidx.constraintlayout.widget.ConstraintLayout>
```

## プログラム

```MainActivity.kt
package com.example.movie03

import android.os.Bundle
import android.view.View
import android.widget.MediaController
import android.widget.VideoView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    fun playMovie(view: View) {
        val videoView = findViewById<VideoView>(R.id.videoViewId)

        // ビデオファイルの取得
        videoView.setVideoPath("android.resource://" + packageName + "/" + R.raw.bigbuckbunny)

        // ビデオのコントロール
        val mediaController = MediaController(this)
        mediaController.setAnchorView(videoView)
        videoView.setMediaController(mediaController)

        // 再生
        videoView.start()
    }
}
```
納品ファイルのつくりかたメモ

自分用メモ


## git diff から更新したファイル一覧をとって、まとめる
```
# 　コミットID使わない
$ git archive --format=zip --prefix=_diff/ HEAD `git diff master --diff-filter=ACMR --name-only` -o _contents.zip

# 　コミットID使う
$ git archive [コミットID2] `git diff --name-only [コミットID1] [コミットID2] --diff-filter=ACMR` -o archive.zip
```

## 更新したファイル一覧があって、そのファイルだけ別フォルダにコピーしたい
```
$ rsync -av --files-from=filelist.txt /source/directory/ /destination/directory/
```

## Zip

```
$ zip xxx.zip -r xxx/ -x "*.DS_Store"
```
【Salesforce】AsyncApexExecutions Limit exceeded.エラーが出たので解決したい

# 問題

下記のメールが届いた。

Developer script exception from 環境の名前 : 'バッチ名' : AsyncApexExecutions Limit exceeded.

# 解決策

バッチクラスでは、最大バッチサイズを 2k 以内に保つようにします。
※参考リンク抜粋

↓

要するに非同期で処理しすぎ！と怒られている・・・
処理レコードを減らしたり、処理項目を減らしたりなどが解決策になるかと。

# 参考リンク

[プロアクティブモニタリング: 非同期 Apex 実行数制限](https://help.salesforce.com/s/articleView?id=000382490&type=1)
Next.jsを使用したチケット売買アプリ

# 目次
[1. Next.jsを使用したチケット売買アプリ](#1-Next.jsを使用したチケット売買アプリ)
[2. アプリの概要](#2-アプリの概要)
[3. 起動方法](#3-起動方法)
[4. コードの説明](#4-コードの説明)
----

# 1. Next.jsを使用したチケット売買アプリ

https://github.com/kouhei-github/transaction-ticket-app

Next.jsを使用して、チケットが売買できるサイトを作成します。
他の売買サイトに比べて表示速度とUI/UXを向上させることがゴールです。
![スクリーンショット 2023-10-29 22 55 38](https://github.com/kouhei-github/transaction-ticket-app/assets/49782052/b3b2c599-d9f6-4275-98d8-75a7890d0e5c)

### 技術スタック
```text
Nodejs v18.3.0
Next.js 13.5.2
Tailwind CSS
Vercel
```


---

## 2. アプリの概要
vercelでデプロイ済みなので、下記よりご確認ください。<br>
[https://transaction-ticket-app.vercel.app/](https://transaction-ticket-app.vercel.app/)

### 2.1 チケットの一覧ページ
[チケットの一覧ページ](https://transaction-ticket-app.vercel.app/) <br>
チケットの一覧ページを表示します。<br>
ここは無限スクロールを実装したいです。<br>
また初期ロード時に、ページがレンダリングされるまで今流行りのSkeletonを導入し、UXを向上させた。
![スクリーンショット 2023-10-29 22 55 38](https://github.com/kouhei-github/transaction-ticket-app/assets/49782052/b3b2c599-d9f6-4275-98d8-75a7890d0e5c)

---

### 2.2 チケットの詳細ページ
[チケットの詳細ページ](https://transaction-ticket-app.vercel.app/event/myId) <br>
各チケットの詳細ページはSSGで構築します。<br>
SSGとはStatic Site Generateの略で、あらかじめ静的なページを構築しDBとの通信をなくしレンダリングを早くすることです。
![スクリーンショット 2023-10-29 22 56 01](https://github.com/kouhei-github/transaction-ticket-app/assets/49782052/559e87a4-04f4-4f0a-b86a-3cfa3afaccab)


---

### 2.3 チケット購入ページ
[チケット購入ページ](https://transaction-ticket-app.vercel.app/ticket/1)<br>
チケットの購入も種類があります。(先行、抽選）<br>
ですのでSSGで静的サイトをあらかじめ構築しておきます
![スクリーンショット 2023-10-29 23 00 51](https://github.com/kouhei-github/transaction-ticket-app/assets/49782052/01e07658-245c-4e8c-9728-cdf77d735868)


---

## 3. 起動方法
アプリをクローン
```shell
git clone
```

node_modulesのインストール
```shell
yarn install
```

アプリの起動
```shell
yarn dev
```

---

## 4. コードの説明
Next.jsのコードを説明していく。

### 4.1 UX向上のためにスケルトンの導入
スケルトンは様々なシーンで見ることが多くなってきました。
YouTube, X(旧Twitter), Indeedなど大手どころのアプリは全て導入しています。


#### 導入
```shell
yarn add react-loading-skeleton
```

#### 使い方
通常のローディングに比べて、待機時間が短く感じる。
[今回はTicketCardコンポーネント](https://github.com/kouhei-github/transaction-ticket-app/blob/main/components/Card/TicketCard.tsx)で使用している
```tsx
{props.isLoading ? <Skeleton height={50} width={370} /> : <h2 className={"text-[18px] font-bold"}>{props.title}</h2>}
```

サンプル
./app/page.tsx
```tsx
'use client'
import {useEffect, useState} from 'react'
import Skeleton from 'react-loading-skeleton'
import 'react-loading-skeleton/dist/skeleton.css';


export default function Home() {

  const [loading, setLoading] = useState(true);
  useEffect(() => {
    // loading開始
    setLoading(true)
    setTickets(ticketInfoMocs)

    const method = async () => {
      // APIでチケットのデータを取得する。
      setTimeout(() => { // ダミーなAPI
        console.log("API 実行")

        // loading終了
        setLoading(false)

      }, 1500 ) // APIで
    }
    // 非同期関数methodを呼び出す。
    method();
  }, []); // currentCtx.currentStepの変更を監視

  if(loading){
    return (
        <Skeleton height={50} width={370} />
    )
  }
  
  return (
        <h2 className={"text-[18px] font-bold"}>{スケルトン}</h2>
  )
}
```



---
【セキュリティ】VPNを使ってどこでも安全にデータ通信を行いたい！

こんにちは！
今回はVPNについて紹介したいと思います！
最後まで読んでいただけたら嬉しいです！

![security-869216_1280.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524127/6dd3c3f7-40ad-946f-1acc-71ad80703a91.jpeg)


## 1,VPNってなに？
VPN（Virtual Private Network、仮想プライベートネットワーク）は、インターネット上の通信を安全にするための技術およびサービスです。VPNは通信を暗号化し、ユーザーのデータやプライバシーを保護する役割を果たします。

## 2,VPNのメリット
#### セキュリティ: 
VPNは通信データを暗号化するため、データを傍受しにくくなります。これにより、オンライン上でのプライバシーやセキュリティが向上します。特に、公共のWi-Fiネットワークなど、セキュリティが不十分なネットワークを利用する際に有用です。

#### プライバシー保護: 
VPNを使用すると、インターネットプロバイダやウェブサイトがユーザーのオンラインアクティビティを追跡しにくくなります。IPアドレスを隠し、ユーザーの位置情報を隠すことができます。

#### 地理的制約の回避: 
VPNを使用すると、インターネットの制約を回避できる場合があります。たとえば、特定の国からのコンテンツへのアクセスを制限しているウェブサイトやストリーミングサービスにアクセスできるようになります。

#### ネットワークアクセス: 
リモートワーカーや遠隔地からのアクセスが必要な場合、VPNは企業内ネットワークに安全にアクセスするための手段として利用されます。これにより、リモートワーカーがセキュアな接続を介して会社のリソースにアクセスできます。


## 3,VPNのデメリット
#### 速度低下:
VPNを使用すると、通信データが暗号化されるため、通信速度が低下することがあります。特に、遠隔地から遠隔アクセスする場合や、遠隔国との通信の場合に速度低下が顕著に現れることがあります。

#### コスト: 
一部の商用VPNサービスには料金が発生します。無料のVPNサービスもありますが、一般に制約が多かったり、セキュリティが不足している可能性があります。

#### 信頼性: 
VPNサービスの信頼性はプロバイダに依存します。信頼性が低いサービスを利用すると、接続の途中で切断されたり、サーバーダウンが発生する可能性があります。

#### 法的問題: 
一部の国や地域では、VPNの使用に関する法的制約が存在します。一部の国では、政府がVPNの使用を規制したり、禁止したりすることがあります。

#### セキュリティリスク: 
VPNサービスやプロバイダにはセキュリティリスクが伴うことがあります。信頼性の低いVPNサービスや無料のVPNは、ユーザーデータの保護を保証しないことがあります。

## 4,VPNってどういう場所で使うべき？
#### 公共のWi-Fiネットワーク:
カフェ、空港、ホテルなどの公共のWi-Fiネットワークは、セキュリティの脆弱性があることがあります。VPNを使用することで、データの暗号化とセキュリティを強化できます。

#### 国際旅行:
国際旅行中に、自国からリモートアクセスする場合や、地域制限のコンテンツにアクセスする場合にもVPNは便利です。地域制限の回避やセキュリティ強化に役立ちます。

#### リモートワーク:
リモートワーカーは、企業のネットワークに安全にアクセスするためにVPNを使用できます。企業のデータへのアクセスをセキュアに保ち、オフィス外からの安全な通信を提供します。

## 5,終わりに
以上で、 VPNについての紹介を終わります。
今回も最後まで読んでいただき、ありがとうございました！
では、また次の記事で〜！
【PHP・Laravel・Rails】これまで学んだフレームワーク・言語でのsessionの使い方振り返ってみた

# 概要
この記事では私がこれまで学習してきたPHP、Laravel、Ruby on Railsでのsessionの使い方について紹介していきたいと思います。
# 対象とする読者
- 様々なフレームワークや言語でのsessionの使い方の違いについて知りたい方
- PHP、Laravel、Ruby on Railsでのセッションの基本から詳細な使い方を学びたい方
- 初学者の方
# PHP
以下がPHPでのsessionを使う際のサンプルコードです。
```php
session_start();//sessionのスタート
if (!isset($_SESSION['count'])) {
  $_SESSION['count'] = 0;
} else {
  $_SESSION['count']++;
}
```
`session_start()`関数でセッションのスタートをします。
セッションを開始すると、PHP はスーパーグローバル`$_SESSION`にすべてのセッションデータを格納します。
通常は、PHP がスクリプトの処理を終了するときに、セッションは自動的に終了します。 手動でセッションを終了させるには`session_write_close()`関数を使います。

# Laravel
Laravelでセッションデータを操作する主な方法は、グローバルなsessionヘルパとRequestインスタンスの２つあります。今回は、Requestインスタンスを介してセッションにアクセスする方法のみ紹介したいと思います。
```php
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * 特定のユーザーのプロファイルを表示
     *
     * @param  Request  $request
     * @param  int  $id
     * @return Response
     */
    public function show(Request $request, $id)
    {
        $value = $request->session()->get('key');//keyの中にあるアイテムを取得する

    }
}
```
リクエストインスタンスを使用してアイテムを取得するには`get`メソッドを使います。session内のデータを全て取得したい場合は`all`メソッドを使用します。

また、データを保存したいときには以下のように`put`メソッドを使います。
```php
$request->session()->put('key', 'value');
```
`put`メソッドの1番目の引数はsessionに保存するための箱の名前、
2番目の引数である`value`の部分にはsessionに保存したい値を入れます。
# Ruby on Rails
RubyのフレームワークであるRuby on Railsでの使い方は次の通りです。
```ruby
#値の設定
session[キー] = "値"
session[:user_id] = 1

#値の参照
session[キー]
session[:user_id]
```
`session[]`の[]内にキー名を入れることで使うことができます。

# 終わりに
さまざまなフレームワークや言語でsessionの使い方について紹介してきました。
この記事を読んでみてさらに詳しい使い方について知りたくなった場合は参考ページも見てみてください。
# 参考

https://www.php.net/manual/ja/session.examples.basic.php

https://readouble.com/laravel/8.x/ja/session.html

https://ichigick.com/rails-session/#toc5
わかりやすい英語で日本語の文法を説明するLLM「JPNsensei-V2」を公開しました。

この前finetuningしたモデル「JPNsensei」に対して、モデルの変更、前処理、RAGとpromptハイパーパラメーターチューニングを追加しました。前より回答が結構良くなりましたので、昨日Huggingfaceに公開しました。

詳しい内容は以下となります。
①モデルの変更
ベースモデルをjapanese-stablelm-instruct-7bに変更しました。

②前処理
以下の４つのことを考えてデータの前処理を行いました。
1.データの分布をさらに確認して、token数を1024以内に限定しました。
2.データのカラムを確認したところ、質問と回答のスコアという項目（q_score,a_score）があったので、スコアが0点以下の質問または回答がある行を削除しました。
3.answerのデータを確認して気づいたこととして、質問に対して参考URLを直接投げるanswerが多くあります。URLは学習する価値ないので、httpがあるデータを削除した方がいいではないかと思いましたが、一応調べてみるとhttpがあるデータは12000件くらいありました。全部消すのが少しもったいないと思って、httpからスタートしたURLを削除+タグあり、削除後answerのtokenが50以下の行はそのまま消すようにしました。（もともとURLがついてなくても50token以下のデータを削除しないようにするため、タグをつけました。）
4.answerのスコア分布を確認したところ、50点以上の回答が2000件くらいがあって、そういう質が良い内容をデータ拡張した方がよいではないかと思いました。LLMに詳しい方に聞いてみたら、重複な内容を学習させたらあまりよくないみたいので、一旦やめました。

③RAG
RAGは特に中身をチューニングせず、langchainで直接繋がってやりました。

④promptハイパーパラメーターチューニング
回答の「安定性」と「重複しない」の２点を重視してチューニング（temperatureとrepetition_penalty周り）しました。

⑤精度検証（「"は"と"が"の違いを説明してください」という質問)
以下の７つパータンに分けて回答を確認してました。
rouge（自然言語処理でよく使われてる評価指標）でも精度を今後確認してみたいと考えています。

1.japanese-stablelm-instruct-7b のみ
![１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/09ee7b29-9dfc-6636-38a5-7aad270cdf45.png)

2.japanese-stablelm-instruct-7b+finetuning（lossが0.9（4epoch段階））
![２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/4316320d-c23f-9cf8-5fdf-f3f1954a3f45.png)

3.japanese-stablelm-instruct-7b+finetuning（lossが0.9（4epoch段階））+promptハイパーパラメーターチューニング
![３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/b1543c09-532c-5a29-fd3e-f5b2a2944dc8.png)

4.japanese-stablelm-instruct-7b+finetuning（lossが0.6（7epoch段階））
![４.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/cddc0728-0bcc-b24c-8790-0c79d7cba903.png)

5.japanese-stablelm-instruct-7b+finetuning（lossが0.6（7epoch段階））+promptハイパーパラメーターチューニング
![５.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/d3089764-8c2a-21c6-678f-e9ef7c3271e8.png)

6.japanese-stablelm-instruct-7b +RAG
![６.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/1aab6954-0655-436b-7673-ac4df1c47f6f.png)

7.japanese-stablelm-instruct-7b+finetuining（lossが0.6（7epoch段階））+promptハイパーパラメーターチューニング+RAG
![７.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/77efb46c-b6f2-ac60-b0f4-d4436d826674.png)

結果としては5と7がよかったです。
5が分かりやすく説明できるようになりました。
7は5よりRAGを追加しましたが、回答が少し怪しいですね。（RAGのルールをもう少しチューニングすれば改善できると思います）


興味ある方試してみてください：

https://huggingface.co/kanxxyc/JPNsensei-V2
Nuxt2のEOLが2024/06まで延期

https://github.com/nuxt/bridge/releases/tag/v3.0.0-rc.1#:~:text=Finally%2C%20in%20view%20of%20the%20delay%20in%20Bridge%20release%2C%20we%20will%20be%20extending%20the%20Nuxt%202%20EOL%20date%20to%20June%2030%2C%202024.

めちゃくちゃ嬉しいです。。業務で移行対応きつかったのでゆっくりできそうです
【Appsheet】別アプリにデータをフィルターした状態で移動する

## はじめに
Appsheetを使用し、各アプリケーションの情報を一元化するアプリを作成しました。
その際に押下したレコードに紐づいたデータを別アプリで表示させる方法について調査しました。

### 以下のような構成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699599/43e505c8-1768-4b7d-24ce-58c27236dc3a.png)

## LINKTOROW()を使用した場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699599/5f8bf812-4369-c393-8a1f-506ab346d8f1.png)


対象レコードをクリックし、別アプリに遷移させてみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699599/5a556d91-c1c4-851c-41d7-4a7918710d7d.png)

今回遷移先の別アプリのデータ表示数が多くなる想定ですのでデータを絞り込んで表示させたいが、LINKTOROW()で遷移後にオートスクロールで一番上などに表示されるわけではなくそのデータが目立つように色が変わるだけでしたのでこちらの案は没に。


## CONCATENATE()を使用し別アプリに遷移させる

URLを生成し、検索パラメーターのsearchTermに直接観覧したいデータのKey値を付与することでフィルターさせた状態で遷移させようとしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699599/2050049e-b152-8664-c277-c157eb24dbd1.png)

Targetの中身
```javascript
CONCATENATE("https://www.appsheet.com/start/【URL生成値】?platform=desktop#viewStack[0][identifier][Type]=Control&viewStack[0][identifier][Name]=",ENCODEURL("在庫"),"&appName=",ENCODEURL([Appname]),"&searchTerm=",ENCODEURL([ID]))
```

絞り込みながら別アプリに遷移できています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699599/a0e78ea3-2d36-599a-170c-5cd5ead87530.png)


うまくいったと思ったのですがこちらの遷移後にAPPGARALLYボタンを押下すると以下のエラーが発生しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699599/4f166209-44d4-5307-2baf-dccbe340504f.png)

どうやらディープリンクでアプリ遷移を行った際には、遷移元のデータを保持しているようで直接URLを生成しアプリ間遷移を行うとエラーが発生してしまうようです。

しかしAppsheet公式記事の [ディープリンクを手動で構築する]の中には検索のパラメーターがありませんでしたので別の方法を模索することに。
https://support.google.com/appsheet/answer/10106757?sjid=486925206027593892-AP

## External: go to a websiteで別タブ表示させることによって回避する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699599/2d2cc947-1458-fe14-884c-c2caf9c84da6.png)
発想を変えDo thisを"External: go to a website"に変更し別タブで表示させることによって遷移元という概念を無くしAPPGARALLYに遷移するボタンを押下した際のエラーが解消されることを確認しました。


## まとめ
Appsheetを使用していると、デフォルトの機能に無いことを行おうとした際に今回のように問題が発生することがあります。
Appsheetの仕様に沿った範囲で行いたいことの実現方法を多角的に模索していく必要がありそうです。
NestJS でクライアントリクエストを受け取る

# はじめに
この記事では、NestJS の Controller でクライアントリクエストを受け取る際の実装方法について記載します。

# 開発環境
開発環境は以下の通りです。

- Windows11
- VSCode
- Node.js 20.5.0
- NestJS 10.0.0
- TypeScript 5.1.3

# 事前準備
以下の手順に沿って、NestJS をインストールします。

https://qiita.com/Yasushi-Mo/items/7c6e01a33c95f520453f

次に以下の記載内容に沿って、コントローラー用のクラスを作成します。

https://qiita.com/Yasushi-Mo/items/a35383ed37f7c8ce46ab#%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%A9%E3%83%BC%E3%81%AE%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E5%AE%9F%E8%A3%85

# リクエストオブジェクトの受け取り
```@Req()``` デコレーターをメソッドの引数に指定することで、リクエストオブジェクトを受け取ることができます。

```app.controller.ts
import { Controller, Get, Req } from '@nestjs/common';
import { Request } from 'express';

@Controller('controllers')
export class AppController {
  @Get('request-object/:param')
  getRequestObject(@Req() request: Request): string {
    return `RequestObjectController returns path param:  ${JSON.stringify(
      request.params,
    )}, query param: ${JSON.stringify(request.query)}`;
  }
}
```

上記の例では、リクエストオブジェクトを受け取り、その中からパスパラメーターとクエリパラメーターを取り出しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/8781edc7-b375-5e77-8d11-247a27944a75.png)

:::note
リクエストオブジェクトから取り出すことのできるプロパティについては、こちらに記載があります。

https://expressjs.com/en/api.html#req

:::

# クエリパラメーターの受け取り
リクエストオブジェクトを受け取るのではなく、その中の特定のプロパティを受け取ることもできます。
```@Query(key?: string)``` デコレーターをメソッドの引数に指定することで、クエリパラメーターを受け取ることができます。

```app.controller.ts
import { Controller, Get, Query } from '@nestjs/common';

@Controller('controllers')
export class AppController {
  @Get('query-parameters')
  getQueryParameters(@Query() param: string): string {
    return `QueryParametersController returns param: ${JSON.stringify(param)}`;
  }
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/8882afcd-1f57-bfb7-8501-7257573afcce.png)


# リクエストボディの受け取り
```@Body(key?: string)``` デコレーターをメソッドの引数に指定することで、リクエストボディを受け取ることができます。

```app.controller.ts
import { Body, Controller, Post } from '@nestjs/common';

@Controller('controllers')
export class AppController {
  @Post('request-body')
  postRequestBody(@Body() body: string): string {
    return `RequestBodyController returns body: ${JSON.stringify(body)}`;
  }
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/5caf1a43-31ca-085d-8dd2-08f4ca2b5c16.png)


# 参考
- [APIを構築するためのコントローラーの使い方まとめ](https://tyotto-good.com/nestjs/controller)
- [Controllers](https://docs.nestjs.com/controllers)
[Ruby][AtCoder] ABCのA問題を解いて使ってきた標準メソッドを調べる

こんにちは！

Rubyに入門したかったけど、特に書くものが思いつかなかったので、AtCoderのA問題をひたすら[解いてみました](https://github.com/wakamenod/ruby-procon) :laughing: 

300問ほど解いて、これまでどんな標準メソッドを使ってきたか、ふと気になりました :thinking: 後、たまに使おうとすると思い出せないメソッドが増えてきたので使用頻度が少ないけど便利なメソッドを一覧にして覚えておきたい。

と言うわけで、調べてみました！

```ruby
require 'parser/current'
require 'ast'

class MethodCounter < AST::Processor
  attr_reader :method_counts

  def initialize
    super
    @method_counts = Hash.new(0)
  end

  def process(node)
    on_send(node) if node.type == :send
    node.children.each do |child|
      process(child) if child.is_a?(AST::Node)
    end
  end

  def on_send(node)
    method_name = node.children[1]
    @method_counts[method_name] += 1
  end
end

ruby_files = Dir.glob('./ruby-procon/*/a/main.rb')
method_counts = Hash.new(0)

counter = MethodCounter.new
ruby_files.each do |file|
  source = File.read(file)
  ast = Parser::CurrentRuby.parse(source)
  counter = MethodCounter.new
  counter.process(ast)
  counter.method_counts.each do |method, count|
    method_counts[method] += count
  end
end

sorted_methods = method_counts.sort_by { |_, v| -v }
sorted_methods.each do |method, count|
  puts "#{method}\t#{count}回"
end
```

結果はこちらです：

```
gets    385回
puts    310回
split   190回
map     190回
+       122回
-       114回
then    105回
*       102回
to_i    100回
chomp   79回
[]      67回
==      67回
/       57回
%       37回
<       36回
p       28回
chars   28回
<=      26回
>       23回
zero?   23回
max     19回
sort    18回
join    16回
min     15回
include?        14回
>=      14回
sum     10回
**      9回
size    9回
index   9回
reverse 8回
abs     7回
each    7回
gsub    6回
tally   6回
to_f    6回
length  5回
uniq    5回
eval    5回
last    5回
count   5回
even?   5回
!=      5回
call    5回
first   4回
to_a    4回
each_with_index 4回
min_by  4回
[]=     4回
!       4回
reduce  3回
max_by  3回
positive?       3回
upcase  3回
find    3回
downcase        3回
all?    3回
each_cons       3回
collect 3回
end_with?       2回
to_s    2回
chr     2回
exit    2回
new     2回
inject  2回
find_index      2回
each_slice      2回
odd?    2回
round   2回
delete  2回
strip   2回
sort_by 1回
|       1回
rindex  1回
concat  1回
each_line       1回
filter  1回
any?    1回
transform_values        1回
group_by        1回
nil?    1回
<<      1回
=~      1回
tap     1回
key     1回
match   1回
add     1回
lazy    1回
ord     1回
minmax  1回
with_index      1回
chunk   1回
take_while      1回
zip     1回
require 1回
to_set  1回
start_with?     1回
slice   1回
tr      1回
scan    1回
negative?       1回
^       1回
take    1回
lambda  1回
to_h    1回
-@      1回
sqrt    1回
transpose       1回
```

(grepして確かめてみたけど、大体合ってるんじゃないでしょうか....!!)

結果を眺めてみると、2~3回しか使ってないメソッドの中には思い出せないのが結構あるので、おさらいが必要です :cry: 

他に競プロ向けに便利なメソッドを知っている！という方がいれば、ぜひコメントで教えてください :boar:
開発Tips

## （抜粋）Xcodeショートカット
- ファイル検索
shift command O
- コードの整形
Ctrl i
- 新しいタブで開く
option 選択


## 使いこなしたいXcodeショートカットまとめ
- コードの整形
Ctrl i
- アイテム表示
shift command L
- ファイル検索
shift command O
- 選択したタブを一つ前に戻す
shift command [
- 新しいタブで開く
option 選択
- 選択したコードを一行上に移動
option command [
- ディスクリプションを追加
option command /
ssh設定

＃鍵の作成
ssh-keygen -t rsa
cd ~/.ssh/
mv id_rsa.pub authorized_keys
※id_rsaファイルをローカルにコピーする


#sshdのファイルの下記４つを編集する
・Port 22
・PermitRootLogin no
・PubkeyAuthentication yes
・AuthorizedKeysFile      .ssh/authorized_keys .ssh/authorized_keys2

`vim /etc/ssh/sshd_config`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21667/1ca88bf9-66de-e403-caf6-8c384d93c9e6.png)

#サービスを再起動
`systemctl restart sshd`

#ssh接続
`ssh {ユーザー名}@{ホスト名} -i id_rsa`
AI-102試験対策のまとめ「Anomaly Detector」

## はじめに
Azure AI Engineer Associate(AI-102)取得に向けた勉強でまとめた内容を本記事では投稿しています。
試験範囲の内容を私が勉強していく中で、
・忘れてしまっていた内容
・他の知識と絡めて理解した方が良い内容
・Microsoft Learnの読解に苦戦した内容
などをできるだけ分かりやすく簡潔にまとめることを意識しています。
Azureの勉強を一から始め、AI-102取得を目指している方の参考になれば幸いです。
※本記事の内容が必ず試験に出るわけではないこと、ご注意ください
※勉強しながら投稿しているため、追加で学んだことがあれば随時投稿内容を更新します。

## 試験対策のまとめ
## Anomaly Detector
時系列データの監視/異常の検出をできる一連のAPIを備えたAIサービス  
機械学習(ML)の知識が少なくても、バッチ検証やリアルタイム推論が可能

### Anomaly Detectorの機能
| 機能 | 異常を検出する変数 | モデル |
| --- | --- | --- |
| 一変量異常検出 | 1つの変数(収益やコストなど) | データパターンに基づいて自動的に選択 |
| 多変量異常検出 | 相関関係を持つ複数の変数 | グラフアテンションネットワーク |

#### **一変量異常検出**
| 機能 | 利用するデータ | 検出する異常 |
| --- | --- | --- |
| ストリーミング検出 | 前に確認されたデータポイント | 最新のデータポイントの異常 |
| バッチ検出 | 時系列データ | データ全体に存在する可能性がある異常 |
| 変更ポイントの検出 | 時系列データ | データに存在する傾向の変更点 |

#### **多変量異常検出**
* 最大300の異なる信号間の依存関係や相互相関が自動的に主要な要因として考慮される
* 複数の信号の相互作用が通常範囲から外れた場合に異常を検知可能
* 例：回転/燃圧/ベアリングなどの20種類の信号を生成する自動車エンジンの20個のセンサー

<br>

* 参考
    - https://learn.microsoft.com/ja-jp/azure/ai-services/anomaly-detector/overview

## 次の試験対策のまとめ
* **AI-102試験対策のまとめ「Azure AI Metrics Advisor」**

https://qiita.com/fsd-jume/items/9673345ed38380cc1de7

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/65aba5d5514e023fd66d