OmniAICreator/Qiita-1.07M huggingface dataset:
Uncaught  TypeError: Cannot read properties of undefined (reading 'map')  エラー解決方法

## Uncaught TypeError: Cannot read properties of undefined (reading 'map')の解決方法

# エラー原因
* 画面表示をする側でコンポーネントに渡すpropsのプロパティ名とpropsを受け取る側（コンポーネントの記述をするファイル）のpropsのプロパティ名が違っていて正しくpropsのプロパティが参照できていなかったから。

* propsのプロパティ名が画面を表示する側ではrecordLiになっていてpropsを受け取るコンポーネント側ではRecordLiとなっていてプロパティ名の大文字・小文字が異なっていた。

# 問題のファイル

```App.jsx
export const App = () =>{
const records = [
  { title: "勉強の記録1", time: 1},
  { title: "勉強の記録2", time: 3},
  { title: "勉強の記録3", time: 5}
];
  return (
    <>
    <h1>学習記録一覧</h1>
    <ListDisplay recordLi={records} />
    </>
  );
}

```
```ListDisplay.jsx

export const ListDisplay = (props)=>{
    const {RecordLi} =props;
    
    return(
        <ul>
        {RecordLi.map((studyList)=>
        (
           <li key={studyList.time}>
            <p>{studyList.title}{studyList.time}時間</p>
            </li>
        )
       )}
         </ul>
    );
    }
```

# 修正後
```App.jsx
export const App = () =>{
const records = [
  { title: "勉強の記録1", time: 1},
  { title: "勉強の記録2", time: 3},
  { title: "勉強の記録3", time: 5}
];
  return (
    <>
    <h1>学習記録一覧</h1>
    <ListDisplay recordLi={records} />
    </>
  );
}
```
```ListDisplay.jsx
export const ListDisplay = (props)=>{
    const {recordLi} =props;
    
    return(
        <ul>
        {recordLi.map((studyList)=>
        (
           <li key={studyList.time}>
            <p>{studyList.title}{studyList.time}時間</p>
           </li>
        )
       )}
         </ul>
    );
}
```
# 今回の所感についてまとめ
* プロパティの参照エラーが出た際にはまずプロパティ名が間違っていないか、cosole.log等をしてプロパティが参照できているのかをまず最初に確認した方がよいと感じた。

* 変数名をキャメルケースで書く
⇒先頭大文字はクラスを表すものになるため
* propsのプロパティ名がrecordLiとなっているので分かりやすいrecordListとエラー解消後つけなおした
StableDiffusionをUbuntuServerで動かす

# はじめに
StableDiffusionをProxmoxVE上で動いているUbuntuServerで動かした備忘録兼レポートです。
間違いとかあったらごめんなさい。


# 構成
- CPU:Ryzen 5 3600
- M/B:Asrock A520M-HDV
- MEM:DDR4-2666 16GB
- GPU:GTX1070

StableDiffusion動かすのには役不足なGPUですが余っていたものを使うため採用しています。

# UEFI設定
ゲストOSでGPUを使うにはPCI Passthroughをする必要があり、PassthroughするにはUEFIの設定を変える必要があります。
私はとりあえずSVM Mode(デフォルトでenable),SR-IOV,IOMMUをenableにしています。

その後ProxmoxのコンソールからGRUBの設定を変更します。

```/etc/default/grub
#初期設定
GRUB_CMDLINE_LINUX_DEFAULT="quiet"

# 以下のように修正
GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=on"
```
変更後は
```
update-grub
reboot
```
で設定適用後再起動します。

# ゲストOSインストール
今回はUbuntu Server 24.04LTSを使用しています。
インストール時の設定は、
- マシン:q35
- BIOS:OVMF(UEFI)

です。リソースは好きなだけ振ってください。
起動時にコンソール画面でEscを連打し、UEFIの設定を開いてSecure bootをdisableにします。これをしないとGPUのドライバインストールでうまくいきません。
あとは画面に従ってインストールします。
インストールが終わったら
```
sudo apt update && sudo apt upgrade
```
しておきましょう

# GPUドライバーインストール
仮想マシンのページを開いてハードウェア→追加→PCI→Rawデバイスを選択し接続しているGPUを選び、
- 全機能
- プライマリGPU
- PCI-Express

にチェックを入れてOKを押して再起動します。
次に[このサイト](
https://developer.nvidia.com/cuda-downloads?target_os=Linux&target_arch=x86_64&Distribution=Ubuntu&target_version=22.04&target_type=deb_network
)からCUDAToolkitとドライバーをダウンロードします。
ページ開くとOSとか色々聞かれるのでポチポチします。こんな感じに答えておきます。
![スクリーンショット 2024-06-25 22.49.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680953/0c049f3c-dfc0-cbb4-ccf8-3107a65038ce.png)
そしたら出てきたコマンドを叩いてインストールしましょう。ドライバーはChoose one optionと言われていますのでどっちか叩きます。（openのドライバいれると事故るらしいので上のlegacyの方使ったほうが良いです。）
完了したら
```
nvidia-smi
```
を叩いてドライバがあたっているか確認しましょう。

# StableDiffusionインストール
AUTOMATIC1111版のStablediffusionを入れていきます。
https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-NVidia-GPUs
ここにnvidiaのGPU使った各OS向けのインストール方法が書いており、Linuxは書いてあるコマンド通りやればインストールできます。
全部叩くとインストールされ初回起動まで行われます。初回は時間が掛かるし起動し終わったタイミングが分かりづらいのですが、![スクリーンショット 2024-06-25 23.07.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680953/72274915-7494-cb20-b380-31f1a96eb298.png)
のようにモデル読み込んだみたいな表示が出れば起動が完了しています。
しかしこのままではWebUIを開くことができないのでCtrl+Cで終了させます。

```nano webui-user.sh
#export COMMANDLINE_ARGS=""
```
のところを
```nano webui-user.sh
export COMMANDLINE_ARGS="--listen --enable-insecure-extension-access"
```
に変更します。
listenでLAN内からアクセスできるようになります。ただこれを有効にするとプラグインを追加できません。なのでenable-insecure-extension-accessも有効にしています。
そしてWebUIを起動させます。
```
bash webui.sh
```
を叩き、LAN内の別端末から
192.168.x.xx(仮想マシンのIP):7860にアクセスするとWebUIを開くことができます。

# 参考
https://qiita.com/ynott/items/343c119e8e8b48c740c3
https://qiita.com/s059ff/items/8595bfcc4909c0d1a4f1
JavaScript: Gameで楽する奴

Monte Carlo法と呼ばれる賭け方を自動計算してくれるprogramを紹介。これを使いこなせば無事に破滅できる事間違いなし! 破滅できなくても文句言わないで下さいね。

:::note warn
警告
これは単なるおもちゃです。なんとかQUEST等のVideo Gameでの利用をお勧めします。現実の世界で賭博行為を推奨するものではありません
:::

<p class=codepen data-height="300" data-default-tab="result" data-slug-hash="zYQaMyL" data-pen-title="Monte Carlo Method Calculator" data-user="xezz" style="height:300px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;border:2px solid;margin:1em 0;padding:1em"> <span>See the Pen <a href="https://codepen.io/xezz/pen/zYQaMyL">Monte Carlo Method Calculator</a> by xezz (<a href="https://codepen.io/xezz">@xezz</a>) on <a href="https://codepen.io">CodePen</a>.</span></p><script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## 余談
結局Save & Loadが1番手っ取り早いんじゃ…? そう言われると身も蓋もないですぞ…
AWSのPublic IP一覧を表示するPythonスクリプト(Lambdaとか）

LambdaのPublic IPの一覧がほしかったので、調べてみました。

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/aws-ip-ranges.html

リンク先の記事にあるように、
AWSのPublic IPの一覧は、下記のURLにjson形式で公開されています。

https://ip-ranges.amazonaws.com/ip-ranges.json

が、大方の予想通り、あまりにも巨大でブラウザで見るにはとてもつらいため
必要なデータだけ抽出するようなPythonスクリプトを作成しました。

    import requests
    
    REGION = "us-west-1"
    SERVICE = "EC2"
    
    ip_ranges = requests.get('https://ip-ranges.amazonaws.com/ip-ranges.json').json()['prefixes']
    
    ips = [item['ip_prefix'] for item in ip_ranges if item["region"] == REGION and item["service"] == SERVICE]
    
    print("データ数 = ",len(ips))
    
    for ip in ips:
        print(str(ip), ",")
    

2行目、3行目で抽出したいリージョンとサービスを指定します。

ちなみにLambdaのPublic IPは、「EC2」のサービスとして含まれているとのことでした。
（EC2とLambdaはハードウェアリソース一緒なんかな。）

---

実行結果
    
    $ python aws_ips.py 
    データ数 =  47
    192.31.212.0/24 ,
    99.77.132.0/24 ,
    64.252.118.0/24 ,
    64.252.122.0/24 ,
    （中略）
    52.52.0.0/15 ,
    208.78.134.0/24 ,
    54.176.0.0/15 ,
    52.94.248.128/28 ,

やったね！
mypyの結果がローカルマシンとCIで異なるので調べたこと

## 遭遇した問題
mypyの結果がローカルマシンとCI (GitHub Actions)で異なる。
ローカルマシンではmypyがエラーを出すのに、CIでは素通りしてしまっていた。

GitHub Actions ワークフローの定義は次のような感じ。
```yaml
on:
  pull_request:
jobs:
  test:
    runs-on: [self-hosted, linux, x64]
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"
          cache: "pip"

      - name: Type check with mypy
        run: |
          mypy --ignore-missing-imports src/**.py tests/**.py
```

## 環境
- Self-hosted runner (ubuntu 22.04)
- fish on Debian 12
- mypy 1.10.0

## 試したこと
- キャッシュ(`.mypy_cache`)削除
- verbose logging (`-v` オプション)

## 原因
verbose logging を有効化したところ、CIでは一部のソースファイルしか読んでいないことが判明した。
CIでは、`src/`直下および`tests/`直下のファイルしか読み込んでいなかった。

ローカルマシンではfishを使っており、この環境では`src/`以下と`tests/`以下の`*.py`ファイルを再帰的に読み込んでいた。

以上より、fishとbashの挙動の違いによるものと判定。

調べると、bashでは`globstar`オプションを有効化しないと`**`で再帰的な検索が有効とならないことが判明。
以下の修正で、期待の挙動をするようになった。
```yaml
      - name: Type check with mypy
        run: |
          shopt -s globstar
          mypy --ignore-missing-imports src/**/*.py tests/**/*.py
```

## まとめ
- bashで`**`による再帰的検索を有効にするには、`globstar`オプションを設定する必要がある。
- fishとbashはかなり違うのでfishの結果を鵜吞みにしない！

## 参考
https://atmarkit.itmedia.co.jp/ait/articles/1912/26/news018.html
シミュレーション 環境でセンサ自体もシミュレーションしたいとき

## はじめに
シミュレーションの完成度を高めるためには、シミュレーション環境内でのセンサー類の特性を再現する必要がある。
(unity でダンシング画像を作りたいとか、その他のCG動画をシミュレーションで作りたいのであれば、仮想的な真値データをそのまま扱ってなんの問題もない。　ここでは、ロボットという不完全な計測結果しか得られない状況での
シミュレーションをする場合の話だ。）

いくつかのシミュレーション環境では、センサの出力をシミュレートするモデルを用意している。
その出力を利用することで、検出器のソフトウェアを利用することができて、シミュレーションの目的を達成することにつながる。

NVIDIAのIsaacでは、そのようなセンサがいくつか用意されている。

## NVIDIA used_assets_sensors
https://docs.omniverse.nvidia.com/isaacsim/latest/features/environment_setup/assets/usd_assets_sensors.html

### [RGBD Sensors](https://docs.omniverse.nvidia.com/isaacsim/latest/features/environment_setup/assets/usd_assets_sensors.html#rgbd-sensors)
### [Lidar Sensors](https://docs.omniverse.nvidia.com/isaacsim/latest/features/environment_setup/assets/usd_assets_sensors.html#lidar-sensors)

ここに書かれているセンサの場合だとシミュレーション環境での点群データを元に各センサの特性に基づいて、センサデータをシミュレーションできるらしい。

これらのページにあるセンサを選んでおく分には、センサメーカーとNVIDIAとの協力関係によってサポートがされると期待される。


## もし、利用するLidarがそれらのリストにない場合
おそらくは、以下の記述を元に、該当のLidarのハードウェア特性の記述をするのだろう。
https://docs.omniverse.nvidia.com/kit/docs/omni.sensors.nv.common/1.0.2/common_extension.html


## すべてをシミュレーションするというのはハードルが高すぎる
- シミュレーションだけでは、シミュレーションの妥当性を示せない。
- シミュレーションをする目的を十分に明確にしよう。
- 何が示せればOKなのか？
- それはシミュレーションで示せるものなのか？
- それはシミュレーションで示した方がいいものなのか？
- 目的とする結果を得るのは、どのような条件で失敗するのかを考えよう。
- それらを考慮したうえで、シミュレーションを検討してください。
Google Play Consoleで「非公開」にしていたアプリの「削除」を依頼してみた

## はじめに
弊社では、自社プロダクトのスマホアプリをApp StoreとGoogle Playにて公開しています。
先日、Google Playにて以前公開していたと思われる、現在メンテナンスを一切していない **「非公開」アプリの削除**を依頼されました。

非公開に設定している場合でも、デベロッパーアカウントが停止になるリスクがあるらしいです😨削除した方が安全そうですね。

https://qiita.com/hukusuke1007/items/1e5352a9bfdd08be3ab1

滅多に経験できる作業ではないので記録に残します。

## 削除の申請方法
前提として、Google Play Console上で自らアプリを削除することはできません。
下記にアクセスし、「**アプリの公開に関する問題**」としてヘルプセンターに削除の申請を行います。

https://support.google.com/googleplay/android-developer/contact/publishing


フォームに沿って必要な情報を記載します。
デベロッパー名やデベロッパーアカウントIDなどは、「？」アイコンにホバーすると、どこに記載されているか教えてくれました。

![スクリーンショット_2024_06_25_22_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3537832/8415437e-5ca4-1598-e6e7-5b498c013b93.png)

中段あたりの「*以下の一般的な問題やリクエストから選択してください。*」は、「アプリの削除をリクエストしたい」を選択します。

![スクリーンショット_2024_06_25_22_47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3537832/b99a5230-e18e-0b16-a130-d1697b891445.png)

「*どのようなことでお困りですか？*」という質問は、「未公開のまま、今後メンテナンスを行うことのない不要なアプリの削除をお願いします。」と記載しました。


![スクリーンショット_2024_06_25_22_52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3537832/132a2fa8-0d33-bdbf-15b0-8c91bbfce977.png)

最後に「*問題のトラブルシューティングに役立つスクリーンショットやその他のファイルを添付してください*」欄があります。Google Play Console上で、削除したいアプリのダッシュボードのアプリ名・パッケージ名が分かるようなスクショを撮り、添付しました。


![スクリーンショット_2024_06_25_22_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3537832/dda5c8fe-ca9b-167a-1a8b-56f8dbb1851d.png)

以上！！送信して完了です🎉
送信が完了すると、「*メールを送信しました*」というメッセージが表示されました。
「*2営業日以内に返信します*」と書かれていたので待ちましょう👍

## 終わりに
2営業日どころか当日に返信がありました。
まさかの「アプリは削除できない」とのこと😱😱😱
「**テスト用、一般ユーザー用に関わらず、過去に一度でもインストールされたアプリは削除することができない**」らしいです。

いや結局消せないんかーーーい!!!!!!!!!
どうしたらいいのー!!!!!!!!!

### 参考

https://lastshooting.blogspot.com/2020/11/google-play-console.html

https://blog.mori-soft.com/entry/2022/04/25/093805
【Pybulletサンプル解説】物体間の制約の生成と更新【constraint.py】

お疲れ様です。秋並です。

Pybullet公式gitリポジトリのサンプルコードを解説するシリーズです（一覧は[こちら](https://qiita.com/akinami/items/7b433b60aeb5115ba4d7)）。

<br>

今回は、constraint.pyを解説します。（コードのリンクは[こちら](https://github.com/bulletphysics/bullet3/blob/master/examples/pybullet/examples/constraint.py)）

本コードを実行すると、箱状のオブジェクトが時間とともに制約が変更されていくことで、位置や角度が変化していく様子を確認できます。

![constraint.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2030125/4cd008d1-1302-a046-8821-42a46877222b.gif)


# 使用している機能
本コードは、以下の機能を使用して「制約の作成、更新」を実現できます
- 制約の作成
- 制約の更新

## 制約の作成
`createConstraint`関数を使用することで、指定したボディ（オブジェクト）間に制約を設けることができます。

```python
constraintId = pybullet.createConstraint(
    parentBodyId, 
    parentLinkIdx, 
    childBodyId, 
    childLinkIdx, 
    jointType, 
    jointAxis, 
    parentFramePosition, 
    childFramePosition)
```
- `parentBodyId`：制約する親ボディのID
- `parentLinkIdx`：親ボディのリンクのインデックス（ベースリンクの場合、`-1`を指定）
- `childBodyId`：制約する子ボディのID（ワールドに対して制約する場合、`-1`を指定）
- `childLinkIdx`：子ボディのリンクのインデックス（ベースリンクの場合、`-1`を指定）
- `jointType`：ジョイントの種類
- `jointAxis`：ジョイントの軸（[x, y, z]、`jointType`が固定軸の場合、[0, 0, 0]でもよい）
- `parentFramePosition`：親フレームの位置（[x, y, z]）
- `childFramePosition`：子フレームの位置（[x, y, z]）

<br>

サンプルコートでは、以下のように「箱状のオブジェクト」をワールド座標の[0, 0, 1]の位置に対して固定ジョイントで制約をかけています。

```python
cid = p.createConstraint(
    cubeId, 
    -1, 
    -1, 
    -1, 
    p.JOINT_FIXED, 
    [0, 0, 0], 
    [0, 0, 0], 
    [0, 0, 1])
```

## 制約の更新
`changeConstraint`関数を使用することで、すでに作成された制約を更新することができます。

```python
pybullet.changeConstraint(
    constraintId,
    pivot,
    jointChildFrameOrientation,
    maxFroce
)
```
- `constraintId`：制約のID
- `pivot`：（更新後の）子ボディのピボット位置（[x, y, z]）
- `jointChildFrameOrientaion`：（更新後の）子ボディのフレーム（[qx, qy, qz, qw]）

サンプルコードでは、箱状のオブジェクトの「位置（[a, 0, 1]）」と「向き（オイラー角[a, 0, 1]をクォータニオンに変換したもの）」が時間とともに変化していきます。
    
# コメントをつけたサンプルコード
サンプルコードにコメントをつけたものが以下になります（もともとあった不要と思われるコメント等については削除しています）

```python
import pybullet as p
import time
import math
import pybullet_data

# GUIモードでpybulletを接続
p.connect(p.GUI)

# Pybulletに関するデータのパスを取得
p.setAdditionalSearchPath(pybullet_data.getDataPath())

# 床を生成
p.loadURDF("plane.urdf")

# 箱状のオブジェクトを生成
cubeId = p.loadURDF("cube_small.urdf", 0, 0, 1)

# 重力を設定
p.setGravity(0, 0, -10)

# リアルタイムシミュレーションを有効化
p.setRealTimeSimulation(1)

# キューブを[0, 0, 1]の位置に固定
cid = p.createConstraint(cubeId, -1, -1, -1, p.JOINT_FIXED, [0, 0, 0], [0, 0, 0], [0, 0, 1])

print(cid)
print(p.getConstraintUniqueId(0))

# 立方体の回転角度を-πに設定
a = -math.pi

while 1:
  # 回転角度を+0.01する
  a = a + 0.01
  
  if (a > math.pi):
    a = -math.pi
  
  time.sleep(.01)
  
  p.setGravity(0, 0, -10)
  
  # 箱の位置を「角度a」に応じて更新
  pivot = [a, 0, 1]

  # オイラー角からクォータニオンを計算
  orn = p.getQuaternionFromEuler([a, 0, 0])

  # 立方体の新しい位置と回転を設定
  p.changeConstraint(cid, pivot, jointChildFrameOrientation=orn, maxForce=50)

# 制約を解除（↑が無限ループなので、実際はたどり着かない）
p.removeConstraint(cid)
```
Polarsの読み込みエラー対処

![eyecatch-polars-1-960x504.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/986141/bd716ce9-e760-0f13-ed4d-41507c14c65a.jpeg)


**Polars**は並列処理エンジン、効率的なアルゴリズム、SIMD(Single Instruction, Multiple Data)によるベクトル化の使用により、Pandasよりも30倍ほど早く処理できると言われているサードパーティのライブラリです。使い勝手はPandasを意識してつくられています。

https://pola.rs/


## 課題
例えば、こちらのkaggleのデータセットを読み込もうとすると次のエラーが出ます。

https://www.kaggle.com/competitions/house-prices-advanced-regression-techniques/overview

```python
[in]
import polars as pl
df = pl.read_csv('/kaggle/input/house-prices-advanced-regression-techniques/train.csv')
[out]
ComputeError: could not parse `NA` as dtype `i64` at column 'MasVnrArea' (column number 27)
```
'MasVnrArea'という名前の列はint64で読み込もうとしているが、`NA`は数値にできないと言われています。
`'NA'`というデータがnullとして扱われていないため、このようなエラーが出ます。

## 解決策
Polarsでは`'null'`が欠損値として扱われるので、オプションで`null_values`をつけて、欠損値を指定します。

```python
df = pl.read_csv('/kaggle/input/house-prices-advanced-regression-techniques/train.csv', null_values=["NA"])
```
無事読み込めました。
![](https://storage.googleapis.com/zenn-user-upload/3efd98a39f8d-20240620.png)
framer-motionを使って テキストアニメーション(iphoneの初期画面に出てきそうなやつ)

# はじめに
みなさん、こんにちは **torihazi**です

最近 Reactを学んでおり、

ちょっと何か作りたいということでタイトルのものを

他の方の記事を参考に作ってみました！！

iphoneの初期設定とかで出てきそうでこなさそうなものです！

よければ！！

# 環境
```
# npm -v
10.7.0
# npx -v
10.7.0
# node --version
v20.14.0

"react": "^18.3.1"
"framer-motion": "^11.2.12"
"styled-components": "^6.1.11"
```
# 完成イメージ
![react_hello-1-ezgif.com-video-to-gif-converter.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2567812/890c1268-d3f9-71a4-b860-8116c1a5cedd.gif)

# コード
```react:HelloWorld.jsx
import { motion } from "framer-motion";
import { styled } from "styled-components";

export const HelloWorld = () => {
  const words = "Hello World";

  return (
    <SDiv>
      {words.split("").map((key, value) => (
        <motion.span
          key={value}
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          transition={{
            duration: 0.5,
            delay: value * 0.05,
            repeat: Infinity,
          }}
        >
          {key}
        </motion.span>
      ))}
    </SDiv>
  );
};

const SDiv = styled.div`
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
`;
```

```react:App.jsx
import { HelloWorld } from "./components/HelloWorld";
import "./App.css";

export const App = () => {
  return (
    <div className="App">
      <HelloWorld />
    </div>
  );
};
```
# 終わりに

framer-motionというものの理解が正直まだまだ浅いですが、

少しづつ積み上げていきたいと思います

プロパティはまだまだいじりがいがありそうです！

使えそうだったらポートフォリオにも使ってみようかと思います！！

# 参考
https://qiita.com/nakanami/items/be58c5d47e2cdd252995
styled-componentsにpropsを渡すときは`$`を付けよう

```console
styled-components: it looks like an unknown prop "isVisible" is being sent through to the DOM, which will likely trigger a React console error. If you would like automatic filtering of unknown props, you can opt-into that behavior via `<StyleSheetManager shouldForwardProp={...}>` (connect an API like `@emotion/is-prop-valid`) or consider using transient props (`$` prefix for automatic filtering.)
```

styled-componentsを使用して作成したコンポーネントに`isVisible`というpropを渡した際に上記の警告が出てきました。


# コード

```Img.tsx
import styled from "styled-components"

const Img = styled.img<{isVisible: boolean}>`
    {(isVisible) =>
        !isVisible &&
        css`
          visibility: hidden;
        `}
`
```

```page.tsx
const Page = () => {
    return(
        <div>
            <Img isVisible={variable} />
        </div>
    )
}
```

# 原因

警告メッセージにもある通り、propがDOMに渡されていることで引き起こされているようです。
警告メッセージ末尾にあるようにpropに`$`マークをつけてあげましょう。

```diff
import styled from "styled-components"

+ const Img = styled.img<{$isVisible: boolean}>`
+     ${( isVisible ) =>
+        !$isVisible &&
        css`
          visibility: hidden;
        `}
`
```

```page.tsx
const Page = () => {
    return(
        <div>
+            <Img $isVisible={variable} />
        </div>
    )
}
```

# 余談

警告メッセージの中には`<StyleSheetManager shouldForwardProp={...}>`を使うことも示唆されていますが、今後こちらの使用方法を調べたいと思います。
SAP S/4 HANA 販売管理（SD）基本知識１：全体概要

### はじめに
- SAP ERPでは、販売管理業務領域の機能群を総称してSDモジュールと呼びます。
- SDとは、Sales and Distributionの略です。
- ここでは、販売管理（SD）モジュールの全体像を把握することを目的とします。

### 全体機能関連図
![全体機能関連図SD.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3432463/34c0bfa6-a6ba-e0c9-825c-8410bf8556ee.png)
- SAPには様々なモジュールがあり、相互に関連しています。
（純粋なSD(販売管理)モジュールの機能としては赤線枠で囲った部分になります）
- 例えば、製品に対する受注を入力すると、生産管理に対して製品の所要が自動的に発生し、MRPを実行すると計画手配が生成されます。
- 出荷業務については、在庫を管理しているMM(在庫管理)モジュールと密接な関係にあります。
出庫を行うと、同時に売上原価計上の仕訳が生成され、FI(財務会計)モジュールに連携されます。
- 請求処理（売上）を行うと、同時に売上計上の仕訳が生成され、FI(財務会計)モジュールに連携されます。

### 販売管理の業務の流れと伝票
![販売管理の業務の流れと伝票.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3432463/ec85faf2-fa9b-a27a-0f18-4f3ede7e7a94.png)
- 販売管理の代表的な業務の流れとしては、
引合→見積→受注→出荷・出庫→売上計上（請求）
となります。
これらの業務に対応して、SAPではそれぞれ伝票や関連帳票が用意されています。
- 引合と見積は必須ではなくオプションの機能です。見積からスタートしたり、受注からスタートすることが可能です。
- 販売管理の各伝票は、元伝票を参照して登録することにより、後続の伝票にデータの内容がコピー・継承されます。
- SD(販売管理)はMM(在庫管理)やFI(財務会計)と密接に関係し、統合されています。出荷・出庫や売上計上（請求）では、販売管理側の処理をトリガーにして、自動的に伝票が登録され、MMやFIにリアルタイムに自動連携されます。
- 販売管理では主要な業務帳票がSAP標準で用意されていますが、フォームやレイアウトはユーザ企業によって異なるため、独自に開発することが多いです。

### 販売管理で使用するおもな組織とマスタ
![販売管理で使用するおもな組織とマスタ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3432463/c1660822-fbd8-9f56-355b-05e3466522b2.png)
- 上の画面は受注伝票の例です。受注伝票のヘッダに販売関連の組織の情報を保持しています。
- 販売管理の伝票はマスタとも深く関連しています。代表的なマスタとして、得意先マスタ、品目マスタ、条件マスタ（価格）が挙げられます。これらのマスタは基本的には、伝票を登録する前に予め登録する必要があります。
- 受注先と出荷先は同じ得意先マスタに登録されており、密接に関連しています。通常、受注先を入力すると、それに紐付く出荷先が自動提案されます。紐付く出荷先が複数ある場合は、選択一覧のポップアップ画面が表示されるので、そこから選択します。
- 条件マスタ（価格）は、品目と密接に関連しており、品目コードを入力するとマスタを検索して、自動提案されます。条件マスタ（価格）は品目コードだけでなく、様々な項目との組合せで決定することも可能です。提案された価格は変更することも可能です。マスタが登録されていない場合は、入力する必要があります。

【参考資料】
・図解入門 よくわかる最新SAPの導入と運用ー
LLM評価:モデル評価とタスク評価の重要な違い


## はじめに
- LLMの評価には複数の種類がある
    - LLMの評価という言葉は一般的に使われているが、モデル評価とタスク評価の区別がはっきりしていないことが多い
        - モデル評価は「モデルの全体的なフィットネス」を評価する
        - タスク評価は特定のタスクにアプリケーションが適しているかを評価する

- モデル評価とタスク評価はどちらも機能的なLLMシステムを構築するために重要だが、いつ、どのように適用するかを理解することが重要
- 多くの実務者にとって、時間の大部分はタスク評価に費やされる

## モデル評価を使用すべきタイミング
- モデル評価は通常、テストする一般的な分野がある
- 各指標はそれぞれ特定のスキルを対象としている
  - 例: HellaSwag、MMLU
- モデル評価の目的は、2つのモデルや同じモデルの2つのスナップショットを区別すること

## タスク評価を使用すべきタイミング
- LLMアプリケーションを本番環境で展開する前に、特殊なタスクを実行するための有効性を確認するために必要
- AIエンジニアが直面する最も頻繁な問題を解決し、以下のような質問に答える
  - 検索システムは正しいデータを取得したか
  - 回答にハルシネーションはないか
  - 重要な質問に関連する回答をしたか

## タスク評価の仕組み

**1. ベンチマークの確立**
   - ゴールデンデータセットの作成
   - 評価用LLMの選択

**2. 評価テンプレートの作成**
   - 入力、評価質問、期待される出力形式を明確に定義

**3. メトリクスと反復**
   - ゴールデンデータセット全体で評価を実行し、精度、適合率、再現率、Fスコアを生成
   - テンプレートを洗練させ、ゴールデンデータセットに過剰適合しないようにする

**4. LLMタスク評価の適用**
   - 評価プロセスをアプリケーションのワークフローに組み込む

**5. システムのライフサイクル全体での評価**
   - 本番前のベンチマークとテストから本番環境での継続的なパフォーマンス評価まで

## モデル評価とタスク評価の違いのまとめ

| カテゴリ | モデル評価 | タスク評価 |
|----------|----------|-----------|
| 真実の基礎 | ベンチマークデータセットに依存 | 内部専門家が選定し、LLMで拡張したゴールデンデータセットに依存 |
| 質問の性質 | 能力の幅広い評価を確保するための標準化された質問セットを含む | 現実世界のシナリオを模倣するために、さまざまなデータシナリオに適応可能な、タスク固有の独自のプロンプトを利用 |
| 頻度と目的 | 確立されたベンチマークを使用して一般的な能力を評価するための一度限りのテストとして実施 | 継続的な実世界のアプリケーションを反映し、システムの改良とチューニングのために繰り返し適用される反復的なプロセス |
| 説明の価値 | 説明は通常、アクショナブルな価値を付加しない。焦点はより結果に置かれる | 説明は、特定の状況でのパフォーマンスの理解に焦点を当てて、改善のためのアクショナブルな洞察を提供する |
| ペルソナ | 新しいモデルを評価するLLM研究者と、アプリケーションのモデルを選択するMLプラクティショナー | アプリケーションのライフタイム全体を通してのMLプラクティショナー |
Nest.jsで作るbff環境 - 基礎知識編

## 導入
こんにちは、今回会社の案件でBFFとGraphQLを導入しました。
BFFってなに？って思った人も多いと思いますが、私も最初はよくわかりませんでした。
そこで、簡単にではありますが、BFF環境を作り、BFFとGraphQLを使ったデータ取得の方法を解説していきます。
今回は、基礎知識編です。

## BFFとは
BFFは、「**Backend for Frontend**」の略称で、フロントエンドとバックエンドの中間に位置し、双方の複雑な処理を緩和させる役割を持っています。

わかりやすく説明すると、「**バックエンドの API から取得したデータをフロントエンド向けに加工するフロントエンド専用のサーバー**」です。

![bff.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/879861/4a9f9989-40db-5024-93b1-94f7c8881a4e.png)

## BFFが必要になった背景
BFFアーキテクチャが必要になった背景は主に３点あります。

### 1.マイクロサービスアーキテクチャの複雑化
近年、システム開発においてマイクロサービスアーキテクチャが主流になりつつあります。マイクロサービスアーキテクチャは、システムを小さなサービスに分割することで、開発・保守の容易性やスケーラビリティの向上を目指す開発手法です。

しかし一方で、APIが増加し、フロントエンド開発が複雑化するといった課題が発生します。

![micro-service.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/879861/d0de40e9-b864-cb9a-d2c4-1102d4503c0e.png)

### 2.デバイス・プラットフォームの多様化
スマートフォンやタブレット端末に普及により、様々なデバイスでWebアプリケーションを利用することが一般的になっています。このような状況下では、それぞれのデバイスに最適なUI/UXを提供する必要が出てきました。

BFFアーキテクチャー利用することで、デバイスごとに最適化されたAPIを提供することで、デバイス・プラットフォームの多様化に対応することができます。

### 3.フロントエンド開発の進化
ReactやVue.jsなどのJavaScriptフレームワークの登場により、フロントエンド開発が大きく進化しました。これらのフレームワークを用いることで、複雑なUI/UXを容易に実装することができます。

しかし、フロントエンド開発が進化する一方で、バックエンドとの連携が複雑化するといった課題も発生しています。BFFアーキテクチャーは、フロントエンドとバックエンドを分離することで、こうした課題を解決することが可能となります。

## BFFのメリット・デメリット
### メリット
- **フロントエンドとバックエンドの分離による開発・保守の容易化**
BFFアーキテクチャでは、フロントエンドとバックエンドを分離することで、それぞれの開発・保守を容易にすることができます。
それぞれの担当者が独立して開発を進めることができるため、開発効率が向上します。
- **デバイスごとに最適化されたAPIの提供**
デバイスごとに最適化されたAPIを提供することで、それぞれのデバイスで快適なユーザー体験を提供することができます。
- **スケーラビリティの向上**
特定のデバイスの利用者が急増した場合、そのデバイス向けのBFFレイヤーのみをスケールアップすることができます。

### デメリット
- **開発・運用コストの増加**
BFFアーキテクチャでは、フロントエンドごとにBFFレイヤーを開発・運用する必要があるため、開発・運用コストが増加します。
- **オーバーアーキテクチャのリスク**
BFFアーキテクチャを過剰に導入すると、オーバーアーキテクチャになりやすいというリスクがあります。
オーバーアーキテクチャとは、必要以上にシステムを複雑化させてしまい、かえって開発・保守が困難になってしまう状態です。
- **テストの複雑化**
BFFアーキテクチャでは、フロントエンドとBFFレイヤー、BFFレイヤーとバックエンドの3つのレイヤー間でテストを行う必要があるため、テストが複雑化します。
添付ファイルでのファイルサイズ上限（10M）チェックについて

VisualforceのApex:InputFileを利用してファイルをアップロードする際に、
添付可能なファイルサイズは10Mまでとなる。

Apex側でContentVersionなどで、クライアントからのファイルを受け取ると自動的にサイズをチェックし、下記のエラーメッセージを設定してくれるが（エラーメッセージを設定してくれるのみ）、勝手にエラー画面に遷移するなどはしていない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159211/9e0be88f-4ef5-9feb-4e4c-432f7f6f7601.png)

なので、保存処理などで入力チェックなどを実装する時に、実装を間違えるとファイルサイズチェックがうまくできなくなってしまうので下記のようにコードを追加してあげるとよい。

```Java
if (ApexPages.getMessages().size() > 0) {
    return null;
}
```
react-modalからの警告`Warning: react-modal: App element is not defined.`を解決する

#　はじめに

Next.js+react-modalを使用してモーダルコンポーネントを作成しましたが、題名にある通り警告のメッセージが表示されました。
全文は以下のとおりです。

```error
Warning: react-modal: App element is not defined. Please use `Modal.setAppElement(el)` or set `appElement={el}`. This is needed so screen readers don't see main content when modal is opened. It is not recommended, but you can opt-out by setting `ariaHideApp={false}`. 
```

# やったこと
## 1. (非推奨) `ariaHideApp={false}`を追加

    警告メッセージにある通り非推奨らしいです。
    モーダルコンポーネントを作成して、`page.tsx`にimportして使う場合はこの方法が良さげです。（私が良い書き方をわかっていないだけかもしれませんが...）
    ```page.tsx
    <Modal 
        isOpen={modalIsOpen}
        onRequestClose={closeModal}
        ariaHideApp={false}
        contentLabel="AlertModal"
        >
        (中略)
    </Modal>
    ```


## 2. `Modal.setAppElement`を使用する

    ```page.tsx
    Modal.setAppElement(".hogehoge")
    const Page=()=>{
        return(
            <div className="hogehoge">
                <Modal isOpen={modalIsOpen}
                onRequestClose={closeModal}
                ariaHideApp={false}
                contentLabel="AlertModal"
                >
                (中略)
                </Modal>
            </div>
        );
    }
    ```

警告メッセージにある通り、setAppElementを使用しました。
Modalの親コンポーネントの`className`を`setAppElement`で指定します。
このとき、先頭に`.`をつけていないと以下のエラーメッセージが出て画面が真っ白になります。

```
Error: react-modal: No elements were found for selector ModalPage.
```


# 作業リポジトリ

https://github.com/IamSBStakumi/ReactComponentTests/tree/fix_modal_confirm
【リハビリJS学習】瞑想アプリを作る④

JS学習のため、瞑想アプリ作成をする第四回。

↓前回はこちら

https://qiita.com/sakuc47/items/c4f1b36715e4a11f6ffc

記載してなかったのですが、参考にしているYoutube動画は外国語なので、字幕を見つつChatGPTで解説を読みながら制作しています！
YouTubeの翻訳はけっこうゆるいのでわかりにくい部分は多々あったのですが、
日本語の動画を見る時よりも
- 自分で調べる意欲がわく（調べないと何もわからない😺）
- 英単語を調べるとjsのプロパティの意味もわかるようになる

と、学びになる面が多いように感じました。

### 15.jsを書いていく
動画から読み取れたこと、調べたことはコメントアウトに記載しています。

``` js
// 
const app = () => {
  const song = document.querySelector('.song');
  const play = document.querySelector('.play');

  // 再生ボタンのアウトラインをアニメーション化
  const outline = document.querySelector('.moving-outline circle');
  const video = document.querySelector('.vid-container video');
  // サウンドを選択 全てのボタンを取得したいのでquerySelectorAll
  const sounds = document.querySelectorAll('.sound-picker button');
  // 時間表示
  const timeDisplay =document.querySelector('.time-display');
  // 再生ボタンの輪郭の長さを取得
  const outlineLength = outline.getTotalLength();
  // 継続時間（実際には曲全体の長さを取得するのではないので fake とする
  let fakeDuration = 600;

  /* アニメーション化 */
  // stroke-dasharrayとstroke-dashoffsetを取得し、
  // それらのプロパティをアニメーション化してゼロから開始しているように見せる

  outline.style.strokeDasharray = outlineLength;
  outline.style.strokeDashoffset = outlineLength;

  // 音楽を再生
  play.addEventListener('click', () => {
    // song.play();
    checkPlaying(song);
  });

  // 音楽の再生＆停止を切り替えるボタン
  // 曲が再生されているか停止されているかを判別して、
  const checkPlaying = song => {
    // もし曲が停止されている場合は曲・ビデオを再生して
    if (song.paused) {
      song.play();
      video.play();
      play.src = './svg/pause.svg';
    } else {
      song.pause();
      video.pause();
      play.src = './svg/play.svg';
    }
  }

  /* サークルをアニメーション化して時間がわかるようにする */
  // 曲の現在の時間を取得できる
  song.ontimeupdate = () => {
    // 再生ボタンを押すと、曲が続くかぎり更新され続ける
    // 曲が停止すると止まる
    // ゼロからはじまる
    let currentTime = song.currentTime;
    // 曲の経過時間を取得する（残りの再生時間）
    let elapsed = fakeDuration - currentTime;
    // %:左辺を右辺で割った余りを計算する演算子
    // 現在の再生位置から次の60秒までの残り時間（秒単位）
    // Math.floor：小数点以下を切り捨て
    let seconds = Math.floor(elapsed % 60);
    // 現在の再生位置から次に60秒までの残り時間（分単位）
    let minutes = Math.floor(elapsed / 60);

    // プログレスバーをアニメーション化する
    let progress = outlineLength - (currentTime / fakeDuration) * outlineLength;
    outline.style.strokeDashoffset = progress;
  }
};

  //
app();
```

再生ボタンを押すとムービーとサウンドが流れ、枠線のアニメーションが動くようになりました👏
![B.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524465/c62fa886-6db9-d125-cb57-caf7eb6fd32f.gif)


https://developer.mozilla.org/ja/docs/Web/API/HTMLMediaElement/timeupdate_event


もう少し続きます！
nodebrewでnodeをいれようとするとError: Darwin arm64 is not supported.エラー

Node.jsのv2.0.0をnodebrewでインストール
```
 nodebrew install v2.0.0
```

 すると、
```
 Error: Darwin arm64 is not supported. at /Users/name/.nodebrew/current/bin/nodebrew line 743.
```


エラーメッセージ "Error: Darwin arm64 is not supported." は、nodebrewがM1チップ (ARM64アーキテクチャ)向けのNode.jsバージョンをサポートしていないことを示しています。Node.jsのARM64向けサポートは、比較的新しいため、すべてのバージョンで確実に動作するわけではありません。


## 方法1: Rosetta 2を使用してx86版Node.jsをインストール
```
softwareupdate --install-rosetta
```

nodebrewでx86版Node.jsをインストール:
```
arch -x86_64 nodebrew nstall v2.0.0
```

で解決しました。終わったら
```
nodebrew ls
```
で確認してみてください。
AWS SAA 勉強方法（参考までに...）


AWS SAA に合格したので勉強方法を共有します。

自分自身、Qiita を含む色々な方の勉強方法の記事を読み参考になりました。

この記事も誰かの SAA 勉強の参考になれば幸いです。

# 受験前のレベル
AWS 初心者と言った感じです。
#### 1年前に CLF に合格
今回の受験においてアドバンテージになったとは思っていません。
（CLF に合格したことにより、バウチャーコードがもらえていて、1年越しに利用して受験料が 10,000 円引きにはなりました...）

#### [「Amazon Web Services基礎からのネットワーク＆サーバー構築改訂４版」](https://amzn.asia/d/08YSNpu1)を読了
AWS 未経験の方にお勧めの書籍です。ハンズオン形式の書籍なので理解しやすいです。
経験者の方だと情報量が少なすぎて正直物足りないと思われます。あくまで未経験向けかなと...

自分は 1週間ないくらいで読み終えました。
そこまでページ数も多くないのでとっつきやすかったです。
サブネットの概念もこちらの書籍でちゃんと理解できました。

受験前のレベルとしてはこんな感じです。

# 学習に利用したサービス・資料
インプットには Udemy, アウトプットには CloudTech,公式の問題集を利用しました
#### 【SAA-C03版】これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座

https://www.udemy.com/course/aws-associate/?couponCode=ST18MT62524

SAA で出題される主要なサービスを網羅的に説明していました。
セールで購入するとめちゃくちゃコスパがいいです。

量がかなり多いのでこの教材を利用する場合は
* 倍速で視聴する
* 特定のハンズオンは飛ばす

などしてもよいかなと思います。

すべて終えるのに 1ヶ月半ないくらいかかりました。（1日だいたい 1h ~ 2h くらい使用）

模擬試験が３つついており（基本レベル１つ、本番レベルが２つ）受験日の3日前から手をつけて2周しました。

#### CloudTech

https://kws-cloud-tech.com/

資格会員に登録し、主に問題演習に利用しました。


#### [AWS Certified Solutions Architect - Associate (SAA-C03) 試験問題サンプル](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-sa-assoc/AWS-Certified-Solutions-Architect-Associate_Sample-Questions.pdf)
無料だったので問題演習に利用しました。

#### [**AWS Certified Solutions Architect - Associate 公式練習問題集**](https://explore.skillbuilder.aws/learn/course/external/view/elearning/13269/aws-certified-solutions-architect-associate-official-practice-question-set-saa-c03-japanese?saa=sec&sec=prep)
こちらも無料だったので問題演習に利用しました。

 

# 勉強方法

自分が実際に行った勉強記録です。

### 学習期間 : 2ヶ月弱
2ヶ月と1週間ほど（4/18 ~ 6/23）かけて勉強していました。

資格勉強しなかった日もあったり、非効率な部分もあるはずなので勉強方法は参考までに…

### 0 ~ 1ヶ月半 : [ SAA-C03版】これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座 ](https://www.udemy.com/course/aws-associate/?couponCode=ST18MT62524) で学習
1日だいたい 1h ~ 2h くらいで進めていました。（もうちょっと時間使ってたかもです！）

もう少し工夫して1ヶ月くらいで終われたと思います。
サービスの細かい設定などを覚えようとせず、ざっくりこういうサービスがあるんだな、こういうことが AWS でできるんだなくらいでよいと思います。

（後から講座を見返すと、AWS の主要なサービスの説明とハンズオンがついていて、資格の勉強の目的としてだけではなく AWS を純粋に勉強できる教材としてもすごくよいものだなと個人的に思いました）

### 1ヶ月半 ~ 試験前

CloudTech の問題をひたすら解く

 [ SAA-C03版】これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座 ](https://www.udemy.com/course/aws-associate/?couponCode=ST18MT62524) の模擬試験を解く

CloudTech は 1 周半（後半（110 ~ 220問）は2 周しました）、Udemy は模擬試験を全て 2 周しました

### 自分でサービスをまとめる

問題を解いていた 1ヶ月半 ~ 試験前の期間、 Notion に AWS サービス一覧ページを作り、間違えた問題に関する AWS サービスの機能や設定をメモしていました。


### ChatGPT の利用
ChatGPT を利用して以下のような質問をして理解を深めてもいました。

例「サービス A とサービス B の概要と利用されるユースケースそれぞれを教えてください。また、サービス A とサービス B の違いを教えてください。」

これでどのサービスをどの場合に利用すればいいのかの理解を深めていました。

# 最後に
資格が取得できたからといって AWS にものすごく強くなったかと言われるとまだまだなので、これからも AWS 学習を続けていきます。
ts-patternで同じ結果の場合分けがしたい

## はじめに
題名通りts-patternで同じ結果の場合分けがしたい時の方法です。

## 対応方法
`P`を活用しましょう！

```typescript
import { P, match } from "ts-pattern";

type Group = "A" | "B" | "C";

const groupResult = (group: Group): string => {
  return match(group)
    .with("A", () => "GroupA")
    .with(P.union("B", "C"), () => "other Group")
    .exhaustive();
}
```

## さいごに
これで同じものを２パターン書く必要ありませんね〜
Notionでの文字装飾・コンテンツ区切りの小ネタ集

# はじめに
この記事では、Notionの公式で出している機能+αで
私が日常でドキュメントを書くときに使っている
「文字装飾」と「コンテンツの区切り」
の小ネタと言われるものをまとめていこうと思っています。

Notionの基本的な機能については公式ドキュメントをご確認ください！
https://www.notion.so/ja-jp/help

# 文字装飾編
テキストに対していろんな装飾ができると思います。
背景を塗る・テキストに色をつける・太字・斜字・斜線etc...
それら+αの小ネタについて書いていきます。

## 背景もテキストもカラフルに
Notionだと行選択の場合背景orテキストのどちらかしか着色できません。

![スクリーンショット 2024-06-25 22.03.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039645/7909c845-c8d6-986e-33bb-94ce7b9997e8.png)

なので、私は行全体では「背景」を着色し、その後テキスト部分のみを選択して文字の色を選んでいます。
そうすると両方カラーにできちゃう。

![スクリーンショット 2024-06-25 22.03.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039645/2e323bab-c63b-8b76-f026-a142cc029e4f.png)

ちょっとめんどくさいけど、1文字ずつ背景色orテキストの色変えるのも可愛いです。
（ただし、1文字ずつやるので長い文字の時はかなりめんどくさいです....）

![スクリーンショット 2024-06-25 22.05.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039645/6ffbaf73-21da-7f8a-5dc8-832933f16e47.png)

## 古の技
実際に見ていただければわかると思いますが、テキストの前後を記号で囲ったりしてみます。
（mmoゲームのユーザーネームとかでよく見るアレですね）
これが意外とアクセントになって可愛い。個人的には↓が好きかなという感じです。
![スクリーンショット 2024-06-25 22.21.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039645/e736431e-d503-0975-19fa-cc685a5870d4.png)

+で下線とか引いちゃってもいい感じに見える。好き。
![スクリーンショット 2024-06-25 22.27.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039645/ef25f50b-c282-3045-e4a0-5a38aa914912.png)


一応元テキストも残しておきます。
 +ﾟ*｡:ﾟ+◆ テキスト ◆+ﾟ:｡*ﾟ+
 
 ★━━‥・テキスト・‥━━★
 
 ◆°◈ テキスト ◈°◆
 
 ○ 。◕ テキスト ◕ 。○

# コンテンツ区切り編
Notionではコンテンツの区切りをわかりやすくするために「区切り線」という機能があります。
ただ、↓のような区切り線で本当に区切ってくれるだけなのでもうちょっと可愛くしたい....

![スクリーンショット 2024-06-25 21.39.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039645/8ba221fc-cb8f-b243-ac17-6ebee42767d2.png)

ということでこちらも+αの小ネタを書いていきます。

## 背景色あり行
通常テキストの行の背景色を塗って区切り線の代わりにしちゃいます。
ちょっと太いけどいいアクセントになるのでおすすめです。

![スクリーンショット 2024-06-25 22.05.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039645/4fe5a825-0fd9-c40c-4b60-2ebfc4522957.png)

区切り線で背景色ありの行を挟んだりしてみても結構可愛い

![スクリーンショット 2024-06-25 22.06.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039645/02d69b40-6bbd-8118-8398-2cc24ca1ecc3.png)


## 画像
細長い画像を準備して区切り線にしちゃいます。丸並べただけとか、点線とかだけでも全然可愛い。

![スクリーンショット 2024-06-25 22.14.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039645/b3d52d3c-497f-153b-889a-a4738d94f177.png)

個人利用であれば好きな作品をくり抜いて使うのも満足度が高いかなと思います。
商用利用可能なものもあると思うので「商用利用可　ラベル」みたいな感じで検索してみても
いいものが見つかるかもしれないです。

## 古の技(パート2)
俗にいう弾幕というものを利用します。
「弾幕　コピペ」とかで調べるといい感じのものが見つかると思います。
個人的には↓が使っていて、可愛いなと思いました。
![スクリーンショット 2024-06-25 22.32.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039645/9d06f37b-1de9-7886-e796-f2d766c0608b.png)
【SwiftData】基本的な構成と使い方 まとめ

サラッと書いておきます。

# 🧑🏻‍💻 手順

1. Scheme (```@Model```) と ModelConfiguration を作成する。

2. それらを使って ModelContainer を作成する。

3. それを使って extension View を作成する。

4. それを View にセットする。

# 🧑🏻‍💻 構成

図で。

![sc 2024-06-25 at 22.24.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588914/22558837-8afa-4437-aef5-64e66a7b1496.png)


# 🧑🏻‍💻 参考

https://android.benigumo.com/20240122/modelcontainer/
C_TS422_2021 SAP Certified Application Associate SAP S/4HANA Production Planning and Manufacturing対策（17/100）

【17日目】
トピック 3：SAPS/4HANAのマスタデータ（6/22）

≪問題17≫
部品表/配合表（BOM）の副明細には、どのようなデータを保持できますか。
（２つ選択）
□設置ポイント
□数量
□不良率（%）
□明細タイプ

≪解答≫
■設置ポイント
■数量
□不良率（%）
□明細タイプ

≪解説≫
◆副明細は、明細の一部数量に関する異なる設置ポイントを表します。副明細数量の合計は、明細数量に代わるものとなります。
◆なお、副明細にはBOMの管理機能がないため、実行できる操作は以下のように限られます。
（1）作業の割当（明細レベルのみ）
（2）廃棄物の計算（明細レベルのみ）
2024 年の生成 AI: 業界全体にわたるイノベーションと影響

![Generative AI the brainy insights.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3824041/ab12206f-d159-acb8-2c6c-a0f5235529d0.png)

世界の生成 AI 市場は、2022 年の 86.5 億ドルから 2032 年までに 1,886.2 億ドルに成長すると予想されています
Google は Gemini モデルを導入し、検索機能を大幅にアップグレードしました。このモデルは、高度な推論、計画、マルチモーダル入力をサポートし、より包括的でコンテキスト認識型の検索結果を可能にします。Gemini が提供する機能である AI 概要は、簡単な概要と詳細情報を提供し、さまざまな Web コンテンツに対するユーザーの満足度とエンゲージメントを高めます。

https://www.thebrainyinsights.com/report/generative-ai-market-13297
Azure: Cosmos DB への アクセス権追加を powershell で

# 背景

CosmosDB を local から使うときに、自分自身のアクセス権を使いたかった際のメモ

# 結論

以下 Powershell を組み込めば OK

やってることは
1. サインインユーザーの ID を取得
1. Cosmos DB で Role を作成
1. 対象 ROle を サインインユーザーに割り当て

```powershell: 

# サインインユーザーの情報を取得
$userInfo = az ad signed-in-user show --query "{id: id, displayName: displayName}" --output json | ConvertFrom-Json

Write-Host ("あなたは " + $userInfo.displayName + ", + " + $userInfo.id)

# ロール 作成
$roleId = az cosmosdb sql role definition create --account-name {cosmos account} --resource-group {resource group} --body ./scripts/cosmosreadwriterole.json --output tsv --query id

# 対象ロールの割り当て
az cosmosdb sql role assignment create --account-name {cosmos account} --resource-group {resource group} --scope / --principal-id $userInfo.id --role-definition-id $roleId
```

# 関連

組み込みの Read, Read/Write Role 使うなら以下

https://learn.microsoft.com/ja-jp/azure/cosmos-db/how-to-setup-rbac#built-in-role-definitions

上のロールを設定した記録は以下

https://qiita.com/baku2san/items/85714f90c094cebedb44

# あとがき

provision する際に一緒に設定するなら、azure.yaml にて呼び出せばOK
その場合は、環境変数で Resource Group とかは置き換える感じか
networkxで隣接行列からグラフを作成し描画する！

## はじめに
日本語情報が見当たらなかったので，備忘録としてメモします．

## 環境
* Python 3.11
* numpy 1.24
* networkx 3.1

## 方法

```Python
import numpy as np
import networkx as nx

# 隣接行列
A = np.array([
    [0, 1, 0, 1, 1],
    [1, 0, 1, 0, 1],
    [0, 1, 0, 0, 1],
    [1, 0, 0, 0, 1],
    [1, 1, 1, 1, 0]
])

# グラフオブジェクトの生成
G = nx.Graph(A)

# 描画
nx.draw(G)
```
下図のような図が得られる．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642842/caca4e78-0b7e-ae35-d805-fd05cd7baf6e.png)

## Appendix
ちなみに，接続行列から直接グラフを生成する方法は存在しない．
そこで，次式を用いることで隣接行列を求めて，グラフを作成すればよい．

$$
\begin{align}
B^\top B &= D - A \\\\
B^{\prime\top} B^\prime &= D + A 
\end{align}
$$
$B$は有向接続行列，$B^\prime$は無向接続行列，$D$は次数行列，$A$は隣接行列である．

以下に例を示す．

```Python
# 無向接続行列
B2 = np.array([
    [1,1,0,0,0],
    [0,1,1,0,0],
    [0,0,1,1,0],
    [1,0,0,1,0],
    [0,1,0,0,1],
    [0,0,1,0,1],
    [0,0,0,1,1],
    [1,0,0,0,1]
])

temp = B2.T@B2 # D + A 
D = np.diag(np.diag(temp))
A = temp - D # D + A - D = A

G = nx.Graph(A)
nx.draw(G)
```
以下の図が得られる．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642842/32bd8fea-ae19-499f-9fa4-8a0c29e92c4b.png)

## 参考文献
* 公式ドキュメント :  https://networkx.org/documentation/stable/reference/convert.html#id1
Nibbles で Welcome to AtCoder を解いてみた

[Qiita Engineer Festa 2024（キータ・エンジニア・フェスタ 2024） - Qiita](https://qiita.com/official-campaigns/engineer-festa/2024)
において、約1ヶ月で38記事という大量の記事の投稿を要求されることがわかった。
そこで、あまりコストをかけずに記事数を稼ぐ方法を考えた結果、「Welcome to AtCoder を様々な言語で解く」ことを思いついた。
単に解くだけでなく、使用する言語仕様の解説を入れれば、記事として一応成立するだろう。

# Welcome to AtCoder

[PracticeA - Welcome to AtCoder](https://atcoder.jp/contests/abs/tasks/practice_1)

Welcome to AtCoder では、以下の形式で整数 $a$, $b$, $c$ および文字列 $s$ が入力として与えられる。

```text
a
b c
s
```

この入力をもとに、与えられた整数の和 $sum = a + b + c$ および文字列 $s$ を、以下の形式で出力することが求められる。

```text
sum s
```

# 今回用いた Nibbles の機能

[競プロの問題をnibblesで解く① #AtCoder - Qiita](https://qiita.com/i_taku_/items/e85f9f4ea482e35dfadd)
[Nibbles Quick Ref](http://www.golfscript.com/nibbles/quickref.html)

Nibbles では、計算を行うと、その結果が自動で出力される。
行う計算の内容は、以下の演算子などを用いて記述できる。
(ここでは今回用いたもののみを紹介する)

|演算子など|意味|
|:-:|---|
|`= 位置 列`|「列」の「位置」番目 (1-origin) の要素を得る|
|`: 列1 列2`|「列1」と「列2」を接合した列を得る|
|`+ 列`|「列」に含まれる数値の合計を求める|
|`. 列 関数`|「列」の各要素にそれぞれ「関数」を適用した結果の列を求める|
|`% 対象 区切り`|「対象」の文字列を「区切り」の文字列で区切った列を求める|
|`` `r 文字列 ``|「文字列」をそれが表す数値に変換する|
|`3`|数値|
|`" "`|文字列|
|`$`|関数の第1引数|
|`@`|入力の最初の行 (文字列)|
|`;;@`|入力の2番目の行 (文字列)|
|`;@`|入力の各行 (文字列の列)|

# 提出コード

```
:+.:@%;;@" "`r$:" "=3;@
```

[提出 #54929212 - AtCoder Beginners Selection](https://atcoder.jp/contests/abs/submissions/54929212)

# 提出コードの解説

「最初の行」と「2番目の行を分割したもの」を連結して数値に変換し、和を求める。
その結果と、空白および3行目を連結し、出力する。

プログラムの構造は以下のようになっている。

![プログラムの構造](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/45d439fd-a0ee-df3b-a9b2-397acb06c68b.png)
C_TS4FI_2021 SAP Certified Associate - SAP S/4HANA 2021 for Financial Accounting対策（4/100）

【4日目】
トピック 1：組織割当およびプロセス統合（4/15）

≪問題4≫
財務会計伝票番号範囲に関する正しい説明は次のどの文ですか。
正しい答えを3つ選択してください。
□財務会計伝票番号範囲は、それが使用される会計年度に対して定義する必要がある。
□財務会計伝票番号範囲には数字と文字を混在させることができる。
□クライアントレベルで定義された財務会計伝票番号範囲は、重複してはならない。
□財務会計伝票番号範囲は、会社コードレベルでのみ定義される。
□同じ財務会計伝票番号範囲を複数の伝票タイプに割り当てることができる。

≪解答≫
■財務会計伝票番号範囲は、それが使用される会計年度に対して定義する必要がある。
□財務会計伝票番号範囲には数字と文字を混在させることができる。
□クライアントレベルで定義された財務会計伝票番号範囲は、重複してはならない。
■財務会計伝票番号範囲は、会社コードレベルでのみ定義される。
■同じ財務会計伝票番号範囲を複数の伝票タイプに割り当てることができる。

≪解説≫
◆各選択肢に対する正誤判定は以下のとおりです。
選択肢1 →〇
複数の会計年度をまたがる継続的な伝票番号の場合は、複数の会計年度に対して1つの伝票番号範囲を定義しますが、「それを使用する会計年度に対して定義する」には、この複数会計年度も含まれます。
選択肢2 →×
番号範囲（開始番号と終了番号）には、外部採番であっても、文字（英字）か数字のいずれか一方だけを使用することができます。
選択肢3 →×
伝票番号範囲はクライアントレベルではなく、会社コードレベルで定義されます。また、同一会社コードおよび同一会計年度に対して、重複してはなりません。
選択肢4 →〇
伝票番号範囲は会社コードレベルで定義されます。
選択肢5 →〇
同じ伝票番号範囲を複数の伝票タイプに割り当てることができます。
S3とLambda、SESを用いてお問合せフォームを作成した話 ３

実は２回で終える予定だったのですが、AWS SUMMITに行った際、AWSのサポーターの方から、「API Gateway使わなくても直接Lambdaの関数たたけるよ^^」と教えていただいたため、確かめることに...

前回までの記事はこちら

https://qiita.com/sakura11054/items/0b5e8603d6d4f92ac746

https://qiita.com/sakura11054/items/a29741cf124ba315d892

https://qiita.com/sakura11054/items/47bba94339cb62f037ef

https://qiita.com/sakura11054/items/678a3b45807999f63b75

# Lambdaの設定

Lambda側の設定は単純です！
前回までで作成したLambda関数を開きます。
設定タブを開くと画像のように関数URLとあるのでこれを開きます。
現状、関数URLなしと表示されているので、関数URLを作成を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/c88dca4f-8ea3-7d8b-6160-dadf698ccd75.png)

認証タイプはNONEを選択します。
NONEの場合、認証なしで関数を使用できてしまうのでセキュリティ上よろしくないです！
今回は公開する予定がなく、関数事態も単にメールを送るだけのシンプルな関数なのでNONEを設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/aa54625f-4a10-aef8-d923-d9c14fec47f9.png)


続いてその他の設定を押下し、CORSを有効化させます。
今回はそれ以外をデフォルトに設定し、保存を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/dc7bdefa-0f86-7f5d-b867-a6b7c70de620.png)

保存完了後、再び関数URLのタブを開きます。
すると、LambdaにアクセスするためのURLが生成されています。
このURLをJSに書き込みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/2fb3f751-79a2-961b-a7d2-afbf490b8252.png)

# S3のJavaScriptを更新

前回、S3置いたJavaScriptのコード編集して再度アップロードします。
変更箇所は以前API Gatewayのエンドポイントを記入していた場所にLambdaのURLを記入します。
この後、フォームから送信ボタンを押下してメールが届けば成功です。

```Javascript:sender.js
document.getElementById('contactForm').addEventListener('submit', function(event) {
    event.preventDefault();
    
    var formData = {
        name: event.target.name.value,
        email: event.target.email.value,
        message: event.target.message.value
    };

    fetch('YOUR_LAMBDA_URL', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(formData)
    })
    .then(response => response.json())
    .then(data => {
        console.log('Success:', data);
        alert('メッセージが送信されました');
    })
    .catch((error) => {
        console.error('Error:', error);
        alert('メッセージの送信に失敗しました');
    });
});
```

# 感想

S3、LambdaとSESだけでお問い合わせフォームを作成することができました。
今まで、API Gatewayや他の機能を使う必要があると思って今したが、Lambda単体でできるのはシンプルでいいですね！
しかも、関数作成はLambdaの費用に含まれているのでURL作成は**無料**の範囲で行うことができます。
ただし、今回は機能としても認証なしで行えましたが、機能によっては認証が必須になるので、用途は選ぶ必要ありますね！
【TypeScript】知識を一段上げる。Template Literal Typesと再帰的な型を理解する

TypeScriptには「Template Literal Types」と「再帰的な型」というものが存在することを知りました。

:::note
そもそもなんなのか？どうやって使うのか？調べていきたいと思います！
:::

## Template Literal Types
「Template Literal Types」とは、文字列の型を柔軟に定義できる機能。

```typescript
type Greeting = "Hello";
type Name = "World" | "TypeScript";

type Message = `${Greeting}, ${Name}!`;

let message: Message = "Hello, World!";  // OK
let message2: Message = "Hello, TypeScript!";  // OK
let message3: Message = "Hello, JavaScript!";  // エラー
```

上記のようにすることで`Message`型は"Hello, World!"か"Hello, TypeScript!"しか受け付けない型になります。

「Template Literal Types」を簡単にまとめると…

- 文字列をベースにした型をつくる
- バッククォート(`)を使って、作った型を組み合わせて1つの型にする

### 複数の型を組み合わせる

```typescript
type Animal = "cat" | "dog";
type Action = "eat" | "sleep";

type AnimalAction = `The ${Animal} will ${Action}`;

let action: AnimalAction = "The cat will eat";  // OK
let action2: AnimalAction = "The dog will sleep";  // OK
let action3: AnimalAction = "The bird will fly";  // エラー
```

### Template Literal Typesの利点
- 文字列の形式を厳密に指定できるため、タイプミスや無効な値を防げる
- IDE[^IDE]で正しい文字列の候補を提示してくれる
- 型定義を見るだけで、許容される文字列の形式が明確になる

:::note
「Template Literal Types」は、文字列を扱う際の型安全性を向上させる機能です。特に、APIエンドポイント、イベント名、設定キーなど、特定の形式に従う文字列を扱う場合に非常に有用です！
:::

## 再帰的な型
再帰的な型とは、自分自身を定義の中で参照する型のこと。
これは複雑なデータ構造や階層構造を表現する際に非常に便利です！

:::note
自分自身を定義の中で参照する？は？
となったことをよく覚えています…具体的なコードで説明します！
:::

```typescript
type FileSystemItem = {
  name: string;
  failItem?: FileSystemItem[];  // 自身の型を参照
};

const myFileSystem: FileSystemItem = {
  name: "root",
  failItem: [
    {
      name: "documents",
      failItem: [
        { name: "report.doc" },
        { name: "invoice.pdf" }
      ]
    },
    {
      name: "images",
      failItem: [
        { name: "photo.jpg" },
        { name: "screenshot.png" }
      ]
    }
  ]
};
```

### 再帰的な型の利点

- 階層構造やグラフ構造など、複雑なデータ構造を簡潔に表現できる
- 深くネストされた構造でも型チェックが可能
- データの深さや複雑さに制限を設けずに型を定義できる

### 再帰的な型の注意点

再帰的な型を使用する際は、必ず停止条件（再帰を終了する条件）を設けることが重要です。
型チェッカーが無限ループに陥る可能性があるためです…。

:::note warn
非常に深いネストや複雑な構造の場合、型推論や型チェックに時間がかかります
:::

再帰的な型は、ツリー構造、グラフ構造、またはネストされたオブジェクトを扱う場合に有用です！

## まとめ
「Template Literal Types」と「再帰的な型」を上手く利用することで型安全で理解しやすいコードを書くことが可能になるのではないかと思います！
使い所だけでも覚えて型定義する際の選択肢としていただければ幸いです！

[^IDE]:Integrated Development Environment（統合開発環境）の略で、ソフトウェア開発に必要な様々なツールを一つにまとめたものです。 例えば、コードを書くエディタやコンパイラ、デバッガ、テストツール、バージョン管理ソフトなどがIDEに含まれます。
SourceTree: 特定のコミットのファイル一覧をクリップボードにコピペ

# 背景

特定のコミットにおけるファイル差分を把握したかった時に、
そのファイル一覧が欲しかったので調べた記録

# 結論

以下を bat ファイルを用意して、カスタム操作に割り当てるだけ

```bat: コミットファイル一覧の取得
@echo off

git diff-tree --no-commit-id --name-only -r "%1" | clip
```



## カスタム操作について

https://confluence.atlassian.com/sourcetreekb/using-git-in-custom-actions-785323500.html

# あとがき

カスタム操作って滅多に使いたくなる時があるわけじゃないけど、やっぱり便利ですな

こうやって残していくと、いつか役立つ時が来る :thinking:
Salesforce 認定Marketing Cloudアドミニストレーターを受けたときの感想



本橋孝昭です

Salesforce資格についてよく「どうやって勉強しましたか」と聞かれるので
認定Marketing Cloudアドミニストレーター合格の方法を記載します


とはいえ、2024年6月時点でこれを記載してますが、資格取得は2021年12月なのでたいして覚えていない（ごめんなさい）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/4131a788-47a8-efc9-854f-9c2f5a201012.png)


## なぜSalesforce 認定Marketing Cloudアドミニストレーターを受けたか？

今でもはっきり覚えている記憶としてSalesforce Certification Daysにはじめて（今考えれば最初で最後？）Salesforce 認定Marketing Cloudアドミニストレーターが登場したからです

しかもなんと当時は70％割引のクーポン付もありました


当時の内容がこちら

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/37d97f21-1c21-0254-534e-d536b3b89a5e.png)


https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000JdssLSAR

これを見て
・なんだSalesforce 認定Marketing Cloudアドミニストレーター　というのがあるのか
・とりあえず70%割引で試験を受けられるクーポンコードがあるので欲しいな
と思い申し込んだような記憶があります


結果的に手元に70%割引で試験を受けられるクーポンコードがあったので「じゃあとりあえず試験受けるか」と思って試験を受けたらSalesforce Certification Daysの内容が大変役に立った　という話です


残念ながらこれ以来Salesforce 認定Marketing CloudアドミニストレーターはSalesforce Certification Daysには登場していない認識です（2024年6月現在）
また、今はSalesforce Certification Daysに出ても割引コードがもらえないですね。とても残念ですね



## 今勉強するにはどうすればいいか？

今勉強するにはこちらのTrailheadの練習問題を解くか

https://trailhead.salesforce.com/ja/content/learn/trails/study-for-the-marketing-cloud-administrator-exam?trailmix_creator_id=welcome4&trailmix_slug=certified-marketing-cloud-administrator-ja


Salesforce社が定期的に開催している有料セミナーでの勉強が早そうですね

Salesforce Certification DaysでまたSalesforce 認定Marketing Cloudアドミニストレーターが開催されるといいですね。
tabcmdを利用して、Tableau Cloudのグループにユーザを一括登録してみた

## 前提
・Tabcmd実行マシンは、Windows OSを前提にしております。
・Tableau Cloud上に、グループとユーザを既に作成済み。
## 参考サイト
https://help.tableau.com/current/online/ja-jp/tabcmd.htm

https://github.com/tableau/tabcmd/releases

https://help.tableau.com/current/online/ja-jp/security_personal_access_tokens.htm

## 手順
### 1.Tabcmdのインストール
#### ①以下のサイトから、Tabcmdをダウンロード
・Windows OSの場合：tabcmd.exe
・mac OSの場合：tabcmd-mac.zip

https://github.com/tableau/tabcmd/releases

#### ②Tabcmdをインストール
ダウンロードしたtabcmd.exeをダブルクリックして、インストール
インストール先など変更の場合は、以下のヘルプをご参照ください。

https://help.tableau.com/current/online/ja-jp/tabcmd.htm
### 2.Tableau CloudのPATを作成
https://help.tableau.com/current/online/ja-jp/security_personal_access_tokens.htm
#### ①Tableau Cloudの右上のプロファイルアイコンをクリックし、「マイアカウントの設定」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562390/1d883033-f63d-8c00-90e2-a28c0c19a9a8.png)
#### ②個人用アクセストークンのトークン名を入力し、「トークンを作成する」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562390/c0941854-f678-ca14-e9a2-39ec24b1af05.png)
※表示されるシークレットは２度と表示されないため、メモしておく
### 3.Tabcmdより、Tableau Cloudへログイン
#### ①コマンドプロンプトを起動し、tabcmd.exeをインストールしたフォルダに移動
例：
```
C:\Users\testuser>cd Downloads
```
#### ②手順2で作成したPATを利用して、Tableau Cloudへログイン
例：(日本のPodではない場合は、-sのURLを変更してください。)
```
tabcmd login -s https://prod-apnortheast-a.online.tableau.com -t サイト名 --token-name トークン名 --token-value トークンシークレット
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562390/f998e57c-0c95-fd2d-f631-0522242ac646.png)
### 4.グループに一括登録するユーザのcsvを作成
・複数グループの場合は、グループの数分のcsvファイルが必要
・csvファイル内容：メールアドレスのみ
・csvファイルエンコード：utf-8
例：a.csv
```
a1@taro.com,a2@taro.com
```
b.csv
```
b1@taro.com,b2@taro.com
```
https://help.tableau.com/current/online/ja-jp/csvguidelines.htm
### 5.グループにユーザを一括登録するバッチを作成
tabcmd addusers ＜グループ名＞ --users ＜CSVファイル名＞
例：tabcmd_addgroup.bat
```
@echo off
cd "C:\Users\taro\Downloads"
tabcmd addusers a --users "C:\Users\taro\Downloads\addgroup\a.csv"
tabcmd addusers b --users "C:\Users\taro\Downloads\addgroup\b.csv"
```
### 6.5で作成したtabcmdバッチをダブルクリックし、実行
### 7.Tableau Cloudのグループ画面から各グループにユーザが追加されていることを確認

## 参考ブログ
https://note.com/hellion555/n/n3e5aed18842b