OmniAICreator/Qiita-1.07M huggingface dataset:
Spring SecurityのOidcUserRequestインポートエラーの解決方法

Spring Securityを使ったセキュリティ設定で`OidcUserRequest`のインポートエラーに直面した場合の解決手順を紹介します。非常に初歩的な失敗ですので

問題の原因は、`OidcUserRequest`クラスのインポート文が誤っているか、または該当クラスがクラスパスに存在しないことにあります。

## 解決手順

1. **依存関係の確認**：
   `build.gradle`でSpring Securityの依存関係が正しく設定されていることを確認します。
   ```groovy
   implementation 'org.springframework.boot:spring-boot-starter-security'
   ```

2. **正しいインポート文の使用**：
誤ったパスを使用していないか確認し、必要に応じて修正します。私は間違えて
```java
import org.springframework.security.oauth2.core.oidc.user.OidcUserRequest
```
と記述してしまっていました。正しくは以下の通りです。
   ```java
   import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
   ```
Spring Securityの`OidcUserRequest`クラスの詳細は[こちら](https://spring.pleiades.io/spring-security/site/docs/current/api/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequest.html)。

3. **IDEのキャッシュクリア**：
   IDEのキャッシュが原因で問題が発生している場合があります。IntelliJ IDEAの場合、「File」>「Invalidate Caches / Restart...」を選択し、キャッシュをクリアしてください。
layerdiffusion

前提

https://self-development.info/stable-diffusion-webui-forge%e3%81%ab%e3%82%88%e3%82%8b%e7%94%bb%e5%83%8f%e7%94%9f%e6%88%90/

が必要

インストール中エラーが発生
```
CUDA Setup failed despite GPU being available. Please run the following command to get more information:

python -m bitsandbytes

```

と表示されたら

```
pip install bitsandbytes-windows
```

でOK

# LayerDiffusion のインストール

https://self-development.info/layerdiffusion%e3%81%8c%e5%ae%9f%e7%8f%be%e3%81%99%e3%82%8b%e9%80%8f%e9%81%8e%e7%94%bb%e5%83%8f-%e7%94%bb%e5%83%8f%e7%94%9f%e6%88%90ai%e3%81%ae%e6%96%b0%e6%99%82%e4%bb%a3/

# 早速使う

![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31338/7d646830-e043-fd19-3efd-5f7c5ee4af66.png)

上記の プロンプトで ガチャ回したら
5枚の画像が出ました。

早いし美しい。


![grid-0000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31338/f5e325fd-be3c-85a2-8b54-b432bda44e38.png)


注意点

・最初のモデルだとうまく生成されない
juggernautXL_version6Rundiffusion.safetensors

を使うこと

# おまけ

animagineXLV3_v30 を使ってみた

![grid-0003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31338/bf2356e5-74b4-b988-a9de-cb6628e5043e.png)

アニメでもできるし、めっちゃ早い。
3枚で1分程度かな
GASのセルの入力規則に関する与太話

# 起きたこと
時刻をGASでスプレッドシートを跨いで、Range.setValue()をしたときに起こった出来事です。

「無効：指定した範囲内の値を入力してください」

と表示される時刻とそうでない時刻の違いについて触れていきます。

# 細かく見ていく
10:00は、無効。
11:00は、無効。
12:00は、無効じゃない。

一見規則性がないようです。

# 原因は...
数字を自動にして見ていくと、
10:00は、0.416666666666667。
11:00は、0.458333333333333。
12:00は、0.5。

どうやら、数値で処理した際の割り切れない値に対してこの「無効」は表示されているようです。

# 追記
コピー先のセルを見たら、「0.416666666667879」となっていました。
コピーしている間に値が変わってしまったようですね。



# 解決法
このURLの先の回答に従った結果、うまくいきました。すべてを書式無しテキストにするみたいですね。
https://teratail.com/questions/365742
jugglingプロジェクトの読み込みに失敗する際の確認点と対処法

## 事象
IM-jugglingでjugglingプロジェクトを開く（ビルド）際、下記エラーが発生する。

ビルド中にエラーが発生しました。
プロジェクト 'project' でビルダー 'JugglingBuilder' の実行中にエラーが発生しました。
```
jp.co.intra_mart.jackling.exception.ResourceUnreachableException: Metadata is not found in all registered repositories(retried 5 times).
	related module information
		id:jp.co.intra_mart.module.pack.im_event_navigator_pack_advanced
		version:8.0.33
```

  ResourceUnreachableと書いてある。これっぽい。

## 原因
/ユーザ/{ユーザ名}/juggling/workspace/.repositroy配下に必要なモジュールが含まれていない。

![1004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2818285/4fa7fbbc-10ea-3fe9-71f6-ef8202be1e74.png)
↑事象が起きた際の.repositoryの状態。空になっている。

jugglingはインターネット接続をすることで必要モジュールをローカルリポジトリにダウンロードしている。そのためjugglingのネットワーク設定が正しくないと、必要モジュールを正常にダウンロードできない。


## 確認事項
確認事項は2つ
①Wi-Fiや優先LANでインターネット接続があるか
**②「ネットワーク」設定でPCと同等のプロキシが設定されているか**

特にこの②が肝要で、jugglingはPCの設定を引き継がない。


## というわけで設定
起動を待つ（遅い）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2818285/907531a5-f73d-d307-322e-2145e58f1954.png)

設定＞一般＞ネットワーク接続でプロキシ設定画面を開く。
アクティブプロバイダーは「手操作」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2818285/b8a83bd0-fda2-9f17-eb5f-142f804702e3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2818285/2fbcb19a-fa02-afe3-688e-35b0148b6d05.png)

各設定をすれば「編集」が押下できるようになるのでそこから。
認証が必要な場合はチェックを付けてユーザ名とパスワードを忘れずに。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2818285/5b63f88b-27c9-39e5-1ea4-df79e5c1364b.png)

適用→OKで設定画面を閉じる。
jugglingを再起動。

## 結果
再起動後、/ユーザ/{ユーザ名}/juggling/workspace/.repositroy配下にフォルダが作成されていることを確認。
juggling.imも正常に開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2818285/4e7c155c-e476-701c-d0f4-8d324f11557e.png)


## まとめ
juggling動かん！ではなく、エラーメッセージをしっかり読むのが大事ですね。
pythonのlog出力ベストプラクティス(?)

# メインの実行ファイルでの記述
```python:main.py
import logging

# ログの設定
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# ロガーの作成
logger = logging.getLogger(__name__)

# ログ出力例
logger.info('This is main.')

```
# メインの実行ファイル以外での記述

```python:my_module.py
import logging

# ロガーの作成
logger = logging.getLogger(__name__)

# ログ出力例
logger.info('This is another module.')

# 他の処理...
```
※ 全てのファイルに書く


# 出力例
```console
>>> logger.info('Hello!')
2024-03-04 17:02:09,446 - __main__ - INFO - Hello!
```
[WSL2] `git`コマンドで,/mnt/以下ではWindows版git,それ以外ではLinux版gitを利用したい

以下を `.bash_aliases` に追加することで解決した。

```shell
alias windows-git='/mnt/c/Program\ Files/Git/bin/git.exe'
alias linux-git='/bin/git'

git-selector () {
    local currentDir=$(pwd -P | cut -d'/' -f2)
    if [ "$currentDir" = "mnt" ]; then
        windows-git "$@"
    else
        linux-git "$@"
    fi
}

alias git=git-selector
```

- - -

PulseSecureを利用していて、WSL2でVPNを通ることができない環境なので必要になった。

同様の状況下なら、他のコマンドでも応用が効くと思う。
cameraXで撮影した画像が勝手に回転するんだけど！？って貴方に【Androidアプリ開発】

```
最終更新日: 20240304
```
いざカメラアプリの開発を開始すると
縦撮影した画像が勝手に90°回転するなど厄介な問題が発生します(端末によるかも)
<br>

最終的には下記の公式ドキュメントを見たらすんなり解決したんですけど
ここ以外に望んだ情報はなかった気がするので本記事に残しておきます

https://developer.android.com/training/camerax/configuration?hl=ja

https://developer.android.com/reference/androidx/camera/core/ImageCapture#setTargetRotation(int)

https://developer.android.com/training/camerax/orientation-rotation?hl=ja

# 要件
画面の向きを縦に固定した状態で
画像を回転したい

# ソース
Java言語で書いています
事情あってソースコードを全部載せることができないのですが
雰囲気でわかると思います

## 端末の回転情報を取得
最初は加速センサーで独自に回転情報取得していたけど
端末によって動作しないことが判明したので
```OrientationEventListener```を採用しました
``` java
 
 OrientationEventListener orientationEventListener;
 private int deviceOrientation = 0;

 
 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

         orientationEventListener = new OrientationEventListener(this) {
            @Override
            public void onOrientationChanged(int orientation) {
                if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
                    return;
                }
                if (orientation >= 45 && orientation < 135) {
                    deviceOrientation = Surface.ROTATION_270;
                } else if (orientation >= 135 && orientation < 225) {
                    deviceOrientation = Surface.ROTATION_180;
                } else if (orientation >= 225 && orientation < 315) {
                    deviceOrientation = Surface.ROTATION_90;
                } else {
                    deviceOrientation = Surface.ROTATION_0;
                }
            }
        };
```

## imageCaptureに端末回転情報を渡す
本記事を見ているということは
```imageCapture```を既に知ってると思うので端折ります
``` java
imageCapture.setTargetRotation(deviceOrientation);
``` 

## ImageProxyから正しい回転に補正する値を取得
```cameraX```で撮影した画像データは```ImageProxy```型変数に格納されます
本記事を見ている人は理解してると思うので端折ります
``` java
imageProxy.getImageInfo().getRotationDegrees();
```

## Matrixで画像回転させる
今回の例だと```ImageProxy```を```Bitmap```に変換してそれを回転させてますね
``` java
private Bitmap imageProxyToBitmap(ImageProxy image)
    {
        ImageProxy.PlaneProxy planeProxy = image.getPlanes()[0];
        ByteBuffer buffer = planeProxy.getBuffer();
        byte[] bytes = new byte[buffer.remaining()];
        buffer.get(bytes);
        Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
        Matrix matrix = new Matrix();
        matrix.postRotate(image.getImageInfo().getRotationDegrees());
        Bitmap bmp2 = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, false);
        return bmp2;
    }
```

# まとめ
1. ```OrientationEventListener```で端末の回転情報を取得
2. ```imageCapture.setTargetRotation```で撮影時の端末回転情報を設定
3. ```imageProxy.getImageInfo().getRotationDegrees```で画像撮影時の回転情報から正常な回転に補正する値を取得
4. 補正値を使って```Matrix```などで画像を回転

# おわりに
公式ドキュメント読むの大事だなーって今回の経験で体感した記憶があります

良かったらTwitterをフォローしてくれると泣いて喜びます

https://twitter.com/rioLi0N
wslでelixir その141

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
練習問題やってみた。

# 練習問題
Livebookで、wssに繋げ。

# セットアップ

```
Mix.install([
	{:socket, "~> 0.3"}
])
```

# サンプルコード

```
socket = Socket.Web.connect! "wsecho.kokoa.dev", secure: true, path: "/ohisama/sampleProject/test


socket 
|> Socket.Web.send!({:text, "test"})

socket 
|> Socket.Web.recv!

```


以上。
[Rails]erb2slimコマンドでNoMethodErrorが発生した場合の対処法

## 経緯
html2slimを使用してerbをslimに変換しようとしたところNoMethodErrorが発生した｡
```bash
$ bundle exec erb2slim app/views/layouts/ --delete

NoMethodError: undefined method exists? for File:Class
```

## 何故発生したか?
Ruby3.2で削除されたFile.exists?メソッドをhtml2slimが使用していた｡

## 対処法
このエラーが発生した当時は、ソースコードの `File.exists?` を `File.exist?` に書き換えて対応したのですが、別名でRuby3.2に対応したhtml2slimが存在することに気付きました。

https://rubygems.org/gems/html2slim-ruby3

という訳で､こちらをGemfileに追加して`bundle install`します｡
以前のhtml2slimはGemfileから削除して下さい｡

```ruby:Gemfile
gem 'html2slim-ruby3'
```

```bash
$ bundle install

$ bundle exec erb2slim app/views/layouts/ --delete
```
今度は正常に変換する事が出来ました!
Nix on mac で Docker セットアップ (colima)

## 概要

Nix-darwin で管理している mac で Docker を使えるようにする。

Docker Desktop は業務での使用に懸念があるので、 [Colima](https://github.com/abiosoft/colima) を使う。

## 手順

### home.nix

Home Manager の設定ファイルに以下を書き加える。

Home Manager を使っていない場合でも、普通に `systemPackages` に入れたら動くと思う。

```nix:home.nix
{
  home.packages = with pkgs;
    [
      colima
      docker
    ];
}
```

設定らしい設定は終わり。

### VM 起動

colima コマンドで Ubuntu VM を立ち上げて Docker を設定させる。

```
colima start
```

```出力
 → colima start                                                                                                      ~/dotfiles
INFO[0000] starting colima
INFO[0000] runtime: docker
INFO[0000] creating and starting ...                     context=vm
INFO[0039] provisioning ...                              context=docker
INFO[0039] starting ...                                  context=docker
INFO[0053] done
```

### docker.sock の権限変更

設定は以上なのだが、このまま起動すると以下のエラーが出て使えない (2024/03/04 時点)。

```
error during connect: Get "http://%2FUsers%2Fkino-ma%2F.colima%2Fdefault%2Fdocker.sock/v1.24/containers/json": EOF
```

Colima に [issue](https://github.com/abiosoft/colima/issues/710) が上がっており、裏にいる Lima VM の `/var/run/docker.sock` の権限が狭いことが原因らしい。

https://github.com/abiosoft/colima/issues/710

[コメント](https://github.com/abiosoft/colima/issues/710#issuecomment-1958601817) にある通り、以下で解決。

```sh
colima ssh -- sudo chmod 666 /var/run/docker.sock
```

### 動作確認

```sh
$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
```

```sh
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
478afc919002: Pull complete
Digest: sha256:d000bc569937abbe195e20322a0bde6b2922d805332fd6d8a68b19f524b7d21d
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (arm64v8)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

```

おわり。
AppwriteにFlutterプロジェクトからAndroidエミュレータで接続する時の接続エラー

AppwriteにFlutterから接続する時、Androidエミュレータのときのみなぜか繋がらない問題が起きました。
(*dockerでローカルでAppwriteを起動しています。)

下記がエラー
ClientException with SocketException: Connection refused (OS Error: Connection refused, errno = 111), address = 127.0.0.1, port = 33098, 

エミュレータをAndroid Studioから削除→再構築
など試してみましたがうまくいかず、

youtubeで検索してたところなぜかこの方法で解決。

Appwriteに接続する時の接続先を

endPoint = 'http://10.0.2.2/v1';

のように、「10.0.2.2」にします。

こうするとうまくいきました。（なんで？）


参考Youtube動画

https://www.youtube.com/watch?v=YyVOEj9dNY8
Raspberry Pi 5 でTinyLlamaを試してみた

## 目的
Raspberry Pi 5 が買えたので軽量LLMであるTinyLlamaを使えるようにしてみた。
すべて参考にした記事のままなので新しいことは特にないです。
自分メモのようなものです。

## 環境
本体 : Raspberry Pi 5
メモリ : 8GByte

## Raspberry Pi 5 の初期設定
OSのインストールまでは省略。
その後TinyLlamaには関係ないけど下記もインストール&設定した。
### 更新
```
$ sudo apt update
$ sudo apt upgrade
```
その後再起動。
### 日本語入力
```
$ sudo apt install fcitx5-mozc
$ im-config -n fcitx5
```
### Chromiumの入力設定
Chromiumのtext inputのサポートバージョンが古いせいでChromiumではfcitx5を使ってもそのままでは日本語入力できないとのことなので、メニューからの起動で下記の引数がつくように設定した。
```
$ chromium-browser --gtk-version=4
```
### docker
```
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh
$ sudo gpasswd -a $USER docker
```
## TinyLlamaのインストール
### モデルのダウンロード
```
$ mkdir tinyllama
$ cd tinyllama
$ wget https://huggingface.co/TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF/resolve/main/tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf
```
### ライブラリのインストール
```
$ python -m venv llama2
$ llama2/bin/pip install llama-cpp-python
```
### スクリプトの作成
llama2.py というファイルを下記の内容で保存する。
```
import sys
from llama_cpp import Llama

llm = Llama(model_path="tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf", verbose=False)
output = llm("<user>\n" + sys.argv[1] + "\n<assistant>\n", max_tokens=40)
print(output['choices'][0]["text"] + "...")
```
### 実行してみる
```
$ llama2/bin/python llama2.py "How tall Mt. Fuji?"
Mt. Fuji is approximately 3,776 meters (12,384 feet) tall....

$ llama2/bin/python llama2.py "富士山の高さは?"
The height of Mount Fuji is unknown....

$ llama2/bin/python llama2.py "How tall Mt. Everest?"
Mt. Everest is a mountain located in the Himalayan region of Nepal, and it stands at approximately 29,029 feet (8841 meters)...

$ llama2/bin/python llama2.py "How to use python venv"
1. Creating a new virtual environment:
   python -m venv env_name

2. Activating the virtual environment:
```
ちゃんと5秒くらいで回答がされていることを確認しました。
日本語がうまく認識できないわけではなさそうだけど、富士山の固有名詞が分からないのかな?
ラズパイでここまで動くのはすごいですね。

スクリプト内のmax_tokensを100にすると11秒くらいかかりました。
```
$ llama2/bin/python llama2.py "How to use python venv"
1. Create a virtual environment:
   python -m venv my_env

2. Activate the virtual environment:
   source my_env/bin/activate

3. Install required packages:
   pip install packages here

4. Test package installation:
   pip install packages here

5. Run your...
```


## 参考URL
Raspberry Pi 5上で軽量LLM、TinyLlamaを動かしてみる
https://qiita.com/kazuhitoyokoi/items/66e8c9e1b447a2850ba7
What is BKUP Database Backup File Format?

# Understanding and Managing BKUP Files
![Backup File Format.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734497/4c68195e-e2d0-98d5-8a68-593cff8dc81b.jpeg)


In the digital era, safeguarding and creating backups for essential data is a top priority. The [.bkup file format](https://softfind.net/bkup-file/) serves as a valuable tool for storing various types of files and acts as a backup extension for restoring original data in the event of unexpected loss due to technical issues.

## What are BKUP Files?

The .bkup file format is commonly used by programs and scripts for creating backups. It is not program-specific, making it versatile for safeguarding different types of data, including confidential files, word-processing documents, and logs.

## Creating a BKUP File

To create a new .bkup file, follow these steps:

1. Open the application you want to backup.
2. Choose a folder to save the backup.
3. From the File menu, select Save As or Export.
4. Opt for the BKUP file format.
5. Assign a name and click Save.

## Opening a BKUP File

If you already have a .bkup file and want to open it, follow these steps:

1. Open the File menu.
2. Right-click and select Open with.
3. Choose the program to open the file.
4. Click Open.

## Restoring a BKUP File

To restore a .bkup file, follow these steps:

1. Find the .bkup file you want to restore.
2. Launch a generic file viewer application or software.
3. Select the file to be restored.
4. Choose the Extract option.
5. Decide where to save the restored file.
6. Click Extract to complete the restoration.

By following these steps, you can easily create, open, and restore .bkup files, ensuring that your data remains secure and accessible whenever needed.
【Bash】同名のファイルが存在したら .bkp1 などのファイルにリネームする

# TL;DR

```bash:test.sh
#!/bin/bash

#=== 関数定義 ============================================
# 引数で渡されたファイルが存在するか確認し、既に存在する場合は
# .bkp1, .bkp2 ... というファイル名で空きを探す関数。
# 出力は標準出力に返される。
# 引数で渡されたファイルが存在しない場合は異常終了する。
function getBackupableFileName {
  ## 引数処理
  # 引数1 探索するファイルのパス
  local file_path=$1

  ## 関数内定数
  # バックアップ用ファイルの拡張子名(ここに数字の1, 2...が着く)
  local BACKUP_EXT=bkp

  ## 関数本体
  # 引数で渡したファイルが存在しなかったら何も返さず異常終了
  if [ ! -e "$file_path" ]; then
    return 1
  fi

  # 引数で渡したファイルが既に存在するため、空き番号を探す
  local n=1
  # バックアップ用拡張子を追加したファイルが存在するかをチェック
  while [ -e "$file_path.$BACKUP_EXT$n" ]; do
    # 既に存在するので番号を1ずつ加算
    n=$(( n + 1 ))
  done

  # 標準出力に結果を吐き出す。
  echo "$file_path.$BACKUP_EXT$n"
}

#=== スクリプト本体 ========================================

# 出力ファイルへのパス(例)
OUTPUT_FILE=/path/to/output.file

# 同名の出力ファイルが既に存在した場合、上書きされないようにリネームして取っておく
if BKP_FILE=$(getBackupableFileName "$OUTPUT_FILE"); then
  mv "$OUTPUT_FILE" "$BKP_FILE"
fi
```


# 技術的に忘れそうなこと
主に自分が忘れるのでメモしておく。

## Bash のコマンド置換の終了ステータス
```bash:terminal
$ VALUE=$(true)
$ echo $?
0
$ VALUE=$(false)
$ echo $?
1
```
コマンド置換( `$(コマンド)` のやつ)を変数の代入に利用した場合の終了ステータスはコマンドの終了ステータスになる。


```bash:切り抜き
# 同名の出力ファイルが既に存在した場合, リネームして取っておく.
if BKP_FILE=$(getBackupableFileName "$OUTPUT_FILE"); then
  mv -v  "$OUTPUT_FILE" "$BKP_FILE"
fi
```
`if`はコマンドの終了ステータスに従って分岐するので、ここでは`getBackupableFileName`が成功(`exit 0`)したら`mv`コマンドでリネームしている。
失敗(`exit 1`)したら処理を行わずスキップする。

## 別案
ここでは`.bkp*`がないか1つ1つ存在チェック(`[ -e  ファイルパス ]`)している。
想像だが、恐らく`.bkp100`あたりを超えると実行時間に悪影響が出る。

こういう場合は一旦`ls`コマンドの出力を変数に確保しておき、その文字列から存在チェックをした方が高速化が見込める。
```bash
BKP_FILE_LIST=$(ls -1 "$file_path.${BACKUP_EXT}*") || :
```

ただし、今回の用途では`.bkp3`あたりが関の山であり、その場合は`[ -e  ファイルパス ]`の方が早い。
用途によって切り替えるのが吉。
ZED SDK のVERSIONを取得する

## 前提
- StereoLabs のステレオカメラを利用している。
- 確認した環境: Jetson

## 実行スクリプト 
```:.py
import pyzed.sl as sl
zed = sl.Camera()
print(zed.get_sdk_version())
```

## 実行結果の例
```
4.0.8
```
ZED SDKを使いこなす body_tracking

BODY_TRACKING のモデルの種類

## 公式のドキュメント
https://www.stereolabs.com/docs/body-tracking

![](https://docs.stereolabs.com/body-tracking/images/keypoints_body18.png)


以下の３つの中から選ぶ。

```.py:
body_param.body_format = sl.BODY_FORMAT.BODY_18  # default value
body_param.body_format = sl.BODY_FORMAT.BODY_34
body_param.body_format = sl.BODY_FORMAT.BODY_38
```


BODY_38 では
親指の先、中指の先、人差し指の付け根、小指の付け根　が加わっている他、
肩の部分などのボーンの位置が異なっている。
学習記録アプリ開発最終話 ~ React学習開始から20日目 ~

# はじめに
どうもこんにちは！僕は現在1ヵ月本気の技術力向上を目指している現役高校生1年生、
@shuniiです！
僕はJISOUというコミュニティでReact学習をしているのですが、参加してから20日目で学習記録アプリを完成させることができたので共有したいと思います！やはり一つのものを完成させると達成感が段違いですね

前回も学習記録アプリを作りました！

https://qiita.com/shunii/items/af2fcf68c60a76be4262

# 前回のアプリと何が違うの？
前回の記事で紹介した学習記録アプリとの相違点をご紹介したいと思います。
- 機能
    - 編集ができるようになった
- 使用言語
    - javascriptからtypescriptに変更
- 使用技術
    - react-hook-formを導入
    - ChakraUIを導入
- UI
    - ChakraUIでUIが超いい感じになった

# 画面はこんな感じです
![スクリーンショット 2024-03-04 101243.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554025/a1aa617e-37ea-4129-b585-5d841f0d6c64.png)

なぜオレンジフルーツかは突っ込まないでください！勘です笑

# 機能アップデート！
編集機能も追加されました！
確かに編集機能ないってわりと致命的だった。リセットボタンも追加したので編集をまちがえてもまた元に戻せます！！

# TypeScript使ってみて
感想の流れ
1. ん～～～、よくわかんないや
2. 補完効く！らく～
3. やっぱちょっとめんどくさい
4. 慣れたら指摘してくれてうれしい( ？w )  

JavaScriptからTypeScriptに移行してみて、はじめの方はめんどくさいなと思ってたんですけど、型定義できてコード書いてる時点でエラー出てくれるのはうれしいなと思いました。typescriptに移行するといい！！みたいな記事感想をよく見ますが、やはり最初はめんどくさいと思います。まだ便利～の境地にはいってないですかね。チーム開発だとより恩恵を感じそうです。

# React Hook Formを導入してみて
https://react-hook-form.com/
うん、紹介する必要もないくらい便利。
フォームを実装するならぜひ導入を検討してみてください。**useState書かなくていいし、onChangeとかいちいち設定しなくてもいい**。楽です。

# ChakraUIの威力

https://chakra-ui.com/

ChakraUIはめちゃくちゃ最高です。自分好みなモダンなデザインをすぐに適用することが出来ます。figmaで作ったデザインをChakraUIに変換できるっぽいことも耳にしました。学習コスト低いのでおすすめです。
しかし、結局どのcssライブラリ使うにせよ、ある程度のcss基礎知識は必要だということを感じました。そこまで自分はcss力ないのでそこ周辺もまた勉強したいとこ。

最速でアプリリリースしたいなら、ChakraUIとかでパパっと作ってしまうのはありだと思いました。

# githubのリポジトリがいい感じになった
og:imageの設定もしてニヤニヤしてます笑、og:imageの設定はリポジトリの
setting >> General >> Social previewでできると思います！
画像はLeonardo.aiっていうのでしました！無料のトークン数めちゃおおいので気軽に画像生成できます。

https://github.com/Shunii85/myreco

<br/>
リポジトリをおしゃれにしたい人必見！！JISOUでコーチングをしてくれている方の記事です！

https://qiita.com/Sicut_study/items/3b762364c95e4673bfbe

# 感想
学習記録アプリという一つのアプリを作ってみて個人開発というものを学べたと思います。supabaseを使ったりしたのでフロントの部分しか開発はしていないのですが、テストやパイプラインの構築など今まで触れてこなかったところを勉強できたのはよかったと思います。
そして開発を進めていく中で、少しずつ自分の調べる力が上がってきました。調べればすぐわかる、という状況が作り出せたらすごく楽しくなってくると思います(ジュニアレベル??)。そこまで基礎力をつけてきましょう！
別の分野でプログラミング挫折した人はぜひフロントおすすめです！

# 終わりに
最近すごく開発・プログラミングしてるのがすごく楽しいです！プログラミングを同じように楽しんでいる方々とより多く関わりたいです！
いいね、コメント大歓迎です！X(Twitter)もよければフォローしてください～

# About Me
- X(Twitter)

https://twitter.com/shunii_hack

# JISOUのメンバー募集中
プログラミングコーチングJISOUではメンバーを募集しています。
気になる方はぜひHPからライン登録お願いします！
https://projisou.jp
P-ツイート 2024: マイクロブログの再発明

P-Tweets でツイート: 2024 年に選ばれるマイクロブログ プラットフォーム

進化し続けるソーシャル メディアの状況において、マイクロブログ プラットフォームは、個人、ブランド、組織が視聴者とつながり、共有し、関与するために不可欠なツールとなっています。 Twitter などのプラットフォームが長年にわたってこの分野を独占してきましたが、独自の機能を備えた新規参入者も現れてきました。 ここ数カ月で大きな注目を集めているプラットフォームの 1 つが P-Tweets です。

[P-Tweets](https://github.com/ptweets) 2024 年初頭にリリースされたマイクロブログ プラットフォームは、その革新的な機能とユーザーフレンドリーなインターフェイスのおかげで、すぐに多くのユーザーに選ばれるプラットフォームになりました。 この記事では、P-Tweets が他のマイクロブログ プラットフォームと比べて際立っている理由と、2024 年に P-Tweets がマイクロブロガーにとって頼りになるプラットフォームになった理由を探っていきます。

プライバシーとセキュリティ

プライバシーとデータ セキュリティが最も重要な時代において、P-Tweets は強化されたプライバシー機能を提供することで他社との差別化を図ってきました。 ユーザーは、公開、非公開、制限付きなどのさまざまなプライバシー設定から選択して、自分の投稿を表示および操作できるユーザーを制御できます。 さらに、P-Tweets は最先端の暗号化技術を採用してユーザー データを保護し、すべてのユーザーに安全でプライベートなエクスペリエンスを保証します。

コンテンツディスカバリー

P-Tweets は、革新的なレコメンデーション エンジンでコンテンツの発見に革命をもたらしました。 このプラットフォームは機械学習アルゴリズムを活用してユーザーの好みや行動を分析し、各ユーザーの興味に合わせたパーソナライズされたコンテンツの推奨を提供します。 これにより、ユーザーは常に関連性の高い魅力的なコンテンツにアクセスできるようになり、プラットフォームが新しい情報を発見し、同じ考えを持つ人々とつながるための貴重なリソースになります。

収益化の機会

P-Tweets は、ユーザーがコンテンツから収益を得ることができるいくつかの収益化機能を導入しました。 このプラットフォームはサブスクリプションベースのモデルを提供しており、ユーザーは月額料金を請求して独占コンテンツにアクセスできます。 さらに、P-Tweets にはチップ機能が統合されており、ユーザーはコンテンツに対する感謝の印としてフォロワーからチップを受け取ることができます。 これらの収益化オプションは、ユーザーにマイクロブログ活動から収入を得る機会を提供し、P ツイートをコンテンツ クリエイターにとって魅力的なプラットフォームにしています。

コミュニティ・エンゲージメント

P-Tweets は、幅広いトピックの共有と議論に熱心なユーザーの活気に満ちたアクティブなコミュニティを育成してきました。 このプラットフォームのユーザーフレンドリーなインターフェイスと直感的なデザインにより、ユーザー同士の交流が容易になり、有意義な会話やつながりが促進されます。 P-Tweets は、ユーザーが同じ興味を共有する他のユーザーとつながることを可能にするグループやイベントなどのさまざまなコミュニティ機能も提供します。 このコミュニティと仲間意識が、プラットフォームの人気を促進する重要な要因の 1 つです。

クロスプラットフォームの統合

P-Tweets は他の人気のあるソーシャル メディア プラットフォームとシームレスに統合されており、ユーザーは Twitter、Facebook、Instagram などのプラットフォームで P-Tweets の投稿を共有できます。 このクロスプラットフォームの統合により、ユーザーはより幅広い視聴者に簡単にリーチし、複数のプラットフォームにわたる可視性を高めることができます。 さらに、P-Tweets は、開発者が他のプラットフォームとのカスタム統合を構築するために使用できる API を提供し、プラットフォームの範囲と機能をさらに拡張します。

結論として、P-Tweets は、その革新的な機能、ユーザーフレンドリーなインターフェイス、活気のあるコミュニティのおかげで、2024 年に選ばれるマイクロブログ プラットフォームとして急速に浮上しました。 P-Tweets は、プライバシー、コンテンツ発見、収益化の機会、コミュニティへの関与、クロスプラットフォーム統合に重点を置いているため、視聴者とつながり、共有し、交流したいと考えている個人、ブランド、組織にとって不可欠なツールとなっています。 コンテンツ クリエイター、ソーシャル メディア インフルエンサー、または他の人とつながりたいと考えている人であっても、P-Tweets は他のマイクロブログ プラットフォームとは一線を画す、ユニークでやりがいのあるエクスペリエンスを提供します。
認証

セッション管理:
メリット:

セキュリティ:

セッションIDがサーバー側で管理されるため、クライアントにはユーザーの認証情報が直接露出されません。
サーバー側でセッションの状態を管理するため、セキュリティが高いと見なされます。
柔軟性:

セッション管理システムはセッションの有効期限や状態を管理できるため、柔軟なセッション管理が可能です。
セッションの無効化:

サーバー側でセッションを無効化することで、セッションのログアウトや不正アクセスへの対処が容易です。
デメリット:

サーバー負荷:

サーバー側でセッションを管理する必要があるため、大規模なトラフィックやセッションの増加に伴い、サーバー負荷が増加する可能性があります。
スケーラビリティ:

複数のサーバーでアプリケーションをスケールさせる場合、セッションの共有や同期が必要であり、実装が複雑になる可能性があります。
トークンベースの認証:
メリット:

クライアント側の軽量化:

トークンはクライアント側に保存されるため、セッション管理よりも通信量が少なく、サーバーへの負荷が低減します。
スケーラビリティ:

セッション情報をサーバー側で保持する必要がないため、サーバーのスケーラビリティが向上します。
クロスドメイン対応:

トークンベースの認証は、クロスドメインのシステム間で認証を行う場合に適しています。
デメリット:

セキュリティリスク:

トークンが盗まれた場合、誰でもアクセスできるため、セキュリティ上のリスクがあります。リフレッシュトークンの安全な管理が必要です。
トークンの期限切れ:

トークンには有効期限があり、期限が切れた場合、再度認証を行う必要があります。これはユーザーエクスペリエンスに影響を与える可能性があります。
以上が、セッション管理とトークンベースの認証のそれぞれのメリットとデメリットです。選択する際には、特定のアプリケーションやプロジェクトのニーズに合ったものを選択する必要があります。
【Linux/Ubuntu/ほか】一時的に日本語キーボード設定にするコマンド

# TL;DR
```bash:shell
$ # 一般ユーザで実行すること
$ setxkbmap jp
```

# 補足
典型的には Ubuntu Live OS などで利用する。

SSH経由では利用できない(たぶん`DISPLAY変数`を渡す必要がある:未検証)が、SSHならそもそもホスト側のキーボード設定に従うので通常は問題にならない。

# 日記
こういう特定の状況でピンポイントに使うコマンドをまとめたい。
飲食業界から開発エンジニアに転職した話

## 対象読者
- 職業としてのエンジニアに興味がある方
- これからエンジニアを目指す方

:::note warn
現状、エンジニアとして稼働されている方にとって有益な文章ではありません。ブラウザバック推奨です。
:::

## はじめに  
本記事では、エンジニアとしてのキャリアが、まだ浅い私が

- 「エンジニアを志したきっかけ」
- 「エンジニアになるまでにやったこと、やらなかったこと」
- 「エンジニアになってから続けていること」

この3点について、自身の経験を踏まえながら書きたいと思います。

## 結論
結論から言うと、私はエンジニアになって良かったと感じています。特に収入面においては、以前の仕事と比べて大きく改善されました。

~~まだキャリアが浅いため、いわゆる"闇"の部分は経験していない可能性があります。~~

## 本文
### 私がエンジニアを志したきっかけ  
前述の通り、主な理由は当時の収入への不満です。
当時、私は飲食業界で働いており、長時間労働も大きな不満でした。

エンジニアを志した当時は30代目前であり、「将来不安」が転職動機として大きかったように思います。

### エンジニアになるまでにやったこと、やらなかったこと

#### やったこと
- 全ての予定を学習時間に割いた。  

#### やらなかったこと
- 遊び

これに尽きます。  
私の頭の出来は良くありませんので、エンジニアを目指すにあたって、既に周回遅れの状況を少しでも追いつくために、エンジニアになるまでの期間は全て学習時間に割いてきました。 

今でこそ、資格の取得や興味のある分野の学習をしながら、趣味に興じる余裕が生まれましたが、当時は、それどころではありませんでした。

また、当時は今ほど未経験からエンジニアを目指せる企業も多くなかったので、そういった会社に就職できたのは単純にラッキーだったと思います。

#### エンジニアになってから続けていること
- 技術書を月2冊以上読む
- 3か月に1つのペースで資格を取得する

現場で期待通りに活躍できるような技術や知識にはまだ至っていませんが、得たものはいつか必ず自分の力になると信じて、これからも継続していきます。

### まとめ
エンジニアの仕事は技術進歩が早く、常に新しい情報をキャッチアップし続ける必要があります。生き残っていくのも容易ではありません。
しかし、テックリードや上流工程以外にも、これまで培ってきたキャリアを活かせる道はたくさんあります。  

最後に、これからエンジニアを目指す方へ。

お金を稼ぐだけなら、もっと稼げる仕事があります。誰でもできる仕事ではないとも思います。それでもこれからエンジニアを目指すのであればチャレンジする価値のある事だと思いますので、諦めずに頑張ってください。

最後まで読んで頂き、ありがとうございました。
スプシをGASでどうにかしたくてGeminiとChatGPTに聞いたけどいまいちだった件

スプレッドシートのURL一覧をGoogleAppScriptで読み込んでリンク先のテキストを取得してChatGPTに投げる。ただそれだけのことなんだけどもものすごく苦労した。主にGASの扱いで。

PythonのことはChatGPTに聞くといい感じで返ってくるのに、GASではなぜかうまくいかない。ならばとGoogleのGeminiに聞いたが、これもまたうまくいかない。あとGeminiの応答がワンテンポ遅いのもなんだか気になる。

![スクリーンショット 2024-03-04 15.30.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356263/9c4753ee-6566-9f40-230f-f4d48af207e3.png)

あの手この手で質問をかえてみたけど、動かない。

ちょっと戻って、GASでスクレイピングする方法を聞く。

![スクリーンショット 2024-03-04 15.33.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356263/39257851-f1da-4f9e-581d-7ca26c2e01ed.png)

このコードも動かない。
JavaScriptはあんまり使った事がなくて、エラーの意味がわからないんだよね。それもGeminiにきいてもいまいちだし。

参考資料のURLに行ってみる。

【一番簡単】GASでWebスクレイピングしよう
https://tetsuooo.net/gas/82/

サンプルコードの上から３つをコピペして使ってみる。

```test.js
  let response = UrlFetchApp.fetch("https://news.yahoo.co.jp/");
  let text = response.getContentText("utf-8");
  // console.log(text);

  //トップニュースのブロックを抽出
  let topic_block = Parser.data(text).from('class="sc-ewMkZo jIVpTC"').to('</div>').build();
  // console.log(topic_block);
```

動いた！

スプシのURL一覧から１行ずつとってきて、リンク先のテキストををゲットしてスプシに書き込む。

よーしできた！

こういうのでいいんだよ。
(3時間)

GPT3.5だから、2020年の学習データはGASが手薄で、Pythonはナレッジが厚かったということなのかな。そしてGeminiはJavascriptに詳しいけれどGASとの区別がついていない感じ。

ある程度知らないと、AIにコードを書いてもらっても、たちまち手詰まりになるんだな。
WindowsでのAngular環境構築（Node.jsのインストール～Hello Worldまで）

## Node.jsのダウンロード
以下サイトで最新バージョンのダウンロード。
https://nodejs.org/en/download

Windowsの一番上をポチっと。

## Node.jsのインストール
画面に従いNextを押下していく。
※今回はすべてデフォルト。

## バージョンとnpmの確認

コマンドプロンプトで以下のコマンドで確認できる。
```
Node --version
npm --version
```

◆参考
https://kinsta.com/jp/blog/how-to-install-node-js/#4-nodejs

## Angularの最新をインストール
以下のコマンドを実行する。
```
npm install -g @angular/cli
ng version //確認
```

バージョンはこの通り。
```
Angular CLI: 17.2.2
Node: 20.11.1
Package Manager: npm 10.2.4
OS: win32 x64
```

## 統合開発環境(IDE)のインストール
Visual Studio Codeを使用。
以下からインストール。
https://code.visualstudio.com/docs/?dv=win64user
推奨されているので**Angular Language Service**もインストールしておく。
https://marketplace.visualstudio.com/items?itemName=Angular.ng-template

## ワークスペース作成
任意のディレクトリで以下のコマンドを実行。
```
ng new my-app
```

## Angularアプリケーションのテスト

ワークスペースに移動する。
```
cd my-app
```
開発サーバーを起動する。
```
ng serve
```
[ローカル環境（http://localhost:4200/）](http://localhost:4200/ "Angular Home")にアクセス！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2371091/ea992918-7aa3-747c-84e1-c4979b5967b5.png)

動作していることを確認できた。

※停止は`Ctrl + c`

## Hello Worldへ修正
以下のレッスン1を実施。
https://angular.jp/tutorial/first-app/first-app-lesson-01

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2371091/9f6751f0-4842-f36e-6026-28d3cf98e3eb.png)

簡単にHello worldを出力できた。
Rails ActionDispatch::Cookies::CookieOverflowというエラーが出る原因と対策

※この記事は僕がぶち当たった問題をとりあえずChatGPTくんに丸投げしてライティングしてもらったものです。

# 概要
この記事では、Railsアプリケーション内で発生する可能性のあるActionDispatch::Cookies::CookieOverflowエラーについて説明します。
このエラーは、クッキーがサイズの上限を超えた場合に発生します。エラーの原因や、解決するためのさまざまな方法について解説します。

# エラーの原因
エラーの原因は、クッキーのサイズが大きすぎることです。
特に、セッション情報をクッキーに保存している場合、その情報が大量になるとエラーが発生しやすくなります。

# 対策
エラーを解決するためには、以下のような方法を検討することができます。

1. クッキーのサイズを小さくする: 必要な情報のみを保存することで、クッキーサイズを削減します。
2. セッション情報のサーバーサイドへの保存: セッション情報をサーバーサイドのメモリやデータベースに保存することで、クッキーのサイズを減らすことができます。
3. クッキーの分割: クッキーが大きすぎる場合は、複数のクッキーに分割して保存することも可能です。
4. クッキーの暗号化: クッキーを暗号化することで、データが安全に保持されるため、クッキーサイズを減らすことができます。

エラーの解決方法は、アプリケーションの要件やニーズに応じて異なります。必要な情報のみを保存し、クッキーサイズを最小限に抑えるようにしましょう。
【自分用】SuperUUIDというclassを作っただけ


# ソースコード
```C++:SuperUUID.hpp
#pragma once
#include <random>
#include <string>
#include <iostream>
#include <sstream>
#include <iomanip>

class SuperUUID {
public:

	SuperUUID(size_t x4ByteNum = 4) {
		Create(x4ByteNum);
	}
	SuperUUID(const std::string& str) {
		StringTo(str);
	}
	~SuperUUID() {
		delete[] Data;
	}
	
	void Create(size_t x4ByteNum) {
        ByteNum4x = x4ByteNum;
		Data = new uint32_t[ByteNum4x];
		std::random_device rand;
		for (size_t i = 0; i < ByteNum4x; ++i) {
			Data[i] = rand();
		}
	}

	SuperUUID& operator =(const SuperUUID& r) {
		this->ByteNum4x = r.ByteNum4x;
		delete[] this->Data;
		this->Data = new uint32_t[this->ByteNum4x];
		std::copy(r.Data, r.Data + r.ByteNum4x, this->Data);
		return *this;
	}
	SuperUUID& operator =(const std::string& r) {
		SuperUUID ret(r);
		return ret;
	}

	bool operator ==(const SuperUUID& r) const {
		if (this->ByteNum4x != r.ByteNum4x) {
			return false;
		}
		for (size_t i = 0; i < ByteNum4x; ++i) {
			if (this->Data[i] != r.Data[i]) {
				return false;
			}
		}
		return true;
	}
	bool operator !=(const SuperUUID& r) const {
		return !((*this) == r);
	}

	std::string ToString() {
		std::string ret;
		std::ostringstream ss;
		for (size_t i = 0; i < ByteNum4x; ++i) {
			ss << std::setfill('0') << std::setw(8) << std::setbase(16) << Data[i];
			ret += ss.str();
			ss.str("");
		}
		return ret;
	}
	void StringTo(const std::string& str) {
		size_t size = (str.size() / 8) + (str.size() % 8 == 0 ? 0 : 1);
		delete[] Data;
		Data = new uint32_t[size];
		ByteNum4x = size;
		std::string tData;
		for (size_t i = 0; i < ByteNum4x; ++i) {
			tData = "0x";
			tData += str.substr(i * 8, 8);
			Data[i] = std::stoul(tData, nullptr, 16);
		}
	}
	
private:

	size_t ByteNum4x;
	uint32_t* Data;
};
```

# 出力例

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3521775/163e5e06-6b69-9eea-e1e0-69cb72c5b8e8.png)

# 使い方
コンストラクタで長さを決めます
`x4ByteNum`*8文字分になります
長さを決めたらあとは自動で作られます
動的なものはデストラクタでちゃんと廃棄されるので安心してください

`std::string`から`SuperUUID`の変換、`SuperUUID`から`std::string`の変換ができます
`std::string`から`SuperUUID`へ変換する場合16進数表記である必要があります
クラスのメンバの更新

https://paiza.jp/works/mondai/class_primer/class_primer__change_member


コメントで頂いたコードを元に作成。
メンバの更新するときに、いろんなWebページでよくあるコードをみると
変数の名前がgetするときもchangeするときも、同じ変数を使っている事が多いんだけど
私としてはよく分かりづらいので、new_をつけてみた。これでわかりやすいはず。
phpのときもこれどの値が入るのかがわかりづらかった。

```py
class Employee():
    def __init__(self,number,name):
        self.number = int(number)
        self.name = name
    
    def getnum(self):
        return self.number
        
    def getname(self):
        return self.name
        
    def change_num(self,new_number):
        self.number = int(new_number)
    
    def change_name(self,new_name):
        self.name = new_name
    
employees = []

def make(number,name):
    employees.append(Employee(number, name))

def getnum(number):
    print(employees[int(number)-1].getnum())

def getname(number):
    print(employees[int(number)-1].getname())

def change_num(number,new_number):
    employees[int(number)-1].change_num(new_number)

def change_name(number,new_name):
    employees[int(number)-1].change_name(new_name)
    
commands = {
    'make': make,
    'getnum' : getnum,
    'getname' : getname,
    'change_num' : change_num,
    'change_name' : change_name,
}



N = int(input())
for _ in range(N):
    command, *args = input().split()
    commands[command](*args)
```
About Fuse: GraphQL and BFF

Fuse について。

https://fusedata.dev/

GraphQL API のクライアントを生成できる Framework らしい。

BFF として、動かすこともできそう。例えば、Cloudflare や Container で。

認知度はまだまだ。

[![Star History Chart](https://api.star-history.com/svg?repos=StellateHQ/fuse&type=Date)](https://star-history.com/#StellateHQ/fuse&Date)

## Getting Started
- 基本的に手順の通り。
```bash
npx create-fuse-app
npm install
npm install --save fuse graphql
npm install --save-dev @graphql-typed-document-node/core
npm i --save-dev @0no-co/graphqlsp
npx fuse dev
```

```bash
node ➜ /workspaces/fuse-dev (main) $ npx fuse dev
Server listening on http://localhost:4000/graphql
```

![image](/images/bc5f9cbbbc181c-a.png)

## Define the schema
- Fuse で定義した `schema.graphqls` を backend と schema を共有するケース。

### Fix `Types`
- 今回は簡単に field を追加する。

https://github.com/danny-yamamoto/fuse-dev/blob/a30454ce7756795b83d044523d7b88eba8178dab/types/User.ts#L7

https://github.com/danny-yamamoto/fuse-dev/blob/a30454ce7756795b83d044523d7b88eba8178dab/types/User.ts#L25

https://github.com/danny-yamamoto/fuse-dev/blob/a30454ce7756795b83d044523d7b88eba8178dab/types/User.ts#L36

### Run the Fuse API server
- 起動する
```bash
node ➜ /workspaces/fuse-dev (main) $ npx fuse dev
Server listening on http://localhost:4000/graphql
```

- schema が追加される

https://github.com/danny-yamamoto/fuse-dev/blob/a30454ce7756795b83d044523d7b88eba8178dab/schema.graphql#L29

> Fake function to fetch users. In real applications, this would talk to an underlying REST API/gRPC service/third-party API/…
> 
> ユーザーをフェッチするための偽の関数。実際のアプリケーションでは、これは基礎となるREST API/gRPCサービス/サードパーティAPI/...と話をするでしょう。

あとは、REST API を呼ぶなり、gRPC を呼ぶなり好きにしてくれと。

以上

## BTW
https://twitter.com/dec12171985/status/1727611120167637487?s=20

プロスポーツ選手は多くが自己破産すると聞きます。アメフトや NBA など。

そんな中、ロビン・ファン・ペルシが良い父になっていたことに驚きを隠せません。

なぜなら、現役のプレースタイルや言動を見ていた者として、プレーはすごい。けど、性格は？？という感じでした。

ロビン・ファン・ペルシ、ごめんなさい ⚽️

私もこんな父になりたい。
サクッと生成AIリップシンクを作った話　～ある日急に上司に口パク動画を作れと言われたら～

どうも、総合職で働いている理系出身文系職です。

社内で様々な施策が動いており、先輩が担当していた動画作成のプロジェクトがアリました。
プロモーション動画をマネジメントに確認していただいたところ、こんな指摘が出ました
<strong>「なんか口パクが不自然じゃない？直せないのこれ？」</strong>

# 前提条件
まず、リップシンクの元は静止画でした。リアルの人間の画像を用いています。
音声素材は分離して貰えなかったのでプロモーション動画の音声部分を使うことになりました。これにはBGMなどが入っているものになります。同時に複数人喋る場面はなかったのが救いでした。


# 急な角度からのお仕事スタート
というわけで口パクの不自然さを直すために技術調査を始めていきます。最近流行りの生成AIなんかもありますが、わざわざ難しいことをしないで済んだほうがいいということもあります。調べていく中で口パクの技術的用語（というか英語）がリップシンクという事がわかり、この用語を軸に進めていくことになりました。

# 最初の技術選定　Web2lip
最初に調べてできたのはWeb2lipでした。ひとまずこの技術を使ってみます.これも生成AIっちゃ生成AIですがちょっと古めの技術（といっても2年前くらい？）を使って見ました。

実際に生成を行ったのですが、私の環境では口周りの描画に相当な違和感が発生することになりました。

口パクは行っているのですが口の周りだけ肌の色がおかしくなり、人間らしくない不自然な挙動になりました。

Wav2lipは口の場所を検出してその部分だけを生成するため違和感が発生しているものという認識になっています。

もしかしたら使用した音声がクリアではないのが原因かと考えボーカル抽出などで話し声をクリアにしても多少良くなっただけで全体的な精度はあまり代わりませんでした。

# 二番目の技術選定　CrazyTalk
別に実装する必要はなくないか？ということで既存サービスも試してみましたがこれは失敗でした。というのもこのCrazyTalk、アニメーション用リップシンクで今回使いたいリアル画像には全く合いませんでした。

口の部分だけアニメになるのでもはやギャグみたいな動画が出来上がってしまいました。

#　三番目の技術選定　SadTalker
最終的に落ち着いたのはこのSadTalkerでした。これはStable diffusionの拡張機能でリップシンク動画を作成できます。仕組みとしては、仕組みとしては一番目に使ったWav2lipでリップシンク動画を作成し、その画像のフレーム一枚一枚を入力としてStable diffusionで画像を再生成するというもの（と認識している。間違っていたら教えてください）です。

Wav2lipのみでは違和感があった動画もStable diffusionで再生成し画像の違和感部分を修正することができました。

実はWav2lipの時点で不自然ながらも口の動きはリップシンクされていて、肌の色や口の形が歪になってしまっていました。この部分は全体を再生成して均すことで綺麗にできたのかなと感じています。

# まとめ
リップシンクというニッチな技術でも様々な技術がありました。条件が合わずそもそも試さなかったものもありましたがなんとなく全体感が掴めたのかなと感じました。そして、生成AIのポテンシャルの高さにも驚きました。汎用AIモデルの名前は伊達ではないと感じました。

シンギュラリティって話で言えば、私ではフォトショップ使ってここまでのことできないし、全然人間より有能じゃないか？なんて考えたりしました。切ない。
docker+vite+vue3環境を構築

## 編注
この記事には更新版があります。

https://qiita.com/devzooiiooz/items/018006bffab235498f58

## 想定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82975/4558f1ab-a8a6-2bba-95f2-4856867620ad.png)

フロントエンドでvueを使用。後ほどバックエンドやデプロイするためのWEBサーバを追加することを想定。
そのため、projectの中であらかじめfrontendを分けておく。
（バックエンドを追加しない場合でもこの手順でOK）

### プロジェクトフォルダとcompose.yaml作成
```sh:
mkdir project && cd project
mkdir frontend && touch compose.yaml
```
### Dockerfile作成
```sh:
mkdir frontend/vue && touch frontend/Dockerfile
```
#### この時点でのディレクトリ＆ファイル構成
```sh:tree
./project
    ├── compose.yaml
    └── ./frontend
        ├── Dockerfile
        └── ./vue
```
### Dockerfile
```docker:Dockefile
FROM node:lts-alpine
WORKDIR /
RUN apk update
```

### compose.yaml
```yaml:compose.yaml
services:
  vue:
    build: ./frontend/
    volumes:
      - type: bind
        source: ./frontend/vue
        target: /vue
    ports:
      - "8082:5173"
```

### 一旦build
```sh:
docker compose build
```
### create-vueでプロジェクトの作成
```sh:
docker compose run vue npm init vue@latest
```
```sh:
create-vue@3.10.4
Ok to proceed? (y) y


> npx
> create-vue


Vue.js - The Progressive JavaScript Framework

✔ Project name: … vue
✔ Add TypeScript? … No / Yes #=>No まだTypeScriptに手を出していない
✔ Add JSX Support? … No / Yes #=>No
✔ Add Vue Router for Single Page Application development? … No / Yes #=>Yes
✔ Add Pinia for state management? … No / Yes #=>Yes
✔ Add Vitest for Unit Testing? … No / Yes #=>No
✔ Add an End-to-End Testing Solution? › No #=>No
✔ Add ESLint for code quality? … No / Yes #=>Yes
✔ Add Prettier for code formatting? … No / Yes #=>Yes
✔ Add Vue DevTools 7 extension for debugging? (experimental) … No / Yes #=>No

Scaffolding project in /vue...

Done. Now run:

  cd vue
  npm install
  npm run format
  npm run dev

npm notice
npm notice New minor version of npm available! 10.7.0 -> 10.8.1
npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.8.1
npm notice To update run: npm install -g npm@10.8.1
npm notice
```
完了するとfrontend/vue配下にファイルが作成される。

### Dockerfileを変更
WORKDIRを’/’から'/vue'へ変更
COPYコマンドを追加
```diff_docker:Dockerfile
FROM node:21.6.2-alpine
+ #変更
- WORKDIR /
+ WORKDIR /vue
+ #追加
+ COPY ./vue ./
RUN apk update
+ # 起動コマンドを追加
+ CMD ["yarn", "dev", "--host"]
```

### 再度build
Dockerfileの変更を反映させるため、再度build
```sh:
docker compose build
```

### 確認
コンテナに入り、プロンプト(カレントディレクトリ：WORKDIR)が/vueだったらOK。
カレントが/vueにならないと次項のyarnが/vue配下にインストールされない。
確認後exitで抜ける
```sh:
docker compose run --rm vue sh
/vue #　exit
```

### yarnのインストール
```sh:
docker compose run --rm vue yarn install
```
インストール完了後vue配下にyarn.lockファイルとnode_modulesフォルダができる。

### 起動
```sh:
docker compose up -d
```
http://localhost:8082
にアクセスし、You dit it！を確認
![スクリーンショット 2024-06-14 10.38.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82975/9c3e01cf-bec0-49a3-8aec-92d856563aac.png)


### 参考
https://qiita.com/genimura/items/88742085294bd0b234a6
私たち「組込屋（エンジニア）」はどこへ行く？（早速「Free沼」に ハマった編　その２）

『早速「Free沼」に ハマった編　その１』※１では、FreeRTOSという無償のOS環境を動かしてみよう、OTAをまず動かしてみようと思いまして、「Free沼」に足を突っ込んだところまでお話しました。

　　※1　https://qiita.com/Cente_mw/items/e0154d336e014c22c264
　
 そもそも、なぜ「Free沼」という造語まで作ったのに、その「沼」に足を踏み入れる愚行に及んだのか。。
　その辺の背景について説明します。
　
　皆さん、EUサイバーレジリエンス法ってご存じでしょうか？　CRA法とも言われていますが　ココに（※２）経産省が出している草案概要があります。草案といっているぐらいなので、まだ施行されていません。
　端的に説明すると、EU諸国に製品を出荷（輸出）する場合には、このセキュリティ要綱に準拠してください！（予告！）という事です。
 
 
 ![EUサーバーレジリエンス法.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032022/5aba84df-6b10-c0b9-2cb9-cb2561d0783d.png)
※2　https://www.meti.go.jp/policy/netsecurity/netsecurity/CRAdraft.pdf

　私たちミドルウェア屋の前身は、家庭用ISDNルーター（※３）を作って国内（一部海外）に販売提供していた事業となります。
　当然、お客様先に製品が販売された後にバグやら脆弱性やら、機能Upやら、、そういったものをお客様に届けなきゃならない。
 
　当時はそんなお客様先でのバージョンアップが一般的では無かった時代ですが、お客様皆様のご理解を頂き、お客様ご自身でルーターのファームウェアのアップデートをして頂いておりました。ソフトの入れ替えに失敗して文鎮化してしまわない様にいつもハラハラしていたことを思い出します。もう20年以上前の話ですね。ああ、オヤジ・ホイホイ話題で申し訳ないです。

![mn128-soho.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032022/41c3d4d8-485b-35c3-181e-633da7979647.jpeg)

　　　※3　MN128-SOHO 　ご存じでしょうか？
   
　話をEUサイバーレジリエンス法（CRA法）に戻しましょう。
　この資料の６ページを見てください。
>⑥	上市後5年間または製品寿命のうち短い期間の間、脆弱性に効果的に対処する

　更に7ページには、
>①	積極的に悪用された脆弱性を発見してから24時間以内にENISAに 通知する

　更に8ぺージには、
>　（８）セキュリティパッチや更新プログラムが遅滞なく無料で配布され、ユーザーへの助言メッセージも添付すること。

　ってあるんです。

　もうお気づきですね？　製品をリリースしたら、最低5年間は脆弱性に対する対応体制を作り、もし何かあれば報告し、脆弱性に対応したパッチや更新プログラムを配布しなければならないのです。これがCEマーキングを取得する条件となるわけです。

　これって、任意では無く、罰則付きの義務化されるわけですから、おいそれとネットワーク商品を世に出すことを躊躇してしまいます。

　で、話は戻って、家庭用ルーターの時代は、「バグがありました、ここにファーム置いておくから勝手にダウンロードして更新してね」
　で済まされていましたが、今やIoT時代ですよね。人間さまがいちいちすべてのIoT機器のファームウェアをUpdateするなんて不可能な世の中になりつつあります。自動アップデートが基本になりつつありますよね。iPhoneなどスマホは当然ですが、最近は車に搭載されているエンターテイメント系のソフトやナビ地図、ナビ本体すらOTAの機能で更新されています。

　話を「その１」の話題まで戻すと、そこで登場するのがAWS IoTと繋がってOTA機能が実現できるITRON系RTOSであるFreeRTOSを使って、

<b>
私：「前に買ったFreeRTOSが乗った評価基板を最新の状態にしてAmazonAWSサーバーに繋がるようにして！<br>
エ：「いや、それが。。。」
</b>

という話題になるのです。全国、全世界にバラまかれたIoT機器に更新プログラムをインストールしたり、パッチを当てたりするのはもう、OTA以外に考えられないと感じているからです。

でもね。その前に、一言でOTAって言いますが、これも細分化して考えないとだめだと思います。
単に新しいファームを用意してデリバリーしたって、どうやって更新する？　更新時に文鎮化しない仕組みはどうする？
そもそもOTAって簡単なの？　。。。。　そして、それぞれのサポートは大丈夫なの？　ここ重要。
単に「お試し」ならば、ああ動いた動いたで、おしまい、ですが、「製品化」ではそうはいきません。先の様にCRA法案だと最低でも5年間は責任のある対応をしなければなりませんし、パッチ提供も必須です。罰金付らしいので。

　このEUサイバーレジリエンス法について詳しく書いているHPもありますので、正確なところはググって頂いて、私たちは、この法律を厳守するために「どんな組込ソフト、組込ハード」を作らなければならないか？　
これは日本にも波及するはずとの考えで、組込屋（エンジニア）が「やるべき仕事」として認識したわけです。

さて、この「組込屋（エンジニア）がやるべき仕事」を見つけてしまったので、さて、解決に向けて「部品集め」から始めましょうか、、、という所です。

<h3>今日の閑話</h3>
　
 この文章を書きながら、横？で一生懸命に情報収集をしているエンジニアが居ます。文中の「エ：」です。（意味わかります？）
 
　突然にFreeRTOSのOTAを動かして！って言われて、その理由をQiitaの記事で知る。。そんなのアリか？
　そんなこんなで、ネタの発掘と発表を同時にやってます。是非「エ：」さんに いいねエールを！　
　こんな点が知りたい、ここを掘って欲しい、頑張れ！　何でも良いですが「いいね」または「コメント」をお願いします。すべてに良い回答が出来ないかもしれませんが、皆様のご意見参考にさせて頂きます！
XR Interaction ToolkitでFinalIKを使わず一人称視点でのVRMアバターの自然な歩行を実装してみる。

# はじめに
自分用のメモ。

oculus integrationを使わずXR Interaction Toolkitで動かしたい。
@4sk様の記事を大いに参考にさせていただいた。AvatarAnimationController.csの実装までは以下の点以外はたぶん一緒。

https://qiita.com/4sk/items/c91bf10962b8dd81563c

* stopにはBasic Motionsのidleを使用
* FinalIK部分は飛ばす
* 移動回転の動作はこれで実装

  https://qiita.com/Kazu_Sack/items/776accbe1e8582b3d735
　 


   


# 環境
*    Windows11
*    Oculus Link対応GPU搭載PC
*    Unity version: 2021.3.15f1
*    XR Interaction Toolkit   Version 2.5.2 

# 実装

AvatarAnimationController.csはoculus integrationを使っているので、XR Interaction Toolkitのみを使うように次のように変更。


```c#:AvatarAnimationController.cs
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;

public class AvatarAnimationController : MonoBehaviour
{
    private Animator controller;
    public ActionBasedContinuousMoveProvider moveProvider;

    void Start()
    {
        controller = GetComponent<Animator>();
        ResetAnimation();
        controller.SetTrigger("stop");
    }

    void ResetAnimation()
    {
        controller.ResetTrigger("walkF");
        controller.ResetTrigger("walkB");
        controller.ResetTrigger("walkR");
        controller.ResetTrigger("walkL");
    }

    void Update()
    {
        // moveProviderからVector2型の値を取得
        Vector2 inputVector = moveProvider.leftHandMoveAction.action.ReadValue<Vector2>();
        float forwardMovement = inputVector.y;
        float sidewaysMovement = inputVector.x;

        // 前進Animation
        if (forwardMovement > 0.1f)
        {
            ResetAnimation();
            controller.SetTrigger("walkF");
        }
        // 後退Animation
        else if (forwardMovement < -0.1f)
        {
            ResetAnimation();
            controller.SetTrigger("walkB");
        }
        // 右横歩き
        else if (sidewaysMovement > 0.1f)
        {
            ResetAnimation();
            controller.SetTrigger("walkR");
        }
        // 左横歩き
        else if (sidewaysMovement < -0.1f)
        {
            ResetAnimation();
            controller.SetTrigger("walkL");
        }
        // idle状態
        else if (Mathf.Approximately(forwardMovement, 0f) && Mathf.Approximately(sidewaysMovement, 0f))
        {
            ResetAnimation();
            controller.SetTrigger("stop");
        }
    }
}

```
あとはインスペクターにContinuousMoveProvider枠があるはずだからそこにContinuousMoveProviderコンポーネント挿してるオブジェクトをぶち込むだけ。
# 結果

![無題の動画 ‐ Clipchampで作成.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3733921/527850a4-c6b8-4635-8754-9d910c3b161b.gif)

立ち止まると沈んだ。よくわからん。あとは一応想定内の動作かな。
JavaScript(TypeScript)のconsoleについておさらい【前編】

コードを組む時にlog()やdebug()をよく使うのですが、他のconsoleの仕様をあまり知らないな…と思ったのでざっくりまとめてみました。

:::note warn
筆者の確認環境は vue3系(TypeScript) × chrome です。
純粋なJS環境ではないのでどこかしら挙動が異なるかもしれません。
予めご了承下さい。
:::

# console.log()
>　一般タイプのログ情報を出力します。このメソッドでは、文字列置換および追加の引数を使用することができます。

```ruby
console.log(出力したいオブジェクト・文字列など任意の値);
```
 
個人的に一番よく使ってます。
ソース内で取得値確認のため仕込む事が多いです。

# console.debug()
>　ログレベルが debug のコンソールへメッセージを出力します。

```ruby
console.debug(出力したいオブジェクト・文字列など任意の値);
```

logと出し分けしたい時にこれも割とよく使います。
逆に言うとこれ以降の物に関しては実業務でほぼ使った記憶がありません…
筆者がペーペーだからでは…という気もしますが。
こういった時に使うよ～といったアドバイスなどございましたら、是非お寄せください:pray:

# console.assert()
>　第 1 引数が false であれば、メッセージとスタックトレースをコンソールに出力します。

```ruby
console.assert(論理式, 出力したいオブジェクト1, 出力したいオブジェクト2, …);
console.assert(論理式, 文字列, 文字列内の文字を置換するオブジェクト1, 文字列内の文字を置換するオブジェクト2, …);
 ```
 
ソース内で置換した文字列を出力するときは、実際に値を書き換えた後にlogで出力しがちだったのであまり使った覚えがありませんでした…。

# console.clear()
>　コンソールをクリアします。

```ruby
console.clear();
 ```
 
これも大体chromeの開発者ツールにあるコンソールを消去ボタンを使いがちなので、あまり活用したことがありませんでした。
![console-kizi-img01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713493/59cad478-c820-c512-6c93-5e317b1f3b40.png)
どんな時に使用するか個人的に謎に思っている物の一つです。

# console.count()
>　指定されたラベルでこの行が呼び出された回数をログ出力します。

```ruby
console.count();
console.count("対象のラベル");
 ```
 
②はそのまま対象のラベルが呼びだれた場合のログが出力されますが、
①の様に対象のラベルを省略した場合は"default" ラベルで呼び出された場合としてログが出力されるようです。
以下は試しにソースから出力してみた例になります。
![console-kizi-img02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713493/7f966691-c0a8-fdc3-2a54-ca9073cc2ae9.png)

# console.countReset()
> 指定されたラベルのカウンターの値をリセットします。

```ruby
console.countReset();
console.countReset("対象のラベル");
 ```
 
先程使用したconsole.count()のソースに当てはめて再度確認した結果が以下になります。
引用元の例を参考に作成したのですが、"Pokémon"のcountが0出力されなかったのでその点については分かり次第追記したいと思います。
![console-kizi-img03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713493/2b7e2c29-f689-4ceb-e78a-49bd8ae8fb58.png)

# console.dir()
>　指定した JavaScript オブジェクトのプロパティの、対話型リストを表示します。このリスト内の三角印をクリックすると、子オブジェクトの内容を調査して表示させることができます。

```ruby
console.dir(対象のオブジェクト);
 ```
 
実際に使用してみましたが、以下のような結果でした。
もっとネストが深いオブジェクトを見たい時などに使うと便利なのかな～といった気がします。
![console-kizi-img04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713493/1e04b2c4-95f4-0b08-72d4-7c8f533bf2b7.png)


中編に続きます！
　
> 引用：https://developer.mozilla.org/ja/docs/Web/API/console
　　『メソッド』より