OmniAICreator/Qiita-1.07M huggingface dataset:
個人開発記録　2024/04/23

# 目的

* とにかくやりきることが一番の目的
* 毎日発信することで、発信する習慣作り
* 個人開発をやりきることで、実績作り


# 開発するもの

X(旧Twitter)のパクリ

# 構成

python
django REST framework
postgreSQL

# 本編

## ローカルのpostgresqlのDBを作成

postgresqlを以下手順に従ってインストール

https://qiita.com/tom-sato/items/037b8f8cb4b326710f71

もろもろインストールが終わった後、pgAdminで`likeX`というDBを作成

## djangoからローカルのpostgresqlのDBに接続

psycopg2-binaryをインストール

```bash
pip install psycopg2-binary
```

DBの設定を変更

```python:likex/settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'likeX',
        'USER': 'postgres',
        'PASSWORD': 'admin',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}
```

以下でDBと接続を確認

```bash
python manage.py dbshell
psql (16.2)
"help"でヘルプを表示します。

likeX=# 
```

```python:likeX/tweet/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    bio = models.CharField(max_length=280, blank=True)
    location = models.CharField(max_length=100, blank=True)
    birth_date = models.DateField(null=True, blank=True)
    # groups と user_permissions の related_name を変更する
    groups = models.ManyToManyField(
        'auth.Group',
        verbose_name='groups',
        blank=True,
        help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.',
        related_name='tweet_user_set',  # ここを変更
        related_query_name='user',
    )
    user_permissions = models.ManyToManyField(
        'auth.Permission',
        verbose_name='user permissions',
        blank=True,
        help_text='Specific permissions for this user.',
        related_name='tweet_user_set',  # ここを変更
        related_query_name='user_permission',
    )


class Tweet(models.Model):
    content = models.CharField(max_length=280)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    likes = models.IntegerField(default=0)


class Relationship(models.Model):
    follower = models.ForeignKey(User, related_name='followers', on_delete=models.CASCADE)  # 誰がフォローしているか
    following = models.ForeignKey(User, related_name='following', on_delete=models.CASCADE)  # 誰をフォローしているか
    created_at = models.DateTimeField(auto_now_add=True)

```

ディレクトリの構成が悪いのか、apps.pyを修正

```python:likeX/tweet/apps.py
from django.apps import AppConfig


class TweetConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    # name = 'tweet' を以下に変更 
    name = 'likeX.tweet' 
```

appを追加

```python:likex/settings.py
INSTALLED_APPS = [
    ...
    'likeX.tweet', # 追加
]
```

マイグレーションを実行

```bash
python manage.py makemigrations tweet
python manage.py migrate
```

pgAdminでlikeXDBにマイグレーションしたテーブルが作成されていることを確認する

# 感想

一番最初の環境構築はとにかく面倒。。
あたりまえだけど成果を早くだしたいなら、慣れたツールやフレームワーク、DBをもってないといけない。
これからそういうのを増やしていこう。
Dockerコンテナ内で開発できるVSCode拡張 Dev Containers

## はじめに
Dockerコンテナ内で開発環境を構築し共有することもできるDev Containersの利用方法についてです。

## インストール
VSCodeの拡張機能からインストールします。

https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers

## 利用方法

### 設定ファイルの追加
まず、VSCodeで開いているフォルダにDevContainersで開くためのファイルを追加します。

`Dev Containers`がインストールされているとVSCodeの左下にステータスバー項目が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2288370/0bfa32ea-4f5d-7423-9d3a-7de0f44f39a8.png)

歯車マークの下にある`><`を選択し、`開発コンテナー構成ファイルを追加`を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2288370/090f9542-7f37-3180-f1c2-71000d88a026.png)

すると、コンテナ構成の追加場所を聞かれます。git 等で共有したい場合はワークスペースに、共有しない場合はユーザーデータフォルダを選択しますが、始めはワークスペースに追加した方が分かり易いかと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2288370/0432dee3-26c3-4a8c-e80c-e1e06159ea9f.png)

次にテンプレートを選択します。Node.js の開発に使うのであれば`Node.js & TypeScript`等です。選んだテンプレートによってNodeのバージョンなどを質問されるかと思いますので適宜選択してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2288370/a49e1336-f062-3a49-fca4-dd620e94c347.png)


最後にインストールする追加機能を選択します。
これで`.devcontainer/devcontainer.json`が作成されます。

### devcontainer.json
この時点で右下に表示されている`コンテナーで再度開く`を押すとコンテナが作成されVSCodeが開きますが、`devcontainer.json`を編集することで開発環境を編集できます。
[リファレンス](https://containers.dev/implementors/json_reference/)に各プロパティの説明がありますが、Dockerfileやdocker-compose.ymlを利用する場合のプロパティを載せておきます。

``` json
{
    "name": "開発コンテナの名前",

     // image を利用する場合
    "image":"開発コンテナの作成に使用するコンテナレジストリ",

     // Dockerfile を使用する場合
    "build": {
        "dockerfile": "Dockerfileへのパス"
    },

     // docker-composeを使用する場合
     "dockerComposeFile":"docker-composeへのパス、配列で複数も可能",
     "service":"docker-compose内のどのサービスが開発コンテナかを指定する",
     "workspaceFolder":"開発コンテナに接続したときにVSCodeが開くフォルダ"
}
```


## 参考URL
[VSCode DEV CONTAINERS](https://code.visualstudio.com/docs/devcontainers/containers)
【Windows】仮想デスクトップを活用して作業を効率化しよう

## はじめに
パソコンで作業をする際に、複数のアプリを開いて作業することがあると思います。その際に、画面上にウィンドウを開き過ぎてごちゃごちゃして、ウィンドウの切り替え操作に手間取ったことはありませんか？

そのような時に仮想デスクトップを活用すると、ウィンドウの整理ができて作業を効率化できます。本記事では、仮想デスクトップの概要とその基本的な操作方法について説明していきます。仮想デスクトップの操作方法については、Windows（Windows10以降）を想定しています。

## 仮想デスクトップ機能について
パソコンを起動して一番最初に表示される画面をデスクトップと言います。デスクトップ画面から様々なアプリを開いたりして作業をする訳ですが、デスクトップは通常パソコン1台につき1つです。しかし、仮想デスクトップ機能を使うことで、仮想的なデスクトップ画面を新たに生成し、複数のデスクトップがあるものとして操作することができます。

1つのデスクトップ内で複数のウィンドウを開いている状態は、いわば1つの机の上に沢山の書類を出しているようなものです。仮想デスクトップ機能を使うことで、複数の机を用意して机ごとに書類を分けて置くようなことができます。

## 仮想デスクトップ操作のショートカット
仮想デスクトップを活用する上で、頻繁に使う操作は、仮想デスクトップの生成・切り替え・削除です。それらの操作と対応するショートカットキーをまとめたものが下表です。ぜひ、実際に操作しながら確認してみてください。

| 操作内容 | ショートカットキー |
|:-:|:-:|
| 仮想デスクトップの生成 | Ctrl + Win + D |
| 仮想デスクトップ画面の切り替え | Ctrl + Win + ←/→ |
| 仮想デスクトップの削除 | Ctrl + Win + F4 |

## おわりに
仮想デスクトップの概要とその操作方法について説明しました。仮想デスクトップを使えば、特にウィンドウ操作に関してはストレスが減ること間違いなしです！！自分の場合は、仮想デスクトップが多すぎてもかえって混乱するので、1個だけ生成して使っています。

本記事で説明したことは必要最低限なので、もっと詳しく知りたい人は、下記の参考動画を見てみてください。

## 参考動画
https://youtu.be/VFD1vhBo_uc?si=RWO2j5gMcWljgqJk
Instagramのフォロワー数をtroccoで取得しSnowflakeに保存する

# これはなに

Instagramのアカウント運用において、フォロワー数は非常に重要なメトリクスです。
複数のSNSを運用している場合、重要指標の推移をダッシュボード等で横断的にモニタリングしたいことがあると思います。

今回はSaaSのtroccoを用いて、Instagramのフォロワー数をAPI経由で取得しSnowflakeに保存する方法を紹介します。

# 事前準備

## trocco®アカウントの作成

trocco®には無料で始められるフリープランがあります。

https://trocco.io/lp/index.html

## facebook グラフAPI トークンの取得

facebookの開発者アカウントの仕組みは少し複雑なのですが、以下などの記事を参照しアクセストークンを取得します。

https://note.com/digitalift/n/n003977fef78e

上記記事に記載の通り、

* Instagramをプロアカウントにする
* facebookページとリンクさせる

といった手順が必要になります。特別な審査が必要な作業ではないため、個人でも問題なく作成することが可能です。

# 実装

トークンが取得できさえすれば、その後の実装は非常に簡単です。

troccoにログインし、転送設定の新規作成に進みます。

* 転送元：HTTP・HTTPS
* 転送先：Snowflake

を選択します。

## 転送元の設定

今回はこちらのAPIを利用します。

https://developers.facebook.com/docs/instagram-api/reference/ig-user?locale=ja_JP

troccoの転送元設定画面にて、以下のようにフォームを埋めていきます。

|設定項目名|設定内容|
|---|---|
|URL|https://graph.facebook.com/v17.0/{ig-user-id}|
|HTTPメソッド|GET|
|入力ファイル形式|JSONPath|
|ルート|$|
|パラメータ access_token|{アクセストークン}|
|パラメータ fields|username,followers_count|

![スクリーンショット 2024-04-24 0.22.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/ce7d7e4e-c612-c31e-6230-f661bd9bd007.png)

fieldsの項目は、APIドキュメントを参照しながら任意の項目を指定できます。

{ig-user-id} の部分は固定となるので、取得対象のinstagramユーザーIDを入力してください。
usernameではない点に注意が必要です。

idを確認する手っ取り早い方法としては、「グラフAPIエクスプローラ」を使って `/me` のエンドポイントを参照することです。

https://developers.facebook.com/tools/explorer/?locale=ja_JP

## 転送先の設定

転送先設定にて、Snowflake側のデータベース、スキーマ、テーブル等を設定していきます。

## プレビュー確認・保存・実行

step2の画面に進むと、取得データのプレビューを確認することができます。

![スクリーンショット 2024-04-24 0.10.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/21e32cff-b8c5-6f8f-c274-55b6696e1a55.png)

テーブル定義等は自動設定のままで問題ないので、確認・保存と進みます。

保存後の画面で「実行」を選択することで、すぐにデータ転送を実際に動かすことが可能です。
以下のように、実際にSnowflakeにデータが入っていることを確認できました。

![スクリーンショット 2024-04-24 0.20.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/8af3adc7-ef08-7720-be68-1a6ef9f24e41.png)

# まとめ

上記の手順を踏むことで、プログラミング作業をすることなく、データ基盤にInstagramのメトリクスを連携することができました。

皆様のSNS運用の一助となれば幸いです。
Professional Scrum Product Owner I (PSPO I) を取得した。

## きっかけ（ここがメイン）
前回の記事でProfessional Scrum Master I (PSM I) を取得したことを記載した。 [^1]

あれから1年が経過し、私自身が開発現場を通して、そもそも本当に取るべき資格はスクラムマスターだったのかという疑問が湧いた。
まずはその理由を書いていこうと思う。

アジャイル型の開発を実践するにあたって、私が一番最初に参考にしたのはIPAの「アジャイル開発の進め方」という資料である。

https://www.ipa.go.jp/digital/hjuojm000000gwoo-att/000065606.pdf

その中で気になったのは開発体制部分である。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953203/9dc30095-9db4-c5c2-ad62-37dc2764e172.png)

この図を見るとスクラムマスターの役割は従来のプロジェクトマネージャーが勤めるのが正しいようだ。
しかし、令和３年度のシステムアーキテクト試験の問題を見ると「システムアーキテクトはスクラムマスタの役割を担う事が多い」とある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953203/c78bb5a5-32fb-c453-618d-4804663aa0c8.png)

同じIPAの資料でありながらこうも差がつくのはどういうことなのだろうか。

ここからは私の推察になる。
おそらく自社ビジネスで完結する場合、スクラムマスターはシステムアーキテクトが勤めるのがよいのだろう。
事業者側と外部ベンダーとで会社が異なる場合、スクラムマスターはプロジェクトマネージャーが勤めるのだろう。

しかし、現実問題として事業者側にプロダクトオーナーが立っていた場合、ベンダー側の窓口がどこか？という問題が発生する。スクラムマスターはチームの為に働くとは言え、橋渡し役としてプロダクトバックログを開発チームに伝える役割を担うのは（アジャイル型開発を採用する利点の一つである）ビジネスアジリティ（俊敏性）を犠牲にしているとしか思えない。

また、ベンダー側にプロダクトオーナーを立てた場合、事業者側のユーザーや顧客と直接交渉や調整することになるのだが、それは越権行為が過ぎるし、商慣習として別の問題が発生する。

とかなんとか考えていたら内閣官房情報通信技術(IT)総合戦略室から「アジャイル開発実践ガイドブック」なるものが出ていた。

https://cio.go.jp/sites/default/files/uploads/documents/Agile-kaihatsu-jissen-guide_20210330.pdf

その中で ”プロダクトオーナー” と ”プロダクトオーナー支援” と別のロールを設けよ、とあった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953203/a8446094-0fde-8bf8-1033-a97a96421368.png)

これであればプロダクトオーナーを事業者側、プロダクトオーナー支援をベンダー側、とそれぞれ立てることで全ての問題が解決する。
（スクラムマスターをシステムアーキテクトが勤めることに違和感はないし、会社間の窓口も一本化する）
（システムアーキテクトが必ずしもスクラムマスターを勤める必要はないとは思うが、開発チームを支援する立場上、ある程度に技術を満遍なく分かる人が望ましいとは思う）

もちろん、実際の試験で「プロダクトオーナーは２人以上である」などという選択肢を選べば不正解であることは間違いない。

「スクラムガイド」や「アジャイルソフトウェア開発宣言」を聖典とし、「改変などまかりならなん」とする原理主義者の方々もいらっしゃるとは思うが、この資料があればそう言った人たちにでも「内閣府がこのようにおっしゃっているで、、、」と正当性を主張することができる。

また、あれは米国のように採用と解雇が容易であり、ビジネス内製化の文化がある場合にのみ成り立つので、日本のようなSIerによる外部ベンダーが開発を請け負う商慣習においては成り立たないのだと思う。

そう言った日本の実情を踏まえ、上手い落としどころを見つけた良い資料を政府はよくぞ作成、公開してくれたと個人的には思っている。

## 本題というか結論
上記の通り、自社ビジネスの場合とベンダー側で仕事を行う場合とでは実際の役割が微妙に異なる、と感じた。
よって契約形態によってはプロダクトオーナーとして動くこともあるので、プロダクトオーナーとしての資格も履歴書につけ足しておこうかと思い取得した。（スクラムマスターの資格でごり押すことも出来ただろうが、さすがにそれはいい大人としてはスマートでないと思ったので）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953203/5ba7630e-5e5a-3a2d-1bd8-3a844ebeec63.png)

## 勉強方法について
勉強方法などは前回記事と変わらない。そちらを参照されたい。 [^1]

違いは前回150ドルで受けられたところが、インフレ率を考慮したのか気が付いたら200ドルになっていたことと、一年前は1ドル=130円ぐらいだったが、150円まで円安が進んだので、実質的には大幅な値上がりであったことぐらいか。（懐が痛い）

[^1]: Professional Scrum Master I (PSM I) を取得した : https://qiita.com/tatsu_sekine/items/65c4ba1f8f724b03f172
既存リポジトリの内容と履歴を新しいリポジトリに複製する方法

## はじめに

前回の記事では、GitLabからGitHubへのリモートリポジトリの向き先を変更する方法を紹介しました【https://qiita.com/hazure_engineer/items/8ddd12105ed4ae3d682a 】。今回は、その続きとして、既存のリポジトリの内容と履歴を新しいリポジトリに完全に複製する方法を説明します。自分はGitLabからAmazon CodeCatalystに移行する際にこの手順を使いましたが、他のプラットフォームに移行する際にも役立つと思います。

### 1. 既存のリポジトリをクローンする
まず、既存のリポジトリ（ソースリポジトリ）をローカルにクローンします。これは `--mirror` オプションを使用して行い、リポジトリ全体の複製を作成します。このオプションを使うと、すべてのブランチ、タグ、コミット履歴が含まれます。

```sh
git clone --mirror 既存のリポジトリのURL
cd クローンしたリポジトリの名前
```

### 2. 新しいリポジトリにプッシュする
クローンしたリポジトリを新しいリポジトリにプッシュするために、まず新しいリモートリポジトリのURLを設定します。

```sh
git remote set-url origin 新しいリポジトリのURL
```

その後、リポジトリ全体を新しいリポジトリにプッシュします。この際にも `--mirror` オプションを使用します。

```sh
git push --mirror
```

`--mirror` オプションにより、すべてのリファレンス（ブランチ、タグ、コミット履歴など）が新しいリポジトリに複製されます。

### 3. 移行が成功したかを確認する
移行が成功したかどうかを確認するために、新しいリポジトリをブラウザで開いて内容をチェックします。また、新しいリポジトリのURLを使ってローカルにクローンして、正しく移行されたかどうかを確認します。

```sh
git clone 新しいリポジトリのURL
cd クローンしたリポジトリの名前
git log
```

`git log` コマンドで、コミット履歴が正しく複製されていることを確認できます。

### まとめ
この手順を実行することで、既存のリポジトリの全内容と履歴を新しいリポジトリに複製することができます。プロジェクトの移行やバックアップを行う際に、この手順を参考にしてください。
ECSのヘルスチェック猶予期間についてハマった点

## はじめに

AWSのALBにぶら下げる形でECS on Fargateを利用しているのですが、起動するまでに数分の時間を要するアプリケーションを運用しており、ヘルスチェック失敗を防ぐためにヘルスチェックの猶予期間（healthCheckGracePeriodSeconds）を設定していました。

ただ、コンテナのデプロイ時に「監視ツール上ではステータスコードの200番しか記録されていない」「その後のアプリケーション自体も正常に動作している」にもかかわらず「`unhealthy`判定がされてしまい、コンテナがエラー終了し、コンテナの再生成が繰り返されてしまう」といった事象に遭遇したため、その調査の過程を記録したものとなります。

## 前提として、ヘルスチェック猶予期間とは何か

ECSサービス定義のパラメータの一つです。

ヘルスチェック猶予期間を設定することで、その期間はECSタスクに対するヘルスチェックの結果を無視する事が可能となっています。

参考：[サービス定義パラメータ > ネットワーク構成 > healthCheckGracePeriodSeconds](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/service_definition_parameters.html#sd-networkconfiguration)

## 何が原因だったのか

結論から述べると「ヘルスチェックの猶予期間が過ぎた時点で、対象のコンテナが`unhealthy`の状態になっていた事」が直接の原因でした。

誤解として「ヘルスチェック猶予期間」は「ヘルスチェック自体が行われなくなる」と認識していましたが、この点は誤りで、正しくは「ヘルスチェック自体は行われるが、その結果自体が無視される」という事となります。

実際に、AWS情報センターにも同様の回答として[ELB に登録されていて、正常に機能している Amazon ECS タスクが異常とマークされて置き換えられるのはなぜですか?](https://repost.aws/ja/knowledge-center/elb-ecs-tasks-improperly-replaced)といったドキュメントがあります。

> Amazon ECS タスクが猶予期間内に ELB ヘルスチェックに応答しない場合、異常のフラグが付けられます。

## 確認したこと

実在しないヘルスチェックパスに対してヘルスチェックを実行する（必ず`unhealthy`となる）コンテナを、ALBのターゲットグループに登録しました。

結果として「失敗のしきい値（回数）×ヘルスチェックの間隔（秒数）」の経過後は、たとえコンテナがヘルスチェックの猶予期間内でも`unhealthy`としてマークされるという事を確認しました。
SpringBootでとにかく最低限のログイン機能追加

# この記事はこれの続きです

https://qiita.com/waokitsune/items/0b8ebb2c851a0562b924

# 概要

とにかく最小限のコーディング。
ユーザーIDとパスワードはSpringBootが用意した固定値。
ユーザーIDとパスワード入力画面も自作しない。

という最低限のログインができることろまでの内容です。

# build.gradle

```dependencies``` セクションに下記を追記します。

```
implementation 'org.springframework.boot:spring-boot-starter-security'
```

build.gradleを変更したら下記を忘れずに。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/7ecf36ce-cb16-7a8e-fd28-f3f75344ddc4.png)


これだけでSpringBootがいろいろ用意してくれます。

# 動作確認

SpringBootを起動すると「固定のパスワードはこれだよ」的なログが出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/a2420c17-fa45-c8eb-c793-2b78f36ef587.png)

ブラウザーでSpringBootのURLにアクセスするとログイン画面になります。
この画面はSpringBootが勝手に用意してくれたものです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/32c07f49-d0bd-5f20-8577-b92f5afb9165.png)

ユーザーIDは『user』固定。
パスワードはログに出力されていた文字列です。

# この記事の続き

https://qiita.com/waokitsune/items/d6ef667e1c5ff5f2aac6

# バージョン

Microsoft Windows [Version 10.0.22631.3447]
JAVA 17.0.10
Spring Boot v3.1.10
laravel-vite-pluginを用いてSCSSからCSSに変換する


### 開発環境
- Windows 10 Pro(64bit)
- Node v20.12.2
- Laravel 10.10
- PHP 8.1.9 (cli) (built: Aug  2 2022 14:17:26) (ZTS Visual C++ 2019 x64)

<font color="red">**※もし、Laravelインストール時に、Viteがインストールされていなければ、Nodeのバージョンを最新にしてから、Viteをインストールしてみてください。**</font>

1./resourcesディレクトリ内に、scssディレクトリを作成し、その中に、app.scssを作成する

2.app.scssに適当なコードを書く
```scss:app.scss

$parent_block_width: 100px;
$parent_block_height: 100px;
$parent_bg_color: red;
$children_block_width: 50px;
$children_block_height: 50px;
$children_bg_color: blue;

.parent{
  width: $parent_block_width;
  height: $parent_block_height;
  background-color: $parent_bg_color;
  .children{
    width: $children_block_width;
    height: $children_block_height;
    background-color: $children_bg_color;
  }
}
```

3.ルートディレクトリにあるvite.config.jsを開き、inputの中に、以下の記述を追加します。
```diff_javascript:vite.config.js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            input: [
            'resources/css/app.css', 
+           'resources/scss/app.scss',
            'resources/js/app.js'
        ],
            refresh: true,
        }),
    ],
});
```

4.Vite用にsassのプリプロセッサをインストールします。
```powershell
npm add -D sass 
```

5.コマンドプロンプト上でビルドします。そうすると、/public/assetsディレクトリ内に**app-xxxxx.css**のファイルが作成されます。
```powershell
npm run build
```

6.最後に読み込ませる方法ですが、Bladeテンプレート内のheadタグ部分に、以下のコードを追加。これを行うと、上記のビルドしたcssファイルを読み込むように変換します。
```php
@vite(['resources/scss/app.scss'])
```


### 参考リンク
- [CSS プリプロセッサー](https://ja.vitejs.dev/guide/features#css-pre-processors)
Dynamics 365 Finance and Operations開発 　X++的基礎技巧①

在D365FO中，财务维度允许用户跟踪和报告财务数据，而无需更改主账户结构。例如，如果您想要按照项目或成本中心跟踪收入和支出，可以创建相应的财务维度，并在进行会计分录时使用它们。
这里有一个实用的X++代码片段，用于创建一个新的财务维度值：

DimensionAttributeValueSetStorage    dimStorage;
DimensionAttribute                   dimAttr;
DimensionAttributeValue              dimAttrValue;
str                                  dimValue = "项目001"; // 您想要创建的财务维度值
;
// 获取或创建财务维度
dimAttr = DimensionAttribute::findByName("项目"); // 替换为您的财务维度名称
if (!dimAttr)
{
    throw error("指定的财务维度不存在。");
}
// 使用财务维度名称和值创建新的财务维度值
dimAttrValue = DimensionAttributeValue::findByDimensionAttributeAndValue(dimAttr, dimValue, true, true, true);
// 将新的财务维度值添加到维度值集合中
dimStorage = DimensionAttributeValueSetStorage::findOrCreate(dimAttrValue.DimensionAttributeValueSet, true);
dimStorage.addItem(dimAttrValue.RecId);
// 保存更改
dimStorage.save();
info(strFmt("已成功创建财务维度值 '%1'", dimValue));

使用上述代码可以创建一个名为"项目001"的新财务维度值，然后您可以在会计分录中引用它。记得替换代码中的"项目"和"项目001"为您实际的维度名称和值。
PHPコード保存時にuse文を自動整理したい

# やりたいこと

VS CodeでPHP保存時にuse文に対して以下を行いたい

- アルファベット順にソート
- 不要なuse文の削除

# 探した拡張機能

## 候補1

https://marketplace.visualstudio.com/items?itemName=DEVSENSE.phptools-vscode

この開発元であるDEVSENSEというところの以下の紹介記事がそのものズバリ。

https://blog.devsense.com/2023/sort-uses-and-remove-unused-uses-on-php-file-save

## 候補2

https://marketplace.visualstudio.com/items?itemName=tarik02.php-imports#review-details

拡張機能のREADMEの設定項目を読むとできそうな感じがある。

# やってみる

候補２の`php-imports`を入れてみる。

候補１の`PHP`を使わなかったのは、use文の整理以外にも様々なことを行うオールインワン拡張機能のようなので、既存の拡張機能との共存に問題ないか不安だったため。

1. vs codeの拡張機能で`php-imports`を検索しインストール
1. コマンドパレットを開き`php imports: init`を選択
1. 設定を開く（cmd + ,）、以下を行う
    1. 設定画面の検索バーで「format on save」を検索
    1. `Editor: Format On Save`にチェックを入れる
    1. `PHP-imports: Format On Save`にチェックを入れる
1. `php imports: init`を実行したときに作成された`.phpimportsrc`ファイルを開く
1. 編集
    ```diff
    ...
    "order": [
    -    "singleUses.class",
    -    "emptyLine",
    -    "singleUses.function",
    -    "singleUses.const",
    -    "emptyLine",
    -    "groupedUses.class",
    -    "emptyLine",
    -    "groupedUses.function",
    -    "groupedUses.const"
    +    "all.class",
    +    "emptyLine",
    +    "singleUses.function",
    +    "singleUses.const"
    ],
    ...
    "psr12": {
    -    "enable": true,
    +    "enable": false,
        ...
    }
    ...
    "unused": {
    -    "enable": false
    +    "enable": true
    }
    ```
※psr12をtrueにしていると以下のようにuse文をまとめます。
```php
use App\Models\{
    Job,
    User
}
```

# Demo
保存時の様子
![format-on-save.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87345/1c258899-aba5-9285-869b-09973bd42e25.gif)
langchainでelasticsearchのBM25

```python:
# %%
from langchain_community.document_loaders.html import UnstructuredHTMLLoader

loader = UnstructuredHTMLLoader(file_path='/home/onoyu1012/workspace/elasticsearch/疾風伝説 特攻の拓 - Wikipedia.html')
data = loader.load()
print(data)
# %%
from langchain_text_splitters.character import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=0)
documents = text_splitter.split_documents(documents=data)
print(len(documents))
for document in documents:
    print(document)
# %%
username = '<INPUT YOUR ES/WxD_USERNAME>'
password = '<INPUT YOUR ES/WxD_PASSWORD>'
host = 'https://%s:%s@<INPUT YOUR ES/WxD_HOST>:<INPUT YOUR ES/WxD_PORT>' % (username, password)
print(host)
# %%
from elasticsearch import Elasticsearch

es_connection = Elasticsearch(hosts=host, ca_certs='<INPUT YOUR ES/WxD_CART FILE PATH>')
# %%
from langchain_elasticsearch import ElasticsearchStore

db = ElasticsearchStore(es_url=host, index_name='test2', strategy=ElasticsearchStore.BM25RetrievalStrategy(), es_connection=es_connection)
# %%
db.add_documents(documents=documents)
# %%
results = db.similarity_search_with_score(query='SR400')
# %%
for result in results:
    print(result)
# %%
```

>(Document(page_content='愛車はケニー・ロバーツ号と名付けたFZR250R。その後、エディ・ローソン号と名付けたゼファー400、爆音ドラックスペシャルGPZ2856F、爆音CoolストリートスペシャルCBX1000、天羽時貞の悪魔の鉄槌（ルシファーズ・ハンマー）SR400。この他に晶のCB350FOUR（通称バケヨン）も一時借りていた。横浜港ヶ丘高校時代には通学用にスクーターを所有していた。\n\n趣味はパソコン。自作のRPGも作っていた。\n\n「爆音小僧」の七代目頭。愛称は「マー坊」「マサト」。聖蘭高校1年D組。拓と同じくらい小柄だが、片手で80キロの人間を持ち上げるほどの怪力の持ち主。大の甘党。拓には初対面の頃から友好的な態度で接している。事故で亡くなった半村誠を、誰よりも尊敬と憧れの目で見ていた。普段の振る舞いは無邪気な女の子を彷彿させるが、キレると手がつけられなくなる。単車の操縦技術はチームトップ。相原勇に似ている、と馬鹿にされると激怒する。龍也、武丸とは犬猿の仲。「港洛中」出身。アキオ、晶とは幼馴染。“上等文句”は「ひき肉にしてやる！」', metadata={'source': '/home/onoyu1012/workspace/elasticsearch/疾風伝説 特攻の拓 - Wikipedia.html'}), 3.1449661)
(Document(page_content='元々いじめられっ子であった為、臆病で、ハッタリもよく使うが、友達を非常に大事にする性格で、「他人の為に“気合”を見せた時には奇跡（ミラクル）を呼ぶ」と秀人は評価している。当初は、単車乗りの技術も稚拙であったが、気合による無茶と偶然で幾度も危機を乗り越え経験を重ねる内に、夏生に“スピードの捉え方が誠に似ている”、秋生に“棲息速度領域はマー坊と同等”とまで言われるようになり、「灰色の亡霊（グレイ・ゴースト）」編では拓の棲息速度域に合わせて組み上げられた爆音Coolストリートスペシャルによって走ることの楽しさに開眼。秋生の予想を大幅に超えたライディングセンスを見せて「化けた」とまで称された。最終局面ではマー坊によって半ば無理矢理「暴走りの特攻」に指名され、爆音小僧の幹部に。\n\n最終回では、爆音小僧の不倶戴天の特攻服（那森須王から）、外道のハチマキ（鳴神秀人から）、蠅王の腕章（来栖奈緒巳から）を身につけ、YAMAHA・SR400（天羽時貞から）で特攻し、神奈川の族の全面戦争を収めた。', metadata={'source': '/home/onoyu1012/workspace/elasticsearch/疾風伝説 特攻の拓 - Wikipedia.html'}), 3.0051546)
(Document(page_content='愛車はノートンタイプのタンク、シングルシートとハーレーダビッドソン用も製造している部品メーカー、ルシファーズ・ハンマーのピストンとシリンダーを執事の桧原に組ませた“悪魔の鉄槌（ルシファーズ・ハンマー）”と呼ばれるヤマハ・SR400。\n\n元「獏羅天」。倫子の双子の兄で音速の四天王の一人。土方から誠とともに“スピードの向こう側”を聞かされ、その領域に魅せられる。十五代目「獏羅天」から、真嶋夏生率いる六代目「爆音小僧」に移籍するも、半村誠の死後単身オーストラリアに渡り、単車のレースに興じるようになる。その後インドネシアを経て日本に帰国すると、以前とはかけ離れた現状に激昂し、一人で「獏羅天」を再興する。最終的には、湘南での拓との単車勝負に敗れたことを契機に、土方と共にレースの世界へ。レーシングチーム「獏羅天」を結成する。龍也には非常に嫌われているが、「爆音小僧」のメンバーには憧れの目で見られており、多少の衝突を含むも比較的良好な関係。特に、拓には「爆音小僧」時代の伝説の“不倶戴天”仕様の特攻服を渡した。双子の妹である倫子に道を尋ねようとした中年男性を「失踪」させた噂も存在する。', metadata={'source': '/home/onoyu1012/workspace/elasticsearch/疾風伝説 特攻の拓 - Wikipedia.html'}), 3.0051546)
ATEM Control

# ATEM Control

ATEM Miniシリーズのすべての機能を使うには、ATEM Controlソフトを使う。ATEM Controlソフトをより詳しく知ることで、活用の幅が広がる。

ATEM Controlソフトの下部には、ページを切り替えるボタンがまとまっている。ページごとに内容を分けているが、自分が関係しない部分は割愛した。

## 1. スイッチャーページ

* プログラムとプレビュー
    * プログラム(PGM)は出力される映像を指す
    * プレビューは次に表示する入力映像を指す。CutやAutoで出力に切り替える。レバーで切り替え
    * ソース選択ボタン：ベースとなる入力映像を切り替える。プログラム、プレビューともに同じ構成になっている
        * Cam1〜：ビデオ入力
        * Blk：黒一色
        * Bars：カラーバー
        * Col1/Col2:設定した色一色
        * MP1：メディアプレーヤーに設定したメディア
* H/Wの数字ボタン
    * 次に表示する入力映像を切り替える。プログラム・プレビューはなし。Auto/Cutを決めておいて、数字ボタンを押したときに切り替わる

### スイッチャーページのパレットを使う

パレットの表示は、上が背面、下が前面となるように並んでいる。
* 入力画像＜最背面＞
* アップストリームキー（例：DVE）
* トランジション
* ダウンストリームキー（例：メディアプレーヤー）
* FTB＜最前面＞

アップストリームとダウンストリームの違いは、入力映像の処理の早い段階（上流＝アップストリーム）での処理か、トランジション処理のあとの段階（下流＝ダウンストリーム）での処理かである。ATEM Miniにはダウンストリームキーヤーもあるため、合計２つのソースを重ねられる、ということ。

例：入力映像に、別のカメラ映像を重ね、さらに枠の画像を重ねる

### 各機能について

* カラージェネレーター
    * COL1/COL2ボタンで呼び出せる、一色で埋める機能
* アップストリームキー、ダウンストリームキー
    * 「キー」や「キーイング」はベースの映像の上に別の画像や映像を合成するために、色や輝度、アルファチャンネルを使って部分的に透明にすることを指す
    * 透明処理だけでなく、別の画像や映像をどの位置に、どの大きさで重ねるかを決める
    * ルマキー：輝度を使ってマスクする(アップ・ダウン両方)
        * フィルソースに重ねる映像を指定
        * キーソースに透明化する箇所を黒にした映像を指定（フィルソースと同じにすると、ルマキーである）
    * リニアキー:輝度を使ってマスクする(アップ・ダウン両方)
        * フィルソースに重ねる映像を指定
        * キーソースに透明化する箇所を黒にした映像を指定（フィルソースとは別にすると、リニアキーである）
        * 画面上ではルマキーとして表示されている
        * クリップにて、黒とする輝度のしきい値を指定
    * プリマルチプライキーとは、入力映像に含められたアルファチャンネルのようなキー信号をもとに透明化をほどこすこと
    * クロマキー:色を使ってマスクする(アップのみ)
        * フィルソースに重ねる映像を指定
        * クロマサンプルボタンで、透明にする色を取り込む
        * フォアグラウンドスライダー
        * バックグラウンドスライダー
    * パターンキー:?(アップのみ)
    * DVEキー:?(アップのみ)
    * キーイングの利用シーン
        * ピクチャーインピクチャー(P in P)
            * パレットにあるDVEのタブで変更
            * フィルソース：P in Pに表示したい映像ソース
            * マスク：必要な部分だけを抜く
            * サイズ・位置
            * 枠、ドロップシャドウ
        * 緑の背景を透明にするクロマキー
            * H/WのKeyボタンで行える
* トランジション
    * トランジションスタイルのパラメーターを設定できる

### スイッチャーページのメディアプレーヤーを使う

* 背景透過の画像を重ねる
    * メディアプレーヤー
    * ダウンストリームキーに表示されるため、重ねての表示ができる
    * DSK1のOnAirによって表示・非表示を切り替える

### スイッチャーページの出力を使う

* ライブ配信の設定や録画の設定をする部分

## 2. メディアページ

メディアプレーヤーに出す画像ファイルを登録しておける。
ATEM本体に保存される

## 3. オーディオページ

（割愛）

## 4. カメラページ

カラーグレーディングができる（Black Magicのカメラのみ）（割愛）

## 5. マクロ機能

マクロは、ユーザーのボタン操作や設定変更を記録する。それを再現したり繰り返したりできる。別のマクロを呼び出す操作を記録することもできる。

* メニューの`マクロ`から、マクロウィンドウを開く

## 6. 設定変更

歯車アイコンを押すと、設定画面が表示される。ここでスイッチャーの一般的な設定を変更できる。

* 一般設定
    * ビデオフォーマットの設定（1080p60など）
* メディア
* オーディオ
    * 音声の分割、ライン/マイク入力の設定など
* マルチビュー
    * マルチビュー画面の内容を変更（入れ替え）できる
* ソース
    * 入力・出力の名前やラベルを変更できる
    * 短いラベルは4文字までで、ボタンに表示される
* リモート

メニューの`出力`から、HDMI出力するソースを選択できる。

## 7. スイッチャーの設定

### ファイル保存

メニューの`ファイル`から、`別名で保存`を選択すると、保存先を選択したのちに出力するデータを選択する画面が出る。すべて選択することもできる。  
設定はXMLファイルとして保存される。

### 今の設定をデフォルトとする

メニューの`ファイル`から、`本体に設定を保存`を選択する。保存した状態が起動時のデフォルト（スタート設定）となる。  
スタート設定を購入時の状態に戻すには、メニューの`ファイル`から、`本体の設定をリセット`を選択する。

## 参照

[Blackmagic Design ATEM Mini の機能を開放しよう！ – ATEM Software Control](https://www.miroc.co.jp/antenna/blackmagic-design-atem-mini-%E3%81%AE%E6%A9%9F%E8%83%BD%E3%82%92%E9%96%8B%E6%94%BE%E3%81%97%E3%82%88%E3%81%86%EF%BC%81-atem-software-control/)

[ATEM Mini マニュアル](https://documents.blackmagicdesign.com/UserManuals/ATEM_Mini_Manual.pdf)
【CSS】フォームのサイズを入力された文字数に応じて変更する方法

CSSで`textarea`や`input`に対して`field-sizing: content;`を指定することで入力された文字数に応じてサイズが変更されるようにできます。

```css
textarea {
  field-sizing: content;
}
```

:::note warn
FirefoxやSafariなどはまだ対応していません。
:::



https://developer.mozilla.org/en-US/docs/Web/CSS/field-sizing
langchainでelasticsearchのvectorsearch

```python
# %%
from langchain_community.document_loaders.html import UnstructuredHTMLLoader

loader = UnstructuredHTMLLoader(file_path='/home/onoyu1012/workspace/elasticsearch/疾風伝説 特攻の拓 - Wikipedia.html')
data = loader.load()
print(data)
# %%
from langchain_text_splitters.character import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=0)
documents = text_splitter.split_documents(documents=data)
print(len(documents))
for document in documents:
    print(document)
# %%
import os

os.environ['HUGGINGFACEHUB_API_TOKEN'] = '<INPUT YOUR HUGGINGFACEHUB_API_TOKEN>'
# %%
from langchain_community.embeddings.huggingface import HuggingFaceEmbeddings
embedding = HuggingFaceEmbeddings(model_name='intfloat/multilingual-e5-large')
# %%
# %%
username = '<INPUT ES/WxD_USERNAME>'
password = '<INPUT ES/WxD_PASSWORD>'
host = 'https://%s:%s@<INPUT YOUR ES/WxD_HOST>:<INPUT YOUR ES/WxD_PORT>' % (username, password)
print(host)
# %%
from elasticsearch import Elasticsearch

es_connection = Elasticsearch(hosts=host, ca_certs='<INPUT YOUR ES/ExD_CA_CART_PATH>')
# %%
from langchain_elasticsearch.vectorstores import ElasticsearchStore

vectorstore = ElasticsearchStore.from_documents(documents=documents, index_name='test', es_connection=es_connection, embedding=embedding)
# %%
vectorstore.similarity_search(query='SR400とは？')
# %%
```
【aws】CloudWatchを用いてlambdaのエラーを確認する

## はじめに
私はaws初学者であり、現在awsのlambda, GateWay, DynamoDBを用いてAPIを開発しています。作成したAPIを叩いたとき、`{"message": "Internal server error"} `というエラーが現れました。このメッセージだけでは、具体的なエラーの原因がわかりません。調べたところ、Lambdaで発生した実行時のエラーはCloudWatchで確認できることがわかりました。今回はその確認方法をまとめて記録します。

## CloudWatchを開く
lambdaの`モニタリング`タブから`CloudWatch ログを表示`を選択し、`CloudWatch/ロググループ/Catfeeder`にアクセスすることができます（手動でCloudWatchを開いてロググループ→Catfeederでアクセスすることもできます）

![１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984024/c3d85fd8-1102-ea2a-8d8c-afea817c6d2e.png)

## ログを確認する
下に少しスクロールしたところにログストリームが並んでおり、タイムスタンプが新しい順にソートされています。今回は最新のログを確認したかったので一番上のものを開きました。

![２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984024/ed0b1666-af1b-36ce-9c1a-1ba86e8ba1d5.png)


ログが並んでおり、トグルを開くことで内容を確認できます。しっかりとエラーが出ていました。私の場合、コードの先頭に誤って”ud”と記述されていたことが原因だとわかりました。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984024/feac9e94-a6a4-5f3d-fc1c-f3ee48819e12.png)



## 最後に
このような簡単なミスに何時間も悩むことがありますが、ログを確認することで迅速に原因を特定できることがわかります！効率よく開発するためにもログは重宝していこうと思います。
powershellでメール送信

メールを送信するためには、次のものが必要です。

1.SMTPサーバのアクセス情報: 送信に使用するSMTP（Simple Mail Transfer Protocol）サーバのホスト名またはIPアドレス、ポート番号、および認証情報（ユーザー名とパスワード）が必要です。SMTPサーバは、メールを送信するためのサーバです。

2.メール送信用のアドレス: 送信元として表示されるメールアドレスが必要です。このアドレスは、SMTPサーバが受け入れるメールアドレスである必要があります。

3.メールの宛先アドレス: メールを送信する先のメールアドレスが必要です。1つ以上の宛先を指定できます。

4.メールの内容: 送信するメールの件名、本文、および必要に応じて添付ファイルなどの内容が必要です。

5.SMTPクライアントソフトウェア: メールを送信するためのSMTPクライアントソフトウェアが必要です。多くのプログラミング言語やフレームワークには、SMTPクライアントを簡単に使用できるライブラリやモジュールが提供されています。

例えば、PowerShellを使用してメールを送信する場合、Send-MailMessageコマンドレットを使用できます。以下は、基本的な使用方法の例です。

```powershell:sendmail.ps1
Send-MailMessage -From "your_email@example.com" -To "recipient@example.com" -Subject "Test Email" -Body "This is a test email" -SmtpServer "smtp.example.com" -Port 587 -Credential (Get-Credential)
```
この例では、-SmtpServerパラメータでSMTPサーバのホスト名を指定し、-CredentialパラメータでSMTPサーバへの認証情報を指定しています。SMTPサーバによっては、SSL/TLSを使用する必要がある場合がありますので、その場合は-UseSslパラメータを追加してください。
「つよつよエンジニア」にはなれないかもしれないけど、諦めたくはない

## まえがき

記事の内容はタイトル通り、
自分はいわゆる **つよつよエンジニア** にはなれないんだろうなと思いつつ、
諦めたくないという気持ちで葛藤している現役エンジニアのポエムになります。

## これまでのキャリア

現在、自分はエンジニアになって2年半くらいです（執筆時点）。

これまでの経歴としては、地元のﾁｮｯﾄｶｼｺｲくらいの高校を卒業し、
関西でﾁｮｯﾄﾕｳﾒｲな私大の経済学部を卒業。

そのまま新卒で東証一部上場の商社の営業部入りました。

（ただし営業部とは言いつつ、
貿易実務とたまにお客様と打ち合わせ程度で、がっつり営業という感じではないです。）

業務量の多さと先行きの不安など（ここは端折ります）から、
エンジニアを目指すことを決め、独学でプログラミング学習を開始。

ちょうど2年目の終わりに退職し、
知り合いから業務委託で仕事を受けつつ1年間フリーランスとして活動しました。

Web制作からスタートし、Nuxt, Vueを使い始め
途中からRailsの案件に参画させていただきフロントエンドをメインに活動していました。

こうして少しだけ実務経験を得た頃に、
色々機会が重なって東京の受託開発企業へ転職。

同じようなスキルセットのままRailsを使いつつ徐々にバックエンドへ移行。
約1年の間に最終的に最大12名ほどの開発メンバーのPMOをやりつつ
フロントエンド・バックエンドの開発をするまでになりました。

そしてさらに成長できる環境を求め、現職の会社にバックエンドエンジニアとして転職をしました。

ちなみに転職活動時点ではちょうど2年くらいの経験年数でしたが、
これまでの幅広い経験とポテンシャル等を評価していただき、
急成長している有名なSaaS系自社開発企業、大手企業の面接も最終面接まで行けたりと割と良い感じで進めることができたのは少し自信になりました。
（※落ちたけど。いけると思ってなかったので緊張しすぎて頭真っ白になってぶっちゃけ失敗した実感あります。）

### キャリアまとめ

つらつらと書きましたが
ここまでのエンジニアとしての実務経験をざっくりまとめると、

* フロントエンド：Nuxt, Vue（トータル2年ほど）
* バックエンド: Rails（トータル2年ほど）

という感じです。
受託企業にいる頃はHerokuを使っていたためインフラは触れる機会がなく、ほぼわからずです。

実務経験を除くと、自己学習でTypeScriptやNestJは触りました。
今は基本情報とAWSクラウドプラクティショナーの資格勉強をしています。

## 感じ始めた「壁」

さて、ここからが本題です。

現状、メンバーとしてプロジェクトに入り
普通に開発ができるレベルにはなっていると思います。

日々知らないことに出会い刺激がありますし、頭を使って考えること自体が好きなので、
正直エンジニアは**天職だと感じている**くらいです。

自由度が高い働き方もできており、月曜日が嫌になるということが今は本当にないです。

しかし、まだまだ知識・経験は圧倒的に不足しており
会社の先輩方と話す機会などがあると自分との間に果てしなーーーい距離を感じます。

まあそれもそのはず。
世の中には自宅でサーバー構築したり、そもそも「勉強」とも思わず
ただただ好きという理由で技術に向き合っている方がたくさんいます。

しかも自分は文系卒で営業から技術職へ転身したので
情報系の学部に入ってずっと技術に触れてきた方々に対しては
ただでさえ大幅な遅れがあります。

わかってはいたことですが、
時折こういった事実を目にし、一生追いつけないんだろうなと思って心が折れそうになります。

これが **感じ始めた「壁」** というやつです。

## これからどうする？

こうした状況で、葛藤が生まれます。

技術職になったからにはそのまま専門性を高めたいし、その分野でもっと活躍したい。

やっていることも楽しくて好き。

でも自分よりすごい人が山のようにいて、そのレベルに到達できる気もしない。

ここで悩むのが「この先どうするか」というキャリアの問題です。

ぶっちゃけマネジメントの方も全然嫌いじゃないと思いますし、
大体のことはやれば平均かそれ以上にはできるという自信はあります。

ただ、
「本当にそれでいいんだろうか。」
「可能性を捨てているんじゃないだろうか。逃げていることになるんじゃないか。」
という思いが湧き上がります。

### 結論

結論自分としては諦めたくはないので **専門性をこのまま高める** 方向性でいこうと考えています。
（マネジメントなどその他を捨てる、という意味ではないです）

ただざっくりとでも撤退基準は持っておいた方がいいと思うので、
**30歳になってまだ同じ気持ちになるのであれば方向転換をする** ということだけ考えました。

現在27歳でエンジニアの経験年数が2年半ほどなので、
30歳だと5年ちょっとになります。

5年も仕事をすると何かを掴めると思いますし、リーダーレベルにはなって然るべき年数だと思っています。

また、キャリア的にも30歳くらいからは自分がこれまで身につけたスキルを
いかに組み合わせて価値発揮し勝負していくかというフェーズに移っていくと思うので
「つよつよエンジニア」を目指し続けるかどうかを考えるにはいいタイミングだろうと感じた次第です。

## まとめ

まずはここまで拙い文章を長々と読んでいただきありがとうございました。

普通に自己解決した感じになっていますが、
結論は書きながら思い浮かびました。

おそらく同じように感じている人は一定数いると思いますので
共感された方はぜひ一緒に頑張っていきましょう！！！
p5.js Web Editor上で AlaSQL を動かしてみる

以下の記事の続きで、引き続き「[AlaSQL](https://alasql.org/)」を扱ってみます。

●ブラウザ上で AlaSQL を利用するための下調べ（簡単なメモ） - Qiita
　https://qiita.com/youtoy/items/f36138ddcb2e696dc5db

今回は、p5.js Web Editor上で AlaSQL を使った簡単な処理を動かしてみようと思います。

## 元にするサンプル
今回、元にする内容は以下の公式サイトに掲載されているサンプルです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/992fea38-f987-efe7-57d7-8913a50f706f.png)

## p5.js Web Editor上で AlaSQL を使う
早速、p5.js Web Editor上で動かしてみます。

ライブラリは、CDN から読みこむこととします。今回は、以下を使います。

●alasql - Libraries - cdnjs - The #1 free and open source CDN built to make life easier for developers
　https://cdnjs.com/libraries/alasql

p5.js Web Editor上では、このライブラリの読み込みを index.html で行います（※ 以下を追記します）。

```html
    <script src="https://cdnjs.cloudflare.com/ajax/libs/alasql/4.3.3/alasql.min.js"></script>
```

あとは、p5.js Web Editor上の sketch.js に、JavaScript のプログラムを書いていきます。

今回はシンプルに、以下の内容としました。

```javascript
function setup() {
  createCanvas(400, 400);
  background(220);

  alasql("CREATE TABLE test (language INT, hello STRING)");
  alasql("INSERT INTO test VALUES (1,'Hello!')");
  alasql("INSERT INTO test VALUES (2,'Aloha!')");
  alasql("INSERT INTO test VALUES (3,'Bonjour!')");

  const result1 = alasql("SELECT * FROM test WHERE language > 1");

  const result2 = alasql("SELECT * FROM test");

  console.log(result1);
  console.log(result2);
}
```

これを動かした際の出力は、以下のとおりです。無事、意図した出力が得られているのが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/fdebceaf-9e4a-a0c9-bcb4-542ea543a736.png)

## 公式の Wiki の関連ページを見てみる
最後に、上記のプログラムで使った処理について、公式の Wiki の掲載ページがどこかを見てみることにします。

今回の内容だと、Wiki の中で、さらに以下などを見ていくと良さそうでした。

●sql · AlaSQL/alasql Wiki
　https://github.com/AlaSQL/alasql/wiki/Sql

以下に、具体的なページのリンクのみ羅列していきます。

### CREATE TABLE

●Create Table · AlaSQL/alasql Wiki
　https://github.com/AlaSQL/alasql/wiki/Create-Table

### INSERT

●INSERT · AlaSQL/alasql Wiki
　https://github.com/AlaSQL/alasql/wiki/Insert

### SELECT

●Select · AlaSQL/alasql Wiki
　https://github.com/AlaSQL/alasql/wiki/Select

●From · AlaSQL/alasql Wiki
　https://github.com/AlaSQL/alasql/wiki/From

●Where · AlaSQL/alasql Wiki
　https://github.com/AlaSQL/alasql/wiki/Where


## その他
その他、以下なども気になったので、引き続き内容を追いかけて行こうと思っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/7155bddb-9d0a-e5dc-b9c8-8c6498398fbf.png)

●Data manipulation · AlaSQL/alasql Wiki
　https://github.com/AlaSQL/alasql/wiki/Data-manipulation
Reactのmemo、useMemo、useCallback

Reactのパフォーマンス変換フックのメモです。

# memo
memo　は親コンポーネントの再レンダリングにより、同時に子コンポーネントが再レンダリングされるのを防ぐ機能。　memoで親に影響されたくないコンポーネントを囲って使う。
でも、propsで受け取っている変数に**変更**があった場合は再レンダリングされる。ここでの「**変更**」とは値の変更ではなく参照場所が変わった時を指す。

 # useCallback
子コンポーネントに渡す関数をuseCallbackでラップした場合、親コンポーネントが再描画された場合に新しい関数が作成されるの防げるため、子コンポーネントが再描画されるのを抑制することができます。
つまり、useCallbackでラップされている関数は再レンダリングされることがないので、memoでコンポーネントを防いでいる場合propsでは変更されてしまうが、
そのpropsでもらっている変数が、親コンポーネント内でuseCallbackで包まれているものであれば、これは子コンポーネントの際レンダリングを防ぐことになる。

# useMemo
useCallbackでは　そもそも関数を再生成しないという機能であったが、useMemoは下記のように書き、変数の変化による再実行を特定の値の時に限定するものである。

```test.tsx
const cachedValue = useMemo(calculateValue, dependencies)
```

これはuseEffectが特定の変数の値が変更されたときに再実行されるのに対して、useMemoも特定の値が変更された場合に実行されていますね。

違いは現時点でわかっていることですが、最初の実行のタイミング、です!!

useMemo はレンダリング中に実行される。
useEffect　はレンダリング後に実行される。

また、非同期などの関数を扱う場合もuseEffectが良いでしょう。


ではさようなら。間違えていることもあると思いますのでご指摘いただけると勉強になって助かります。
React/TypeScriptでreact-speech-recognitionで  regeneratorruntime is not definedエラーが出る

# はじめに

音声入力をやろうとしたところえらーがはっせいしたのでまとめます

# 問題

以下のサイトを参考にTypeScriptで実装したいたところエラーが発生しました

```
 regeneratorruntime is not defined
 ```

 https://bgtu-techblog.com/2023/05/21/%E9%9F%B3%E5%A3%B0%E8%AA%8D%E8%AD%98%E3%81%A7%E9%9F%B3%E5%A3%B0%E3%82%92%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E5%8C%96%E3%81%99%E3%82%8Breact%E3%83%95%E3%83%83%E3%82%AF%E3%80%90react-speech-recognition/

 ```tsx
 import React from "react";
import SpeechRecognition, {
  useSpeechRecognition,
} from "react-speech-recognition";

const ReactSpeechRecognitionComponent: React.FC = () => {
  const {
    transcript,
    listening,
    resetTranscript,
    browserSupportsSpeechRecognition,
  } = useSpeechRecognition();

  if (!browserSupportsSpeechRecognition) {
    return <span>ブラウザが音声認識未対応です</span>;
  }

  return (
    <div id="react-speech-recognition">
      <p>入力: {listening ? "on" : "off"}</p>
      <button type="button" onClick={() => SpeechRecognition.startListening()}>
        入力開始
      </button>
      <button type="button" onClick={() => SpeechRecognition.stopListening()}>
        Stop
      </button>
      <button type="button" onClick={() => resetTranscript()}>
        リセット
      </button>
      <p>{transcript}</p>
    </div>
  );
};
export default ReactSpeechRecognitionComponent;
```

# 解決方法

まずは`regenerator-runtime`をインストールします

```
$ regenerator-runtime
```

そして`react-speech-recognization`の手前で追加したライブラリをインポートします

 ```tsx
import 'regenerator-runtime'; // 最初に追加
import React from "react";
import SpeechRecognition, {
  useSpeechRecognition,
} from "react-speech-recognition";

const ReactSpeechRecognitionComponent: React.FC = () => {
  const {
    transcript,
    listening,
    resetTranscript,
    browserSupportsSpeechRecognition,
  } = useSpeechRecognition();

  if (!browserSupportsSpeechRecognition) {
    return <span>ブラウザが音声認識未対応です</span>;
  }

  return (
    <div id="react-speech-recognition">
      <p>入力: {listening ? "on" : "off"}</p>
      <button type="button" onClick={() => SpeechRecognition.startListening()}>
        入力開始
      </button>
      <button type="button" onClick={() => SpeechRecognition.stopListening()}>
        Stop
      </button>
      <button type="button" onClick={() => resetTranscript()}>
        リセット
      </button>
      <p>{transcript}</p>
    </div>
  );
};
export default ReactSpeechRecognitionComponent;
```

これで無事音声入力ができました

# おわりに

音声入力はAIが必要なのにライブラリでこんなにも簡単に正確にできるとは思いませんでした。
やれることが増えて嬉しいです。
PowerAutomate: SharePoint 内で、ファイル・フォルダーで抽出する：{IsFolder} で抽出したい時用 by Filter Query

# 背景

FilterQuery 備忘録シリーズ

{IsFolder} でフィルターしたいんだけど、出来ない！！って時の対処法

取得結果を見て、{IsFolder} でやっても出来ない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/7ef621df-c6dc-79cf-45ad-c4bc4b7fc529.png)

# 概要

FSObjType で指定してやれば OK

```text: ファイル、もしくはフォルダーで絞る例
FSObjType eq 0 or FSObjType eq 1
```

:::note
0: File / 1: Foler で Filter する意図として使う。
通常であれば、or でこのように繋がず、and で他の条件と共に利用する
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/a4493b65-38ce-6b0c-20b7-a307bcc25fad.png)


## 利用例

or で取得しているので、ファイル、フォルダー共に取得出来ている。
で、OrderBy で Files が先に並んでいる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/ea8d02a9-6fd6-7664-35a2-c4b0a386afce.png)


# FSObjType の定義

FileSystemObjectType の Enum 定義は以下

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/6d631292-35ab-5ab1-37dd-55abc5ddd152.png)

https://learn.microsoft.com/en-us/dotnet/api/microsoft.sharepoint.client.filesystemobjecttype?view=sharepoint-csom#fields

# あとがき

気力が持ったので書いた・・ :(

# keyword

How to extract files/folders by the Filter Query. {IsFolder} does not work.
Perlのfor文と置換演算子でcase文的なことをする

## 例
```perl
sub foo {
    my $foo = shift;

    for ($foo) {
        s/abc/abc/ and return 1;
        s/def/def/ and return 2;
        s/ghi/ghi/ and return 3;
    }
}
```
`foo`サブルーチンは引数の文字列に`'abc'`が含まれれば`1`を、
`'def'`が含まれれば`2`を、
`'ghi'`が含まれれば`3`を返します。

## 解説
- `for`文の`()`の中の配列の要素が各ループごとに`$_`に入ります
    - スカラ値をリストコンテキストで評価すると、そのスカラ値を唯一の要素に持つリストになります
- `s///`（などの）演算子は指定がなければ`$_`に対し適用されます
- `s///`はマッチングした場合にtruthyを、そうでない場合にfalsyを返します
- Perlでは`and`は短絡評価します
    - つまり、`and`の左辺がfalsyならば右辺は評価されません
GitLabをDockerで動かす場合のメモ

# Windows編
Windows版はDockerimegesが提供されているので、それをdocker-compose.ymlを使って稼働させます。

``` docker-compose.yml
version: '2'

services:
  gitlab:
    image: 'gitlab/gitlab-ce:14.0.2-ce.0' # intel番はイメージあるので、最新のイメージ確認して指定
    restart: "no"
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'http://localhost:5680'
        mattermost_external_url 'http://mattermost.$DOMAIN' #チャットサービス使わないかな
        registry_external_url 'http://registry.$DOMAIN'
      TZ: Asia/Tokyo
    ports:
      - '5680:5680' #'5680:80' でないことに注意
      - '5443:443'
    volumes:
      - '~/src/gitlocal/etc:/etc/gitlab'
      - '~/src/gitlocal/logs:/var/log/gitlab'
      - '~/src/gitlocal/data:/var/opt/gitlab'
      - '~/src/gitlocal/bk:/bk'


# docker-compose -p git_project2 up

```

# Mac ARM編
Mac版はimagesが無いので自分で「リソース取得＆ビルド」「docker-compose.yml」で構築します。

https://github.com/zengxs/gitlab-arm64

上記からDockerfileを含むリソース一式を持ってきます。
んで、imageをビルドします。


ビルド終わったらWindwosと同じで以下のdocker-compose.ymlで稼働させます。

``` docker-compose.yml
version: '2'

services:
  gitlab:
    image: 'gitlab/gitlab-ce:14.0.2-ce.0' # intel番はイメージあるので、最新のイメージ確認して指定
    restart: "no"
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'http://localhost:5680'
        mattermost_external_url 'http://mattermost.$DOMAIN' #チャットサービス使わないかな
        registry_external_url 'http://registry.$DOMAIN'
      TZ: Asia/Tokyo
    ports:
      - '5680:5680' #'5680:80' でないことに注意
      - '5443:443'
    volumes:
      - '~/src/gitlocal/etc:/etc/gitlab'
      - '~/src/gitlocal/logs:/var/log/gitlab'
      - '~/src/gitlocal/data:/var/opt/gitlab'
      - '~/src/gitlocal/bk:/bk'


# docker-compose -p git_project2 up


```
快捷方式后缀删除

1 打开注册表
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734236/feee0f3d-ab25-cb82-36ae-08eb252101e9.png)

2 进入Link文件
コンピューター\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734236/8cf650bd-f789-94be-dacf-c762bdf7c6aa.png)

3 第一位任意数组[..]改成[00]
3_1 变更之前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734236/2dde210c-802b-4852-f055-d7dd2ce553ed.png)

3_2 变更之后
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734236/cb3709c0-5271-2e6f-3cc3-65a9aff2a1e3.png)

4 重启电脑

5 效果
 生产的快捷文件的快捷方式后缀自动消失
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734236/6cf5ea77-f97b-efdb-2462-16a066fef64e.png)
Android 9以下ではandroid:backgroundで@colorを指定できない件

タイトルの通り、Viewの背景にべた塗りの色を指定したくて、以下のように指定しました

```xml
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/primary_50"
    android:text="Hello World!"
    />
```

結果、Android9以下で

```
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example/com.example.MainActivity}: android.view.InflateException: Binary XML file line #21: Binary XML file line #21: Error inflating class TextView
...
Caused by: android.view.InflateException: Binary XML file line #21: Binary XML file line #21: Error inflating class TextView
Caused by: android.view.InflateException: Binary XML file line #21: Error inflating class TextView
Caused by: android.content.res.Resources$NotFoundException: Drawable com.example:color/primary_50 with resource ID #0x7f0502f0
Caused by: android.content.res.Resources$NotFoundException: File res/color/primary_50.xml from drawable resource ID #0x7f0502f0
```

って感じでクラッシュしてしまいました。Android 10以上では問題ありません。

# 原因

実は、このcolor、以下のように`selector`で定義していたのでした。
※colors.xmlで定義した色であれば問題ありません。

```primary_50.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:alpha="0.5" android:color="?attr/colorPrimary" />
</selector>
```

これ自体はテーマカラーにアルファ値を設定するテクニックであり、間違っているわけでも、Android 9以下でサポートされていないというわけでもありません。
ただ、`android:background`でxmlリソースを指定した場合、Android 9以下ではdrawableを期待してパースされるので、クラッシュしてしまったようでした。

# 対策

selectorを使ったcolorの定義が悪いわけでも無く、Android 9以下でも問題無く使えます。ただ、`android:background`で指定できないというだけです。

なので、以下のようにこの色をべた塗りするdrawableを定義し

```bg_primary.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/primary_50" />
</shape>
```

以下のようにdrawableを指定すると問題無く動作します。

```xml
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/bg_primary"
    android:text="Hello World!"
    />
```

----

コンパイル時点で問題は検出されないですし、上位バージョンであれば問題無く動作する記述というのは、見逃してしまいがちです。気をつけましょう。

以上です。
Dockerコマンドの挙動を図解にして覚えやすくしてみた

## 対象者

- Docker使いたいけどよくわからない
- Docker使い始めたけどコマンド言われるがままに打っていてよくわかってない
- コマンドと動作を図示で理解したい

こんな人の理解の一助になれば幸いです。

(前提条件: docker version 26.0.2)

## Dockerコマンドを可視化してみた

勝手にローカルのPCをmacにしているのはご愛嬌です

![dockerコマンド図解](https://bitter-snowdrop-03e.notion.site/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Fc1a7fda7-198a-466a-8dd2-0bad57d3f317%2Fde448e17-4ce0-4de9-af93-48ea4367521d%2FUntitled.png?table=block&id=432c2fcc-20f7-4c91-a794-9512c59d1062&spaceId=c1a7fda7-198a-466a-8dd2-0bad57d3f317&width=1070&userId=&cache=v2)

※2024/5/16 9時: 訂正版の画像に差し替え

コメントで間違いを指摘していただきありがとうございます🙇

細かいオプションなどは一旦無視してライフサイクルの部分を抜き出してみました。

## Docker imageの操作

dockerの肝となるコンテナは、imageから生成します。

そのimageは、

- docker hubからpullしてくる
- dockerfileからbuildする

この2択で生成します。

コマンドは、

```bash
docker image build .
```

など、

`docker image ~` と記述してimageを作る・削除するといったものになる。

## Docker Containerの操作

続いて、コンテナの操作についてですが、基本的に、 `docker container ~`  と記述して、

コンテナを

- 生成
- 起動
- 停止
- 削除

する形になります。

ただ、imageから一気にコンテナを生成しつつ起動する

`docker container run ~` がよく使われるのでこっちを覚えている人が多いかなと思います。

そのうち、毎回 `docker container run --rm -dit -p 8080:8080 ~` のような長ったらしいコマンドを撃ち続けることに嫌気が刺してきたら次は、 `docker-compose.yml`  を書けるようになると楽になります。

Docker compose のライフサイクルについても図解してみましたので、
よければこちらの記事もご覧ください。

https://qiita.com/Tanachu8/items/bb352b8abc43cc9da9ba
Docker環境でディスプレイに画像を表示する

Docker環境は慣れると環境構築が楽で良いですが、画像を表示させようとするとちょっと面倒です。
ここでは、Dockerfileとdocker-compose.ymlを使った設定について記述します。
ubuntu22.04環境です。

VScodeのDocker拡張を入れておけば、ymlファイルを右クリックしてupを選ぶだけでコンテナができるので便利です。

## Dockerfileの追加設定
```
# ディスプレイ関連の追加設定
# 環境変数の設定
ENV DISPLAY=host.docker.internal:0.0
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Asia/Tokyo

RUN apt-get install dialog 
RUN apt-get install -y --no-install-recommends tzdata python3-tk
RUN dpkg --configure -a 
```
python3-tkをインストールするときに、地域などを対話的に聞かれるので周辺の対策をしています。RUNは&&でまとめてもOKです。

## docker-compose.ymlの追加設定
volumesとenvironmentを追加
```
    volumes:
     - /tmp/.X11-unix:/tmp/.X11-unix
    environment:
     - DISPLAY

```
### displayのアクセス権限設定
xhost コマンドは使わずに、コンテナから画像表示が可能でした。
```
xhost +    #　コンテナなど外部からアクセスするとき
xhost -    #　元に戻してセキュアな状態にするとき
```


### 私の設定ファイルの全体像
一般ユーザーとして利用できるコンテナです。sudoが使えます。GPU対応、CUDAとかcuDNNとかほとんど気にせず使えるのがありがたい。

```Dockerfile.

FROM nvcr.io/nvidia/tensorflow:24.02-tf2-py3

# apt-get のアップデーテトとopenCV関係のライブラリを導入
RUN apt-get update && apt-get upgrade -y && apt-get install -y libgl1-mesa-dev

# sudoができる一般ユーザーを作成
# sudoのインストールと設定用フォルダの作成 ｐオプションで上位フォルダがなくても作成
RUN apt-get update && apt-get install -y sudo && mkdir -p /etc/sudoers.d

ARG USERNAME=user
ARG GROUPNAME=user
ARG UID=1000
ARG GID=1000
ARG PASSWORD=user
# 以下で、ユーザーグループの作成、ユーザーを作成 ｍ：ホーム作成　ｓ：ログインシェル指定　ｇ：グループ指定　Ｇ：補助グループ指定
# パスワードを設定し、sudoができるメンバーとして設定する。
RUN groupadd -g $GID $GROUPNAME && \
    useradd -m -s /bin/bash -u $UID -g $GID -G sudo $USERNAME && \
    echo $USERNAME:$PASSWORD | chpasswd && \
    echo "$USERNAME   ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

# ディスプレイ関連の追加設定 管理者権限があるときに行うこと
# 環境変数の設定
ENV DISPLAY=host.docker.internal:0.0
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Asia/Tokyo

RUN apt-get install dialog 
RUN apt-get install -y --no-install-recommends tzdata python3-tk
RUN dpkg --configure -a 

# 作成したユーザーに切り替える。以降の処理は一般ユーザーになる。

USER ${UID}

# ドット.カレントディレクトリを/codeにコピーする。ADDでコピーすることで、コンテナ内での編集がローカルにも反映される。
# コピーする際に所有権を変更している。
ADD  --chown=$USERNAME:$GROUPNAME . /code

# WORKDIRで作業ディレクトリを指定。以降のpipなどはこの場所からの実行になる。
WORKDIR /code

# pythonのライブラリを設定する。
RUN pip install --upgrade pip && pip install -r requirements.txt

```

```docker-compose.yml

version: '3'
services:
  test:
    build: .
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
    ports:
     - "8888:8888" #for jupyter notebook hostname to 0.0.0.0
    volumes:
     - /tmp/.X11-unix:/tmp/.X11-unix
     - .:/code:cached # プロジェクトフォルダを/codeに割り当てる。
    environment:
     - DISPLAY
    tty: true

```
お好みで
```requirements.txt
jupyter
opencv-contrib-python
scikit-learn
matplotlib
Pillow
```

テストプログラム。同一フォルダにcat.jpgをおいて表示させてみる。
```test.py
# import matplotlib # バックエンド設定しなくても動作した
# matplotlib.use('TkAgg')  # または 'Qt5Agg' など、利用可能な対話型バックエンド
import matplotlib.pyplot as plt
from PIL import Image

# 画像を読み込んで表示
image = Image.open('cat.jpg')
plt.imshow(image)
plt.axis('off')
plt.show()
```
LINEスタンプアレンジ機能はMessagingAPIで制御できるのか

LINEアプリでスタンプアレンジ機能がリリースされました！

https://www.lycorp.co.jp/ja/news/release/008308/



LINEのMessagingAPIでも通常のスタンプは送ることができます。

https://developers.line.biz/ja/docs/messaging-api/sticker-list/

では、スタンプアレンジは送付できるのか？
どのようにステッカーIDを送ればよいかわからないので、スマホから送信して
どのようなステッカーIDやパッケージIDを指定して送付すればよいか確認するために
まずは、受信されるjsonがどのようなものか、送信してみて確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624933/84f110f5-936a-db47-8988-c7dee7af275a.png)

このような感じで、送ってみたところ、webhookで受信できたものの一部です

```javascript:webhook.json
packageId=30563
stickerId=651698630
```

スタンプアレンジされたものは、すべて同じパッケージIDとステッカーIDでした。

どうやらAPIでは現状できないようです。送信もエラーがかえってきました。


ちなみに、LINE オフィシャルアカウントマネージャーのチャット画面で見てみると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624933/32463e7f-0683-46b4-f0e9-6a312a73790c.png)

こちらもPCでは確認できませんでした。。。

PC版LINEのアプリでも

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624933/329b9c8a-22b9-bac9-a6a9-7803ab9f01d2.png)

となりました。

現在は、スマホのLINEアプリのみの機能となっているようです。

将来的にはどうなるかわかりませんが、2024年5月13日時点では、スマホ同士でのやり取りのみで楽しめる機能でした。

でも楽しいのでいろいろスマホ同士で送ってカスタマイズしましょう！