OmniAICreator/Qiita-1.07M huggingface dataset:
plunkerでthree.js

# 概要

plunkerでthree.jsやってみた。
練習問題やってみた。

# 練習問題

文字で3Dモデリングせよ。

# 方針
インタープリター方式でやる。
モデリング言語を設計する。

# 言語仕様

# p 0 100 0
頂点を作る。x: 0, y: 100, z: 0

# s 1 2 3 4
面を作る。頂点は1から

# 例cube

```
p 0 0 0
p 100 0 0
p 0 100 0
p 100 100 0
p 0 0 100
p 100 0 100
p 0 100 100
p 100 100 100
s 1 3 4 2
s 1 5 7 3
s 2 4 8 6
s 1 2 6 5
s 3 7 8 4
s 5 6 8 7
```

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/8301aa37-f868-3eb4-c650-6405c0e4de6d.png)

# サンプルコード

```


	var width = 400; 
	var height = 400;
	var scene = new THREE.Scene();
	scene.add(new THREE.AmbientLight(0xffffff));
	var camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);
	var renderer = new THREE.WebGLRenderer();
	renderer.setSize(width, height);
	var container = document.createElement('div');
	document.body.appendChild(container);
	container.appendChild(renderer.domElement);	
	camera.position.set(0, 100, 400);
	scene.background = new THREE.Color(0xeeeeee);
	scene.add(new THREE.GridHelper(400, 10));
	var controls = new THREE.OrbitControls(camera, container);
	var geometry = new THREE.Geometry();
	var norml = new THREE.Vector3(0, 0, 1);
	var html = 
	"p 0 0 0\n" +
	"p 100 0 0\n" +
	"p 0 100 0\n" +
	"p 100 100 0\n" +
	"p 0 0 100\n" +
	"p 100 0 100\n" +
	"p 0 100 100\n" +
	"p 100 100 100\n" +
	"s 1 3 4 2\n" +
	"s 1 5 7 3\n" +
	"s 2 4 8 6\n" +
	"s 1 2 6 5\n" +
	"s 3 7 8 4\n" +
	"s 5 6 8 7";
	var textArray = html.split(/\r\n|\r|\n/);
	for (var i = 0; i < textArray.length; i++)
	{
		var line = textArray[i];
		if (line.indexOf('p ') === 0)
		{
			var tmp = line.split(' ');
			geometry.vertices.push(new THREE.Vector3(tmp[1], tmp[2], tmp[3]));
		}
		else if (line.indexOf('s ') === 0)
		{
			var tmp = line.split(' ');
			geometry.faces.push(new THREE.Face3(tmp[1] - 1, tmp[2] - 1, tmp[3] - 1, [norml, norml, norml]));
			geometry.faces.push(new THREE.Face3(tmp[1] - 1, tmp[3] - 1, tmp[4] - 1, [norml, norml, norml]));
		}
	}	
	geometry.computeFaceNormals();
	geometry.computeVertexNormals();
	var materials = [
		new THREE.MeshLambertMaterial({
			color: 0xffffff
		}),
		new THREE.MeshBasicMaterial({
			color: 0x3333ff, 
			wireframe: true,
			transparent: true
		})
	];
	var mesh = new THREE.SceneUtils.createMultiMaterialObject(geometry, materials);
	mesh.position.z = -5;
	scene.add(mesh);
function tick() {
  controls.update();
  renderer.render(scene, camera);
  requestAnimationFrame(tick);
}
tick();



```

# 成果物

https://embed.plnkr.co/plunk/zynhZx8KSD74HVqA


以上。
SSH認証でGithubに接続

SSH認証でGithubに接続した手順を記録します。
## 前回
- [Gitのインストール](https://qiita.com/aomrikti/items/2b482c1bbde062ef99fd)

## SSH公開鍵・秘密鍵のキーペアを作成
- [Git Bash]を開く
- Githubの[公式サイト](https://docs.github.com/ja/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent)を参考に、下記のとおりに入力してEd25519でSSH認証に必要な鍵を作成する
```
$ ssh-keygen -t ed25519
```
- パスフレーズを設定しない場合は、そのままEnterで進む
- デフォルトの名前は秘密鍵が「id_ed25519」、公開鍵が「id_ed25519.pub」

## 公開鍵をGithubアカウントに追加
- SSH公開鍵をクリップボードにコピーする
```
$ clip < ~/.ssh/id_ed25519.pub
```
- Githubのアカウントのトップページから「Setting」内の「SSHキーとGPGキー」のページに移動し、「New SSH Key」をクリックする

- 下記の画面の[Title]フィールドには任意のラベルを入力、[Key type]は「Authentication Key」を選択、[key]には先ほどコピーしたSSH公開鍵を貼り付ける。最後に [Add SSH key]をクリックする
<img width="400" alt="github1.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570127/73e3adfc-f57d-8c1c-4f7e-73775d2bfda7.jpeg">

## 接続の確認
- [Git Bash]で下記のとおり入力する
```
ssh -T git@github.com
```
- 下記のようなメッセージが出力されれば、接続されていることを確認できる
```
Hi(アカウント名)! You've successfully authenticated, but Github does not provide shell access.
```

## 参考

https://qiita.com/shizuma/items/2b2f873a0034839e47ce


https://docs.github.com/ja/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent
VSCodeでJavaを書いてる時に、うまくコピー＆ペーストができない件の対処方法

自分用のメモです。

# 現象
VSCodeで`Language Support for Java(TM) by Red Hat`という拡張機能を有効にしてあり、かつJavaファイル編集中にコピペを行う以下のような事象が発生します。

「\`Language Support for Java(TM) by Red Hat\`拡張子を使用して貼り付ける」か「プレーンテキストの挿入」かを求められてスムーズにペーストができません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884998/f399f76a-e8cf-71e8-537e-d95dbd5e9bec.png)

# 解決方法
以下のページにて解決方法が記載されていたので要約します。

https://github.com/redhat-developer/vscode-java/issues/3237

対症療法ですが、VSCodeのsettings.jsonファイルに以下を追記すると事象は発生しなくなります。

```json
{

    ... 

    "[java]": {
      "editor.pasteAs.enabled": false
   }
}
```

Javaファイル編集中は`〇〇として貼り付け`系の処理を止めちゃっているわけです。拡張機能の組み合わせによっては支障も出そうなので注意が必要です。

---

# 2024/03/30 追記 この事象についてまとめている人が他にもいるっぽいです

同じ事象についてアップデートしていた方がいるようなので、より新しい情報を知りたい方はこちらの記事を確認してみてくださいmm

https://qiita.com/UMA9626/items/00296d0ba802e703991e
[雑記] .circleci/config.ymlの分割

上長からconfig.yml分割できないか調査してくれない？ということで調査。

まず、CircleCI公式ドキュメント https://circleci.com/docs/faq/#split-config-into-different-files で
　「.circleci/config.yml の複数ファイルへの分割はサポートされていない」
と明言されている。残念・・・

が、同時に
　「本件についてもっと情報がほしいなら、この[サポート記事](https://support.circleci.com/hc/en-us/articles/360056463852-Can-I-split-a-config-into-multiple-files) を見たらいい」
とも記述されていた。

対象の記事には
　「Dynamic Configuration の セットアップワークフロー を使用すると、.circleci/フォルダに存在しない別のconfig.yml をトリガーにできる」
と記述されている。で、[Dynamic Configuaration のドキュメント](https://circleci.com/docs/ja/dynamic-config/)を参照すると、Dynamic Configuataionを利用するには
- CircleCIのProjectSettingから、Enable dynamic config using setup workflows を ONにする
- config.yml に setup: true  を追加する
- ワークフローの最後に continuation orb からジョブを呼び出す

が必要とわかった。

「Dynamic Configurationのセットアップワークフローを利用することで、.circleci/config.ymlとは別のymlでCircleCIを実行できる」ということで、
あとはその別のymlを生成する処理、今回の要件でいうと「分割したymlから continuation orb に実行させるymlを生成する」ステップを、
セットワップワークフロー内で「continuation orb からジョブを呼び出す」のStepの前に実行すればいい。

・・・これらをすごくうまいことやっているのが

https://christina04.hatenablog.com/entry/circleci-dynamic-config

で、「分割したymlから continuation orb に実行させるymlを生成する」を yq (jqコマンドのyaml版)を利用して実現している。

実際に記事の通りやってみたらできた！感謝感謝。

---

2023/10/19追記

この手法、自身の環境だとあまり使い勝手がよくないかも・・・
というのも、やっていることは「分割したconfig.ymlファイルをCI実行時にマージし、それを使ってもっかいCI走らせる」という感じで、
- 毎回マージ処理が走るの無駄。
- 生成はyqにまかせているため、本当に期待通りのマージ後ファイルが生成されて、本当に実行したいCIが走るかまでは担保できてない。

という、デメリットがあることに気づいた。
特に、yqでのマージについては、分割前のconfig.yml内でアンカー(&)とエイリアス(*)を利用している場合、

```
yq eval-all '. as $item ireduce ({}; . * $item )' file1.yml file2.yml > merged.yml
```
記事の通りに実行すると「参照できないが？」的なエラーが発生してしまう。
これを防ぐために、一旦「同一ファイルだけど内部的には分割されている扱いのファイル(エイリアスがアンカーを参照できる状態にする)」を作ってからyqにかけるみたいな工夫が必要だった。

```
TARGET_YML_FILES=$("file1.yml" "file2.yml")

for TARGET_YML_FILE in ${TARGET_YML_FILES[@]}; do
  cat "${TARGET_YML_FILE}" >> tmp.yml
  echo "---" >> tmp.yml # "---"でYAMLを区切ると1ファイル内で分割されている扱いになる
done
sed -i '$d' tmp.yml # 末尾の"---"を削除
```

で、がんばったもののyqもバージョン違いで挙動が異なり、古いバージョンだと↑の末尾の"---"を削除しないとエラーになるのに、新しいバージョンだと削除しなくてもエラーにならない・・・というのもあり。その辺の不安定さも、今後これで本運用していくにあたっての懸念になる。

・・・分割したconfig.ymlからマージしてできる **「CI実行のための本質的なconfig.yml」はgit上で差分管理したい** し、yqコマンドをローカルで実行して単純に.circleci/config.ymlを作成する運用にした方がよさそう。結構がんばったけど残念。
Dynamic Configurationは、単純にdevelop用、staging用、production用の.circleci/config.ymlを作っておき、workflowで対象ブランチごとに読み込ませたいconfig.ymlを設定するようにする、くらいにとどめておくのがいいのかもしれない。
M1MacでCircleCIのローカルビルド失敗する


# ローカル環境で .circleci

このホームページみたらインストールできる
https://circleci.com/docs/ja/how-to-use-the-circleci-local-cli/

## ビルド
## コンフィグチェック

```
$ circleci config validate
Config file at .circleci/config.yml is valid.
```

pushしてこんなメッセージを何度も見た方は朗報です。

![スクリーンショット 2023-10-13 12.55.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112929/aac47d69-03b9-efec-8e31-fb964afb97e6.png)

ローカルでエラーが出ます。

```terminal
$ circleci config validate
Error: config compilation contains errors: config compilation contains errors:
        - ERROR IN CONFIG FILE:
```


# 当該の問題

イシュー見る感じだと、ubuntuでもmacでも起こるっぽい？
https://github.com/CircleCI-Public/circleci-cli/issues/716

## tmp読み込めない

```terminal
$ circleci local execute {jobの名前}
(中略)
docker: Error response from daemon: Mounts denied: 
The path /tmp/3945127950_circleci_config.yml is not shared from the host and is not known to Docker.
You can configure shared paths from Docker -> Preferences... -> Resources -> File Sharing.
See https://docs.docker.com/desktop/mac for more info.
```

エラーメッセージ通りに、Dockerデスクトップの設定 Preferences -> Resources -> File Sharing で `/tmp/` を追加する。

`/tmp/{数値}_circleci_config.yml` 数値は毎回変更されるので /tmp/ で設定。


## ymlファイルがディレクトリとして認識される

```
$ circleci local execute {jobの名前}
(中略)
Error: failed to start event processor: failed to compute task config: failed to read config file: read /tmp/local_build_config.yml: is a directory
```

## 原因と解決策

イシューの最後にもかかれていますが /tmp というパスの競合でゴニョゴニョしてるみたいでした。https://github.com/CircleCI-Public/circleci-cli/pull/967 のPRを待つか、このPRをローカルビルドすれば動くかなと思います。

> Thanks everyone for reporting this issue and contributing in the comments!
> 
> The underlying problem comes from Lima not accepting /tmp as a mount for its VMs, as it considers it a "system path" similar to /etc or /usr.. Any container distribution using Lima will face this issue, including colima and Rancher Desktop.
>
> We're currently at work on this, and we seem to have found a solution in #967.
We're still working on adding some tests and checks to make sure this is reliable and future-proof, and we'll release it as soon as we can.
> https://github.com/CircleCI-Public/circleci-cli/issues/716#issuecomment-1680680789


自分は一旦ローカルのconfigがバリデーションエラーでないかチェックするだけで充分だと思ったのでそれだけを使う予定です。
Dataflowでshift-jisをUTF8に変換するジョブを作る

# 前提
shift-jisをutfに変換したい. BigQueryに入れたい場合などに、shift-jis対応していないので、UTF8にしたい需要は結構あるはず。
さらに、ファイルが大きい場合、分散処理を行いたい。
なのでDataflowでサクッとできるようなものを作った

# 実装
- python3.9
- beam 2.37.0

```py:converting_to_shiftjis.py
import argparse
import logging

import apache_beam as beam
from apache_beam.io import ReadFromText, WriteToText
from apache_beam.options.pipeline_options import PipelineOptions, SetupOptions
from apache_beam.coders.coders import Coder


class ShiftJisCoder(Coder):
    def encode(self, value):
        return value.encode('shift_jis')

    def decode(self, value):
        return value.decode('shift_jis')

    def is_deterministic(self):
        return True


def run(argv=None, save_main_session=True):
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--input',
        dest='input',
        default='./shift-jis.txt',
        help='Input file to process.')
    parser.add_argument(
        '--output',
        dest='output',
        required=True,
        help='Output file to write results to.')
    known_args, pipeline_args = parser.parse_known_args(argv)

    pipeline_options = PipelineOptions(pipeline_args)
    pipeline_options.view_as(
        SetupOptions
    ).save_main_session = save_main_session

    with beam.Pipeline(options=pipeline_options) as p:
        lines: ReadFromText = p | 'Read' >> ReadFromText(
                known_args.input, coder=ShiftJisCoder())
        lines | 'Write' >> WriteToText(known_args.output)


if __name__ == '__main__':
    logging.getLogger().setLevel(logging.INFO)
    run()
```

### 実行

```sh
python -m converting_to_shiftjis \
    --region $DATAFLOW_REGION \
    --input gs://dataflow-samples/input.txt \
    --output gs://STORAGE_BUCKET/results/outputs \
    --runner DataflowRunner \
    --project $PROJECT_ID \
    --temp_location gs://$STORAGE_BUCKET/tmp/
```

# 参照

https://cloud.google.com/dataflow/docs/quickstarts/create-pipeline-python?hl=ja

https://stackoverflow.com/questions/51935581/apache-beam-gcp-dataflow-encoding-issue

https://github.com/apache/beam/blob/master/sdks/python/apache_beam/examples/wordcount.py
React JSX記法とは

# JSX記法とは
JSXとは"<font color="skyblue">JavaScript XML</font>"の略で，Reactを実装するためのJavaScriptの拡張構文である．
JSXはJavaScriptの中にHTMLとほとんど同じように記述することができる．そのため，UIを簡単に記述し，視覚的に理解しやすくなった．

例として，Reactのコンポーネントを生成する同一の内容をJSX記法を利用した場合と利用しない場合を比較する．
**JSX記法を利用しない場合**
```javascript
React.createElemet(
	'button',
	{className: 'btn'},
	'Click me!'
}
```
**JSX記法を利用した場合**
```React
<button className={'btn'}>
	Click me!
</button>
```
このように，JSX記法を利用する場合，HTMLのように記述することができるため，UIを直感的に記述することができる．

# jsx拡張子とjs拡張子の違い
Reactでは，**JS拡張子(.js)** のファイルと**JSX拡張子(.jsx)** のファイルの両方を読み込むことができる．一般的には，<ins>JSXコードを含む場合はjsx拡張子</ins>を使い，<ins>JSXコードを含まない場合はjs拡張子</ins>を使うことが推奨されている．

それぞれの役割を整理すると以下のようになる
JSファイル　→　Reactコンポーネントのロジックを実装，
JSXファイル　→　マークアップやUIの構築を行う．

これによって，コンポーネントのロジックとビューの作成の分離が可能であり，再利用性やメンテナンス性が向上する．

# JSXはどのように読み込まれる？
JSXコードがJavaScriptファイルに含まれているとブラウザでは実行することができない．そのため，<font color="green">**トランスパイラ**</font>を利用して変換する必要がある．

<font color="green">**トランスパイラ**</font>とは
→ 新しいJavaScriptの記法を古い記法に変換してくれるものである．開発は新しい記法で行い，実行するときは古い記法で行うようにすれば，どんなブラウザでも問題なく実行できるということから生まれた．

JSXを利用しない場合は’React.createElement’によってReactの要素を生成している．JSXを利用したプログラムでは，’React.createElement’を使用する必要がなく，トランスパイルが従来の’React.createElement’の式に変換して，Reactの要素を生成している．

Reactでよく使われるトランスパイラとして，「Babel」というものがある．Babelについては別の方がまとめていた．

https://qiita.com/micropig3402/items/064394428791144f5488

# 実際の書き方について
実際のコンポーネントの書き方は別の記事にまとめた．

https://qiita.com/thirai67/items/2254fd011aa8511eb36e

https://qiita.com/thirai67/items/7990026da7dc4209c1f1

https://qiita.com/thirai67/items/219a0290b51a0d9e5af2
Node.jsのバージョンをアップグレードする方法

Node.jsのバージョンをアップグレードする方法は、主に2つの方法があります。以下にそれらの方法を説明します。

**方法1: nvm (Node Version Manager)を使用する**

nvm（Node Version Manager）は、Node.jsのバージョンを管理するためのユーティリティです。nvmを使用すると、異なるバージョンのNode.jsを簡単に切り替えることができます。以下は、nvmを使用してNode.jsをアップグレードする手順です。

1. nvmをインストールします。インストール方法は、nvmの公式ウェブサイトにアクセスして、指示に従うことができます。

2. ターミナルを開いて、次のコマンドを使用して利用可能なNode.jsのバージョンを表示します：

```
nvm ls-remote
```

3. アップグレードしたいNode.jsのバージョンを選択し、次のコマンドでインストールします。例えば、Node.js 16をインストールする場合：

```
nvm install 16
```

4. インストールが完了したら、次のコマンドで新しいバージョンを使用できるように設定します：

```
nvm use 16
```

これで、Node.jsのバージョンがアップグレードされました。

**方法2: 直接Node.jsを再インストールする**

Node.jsの公式ウェブサイトから最新のNode.jsインストーラーをダウンロードして、再インストールすることもできます。

1. Node.jsの公式ウェブサイトにアクセスし、最新バージョンのNode.jsインストーラーをダウンロードします。

2. ダウンロードが完了したら、インストーラーを実行してNode.jsを新しいバージョンに更新します。

3. インストールが完了したら、ターミナルで以下のコマンドを実行して、Node.jsのバージョンが更新されたことを確認します：

```
node -v
```

これで、Node.jsのバージョンがアップグレードされています。

どちらの方法を選択するかは、あなたの好みやプロジェクトのニーズに応じて異なります。 nvmを使用すると、複数のNode.jsバージョンを管理しやすくなり、プロジェクトごとに異なるバージョンを設定できます。
GCPのCloud Vsion APIを使ってOCR（画像からテキスト抽出）してみる

# はじめに

今回はGCPのCloud Vison APIを利用して画像からテキスト（日本語）を抽出します。

経緯として、Tesseractを使用してみたんですが、精度の高いバージョンでも日本語の読み取り制度が低いんですよね...

今回は個人使用でリクエスト数も少ないため、GCPのAPIの中で探したところ、Cloud Vision APIを見つけたので使うことにしました。

# 料金

GCPのAPIなので料金がかかります。が！個人使用レベルなら基本無料です。というのもリクエストの送信が1000回を超えると1001回目から有料になるみたいです（それまでは無料）。

https://cloud.google.com/vision/pricing?hl=ja

その後は1000回ごとに1.5ドルかかるってことですかね？（間違ってたら指摘お願いします）

今回の使い方的には月に1000回も利用しないので大丈夫でしょう。

# 環境
- Python
    - google-cloud-vision 
- gcloud CLI

## google-cloud-visionのインストール

Cloud Vision APIを使うために必要となるのでpipでインストールしておきます

```
pip install --upgrade google-cloud-vision
```


https://pypi.org/project/google-cloud-vision/

ちなみにGCPのAPI関連ライブラリはここにまとまっていて、下の方からPyPIにアクセス可能です

https://github.com/googleapis/google-cloud-python

## GCPでプロジェクトを作成

GCPで新規プロジェクトを適当に作ります。
そこにAPIライブラリからCloud Vision APIを探して有効にします。

## gcloud CLIを使用した認証

今回使用するAPIはADC（アプリケーションデフォルト認証）が必要となります。ローカル環境で開発することになるので以下を参考にgcloud CLIから認証をしましょう。

https://cloud.google.com/docs/authentication/provide-credentials-adc?hl=ja#local-dev

まず、gcloud CLIをインストールします。

https://cloud.google.com/sdk/docs/install?hl=ja

そこからgcloud CLIにこのコマンドを入力します。
```
gcloud auth application-default login
```

認証過程でどのプロジェクトを利用するかなど聞かれるので適宜読みながら入力してください。

# OCRしてみる

ここのクイックスタートを参考にコードを書きました。

https://cloud.google.com/vision/docs/detect-labels-image-client-libraries?hl=ja

```python
from google.cloud import vision

def detect_text(path):
    client = vision.ImageAnnotatorClient()

    with open(path, "rb") as image_file:
        content = image_file.read()

    image = vision.Image(content=content)

    response = client.text_detection(image=image)
    texts = response.text_annotations

    return texts[0].description
```

たったこれだけで高精度なOCRが使えるのはとても便利ですね。

# おまけ

今回このAPIを使った理由ですが、WinningPost10というゲームをしていて、馬のリストを画像から生成したかったからなんです。

最後にStreamlitを使ったアプリとしてコードを書いたので参考にしてみてください。

```python
from google.cloud import vision
import streamlit as st
import pandas as pd


def detect_text(file):
    client = vision.ImageAnnotatorClient()

    # with open("a.png", "rb") as image_file:
    #     content = image_file.read()

    image = vision.Image(content=file)

    response = client.text_detection(image=image)
    texts = response.text_annotations

    return texts[0].description

files = st.file_uploader("画像アップロード", accept_multiple_files=True)
texts = []
for f in files:
    st.write("filename:", f.name)
    texts.append(detect_text(f.read()))

    
if len(files) >= 1:
    st.dataframe(pd.DataFrame("\n".join(texts).split("\n")))
```
![スクリーンショット 2023-10-17 153026.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/e306bea2-95ae-d50a-5976-ac4418857c09.png)

このようなスクショが↓のように処理されてリスト化されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/942a7391-5cf9-b40d-40c2-37475caa55aa.png)
Minecraft Server機を移行しようと決心

# Raspberry Pi serverからUbuntu 20.04に移行するお話

## 経緯
先日の記事の通りマルチのマインクラフトサーバーを無事作り上げたが、もうサーバーが耐えられないワールドが発展してしまったのでサーバー機を用意して本格的なサーバーに移行することになった。

こちらがサーバーの警告文である。  
```
[Sun 00:06:54 WARN  Server] Can't keep up! Is the server overloaded? Running 5002ms or 100 ticks behind
```  
これが数分ごとに送られてくるようになったので移行を決意した。  

今更調べて分かったことだが、マイクラのサーバーにはCPUのシングルスレッドが重要ということが分かった。  
Raspberry PiのCPUは **Cortex-A72 (ARM v8)** であり、Intel CPUに置き換えると " **Core2 duo T6500** " 相当らしい....  
このレベルならメモリをいくら割り当ててもボトルネックが起こるわけだ....

## サーバー移行するにあたって
現サーバーから新サーバーに移行するにあたって、ワールドデータをコピーして、新サーバーに置き換えるという作業が必要になってくる。  
ワールドデータがおかれているディレクトリごとバックアップをとり、そのディレクトリをSCPして新サーバーに移設しようと思う。  

## おわりに
Ubuntu Serverのセットアップについても記事にする予定なので、新サーバーが届き次第、順次作業していこうと思う。  


ps.最近マイクラよりサーバー設定の時間の方が長くなっている気がするw
Python コードで Word 文書を最初から作成する

プログラミング言語を使用して文書を作成することは、自動化された処理方法の一つです。専門のライブラリを使用することで、この操作を実行することができます。コードを使用していても、必要に応じて文書の形式やレイアウトをカスタマイズすることができます。この方法により、一括で文書を生成することができ、作業効率を向上させ、手動操作を減らすことができます。以下は、Python言語を使用して簡単なWord文書を作成する手順の例です。
## ツール
* Visual Studio Code
* [Spire.Doc for Python](https://www.e-iceblue.com/Introduce/word-for-net-introduce.html)

## インストール方法
* まず、[Python](https://www.python.org/downloads/) をインストールします。
* VS Code で「Extensions」をクリックし、「Python」を検索してインストールします。
* 「Explorer」-「NO FOLRDER OPENED」-「Open Folder」
* 既存のフォルダーをワークスペースとして選択するか、新しいフォルダーを作成することもできます。
* そのフォルダーに「.py」 ファイルを追加し、任意の名前を付けます。
* 「Terminal」-「New Terminal」をクリックします。
* 次のコマンドを入力して、[Spire.Doc for Python](https://www.e-iceblue.com/Introduce/word-for-net-introduce.html) と plum-dispatch v1.7.4 をインストールします。
```
pip install Spire.Doc
```
## サンプルコード
このライブラリは、Word文書のモデルを表すために使用されるDocumentクラスを提供しています。文書には少なくとも1つのセクションが含まれる必要があります。各セクションには、段落、表、グラフ、画像などの要素が含まれることができます。以下はコードのデモです。必要なWord文書を作成するために、コードを必要に応じて変更することができます。
```python
from spire.doc import *	
from spire.doc.common import *

#Document オブジェクトを作成する
doc = Document()

#セクションを追加する
section = doc.AddSection()

#ページ余白を設定する
section.PageSetup.Margins.All = 40

#タイトルを追加する
titleParagraph = section.AddParagraph()
titleParagraph.AppendText("金閣寺の紹介")

#段落を追加する
bodyParagraph_1 = section.AddParagraph()
bodyParagraph_1.AppendText("金閣寺（きんかくじ）は、日本の京都市にある仏教寺院です。" +
                           "正式な名前は「鹿苑寺（ろくおんじ）」ですが、通称として金閣寺と呼ばれています。")

bodyParagraph_2 = section.AddParagraph()
bodyParagraph_2.AppendText("金閣寺は、室町時代に建てられた禅宗の寺院であり、日本を代表する観光名所の一つです。 " +
                           "特徴的な金箔で覆われた三層の塔屋が美しい姿を見せています。 ")

#タイトルに「Heading1」を適用する
titleParagraph.ApplyStyle(BuiltinStyle.Heading1)

#段落のスタイルを作成する
style2 = ParagraphStyle(doc)
style2.Name = "paraStyle"
style2.CharacterFormat.FontName = "Yu Mincho"
style2.CharacterFormat.FontSize = 12
doc.Styles.Add(style2)
bodyParagraph_1.ApplyStyle("paraStyle")
bodyParagraph_2.ApplyStyle("paraStyle")

#段落の水平方向の配置を設定する
titleParagraph.Format.HorizontalAlignment = HorizontalAlignment.Center
bodyParagraph_1.Format.HorizontalAlignment = HorizontalAlignment.Left
bodyParagraph_2.Format.HorizontalAlignment = HorizontalAlignment.Left

#間隔の設定
titleParagraph.Format.AfterSpacing = 10
bodyParagraph_1.Format.AfterSpacing = 10

#ファイルに保存する
doc.SaveToFile("output/SampleFile.docx", FileFormat.Docx2019)
```
### これは上記のコードで使用されるメソッドです

1. Document.AddSection(): セクションの追加
2. Section.PageSetUp.Margins: ページ余白の設定
3. Section.AddParagraph(): 段落の追加
4. Paragraph.AppendText(): 段落にテキストを追加する
4. Paragraph.ApplyStyle():	段落にスタイルを適用する

## 結果文書
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/8147d6f4-6443-466a-37f8-2f0b34c83d48.png)
Azure Static Web Appsを使ってNuxt3サイトをデプロイしてみた

## はじめに
Azure Static Web Appsを使って、Nuxt3サイトをデプロイしてみました。Azure Static Web Appsは、静的なウェブアプリケーションのホスティングとデプロイをシンプルに行えるMicrosoft Azureのサービスです。

## 開発環境
- Windows 11
- Nuxt.js 3.0.0-rc.6
- npm 8.19.4
- Node.js 16.20.0

## 実装
### Nuxt 3 アプリを設定する
1. http://github.com/staticwebdev/nuxt-3-starter/generate に移動します。
GitHubへのログインを求められた場合は、ログインしてください。

1. リポジトリ名を入力し、リポジトリの公開範囲を選択します。私はリポジトリ名を「nuxt-app-test」とし、プライベートリポジトリに設定しました。
設定が終わったら[Create repository]を選択します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124507/c4dd9f3d-3c66-10c9-f5c2-eddebf858e71.png)

1. 作成したリポジトリをお使いのコンピューターにクローンします。

    ```
    git clone [作成したリポジトリのURL]
    ```
  
1. クローンされた Nuxt.js アプリに移動します。
    ```
    cd nuxt-app-test
    ```

1. 依存関係をインストールします。
    ```
    npm install
    ```

1. Nuxt.js アプリを起動します。
末尾に「-- -o」をつけてコマンドを実行すると、自動的にアプリ画面に移動します。
    ```
    npm run dev -- -o
    ```
アプリ画面は以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124507/bbed9917-a5ac-77b1-66fc-7eaeb4002a54.png)
  

### Nuxt 3 サイトをデプロイする
1. [Azure Portal](https://portal.azure.com/#home) に移動します。

1. [リソースの作成] を選択します。

1. Static Web Appsもしくは静的Webアプリと検索し、[Static Web Apps]もしくは[静的Webアプリ]を選択します。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124507/1f8b3ab7-8728-6695-6fee-cbc3cfa1b791.png)

1. [作成] を選択します。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124507/5661b2db-72f3-b40e-2e4e-23b9d82d4049.png)

1. [基本] タブで、以下の値を入力します。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124507/99f63870-0b4b-7e1d-f1d5-9e0086b1029d.png)

1. [GitHub でサインイン] を選択し、遷移した認証画面にある[Authorize Azure-App-Service-Static-Web-Apps]を選択します。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124507/9cc5c352-7d03-c131-38cf-25fa26e2e2bf.png)


1. 以下のように GitHub 値を入力します。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124507/2a6c9203-3fc9-1658-cb5a-2409c9af90f7.png)

1. [確認および作成]を選択し、項目がすべて正しければ、[作成]を選択します。デプロイが開始されます。
![記事投稿用.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124507/47282966-d0a4-7b1f-d721-a0ae8f66edf1.png)

1. デプロイが完了すると、「展開が成功しました」という通知が来ます。その通知に表示されている[リソースに移動]を選択します。
「保存されていない編集は破棄されます。」というダイアログが表示された場合は[OK]を選択します。ここでの「保存されていない変更」とは、先ほど作成した静的Webアプリのことではなく、現在表示されている画面の内容を示すため、保存は不要です。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124507/20e2d4f7-e780-4c16-94c0-c0a80b391649.png)

1. アプリを作成すると、Azure Static Web Apps によって、リポジトリに GitHub Actions ワークフロー ファイルが作成されます。 
ターミナルに戻り、以下のコマンドを実行して、新しいファイルを含むコミットをプルします。
    ```
    git pull
    ```
　
プルした後は、普段の開発と同じく、コードを変更してプッシュします。
GitHub Actions によって、プッシュのタイミングでアプリが自動的にビルドおよびデプロイされるため、非常に便利です。


## おわりに
Azure Static Web Appsを使って、Nuxt3プロジェクトを作成してみました。
Azure Static Web Appsを使えば簡単にWebアプリをビルドすることができ、変更のリリースもGitHubで管理することができるので、非常に便利です。
ぜひ、試してみてください。
最後までお読みいただき、ありがとうございました！

　
記事に関する質問等ございましたら、コメントもしくは以下のDMにてよろしくお願いします。

https://twitter.com/t___tatsuki


## 参考文献

https://learn.microsoft.com/ja-jp/azure/static-web-apps/deploy-nuxtjs
CodeSandBoxでNuxt3/Vuetify3環境を速攻作成

# 前置き
* 前回、[テンプレートを使わずにNuxt3環境を構築する手順](https://qiita.com/thetsuthetsu/items/e34818cfd01c0be995be "テンプレートを使わずにNuxt3環境を構築する手順")を説明したが、Nuxt3 + Vuetify3のテンプレートがあったので、これを利用して、ハマりどころを説明する。

# テンプレートの選択

* Nuxt3 Vuetify3 Templateを選択

![start_from_template.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282300/40753fa9-5f21-189b-f79b-5369b057a2d4.png)

# [ハマり１] NodeJSバージョンへの警告発生
![node_js_version.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282300/87bf52e4-4d28-1189-c43a-4763c593af52.png)


* NodeJSバージョンを18にupgrade
1. ref: https://codesandbox.io/docs/learn/environment/vm#configuring-nodejs-version
2. .codesandbox/Dockerfileを作成し、以下を定義
    ```
    FROM node:18
    ```
3. システム再起動のメッセージに従う。(Restarting)

# [ハマり２]「defineNuxtConfig is not a function」 エラー

![nuxtconfig_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282300/05996ac7-05bd-0b79-8231-7db57eb0fb84.png)

* nuxt.config.tsの以下を修正
```
import { defineNuxtConfig } from "nuxt";
    ↓
import { defineNuxtConfig } from "nuxt/config";
```

# 無事起動に成功
* 起動ターミナル（正常起動）


![terminal_success.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282300/913422f7-6a02-1d8a-67ed-98df4a4d1393.png)


* ブラウザアクセス（成功アクセス）
![access_success.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282300/148b863d-369f-c0bc-6d3d-1e2614f37b79.png)
1つのPythonプログラムでRealSenseを複数台同時に使用する方法

# 初めに
1つのPythonのプログラムでIntel RealSense D455を複数台同時に使用する方法についての備忘録です。
2台以上のRealSenseを1つのプログラムで動作させたいときの助けになれば幸いです。

RealSense D455
https://www.intelrealsense.com/depth-camera-d455/

複数台使用する際の説明には、こちらの「RealSenseD400シリーズでキャプチャした点群を.plyとして保存する」という記事を参考にさせていただきます。
https://qiita.com/SatoshiGachiFujimoto/items/50d0f0a65b730647fe84

# 手順
大まかな手順については以下の通りです。
1. RealSenseのシリアル番号を確認する。
2. シリアル番号を指定してpythonプログラムを記述する。

### 1. RealSenseのシリアル番号を確認
こちらについては、
1. Intel RealSense Viewerを使う
2. pythonプログラムの実行
の2通りで求めることができます。
#### Intel RealSense Viewerを使う方法
公式から出されてるアプリであるIntel RealSense Viewerを使用してシリアル番号を調べます。
https://github.com/IntelRealSense/librealsense/releases/tag/v2.54.2

PCにシリアル番号を調べたいRealSenseを1台のみつないだ状態でViewerを起動します。
起動後、現在つないでいるRealSenseのシリアル番号を確認できます。
![qiita1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3328885/1cfd2121-8681-cbca-b4e6-6093c94115bb.png)
①右上のメニューからinfoを選択
②シリアル番号を確認

#### pythonプログラムで確認する方法
Pythonプログラムを実行することで現在つないでいるRealSenseのシリアル番号を調べます。
こちらの方法も1台ずつシリアル番号を調べてください。
```python
import pyrealsense2 as rs

# RealSenseカメラを初期化
pipeline = rs.pipeline()
config = rs.config()
pipeline.start(config)

# カメラの情報を取得
pipeline_profile = pipeline.get_active_profile()
device = pipeline_profile.get_device()
serial_number = device.get_info(rs.camera_info.serial_number)

print(f"RealSenseカメラのシリアル番号: {serial_number}")

# RealSenseカメラをシャットダウン
pipeline.stop()
```

### 2. シリアル番号を指定してpythonプログラムを記述する。
次に、シリアル番号を指定するコードをpythonプログラムに追加し、完了です。
参考にさせていただいたプログラムを2台使用するために拡張したプログラムのシリアル番号を指定する箇所を添付いたします。
```python
# Create a pipeline
pipeline1 = rs.pipeline()
pipeline2 = rs.pipeline()

config1 = rs.config()
config1.enable_device('117222251152')  # realsense1のシリアル番号を指定
config1.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
config1.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)

config2 = rs.config()
config2.enable_device('053122250872')  # realsense2のシリアル番号を指定
config2.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
config2.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
```
この他にも、profileやintrinsicなども1,2の番号で識別してあげる必要がありますが、それさえすれば1つのプログラムで複数のRealSenseを使用可能です。
2つの点群データをレジストレーションするための回転行列を事前に求めておけば、リアルタイムでマージした点群を作成することも可能です。
参考プログラムのように、sキーを押すと複数の点群を別で保存したり、マージ後の点群を1つのデータとして保存できるようになるはずです。

# 終わりに
今回は1つのpythonプログラムで複数のRealSenseを使用する方法を紹介いたしました。
私の環境ではUSBハブを用いて、同時に4台のRealSenseを動かすことができました。
「sympyのRational」を調べました。

**目的:ラプラス変換の結果の小数の部分は、分数のはずです。**

オリジナル。以下のコメントより。ありがとうございました。

https://qiita.com/mrrclb48z/items/6b02ec9416ffd7f0c8c3#comment-80691364471089bd3224

# DOC
limit_denominator(max_denominator=1000000)
https://docs.sympy.org/latest/modules/core.html#sympy.core.numbers.Rational.limit_denominator

# sympyで
```python
from sympy import *
print("#",1/6)
print("#",Rational(0.16666666666666666).limit_denominator(10**12) )
print("#",Rational(1/6)                .limit_denominator(10**12) )
print("#",Rational(1,6)                .limit_denominator(10**12) )
# 0.16666666666666666
# 1/6
# 1/6
# 1/6
```
# sympyの自作myRld関数(小数を分数変換)で
・結果が、1/6*t**3 + t になっていません。
・１個のみです。←n個の時はどうするの？
　再帰？またはループの勉強中です。
```python
from sympy import *
import re
var('t',positive=True)
def myRld(f): # ver0.1
     li = re.findall(r'[.0-9]+',str(f))
     sorted_li=sorted(li ,key=lambda s:len(s))
     syosu    =sorted_li[-1]
     bunsu=Rational(sympify(syosu)).limit_denominator(10**12)
     return sympify( str(f).replace(str(syosu),str(bunsu)) )
f=0.166666666666667*t**3 + t
print("#",      f )
print("#",myRld(f))
# 0.166666666666667*t**3 + t
# t**3/6 + t
```

# いつもの? sympyの実行環境と 参考のおすすめです。
(テンプレート)

https://qiita.com/mrrclb48z/items/00dd08b0317069be9342

# いつもと違うおすすめです。

https://chaingng.github.io/post/python_re_digit/

https://yumarublog.com/python/lsmr/
未経験からフロントエンドエンジニアを目指す

# 概要
　簡単な自己紹介からさせていただきます。現在地方在住、高卒、今年26になります。普通科の高校を卒業後、大学に行かず地元で働き始め、直近は派遣で働いておりましたが、2023年5月いっぱいで仕事を辞め、2023年6月から私の住んでいる地域の「基礎から学ぶウェブデザイン科」という職業訓練を受けさせていただき、現在10月までやってきました。

　訓練は6か月間あり、ウェブデザイン科ではありますが、1か月目はWord、2か月目はExcelの勉強で残り4か月でウェブデザインの勉強という内容です。基本的にはHTML,CSSの学習とあとはGIMPという画像編集ソフトの学習になってます。
HTMLとCSSはある程度終わって現在はGIMPの学習になってますが、学習を進めるうちに、javascriptに興味がわき、そこに向けての学習を記録としても残していこうと思いQiitaに投稿していこうと思いました。
訓練自体はウェブデザイナーを目指すのが目的の訓練ですが、自分はどちらかといえばエンジニアの方に興味があるのでその学習記録を残していければと思っています。



## きっかけ
　小学生の頃から自宅のパソコンで今はなきフラッシュゲームなどをやったり、その頃今ほど有名ではなかったマインクラフトをやり始め、中学時代は時間さえあればマイクラをしてたのを覚えています。ITだったりPC関連技術に関する興味関心はそこから始まったのかなと思います。
そういった背景から漠然と将来はIT関連の仕事をしたいと思うようになりました。

　しかし、学歴や資格、技術があるわけではないのでそういった仕事にはつけず、接客業、営業職、工場勤務を経験し、しかしどれも自分に向いているとは思えず、何より今後の人生において、挑戦しなかったら後で絶対に後悔すると思い、遅いながらITの勉強をはじめました。




## 学習に取り組む以前は・・・
　以前からIT関連の仕事をしたいしたいと思っていましたが、IT業界のことは何も知らない状態でした。そしてその頃、”おすすめのプログラミング言語”などという今考えれば意味の分からない検索をして、一番人気だったのがPythonだったので「Pythonをやればいいんだ！」「一番人気の言語をやっておけば間違いない！」と思っていました。恥ずかしい、、、。




## 現在
　そして学習を進める中で、言語から選ぶのではなく、自分が何がしたいかによって言語は変わってくるということを学びました。自分はサイトの見た目だったり動きだったり、俗にゆうフロントエンドの仕事がしたいので、だったらHTML、CSS、Javascriptの学習が必要だなと、今後自分がどんな学習を、何の学習をすればよいかが明確になりました。

:::note info
**自分が何をしたいか具体的に考え、明確にする。**
:::



## 職業訓練について
　概要で少し記述しましたが、訓練ではウェブの学習だけではなくWord、Excelの学習もありました。そして日商PC検定文書作成（Word）2級、日商PC検定データ活用（Excel）2級を受け、両方一発合格することが出来ました。自分は高校が普通科だったこともあり、なんらかの資格を取得するという機会がなく、辛うじてあった英検も自由受験で受けてこなかったため、資格といえば運転免許しか持っていませんでした。この学習をする前は、「ウェブの訓練なのにOfficeの勉強？そんなのいいから早くウェブの学習したい。。。」と思っていましたが、今となっては、この資格がどれだけ有効かは一旦おいておいて、何も持っていない自分にとっては履歴書に書ける資格を取得できたのはよかったかなと思います。調べたところによると、同種の資格であるMOSよりもより実践的な使い方ができることをアピールできるみたいで持ってないよりはいいかなと思いました。

　話が少し逸れてしまいましたが、概要にも書きましたが、この訓練ではJavascriptだったりはやらないので、UdemyやYouTubeをつかって学習を進めているところです。
HTML,CSSは基本的なところはほとんどできるようになりました。
CSSで複雑な動きだったりアニメーションを作れと言われれば、時間がかかるかもしれませんが、、、。




## 目標
　目標はもちろんフロントエンドエンジニアになることですが、人生の最終的な目標はフルスタックエンジニアになりたいです。フロントエンドエンジニアになるために必要な学習を進めていき、ポートフォリオを作ってIT業界に転職するのが直近の目標ですが、自分が調べる限り結構大変な道のりでした。
自分調べだとHTML,CSS,Javascript,Typescript,React,Next.js,saas,tailwindCSS,firebase、、、
　現在はJavascriptの勉強をしていますが、基本的な文法やDOM操作くらいはできるようになりましたが、細かい仕様だったり、わからないことだらけです。

　自分は完璧主義な部分があって全部を理解して進んでいこうとして学習速度が遅くなりがちなので、ある程度の理解で進めていき、インプットでつまずいて時間を使うよりも、アウトプットを中心としてわからないことがあればその都度学んでいくという進め方を意識できればと思っています。
　スクールに行くことも検討しましたが、資金的に厳しかったのでとりあえず独学でやっているところです。同じような境遇の方がいれば学習の進め方や学習方法について共有できればと思いますので、コメントを頂けると幸いです。






## マークダウンmemo
:::note warn
警告
○○に注意してください。
:::

:::note alert
より強い警告
○○しないでください。
:::



```html
<h1 class="test">```の後に言語を記述するとその言語に応じてハイライトされる</h1>
```

```css
h1{
    color:#000000;
}
```

```js
const test = document.querySelector("test");
```




```
リンクを張るver1
<https://yahoo.co.jp> 
```
<https://yahoo.co.jp> 


```
リンクを張るver2
https://yahoo.co.jp
```
https://yahoo.co.jp


```
リンクを張るver3
[こちらへ](<https://yahoo.co.jp>) or [こちらへ](https://yahoo.co.jp)
```
[こちらへ](<https://yahoo.co.jp>) or [こちらへ](https://yahoo.co.jp)
人間単語帳アプリを作っている話


はじめまして！ kikedaと申します。
大学院生をやりながら、個人開発でアプリを作ったりしています。

最近、私は「人間単語帳アプリ」なるものを制作しています。
リポジトリはpublicにしていますので以下からソースが見られます。

https://github.com/kikeda1102/Hitomemo2

現状まだ開発途中なのですが、最近Qiitaの[個人開発エンジニア応援企画](https://qiita.com/official-events/09dee22c436b60f856c9)というのを見かけたので、これを良い機会として今回おおまかに紹介させて頂きたいと思います！



【2023/12/29 追記】
iOS版のアプリが完成しました！
iOSユーザーの方、ぜひDLして使ってみてください！！

https://apps.apple.com/us/app/hitomemo-%E4%BA%BA%E9%96%93%E5%8D%98%E8%AA%9E%E5%B8%B3/id6474950113?itsct=apps_box_link&itscg=30200


## 目次
[1.どんなアプリか](#どんなアプリか)
[2.技術面、特徴](#技術面と特徴)
[3.制作のきっかけ](#制作のきっかけ)
[4.苦労した点](#苦労した点)
[5.現状と今後](#現状と今後)

## どんなアプリか

「人間単語帳」は、知り合った人の名前やプロフィールを記録し覚えるためのメモアプリです。

アプリのメイン画面では、登録してある人達のカードが一覧表示されます。
カードをタップすると詳細画面に移り、詳細の確認および編集/削除ができます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558589/585555a2-f32e-102f-2d48-978c8904871f.png" width="40%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558589/4b45da33-672f-86fc-7c65-8c2f140731d6.png" width="40%">


登録画面では、名前に加えて、
* 所属組織（学校、職場、...）
* 特徴（出身、趣味...）
* その他エピソードなど

といった、その人のプロフィールに関するメモを箇条書きのような感覚で登録します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558589/3d51ae68-148f-315a-c995-559a89e359aa.png" width="40%">


特徴的なのが、クイズ機能です。
問題数を選択してスタートすると、プロフィールだけが表示され、対応する正しい名前を選択肢から選ぶというクイズが始まります。
このクイズによって単語帳で英単語を覚えるような感覚で、知り合った人の名前を暗記することができます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558589/1861910b-fb5e-6d0d-4a78-3347356be777.png" width="40%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558589/2d4fca5d-cf4d-b553-b833-f34c9e25b61d.png" width="40%">

以上が本アプリの主な機能です！

## 技術面と特徴

開発には[Flutter](https://flutter.dev/)を使用しています。
iOS, android, その他様々なプラットフォームを統一的に開発することができる個人開発にはもってこいのフレームワークです。

単純なアプリなので、基本的には標準のライブラリばかり使用しています。
パッケージを管理するファイルpubspec.yamlの記述は現状これだけです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558589/e3c73a2b-48c3-0266-d945-b49572f681a1.png" width="90%">

(今後画像登録機能を追加したり、多言語対応などでもう少し増えるとは思います。
また実は初めは状態管理にRiverpodを使用していたのですが、今の自分にはとっつきづらく😅、StatefulWidgetで書いています。)

データ永続化のためのDBとしては[Isar](https://isar.dev/ja/
)を採用しています。
こちらは数あるFlutter向けのローカルDBの一つですが、ブラウザでレコードの状態が確認/編集できるInspectorなどの機能が開発するうえで非常に便利です。
こちらも個人開発にはおすすめです。

## 制作のきっかけ

* 「久々に会ったこの人、パッと名前が思い出せない、何さんだっけ...?」
* たまにしか会わない人との細かいプロフィールを忘れてしまう。
* 他の人と名前やエピソードを間違えてしまい、気まずい思いをする。

全て、自分自身で経験済みです😇

これらの悩みを解消するため、このアプリを作ろうと思い立ちました。

## 苦労した点
DBを使う以上、読み出しや書き込みで非同期処理が必要になるため、FutureBuilderやStreamBuilderの扱いで苦労しました。
また関連してレコードのプロパティであるlistを編集する際、組み込み関数のadd()やremoveAt()が使えず、代替表記することが必要でした。

静的解析ではエラーにならず実行後にExceptionが発生することも多く、ブレークポイントを張ってのデバッグも必要になりました。

これらエラー解決にあたり、一人だけでは難しいと感じたので、オンラインのFlutter開発コミュニティや、大学のIT系コミュニティにも顔を出すようにして、有識者の皆さんにアドバイスを受けながら進めています。
こういったプロの方々の助けにより何とか解決できたので、今となってはとてもいい勉強になったと感じています。


## 現状と今後
先にご紹介したメインの機能の70%ぐらいは実装完了しています。
あとはクイズ機能と、編集機能の細かいところを詰めていきたいという感じです。

11月中を目処にリリースを目指したいと考えています。

感想や改善案など、反応いただけると何でも嬉しいです！

ご覧いただきありがとうございました。
SQLを学びます。③　前編

# 初めに


こんにちはiwanagaです。

前回まではSQLの基礎やツールの紹介でしたが、今回からは4大命令文も含めた基礎的な構文も書いていこうかと思います。

# SELECT文について
やはりSQLにおいて基礎中の基礎はSELECT文だと思います。
皆様も業務を想像してみてください。もし自分が入って数日のペーペーだとしていきなり上司がデータを書き換えろと指示すると思いますか？恐らく言いません。僕ならやりたくないですし、上司も怖くてやらせません。

なので最初はデータ抽出をしっかりと出来るようになった方が良いと思います。
と言うわけでSELECT文を一緒に頑張りましょう。
まずは下記に今回学習するにあたって必要なテーブルを記載します。

テーブル名：grade1_class2

|出席番号(number)|名前(name)|性別(gender)|身長(height)|
|:---:|:---:|:---:|:---:|
|1|アベ|男|170|
|2|イトウ|女|160|
|3|ウエノ|男|190|
|4|エガシラ|女|172|
|5|オオノ|その他|175|
|6|ボブ|無|200|

・基礎的なSELECT文
→SELECT [抽出したいカラム] FROM [テーブル名];です。　
 なのでこれを上記のテーブルに当てはめると下記のようになります。

```
SELECT name FROM grade1_class2;
```
そうすると下記のような結果が出ます。
※管理ツールによって表示は色々ありますのでイメージ図です。

|名前(name)|
|:---:|
|アベ|
|イトウ|
|ウエノ|
|エガシラ|
|オオノ|
|ボブ|

ここまでは簡単ですね。ここから更に複数のカラムを選ぶ時にカラムの次に「,」を入れると複数のカラムを抽出できます。これを文にすると...
→SELECT [抽出したいカラム①], [抽出したいカラム②]FROM [テーブル名];になります。
 なのでこれを上記のテーブルに当てはめると下記のようになります。
```
SELECT numbe,name FROM grade1_class2;
```
そうすると下記のような結果が出ます。

|出席番号(number)|名前(name)|
|:---:|:---:|
|1|アベ|
|2|イトウ|
|3|ウエノ|
|4|エガシラ|
|5|オオノ|
|6|ボブ|

正直これも簡単ですね。最後に全部抽出するにはどうすればいいか？結構簡単で*を入れれば大丈夫です。これを文にすると...
→SELECT * FROM [テーブル名];になります。
 なのでこれを上記のテーブルに当てはめると下記のようになります。
```
SELECT * FROM grade1_class2;
```
そうすると下記のような結果が出ます。
|出席番号(number)|名前(name)|性別(gender)|身長(height)|
|:---:|:---:|:---:|:---:|
|1|アベ|男|170|
|2|イトウ|女|160|
|3|ウエノ|男|190|
|4|エガシラ|女|172|
|5|オオノ|その他|175|
|6|ボブ|無|200|

正直これが一番簡単ですね。
基礎的なSELECT文では"カラム名"、","、"*"を覚えておけばほぼほぼ大丈夫かと思います。
それと同時にテーブル全体の紐付きを意識する事が必要になります。

# 最後に
正直ここまでの内容は割と簡単でした。しかしこれはまだ基礎の基礎です。今回は"SELECT"だけでしたがSELECT文には"where"や"as"や"order by"等色々あります。

ただここの内容を完璧に覚えればそれだけでも仕事が見つかるかもしれないレベルで必要な事です。やはり基礎は大切ですね。

皆様今回もご覧いただきありがとうございました！

参照
https://www.sejuku.net/blog/72964

エンジニアファーストの会社 株式会社CRE-CO　iwanaga
「チャット」の実装について歴史を振り返ってみる

1980年代から1990年代にかけてインターネットの普及にともなって「チャットサービス」が広がっていきました。
2023年の今現在でも現役バリバリのツールで、近年ではメールよりも多く使われています。

チャットの開発は多くの課題がありましたが、技術の進化でその課題を乗り越えてきました。
例えば以下のような課題です。
* 同時接続数の上昇による負荷
* リアルタイム性

この記事ではチャットのリアルタイム性に対する実装について過去の例と、現在の例について解説します。

## 実装例

### 過去の実装例1 - 定期的にサーバーに更新リクエストを送る
最も原始的なやり方です。数秒毎に最新のポストをサーバーへリクエストして取得しにいく方法です。
Ajaxとか仮想DOMとか無かった時代ではページそのものをリロードしてたのではないでしょうか。
```javascript
const getNewPost = function(){
  location.reload();
};

setInterval(getNewPost, 5000);
```
この実装では、人数が多い場合のサーバー負荷や、更新が遅いという問題があります。

## 過去の実装例2 - Comet
ほんのわずかな期間だけ話題にあがったCometです。
Cometはプル型ではなくプッシュ型で更新情報をブラウザに反映させる技術でした。JavaScriptがサーバーとつながりっぱなしにしておく技術です。ロングポーリングと呼ばれていました。
あまりに情報が少なく、記憶からも消えかけてきてるので詳細な実装は割愛します。。。

### 過去の実装例3 - Websocket
Websocketを利用したリアルタイム通信技術です。
```javascript
// サーバー側
io.on("connection", (socket) => {
  socket.emit("hello", "world");
});

// クライアント側
socket.on("hello", (message) => {
  console.log(message);
});
```
HTTPからWebSocketへのプロトコルのアップグレードが必要だったため、ルーターに弾かれるという事もしばしありました。
このWebsocketの登場で、リアルタイム性はかなり向上されました。
しかし、同時接続数が増えてくると1台のサーバーではさばききれなく、スケールアウトが必要になってきます。
データの同期が必要となり、バックエンド側にはRedisのPubSubなどで対応をしてきました。

### 現在 - PaaSの活用
現在ではSDKとインフラを提供しているサービスが多くあります。
サーバー側の実装は不要で、スケールアウトもすべておまかせする事ができます。
同時接続数の上昇による負荷とリアルタイム性どちらもクリアでき、メンテナンスコストを抑える事が可能です。

## Tencent Cloud Chatの紹介
Tencent CloudのChatは、リアルタイムチャットサービスです。Webブラウザやモバイルアプリで利用することができ、1対1のチャットやグループチャットなどの機能を提供しています。

### 特徴
* 高可用性：テンセントクラウドのグローバルネットワークを活用することで、高い可用性を実現しています。
* スケーラビリティ：ユーザー数やメッセージ数に合わせて、柔軟にスケールすることができます。

## 機能
* 1対1のチャットやグループチャット
* Push通信
* 画像、ボイス、動画、ファイルなどのメッセージを送信
* スタンプの送信
* 既読機能
* グループの作成、メンバーの管理、グループの設定

## まとめ
チャットサービスは、コミュニケーションの手段としてだけでなく、ビジネスや教育など、さまざまな分野で活用されています。今後も、チャットサービスのさらなる普及が期待されますが、機能の拡張やスケール等を考慮するとPaaSなどのパッケージ化されたサービスを活用するほうがよさそうです。

## 最後に
[**Tencent Cloudに関するお問い合わせはこちらから**](https://jp.vcube.com/form-inquiry-md06-tencent.html)
オリジナル絵文字を作れる「AI Emoji Generator」が面白い！

AIを使った面白いツールがあったので共有します。
[pondorasti](https://github.com/Pondorasti)さんが作成されている「<b>AI Emoji Generator</b>」というツールで、簡単なプロンプトでオリジナルの絵文字を生成することができます。

https://emojis.sh/

# 使用方法
黒い枠が入力ウインドウです。
下の<b>Recents</b>には直近で入力されたプロンプトとその結果が表示されています。
他の人が入力したものも見ることができるので、プロンプトの参考にしましょう。
![スクリーンショット 2023-10-12 235443.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/427364a8-fc75-88a1-9da5-8b85b9b2e6dc.png)

使用方法はとても簡単。入力欄にプロンプトを打ち込んでEnterを押すだけです。
日本語には対応していないので英語で入力しましょう。単語のつなぎは-(ハイフン)で行います。
今回は<b>dancing-cat</b>（踊る猫）と入力してみます。
![スクリーンショット 2023-10-12 235927.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/b01c409c-7d49-e4ce-cede-639975bd4145.png)

出力されました！ダウンロードのボタンでpng画像として保存することが出来ます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/27cdf939-0ad0-cb9f-95a3-46f8ff717eb9.png" width=50%>

また、同じプロンプトでも出力内容は毎回変わります。お気に入りのものが出るまで引き直すのも楽しいですね。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/f390578f-7064-fc44-a3b8-d59ccf8f2da1.png" width=50%>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/4b73bc07-1dfb-1e4f-dbf5-ecb4e1b59382.png" width=50%>


# 作品紹介
割と無茶なオーダーにも対応してくれます。最近のAIはすごいですね。
いくつか紹介します。

## surprised-cola(驚くコーラ)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/de36e260-0d4d-7cc8-639d-2cec148d4cf7.png" width=50%>

## round-cat(丸い猫)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/e614a34d-cc28-5404-a475-b4557d4056b6.png" width=50%>

## genius-bird(天才の鳥)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/2d89f2b3-399a-6fcf-aa44-51c288c129c7.png" width=50%>

## frenchfries-fighter(フライドポテトの戦士)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/db5e5f66-5a61-64af-6be0-45589bd45723.png" width=50%>

みなさんもぜひ遊んでみてください。


# Slackでも
画像で保存できるので、もちろんSlackのスタンプとしても使えます。
連絡がちょっと楽しくなりますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/a670976a-7819-424a-d77d-0dded3de42e8.png)
ClamAVのfreshclamで WARNING: ******* RESULT 200, SIZE: 9781 ******* が出る問題対応

# 結論

（2023/10/17時点の情報です）
公式バグ。今後のアップデートで解消見込み。

# ログ

【freshclam】
WARNING: Tue Oct 17 00:47:51 2023 ->  ******* RESULT 200, SIZE: 9781 *******

# 情報源

https://www.mail-archive.com/clamav-users@lists.clamav.net/msg52685.html
> It appears that this warning was added by accident while fixing a bug shortly 
before release and no one noticed in review.  We'll remove the warning in 1.1.1 
and 1.2.0.
(機械翻訳)
この警告は、間もなくバグを修正する際に誤って追加されたようです
発売前なのにレビューでは誰も気づかなかった。 1.1.1 では警告を削除します。
そして1.2.0。
.bat（バッチファイル）が最後まで動かない

# 問題

こんなbatファイルを作成したら、動きませんでした。

```bat
diff2html -v
sleep 1
git diff fca2767d0016fd3ade076c95e7dc816d0a7e1dcf -U9999 -- main.md --format= | diff2html --input stdin --style side --file diff.html -t "nantoka diff"
```

最後に`pause`を入れても動かないので、

- git diffかdiff2htmlが悪さしてんのかなあ…
- ファイル名がまずいかな…
- 文字コードがまずいかな…（そもそもUTF-8だし日本語入ってないし試しても変化なし）

と思っていたのですが、ことはもっと単純でした。

# 解決

https://qiita.com/keyta/items/e8783c212916cfbaaba5

リンク先の記事では「bat内でbatを呼ぶとその後の処理が動かないよ！」と書いてありました。

**これはbat内でアプリを呼んでも一緒では？？？** → 正解でした。

# 正解

## そもそも余計なコマンド入れないパターン

```bat
git diff fca2767d0016fd3ade076c95e7dc816d0a7e1dcf -U9999 -- main.md --format= | diff2html --input stdin --style side --file diff.html -t "nantoka diff"
```

これ1行で解決してしまえば、そもそもこんな思いをする必要はありません。

## callを使うパターン

```diff_batchfile
- diff2thml -v
+ call diff2html -v
sleep 1
git diff fca2767d0016fd3ade076c95e7dc816d0a7e1dcf -U9999 -- main.md --format= | diff2html --input stdin --style side --file diff.html -t "nantoka diff"
```

## 余談

このコマンドでdiffを取得できるわけですが、差分の中に日本語が入っていると`.ps1`（Windows PowerShell）で動きません。文字コードがうんちゃらかんちゃらでどうたらこうたらが原因っぽいですが、直すのが面倒なので諦めました。
もしやり方知ってる方がいたら教えてください。
[Rust] Iteratorは消費した後も巻き戻せる（場合が多い）

Rust日本語公式ドキュメントのIteratorの解説を読むと、Iteratorは一度しか使えないというニュアンスを受ける。

>  つまり、このコードはイテレータを消費、または使い込むのです。 nextの各呼び出しは、イテレータの要素を一つ、食います。

食べたら無くなるということは、抽象的なイテレータを受け取る関数はそのイテレータを一度しか使えないと考えるかもしれない。しかしFilterやMapなどを多用しても要素がCloneトレイトを実装している場合はそのIteratorもclone()を呼び出せるため、clone()によりイテレーターを巻き戻すことができる。このことを利用して循環イテレーターを生成するcycle()などが実装されている。

以下に0から20までのRangeにMapを適用したイテレーターを受けとり、イテレーターを巻き戻しながら素数の倍数を出力する関数の例を示す

```rust
fn main() {
    reuse_iterator((0..20).map(|v| v as i32))
}
fn reuse_iterator(vec: impl Iterator<Item=i32> + Clone){
    for div in [3,5,7,11]{
        print!("multiple of {:>2} are",div);
        for i in vec.clone().filter(|v| {
            if (*v)%div==0{
                true
            }else{
                print!("*　");//イテレーターが怠惰であることを確認
                false
            }
        }){
            print!("{:>2}",i);
        }
        println!();
    }
}
```
出力

イテレーターが怠惰であること、イテレーターを消費した後もCloneにより再使用できていることを示す
```
multiple of  3 are 0*　*　 3*　*　 6*　*　 9*　*　12*　*　15*　*　18*　
multiple of  5 are 0*　*　*　*　 5*　*　*　*　10*　*　*　*　15*　*　*　*　
multiple of  7 are 0*　*　*　*　*　*　 7*　*　*　*　*　*　14*　*　*　*　*　
multiple of 11 are 0*　*　*　*　*　*　*　*　*　*　11*　*　*　*　*　*　*　*　
```
memo

https://qiita.com/riversun/items/93604f4c7c5aa020da82

コードの中の「names」という文字をすべて「points」に置き換えたい。

eclipseの場合はリファクタリング機能の「名前を変更」で可能です。
ソースコード上のnamesの文字列を右クリック→リファクタリング→名前を変更
<ul>
<li>ショートカットキー
alt+shift+R
</li>
<li>キーバインド一覧
ウィンドウメニュー→設定をクリック→一般ツリー→キー
</li>
</ul>


カーソルをアクティブにして、選択する列を選択するには、次のコマンドを使用します。
<ul>
<li>Windows： Alt+ Shift+A</li>
<li>Mac：command+ option+A</li>
<li>LinuxベースのOS： Alt+ Shift+A</li>
</ul>

ビルドツールが
Mavenの場合はpom.xml
Gradleの場合はbuild.gradle
Databricksのテーブルに対するAI提案コメントがサポートされました！

日本リージョンでもデプロイされたので記事にまとめます。

# AI提案コメントとは

テーブルのメタデータ(テーブル名、カラム名、データ型など)からコメントを自動生成する機能です。

# ウォークスルー

カタログエクスプローラからテーブルにアクセスするとテーブルのコメントが提案されます。そのまま提案を受け入れる場合には**承認**、編集する場合には**編集**を選択します。
![Screenshot 2023-10-14 at 20.49.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/eea5b81c-de48-d10a-f165-54f27af702ba.png)

列一覧の右上にある**AI生成**をクリックすると、コメントの無い列のコメントが生成されます。チェックマークをクリックすることで承認となります。
![Screenshot 2023-10-14 at 20.51.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/be4df800-d36b-d2f2-30ad-c855dc0ecb09.png)

![Screenshot 2023-10-14 at 20.52.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/fe9c10be-c343-a00b-0582-6c39aa7084c8.png)

正直なところ、言語設定に合わせてコメントの言語も切り替えてほしいですよね…。是非、フィードバックお願いします！
![Screenshot 2023-10-17 at 15.47.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/31411d91-3cfc-860b-c871-1fe7726907d1.png)



### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
B2C CommerceのBusiness Managerで商品を手動で登録し、サイトに表示する

# はじめに
RefArchの商品が英語になっていて、日本語のサイトを作成するときに、日本語の商品をBusiness Managerで登録する。

# 手順
## カタログの作成
マーチャントツール >  商品とカタログ >  カタログ
新規をクリック

![スクリーンショット 2023-10-30 18.59.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2674841/112e8e01-3b22-7872-e3eb-9c0f731f6de9.png)

## カテゴリの作成
マーチャントツール >  商品とカタログ >  カタログ > (作成したカテゴリ)
新規をクリック

![スクリーンショット 2023-10-30 19.00.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2674841/402a38c5-a012-572e-2a2b-db70c7e39bf2.png)

## 商品の登録
マーチャントツール >  商品とカタログ >  商品
新規をクリック
![スクリーンショット 2023-10-17 14.54.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2674841/79d63ee1-61ca-abc5-04d2-8da603fd9784.png)

## 商品にカテゴリを割り当て
マーチャントツール >  商品とカタログ >  商品 > （作成した商品） - カテゴリ
作成したカテゴリの分類と主要にチェックし、「適用」をクリック

![スクリーンショット 2023-10-30 19.03.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2674841/c1060162-b473-5b99-2c37-df2318203a79.png)

## 検索インデックスの再作成
マーチャントツール >  検索 >  検索インデックス
全てチェックし、再作成ボタン
![スクリーンショット 2023-10-30 19.07.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2674841/5d683795-6f31-a2dd-157e-76b923825193.png)


## サイトの言語設定
言語の選択：　日本語（日本）
ID:（任意）
カタログ：（任意を選択）　※事前に日本語のカタログをインストール済み
適用をクリック
![スクリーンショット 2023-10-17 14.56.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2674841/08d5b887-7b6a-409f-c3e1-52a76baa4bfa.png)

## 価格表の適用
価格設定タブ > 新規![スクリーンショット 2023-10-17 15.16.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2674841/45462653-fbd4-59f9-535d-f823e71419d3.png)

価格表の価格テーブルに任意の価格を入力し、適用
jpy-m-list-pricesとjpy-m-sale-pricesをクリックし、割り当てる
![スクリーンショット 2023-10-17 15.15.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2674841/2ed2cb02-b875-0b1a-7716-89ad329804b1.png)

![スクリーンショット 2023-10-17 15.17.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2674841/bbb5aadb-9f95-4766-84ad-4efd983d2cdc.png)

## 在庫の追加
在庫タブ > 在庫リスト（割り当て済みのサイト）の作成
![スクリーンショット 2023-10-17 15.07.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2674841/4bb39be7-32ec-8b81-643e-b071fdda5023.png)

無期限：　チェック
割り当て：　数量を入力
![スクリーンショット 2023-10-17 15.08.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2674841/3be0474d-8d12-85a4-943e-55a6cf7d9356.png)
入手可能性ステータス:	在庫あり　に変わる

## 参考
公式サイト

https://trailhead.salesforce.com/ja/content/learn/modules/b2c-catalog-category-product/b2c-create-categories