OmniAICreator/Qiita-1.07M huggingface dataset:
Export video

instantNeRFを2023年1月版に実装されたビデオ生成機能を試しました。
今回使用したgithubのSHA1は690e083でした。

:::note
業務外の個人的な検討活動です。
:::

#### テストデータ
sketchfabのNefertiti statueを使用させていただきました。ありがとうございます。

https://sketchfab.com/3d-models/nefertiti-statue-d148f771c3f44225b56cb7ce8d3c5ce6

#### instant-ngp.exe
GUIの実行ファイルは2022/12/20にtestbed.exeから名前が変わったようです。

#### testbed.cu
ソースコードを覗いていたところ、"Export video"というメニューを見つけました。
昨年末に確認していたtestbed.exeからはビデオ出力はできなかったので、instant-ngp.exeを実行して確認してみました。

![230128_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/6ca9fb85-2be2-4be5-a544-f751e4f2e147.png)

#### Export video
起動した時点ではメニューに現れませんでした。

![230128_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/12fbe2ae-9721-0cb1-8af5-15affaa06641.png)

カメラパスを設定し始めるとcamera pathウィンドウの下の方にメニューが追加されました。ウィンドウを広げないと見えませんでした。

![230128.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/01922667-a702-ae5a-6868-94b9b567df81.png)

この設定の場合、約1分でレンダリングが完了しました。

#### 比較　run.py

同じ条件のレンダリングをrun.pyから実行した場合は約2分かかりました。

```
(ngp) PS D:\git\instantNGP202301\instant-ngp>
python scripts\run.py --scene data\221214a  --load_snapshot data\221214a\base.ingp --video_fps 60 --video_n_seconds 5 --video_spp 1 --video_camera_path data\221214a\base_cam.json --video_output data\221214a\videoPy.mp4 --width 1920  --height 1080
```

#### spp
Export videoにあるsppはモーションブラーを再現するために複数の画像をまとめるらしいので、画像をブラーさせたくない場合やレンダリング時間を早めに終わらせて確認したい場合は1にした方がよいかもしれません。

>　ビデオをレンダリングする場合、モーションブラー用に複数の spp を蓄積したいと思います。したがって、ターゲット spp に達した時点でフレームをダンプし、_then_ のみリセットします。
（DeepLを使いました　https://www.deepl.com/translator）

![230128_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/ed033a02-ec29-9298-80b3-9ff29fc260cd.png)


#### 備考
githubのreadmeに書いてあるリンク先のyoutubeにはvideo exportのことを紹介していました。

<iframe width="560" height="315" src="https://www.youtube.com/embed/3TWxO1PftMc?start=428" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
神クラウドRDB、Cloudflare D1 を使い倒そう！

価格破壊で有名な Cloudflare 様が RDB サービスを公開してくれました。その名も「Cloudflare D1」
2023/01/28 現在オープンアルファだからということで、なんと**無料!**
意識高い方々が**神っぽいな神っぽいな**と評価のこのサービス、だけどぶっちゃけ**何が神なの？**
「**御託はいいから！**」ということで実力行使で神っぷりを満喫できるようにとデモを作りました。
せっかくのチャンス、みんなでこの神サービスを使い倒しましょう😆

:::note warn
アルファ版のため急な仕様変更で動作しなくなる可能性があります。
そのリスクを許容できる範囲でご利用ください。
:::

# デモ

||URL|
|--|--|
|デモ|https://kit-d1-proxy.pages.dev/|
|リポジトリ|https://github.com/dyn-do/kit-d1-proxy|
|説明|https://github.com/dyn-do/kit-d1-proxy/blob/main/README.ja.md|


### なにこれ？
Cloudflare D1 をブラウザの JS から直接操作できるようにする Web API のサーバーです。
コーディング一切無し、説明に沿って Github と Cloudflare の操作をするだけであなただけの SQL な Web API が作れます。
デモ画面では SQL を実行する fetch リクエストを生成したり、結果を確認したりできます。

クラウドメモやチャット、ランキングなど DB が必要な機能にご活用ください。
ソースは Sveltekit で作られています。

# D1 のここがすごい！

|スゴさ|説明|
|--|--|
|**SQL！**|FireStore や DynamoDB のような独自ルールJSONストアではなく汎用 SQL です。<br>単なるキーバーリューではなく集計ももちろん容易です。|
|**早い！**|ものすごく早いです！（語彙<br>要検証ですが、体感は FireStore 並み。比較対象として適正ではないかもですが、 Glitch で同じことしたら数秒は待たされる通信も1秒未満で結果を返してくれます。
|**シームレス連携！**|Cloudflare の Pages や Workers の Request 内に接続のインスタンスを埋め込んで渡してくれます。文章で説明すると長くなるので端折りますが、連携がとても楽|
|**リージョン設定不要！**|AWS や GCP のようにサーバーをどこにしようかと悩むこともありません。|

開発中なので細かく気になる点はあります。目立ったデメリットは下記が思いつきました。

|(悪し...)|説明|
|--|--|
|リモート操作ができない|SQLite にはサーバー機能がないため、MySQL や PosgresSQL のように別のサーバーから接続したり、DB ツールで内容をネット越しに確認したりすることが難しいです。<br>幸い有志で D1 用 の JDBC を作ってくれた方がいました。<br>[d1-jdbc-driver](https://github.com/isaac-mcfadyen/d1-jdbc-driver)<br>ですが説明に書かれている通りまだ課題があり未完成かな|
|SQLite のライブラリが直接使えない|中身が SQLite でも接続は SQLite ドライバを使用するわけではないため、SQLite で利用できるライブラリがそのまま使えるわけではありません。O/Rマッピングなどのライブラリは組み立てた SQL をいちど文字列で出力し、D1 の API に投げる、という工夫が必要になりそうです。|


# 無料枠の比較

アルファ版を無料というのは少々不適ですが、多くの方が気にされるのは **無料でどれだけ使えるの？** ではないでしょうか？
個人利用で有名な RDB サービスと比較です。
間違っていたらご指摘ください。

||Cloudflare D1|PlanetScale|Supabase|
|--|--|--|--|
|DB の種類|SQLite|MySQL|PostgreSQL|
|インスタンス数|10|1|2|
|インスタンス毎のサイズ|100MB|5GB|500MB|

こうやって見ると一長一短ですね
といってもポケモンみたいに「一つを選べ」ではないので、用途に応じて使い分ければよいですね。

# 総括
勢い任せに書きました。~~**今だけ無料に釣られただけじゃ**~~
所感としては他の DB サービスより**ハードルがとても低いです。**
気にする設定も画面操作も少ないため、気軽に Web アプリに組み込めるはずです。
まだ料金体系が発表されていませんが、Cloudflare さんならきっととっつきやすい価格にしてくれるでしょう（何様？

今でも十分便利ですが、開発中ということもありエコシステムがまだまだ未成熟です。
認知が広がってユーザー製ライブラリが充実したらより便利になると思いましたので、周知のために今回のデモを作りました
この記事を通じて Cloudflare D1 に興味を持っていただける方が増えたら、と期待しております。

### 最後にPGの話
2023/01/28 現在、アルファ版なのでしょうがないのですが、公式チュートリアル通りに書いても**まともに動きません**
ほかの人の記事見ると **本当に動いたの？** と疑うばかり😅
そのためデモのコードは**全然チュートリアル通りに書いてません**。
公式イシューの回避策を試したり、wrangler CLI のソースを見たり、ログ仕込んでデプロイ⇒インスタンスのクラスやメソッド名を出力⇒またログ仕込んでデプロイ、の繰り返しを何度もしたり……で今回のデモはできました

ですが、その結果 D1 の洗練された構造も理解できました。
裏技もありますのでまた時間あれば語ります～
小数点数の基本について調べた

これまでコンピュータ上での小数点数についてきちんと学んだことがなく、「浮動小数点数が小数を表す」くらいの理解しかしていなかった。
[プログラムはなぜ動くのか](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AF%E3%81%AA%E3%81%9C%E5%8B%95%E3%81%8F%E3%81%AE%E3%81%8B-%E7%AC%AC%EF%BC%92%E7%89%88-%E7%9F%A5%E3%81%A3%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E5%9F%BA%E7%A4%8E%E7%9F%A5%E8%AD%98-%E7%9F%A2%E6%B2%A2%E4%B9%85%E9%9B%84/dp/4822283151/ref=sr_1_2?adgrpid=53631245656&gclid=CjwKCAiArNOeBhAHEiwAze_nKFh5ZWYjVL-JKMW8T-M9lsvSPOUcb7bUmjVNNt1ufKlXQYJ8biLM-xoC7-UQAvD_BwE&hvadid=618622417813&hvdev=c&hvlocphy=1009533&hvnetw=g&hvqmt=e&hvrand=4920020858429554984&hvtargid=kwd-334563073858&hydadcr=27265_14598048&jp-ad-ap=0&keywords=%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AF%E3%81%AA%E3%81%9C%E5%8B%95%E3%81%8F%E3%81%AE%E3%81%8B&qid=1674909842&sr=8-2)を読んで調べたので備忘録。

## 小数点数の計算は誤差が生じることがある

- 小数点数の中には二進数では正確に表すことができない値がある
- 正確に表すことができない値は計算上では近似値で扱われる
- 近似値を用いる計算は誤差が生じる可能性がある

## 浮動小数点数

- コンピュータ内では小数点数を **浮動小数点数** で表す
- 倍精度浮動小数点数は64bit、単精度浮動小数点数は32bitで表す
- [IEEE754](https://ja.wikipedia.org/wiki/IEEE_754)に準拠した表現だと、**符号部**、**仮数**、**指数**、**基数**のパーツから成る
- 基数部は必ず2になる為、bitとして保持しない
- 符号部は0なら正、1なら負の数
- つまり仮数部に2の指数部乗を乗じた値で小数点数を表す
- 仮数部は小数点数以上の値を1に固定して表現する
    - e.g.) 11.01 -> 1.101
    - 1は1bitとして保持しない
- 指数部はイクセス表現で表現する
    - 中央の値をゼロとみなす
    - 0からの差で値を表現する
    - e.g.) 8bitなら127が0、128は1、126は-1

## 参考

- https://www.amazon.co.jp/dp/4822283151
- https://ja.wikipedia.org/wiki/IEEE_754
【Nginx】Nginxとは





# Nginxとは


Nginxは、webサーバーソフトウェアです。

* webサーバー
* リバースプロキシサーバー
* キャッシュサーバー
* ロードバランサー

上記のような役割を果たすことができます。





# webサーバーの設定

ここではNginxをwebサーバーとして使う場合を念頭に設定方法を見ていきます。



## 設定ファイル

デフォルトの設定ファイルは、`/etc/nginx/nginx.conf`です。（OSによってファイルの場所が異なることがある。）
`/etc/nginx/conf.d/`配下に、追加で設定ファイルを置くことができます。`~.conf`というファイルを設置してアプリごとや用途ごとに設定しておきます。これらはnginx.confでincludeで呼び出して使われます。

```
include /etc/nginx/conf.d/*.conf;
```

<br>
<br>

設定ファイルは、ディレクティブとパラメータで構成されます。

```
ディレクティブ パラメータ;
user nobody;
```






`events`、`http`、`server`、`location`ディレクティブはコンテキストとして参照されます。コンテキストは{}で囲まれた部分です。
コンテキスト外に置かれているディレクティブはmainコンテキストに属します。

```conf
user nobody; # a directive in the 'main' context

http {

    # Configuration specific to HTTP and affecting all virtual servers

    server {
        # configuration of virtual server 1

        location /one {
            # configuration for processing URIs with '/one'
        }

        location /two {
            # configuration for processing URIs with '/two'
        }
    }

    server {
        # configuration of virtual server 2
    }
}
```


## バーチャルサーバの設定

HTTPリクエストを処理するためには、設定ファイルにバーチャルサーバを定義します。

```conf
http {
    server {
        listen 127.0.0.1:8080;
        # The rest of server configuration
    }
}
```

serverディレクティブには、listenディレクティブを含める必要があります。これはNginxがlistenするIPアドレスとポート番号を指定します。IPアドレスが省略された場合は、全てのIPアドレスでlistenすることになります。

serverディレクティブを複数設定してバーチャルサーバを複数定義することもできます。



## locationの設定

locationディレクティブを設定することで、リクエストURLに応じて処理を分けることができます。

```conf
server {
    location / {
        # URIが/に合致する場合の処理
    }

    location /images/ {
        # URIが/images/に合致する場合の処理
    }
}
```


Nginxは全てのlocationディレクティブのパラメータに対してURIをテストし、適合するディレクティブを適用します。

locationディレクティブのパラメータはプリフィックスの文字列または正規表現で記述します。


```conf
location /some/path/ {
    ...
}

location ~ \.html? {
    ...
}

# /some/path/document.htmlのようなリクエストが合致する。
```

<br>

locationを複数設定することで、URLによって処理をそれぞれ分けることができます。

```conf
server {
    location / {
        # プロキシに処理を渡す
        proxy_pass http://www.example.com;
    }

    location /images/ {
        # 静的ファイルを提供する
        root /data;
    }
}
```


proxy_passディレクティブは、指定したURLにあるサーバにリクエストを渡します。上の例では、"/images/"で始まらないURLへの全てのリクエストを、プロキシされたサーバに渡します。
rootディレクティブは静的なファイルが存在するパスを指示します。

## エラーページの設定

error_pageディレクティブを使うことで、特定のエラーコードで返されるページを設定できます。
以下では404エラーのときに返すページを設定しています。

```conf
error_page 404 /404.html;
```

<br>

リダイレクトさせることもできます。


```conf
location /old/path.html {
    error_page 404 =301 http:/example.com/new/path.html;
}
```

古いURLでアクセスしてきたときに301で新しいURLにリダイレクトします。（301コードはブラウザにページが移動したことを伝え、古いアドレスを新しいものに自動的に置き換えるように伝えます。）


## 変数

nginx.confファイルは変数を設定することができます。$記号が変数の印です。

独自の変数を定義することもできますが、定義済みの変数もあります。
例えば、`$remote_addr`はクライアントのIPアドレス、`$uri`は現在のURIの値を持っています。



# まとめ


Nginxは、webサーバーソフトウェアです。

nginx.confがデフォルトの設定ファイルで、`/etc/nginx/conf.d/`配下に独自に設定ファイルを追加します。

webサーバーとして使いたい場合、`server`ディレクティブにバーチャルサーバを設定し、`location`ディレクティブにURLごとの処理を指定します。


<br>



# 参考

https://hogetech.info/network/web/nginx1

http://mogile.web.fc2.com/nginx/admin-guide/web-server.html
配列をactiverecordへ変換する

# はじめに
find_in_batchesメソッドはactiverecordに対してのみ使用できるので配列をactiverecordへ変換したい

# 方法
配列に格納されたデータのidのみを別の配列に格納する
（push・・・配列に要素を追加）
```
@channel_ids = []

channels = user.channels
channels.each do |channel|
  @channel_ids.push(channel.id)
end
```

idのみを格納した配列をwhere句へ指定して、再度データを取得することでactiverecordへ変換したデータが取得できる
```
target_channels = Channel.where(id: @channel_ids)
```

# 参考文献
もっと簡単に書けました
```wwhere(id: user.channels.pluck(:id))```

- [Railsで配列をActive Record Relationに変換したい](https://qiita.com/fgem28/items/25e25d400f2ce21f4235)
MisskeyユーザーでMisskeyの再起動したくない？

MisskeyをMisskeyユーザーで実行している場合、misskeyユーザーを`sudo`に入れてない人がほとんどかと思います。

そのためmisskeyユーザーで設定変更やアップデートを行った際には、一旦misskeyユーザーから退出して、`systemctl restart misskey`などと実行しているはずです。

ただ毎回ユーザー切り替えて反映するのもなかなか面倒だなと思うわけでして、今回はMisskeyのプロセスだけをmisskeyユーザーが自由にいじれるようにスクリプト書いてみます。

環境要件としてはFedora/Ubuntuあたりで`systemctl`によってMisskeyを管理していることです。


以下のスクリプトをそのまま`/usr/local/bin/misskey_ctl`として保存します。

```bash:/usr/local/bin/misskey_ctl
#!/bin/bash

cmd="$1"

case $cmd in
  "start")
     systemctl start misskey
     ;;
  "stop")
     systemctl stop misskey
     ;;
  "restart")
     systemctl restart misskey
     ;;
  "status")
     systemctl status misskey
     ;;
  *)
    echo "Usage: misskey_ctl start|stop|restart|status"
    ;;
esac
```

しかし`systemctl`の実行には`sudo`が必要です。そのためmisskeyユーザーが`misskey_ctl`に限り`sudo`実行できるように以下のコマンドを実行します。

```
sudo chown root:root /usr/local/bin/misskey_ctl
sudo chmod 744 /usr/local/bin/misskey_ctl
```

その上で`sudo`関連の設定を変更する専用のコマンドを実行します。

```
sudo visudo
```

で`vi`か`nano`が開いたら

```
misskey ALL=NOPASSWD: /usr/local/bin/misskey_ctl
```

を最終行に追記して保存を実行します。

特にメッセージが出なければ設定変更は成功です。

あとはmisskeyユーザーにログインして、

```
sudo misskey_ctl status
```

のように実行してプロセスの状態が確認できることを確認してください。
Ruby on Rails Webアプリケーションの雛形を作ろう

# アプリケーションを立ち上げるときのコマンド
条件
- Railsのバージョンは6.0.0を用いる
- アプリケーション名は、「output_projects」
- データベース管理システムにMySQLを使用する

```
rails _6.0.0_ new output_projects -d mysql
```

# データベースを作成するためのコマンド

```
rails db:create
```
サーバーサイドは、アプリケーションとデータベースがセットで存在しています。<br>
アプリケーションにおいて、データベースは必要不可欠なものです。<br>

# ローカルサーバーを起動するコマンド
```
rails s
```
sはサーバーのsです。
pythonでのMPI並列化

pythonでMPI通信を行うときは`mpi4py`というパッケージを利用します。

# mpi4pyのインストール

## 普通のやり方

https://anaconda.org/conda-forge/mpi4py

```
pip install mpi4py
```

や

```
conda install -c conda-forge mpi4py
```

でインストールできます。

## オフラインでのやり方

並列化計算をするようなクラスタコンピューターはセキュリティのためにオフラインになっていることが多いです。そのような場合は手動でインストールします。
まずは

https://pypi.org/project/mpi4py/

から`mpi4py-(バージョン).tar.gz`をダウンロードして並列計算を行うコンピューターに送ります。そこで

```
tar zxvf mpi4py-(バージョン).tar.gz
```

とファイルを解凍してできたフォルダ`mpi4py-(バージョン)`に入ります。そのフォルダに入っている`setup.py`を

```
python setup.py install
```

と実行すればmpi4pyモジュールが使えるようになります。

# 実行

使用するマシンの仕様にも依りますが

```
mpirun -np (コア数) python (実行コード)
```

などで実行できます。

# 基本的な使い方

クラス`MPI.COMM_WORLD`に必要な変数や関数が大体入っています。

例えば使用するコア数や自分のコアの番号は

```mpi.py
size = MPI.COMM_WORLD.Get_size()
rank = MPI.COMM_WORLD.Get_rank()
```

で取得できます。

# テストコード

```helloMPI.py
from mpi4py import MPI

comm = MPI.COMM_WORLD 

size = comm.Get_size()
rank = comm.Get_rank()

print("Hello world {0} / {1}".format(rank, size))
```

10並列での実行結果:

```
Hello world 1 / 10
Hello world 6 / 10
Hello world 0 / 10
Hello world 5 / 10
Hello world 4 / 10
Hello world 3 / 10
Hello world 8 / 10
Hello world 2 / 10
Hello world 7 / 10
Hello world 9 / 10
```

# Allreduce

```allreduce.py
from mpi4py import MPI
import numpy as np


comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()

sendbuf = rank*np.ones(10, dtype="float64")
recvbuf = np.empty(sendbuf.shape, dtype="float64")

comm.Allreduce(sendbuf, recvbuf, MPI.SUM)


if(rank == 0):
    print("procs:{0}".format(size))
    print(recvbuf)
```

4並列での実行結果

```
procs:4
[6. 6. 6. 6. 6. 6. 6. 6. 6. 6.]
```

## 配列の分割

配列の和をとるときに次のクラス`assign`を使って各コアが計算する部分配列を定めて分割して和を計算します。例としてすべて要素が1の$2\times 2$行列の配列を作り、行列の和を計算しました。

```Allreduce.py
from mpi4py import MPI
import numpy as np
import itertools

class assign:

    def __init__(self,procs,size):
        self.size = size
        self.procs = procs
        self.num = [ size//procs + (1 if i<size%procs else 0) for i in range(procs) ]
        self.id = [0] + list(itertools.accumulate( self.num))

size = 10
arr = np.ones((size,2,2))

comm = MPI.COMM_WORLD
procs = comm.Get_size()
rank = comm.Get_rank()

ASGN = assign(procs,size)

sendbuf = np.sum(arr[ASGN.id[rank]:ASGN.id[rank+1]],axis=0)
recvbuf =  np.empty(sendbuf.shape)

comm.Allreduce(sendbuf, recvbuf, MPI.SUM)

if(rank == 0):
    print("procs:{0}".format(procs))
    print(recvbuf)
    print(np.sum(arr,axis=0))
```

出力：

```
procs:4
[[10. 10.]
 [10. 10.]]
[[10. 10.]
 [10. 10.]]
```


# 参考資料
- https://scrapbox.io/PythonOsaka/mpi4py%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86
非SAPエンジニアが、四苦八苦してAWS Certified: SAP on AWS - Specialty 試験 (PAS-C01)に合格した話

# はじめに
SAPを全然触ったことがないエンジニアが、AWS資格のPAS-C01に合格したので、その合格記として書いていこうと思います。

# 生い立ち
私は、エンジニア歴5年目で、AWS資格の9個目として本資格に挑戦をしました。(SAPは全然分からないマンです。)
本試験は、1度目は、729点というぼちぼちな点数で不合格でした。
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252895/f6604905-ff6c-26c8-26c7-f751b0d69d42.png)

2度目にして、755点で無事合格でした。(ギリギリの合格でした。。。)
![1-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252895/c515fbbe-ef41-5a97-af0f-d0e00d1948cd.png)

スコアパフォーマンスでは、「移行」と「運用とメンテナンス」が弱いと判定されました。
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252895/3155138c-3cda-2d62-3d51-e8db208bf41a.png)

今回は、おなさけで合格をもらった身分なので、テストを通して「ここは勉強をしててよかった」や「ここは勉強不足であった」などをまとめていこうと思います。

# 勉強しててよかったと感じた箇所

**1.SAPの中の人が書いたブログ記事①「PAS-C01の重要ポイントをまとめた記事」**

https://blogs.sap.com/2022/12/16/get-aws-certified-sap-on-aws-specialty-pas-c01/

**2.SAPの中の人が書いたブログ記事②「AWS で SAP Oracle を実行するために必要な知識」**

https://blogs.sap.com/2021/02/08/key-topics-for-running-sap-oracle-on-aws/

**3.EBSボリュームタイプの種類**

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ebs-volume-types.html

**4. S3 Glacierの種類**

https://aws.amazon.com/jp/s3/storage-classes/glacier/

**5.AWS Control Tower**

https://aws.amazon.com/jp/controltower/


**6.試験合格者がまとめたYouTube動画**

https://www.youtube.com/playlist?list=PLrbutKlth8WG7Fp7AOP_LGHIjRuWnRBI1

**7.Whizlabsの練習問題**

https://www.whizlabs.com/learn/course/sap-on-aws-certification-exam-training/2481


# 勉強不足だと感じた箇所

- SAP 異種コピー全般
- オーバーレイIPアドレスの設定関連
- AWS Data Provider for SAP
- AWS Launch Wizard
- ルートテーブルを更新する際に必要なIAM権限

# 最後に
SAPよっくわかんねぇよぉぉぉぉぉぉぉぉ
合格で、ほんとよかったあああああああああああああああ(; ･`д･´)
Factoryで生成されるUserのidに合わせて他テーブルのFactoryを生成する方法

Factoryで生成されるUserテーブルのidと他テーブルのuser_idカラムと紐付けしたかったのでその備忘録です

## ItemFactoryの作成
UserFactryは既存のものを使用します。
ItemFactoryを生成する時は事前にuser_idのカラムがあるテーブルをマイグレーションしてください

コメントアウトをしている'user_id'=>$this->faker->numberBetween(1,10)は1~10のランダムな数字を生成することで10人のUserのidに対応するように最初記述したのですが、これでは10人以上のUserがFactoryされた時に対応ができないので、その対処法を考えます。
```php:ItemFacrtory
class ItemFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {

        return [
            //'user_id'=>$this->faker->numberBetween(1,10),
        ];
    }
}

```

## Seederの作成
Userを10人生成します。そこにeach()を使用することで、User一人に対して,３つのItemを生成します。そのタイミングで'user_id'のカラムをUserのidと紐づけます。

これによって、Userが生成されるタイミングで、user_idとidを紐づけることで,10人以降のUserと紐付かないという問題が解消されます。

```php:seeder
class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        \App\Models\User::factory(10)->create()->each(function($user){
            \App\Models\Item::factory(3)->create([
                'user_id' =>$user->id
            ]);
        });
    }
}
```
Houdiniのよく使うノード群をテンプレート化して使い回す


# はじめに

よく使うノード群を保存しておいて好きな時に呼び出して使い回せるように、シェルフに以下の2つのスクリプトを登録します。

シェルフへの登録の仕方は[こちら](http://ikatnek.blogspot.com/p/how-to-make-shelf-tool.html)です。


# コード

選択したノード群を保存するコード

```python:Save_Nodes.py

import hou

# cpioを保存するディレクトリを設定
dirPath = "DIRECTORY"

def SaveTemplate(name):

    sel = hou.selectedNodes()
    path = sel[0].path()
    nodeCategoryName = sel[0].type().category().name()
    pathSplit = path.split("/")
    pathSplit.pop(-1)
    
    getRootPath = "/".join(pathSplit)
    rootName = getRootPath[1:].replace("/","_")
    
    contextnode = hou.node(getRootPath)
    
    filename = "{}/{}_{}".format(dirPath, nodeCategoryName, name + ".cpio")
    
    contextnode.saveItemsToFile(sel, filename, save_hda_fallbacks = False)
    hou.ui.displayMessage("Success!\n" + "Save File: "+filename)
    print("Save File: "+filename)


Dialog = hou.ui.readInput(message ="Save Select Nodes?\n",title = "Save Template",severity=hou.severityType.Message,buttons=["Save","Cancel"])

if Dialog[0]==0:
    SaveTemplate(Dialog[1])

```
#### 説明
houにあるsaveItemsToFileなどを使用してノード群をcpioファイルとして保存しています。

*****

ノードを読み込むコード

```python:Import_Nodes.py

import hou
import os

# cpioを保存してあるディレクトリを設定
dirPath = "DIRECTORY"

files = os.listdir(dirPath)
fileList = [f for f in files if os.path.isfile(os.path.join(dirPath, f))]

def ImportTemplate(filename):
    desktop = hou.ui.curDesktop()
    pane =  desktop.paneTabOfType(hou.paneTabType.NetworkEditor)
    current_context = pane.pwd().path()
    
    hou.clearAllSelected()
    
    contextnode = hou.node(current_context)
    nodes = contextnode.loadItemsFromFile(filename, ignore_load_warnings=False)
    sel = hou.selectedNodes()
    
    firstNodePos = sel[0].position()
    for node in sel:
        node.setPosition(
        node.position() + hou.ui.paneTabOfType(hou.paneTabType.NetworkEditor).visibleBounds().center() - firstNodePos
        )

Dialog = hou.ui.selectFromList(fileList, message='Select Import File')
 
if len(Dialog)!=0:
    for i in Dialog:
        ImportTemplate("{}/{}".format(dirPath, fileList[i]))

```
#### 解説
ディレクトリからcpioのファイルを読み込んでloadItemsFromFileでcpioファイルからHoudiniにノードをペーストしています。

読み込んだノード群は、ビューワーの中央になるように調整しています。
Debian11/UbuntuLTS環境でAzure ファイル共有に接続する際必要なパッケージ（と作業メモ）


Azureファイル共有を作成しようと思った際、普段NFSを作らない/手順書通りにしか作ったことがない人（つまり私）のために備忘録を残します。

```Debian:error
mount: /mnt/XXXXXXX: bad option; 
for several filesystems (e.g. nfs, cifs)
you might need a /sbin/mount.<type> helper program.
```
Azureファイル共有でこういうエラーが出ている人向けです。

作業手順は下記にありますが、まず何が起こっているのか整理。
①mountコマンドのエラーであってAzureのエラーではなさそう。
②you might need ~のあたりから、何かが足りなそう。
③足りないもの（先に言うとSMBやCIFSクライアント）をインストールすれば解決するのでは？
という風に解決しました。

【作業手順】

1.Azure仮想マシン（検証用Debian/Ubuntu）を作成する。（ssh接続）
2.ストレージアカウントを作成する。
3.ストレージアカウントでAzureファイル共有を作成する。
4.ローカルのターミナルでAzure仮想マシンへ接続する。
5.下記のパッケージをインストールする。
```bash:bash
sudo apt update
sudo apt install cifs-utils
```
6.Azureファイル共有から接続用のスクリプトを走らせる。

以上。

なぜ記事に残したかというと、AZ-104の対策本ではこのパッケージをインストールするところが抜けていたので、わからない人向けに需要がありそうだなと思ったからです。

最終的にファイル共有する際は、そのファイル共有で使われているプロトコルを扱えるクライアント/サーバーがいないといけないという理解になりました。

【参考情報】
https://learn.microsoft.com/ja-jp/azure/storage/files/storage-how-to-use-files-linux?tabs=smb311#prerequisites
Power BIでリッチテキスト・HTMLテキストを変換する


Power BI Desktopでレポートを作る際に、Dataverseのリッチテキスト列やHTMLとして保存したデータをテキストに変換する方法を書きます。
Power BIでHTMLを変換する方法が大きく２つあります。

イメージとして、下の画像で、左の列（crd83_memo）のようにHTMLで保存されたテキストを右の列（custom_memo.text）のようにテキスト文に変換します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/2ec9e1f7-8183-135e-8df0-170135c807cb.png)

１つ目がPower Queryで変換する方法、２つ目が[カスタムビジュアル](https://learn.microsoft.com/ja-jp/power-bi/developer/visuals/power-bi-custom-visuals)を使う方法です。

# 1. Power Queryで変換する方法
[レポート]ワークスペースで[ホーム]>[データの変換]>[データの変換]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/ce8e048b-45fe-e201-1b50-46b95a261e46.png)

表示されるPower Queryエディターで[列の追加]>[カスタム列]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/940bbb35-60aa-bbc3-a6ad-8031b131ca36.png)

次にカスタム列を定義します。
列名を入れて、カスタム列の式に以下のような式を入れます。
```
try Html.Table([ColumnName] , {{"text",":root"}}) otherwise null
```
ColumnNameには変換したい列名を入れてください。今回は「crd83_memo」です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/cc794414-66a4-01d9-cdea-8018c4160182.png)

入力したら[OK]ボタンを押します。一番右に今作った列が追加されますのでその列名の右のボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/a92cf633-14c8-fa9b-7335-0d5cb70cf6ef.png)

ここで[OK]ボタンをクリックします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/162a2ec8-7fa0-7d9e-f46c-fc4a88eb485e.png" width=50%>

プレーンなテキストになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/e48c1567-1450-6996-d252-4fe33e584364.png)

レポートでテーブルビジュアルで列を選択して、表示させると以下の画像のように表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/2ec9e1f7-8183-135e-8df0-170135c807cb.png)
# 2.カスタムビジュアルを使う方法

以下のURLにアクセスして、AppSourceからダウンロードします。

https://appsource.microsoft.com/en-us/product/power-bi-visuals/wa200001930?tab=overview&exp=ubp8

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/812c77a4-456e-ac72-f198-201f32f28ffc.png)

Power BI Desktopでのカスタムビジョンの入れ込み方法を教えてくれるので、基本的にこの方法で作業を進めます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/811941db-7439-65bd-8029-17f5acf31887.png" width=60%>

Power BI Desktopの視覚化で三点リーダーをクリックし、[ビジュアルをファイルからインポート]を選択します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/36f9abb9-c4ad-8383-987f-76a0c879583a.png" width=60%>

ポップアップで[インポート]ボタンをクリックします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/9b6da1ac-a465-3bc9-5f08-3fe0ce687692.png" width=60%>

ダウンロードしたファイルを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/3083f82a-4bc2-34f5-ebd1-455350ce1653.png)

視覚化の下に新しくHTML Contentビジュアルが追加されました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/dc60ab0c-f282-72de-1087-860b35e745ec.png" width=30%>

HTML Contentビジュアルを選択し、列に表示させたい列をValuesに選択すると、HTMLテキストが変換されて表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/0c57b18e-928c-d059-7085-7e57223936cd.png)



# まとめ
今回は、HTML形式のデータををPower BIで表示する方法をまとめました。
ぜひ参考にしていただければと思います。
Composer を Windows にインストールする手順

# Composer のダウンロード
公式サイトの「Introduction のページの  Composer-Setup.exe のセクションにあるダウンロードのリンクをクリックして、インストーラをダウンロードします。
https://getcomposer.org/download/
# Composer のインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/05bbfde4-1d9f-296f-52ff-2d0bd04021a9.png)
 自動的に PHP のパスが入力されなかった場合は「Browse」をボタンから、利用する php.exe を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/5bb5b139-3cb0-c857-e570-d9464fbbbc2e.png)
プロキシの設定画面が表示されます。 インターネットに接続するためにプロキシを利用する必要がある場合は、設定します。 必要がない場合は「Next」をクリックして次に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/45f07538-f241-d5c5-66ce-df7d161860e9.png)

これは、PHP で openssl (SSLライブラリ)を利用する拡張が有効になっていない場合に表示されます。 その場合、PHP の設定の変更が必要です。 (無視して突き進むことはできますが)インストーラを一旦閉じて、ご利用の PHP の設定ファイル php.ini を修正しましょう。
以下記事を参照して設定してください。

https://qiita.com/taidong5588/items/f250ab10e4122a04046a

利用する PHP の情報などが正しいことを確認して、「Install」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/2f24f073-1187-6375-6e19-ca86ed58ce97.png)
インストールの完了を知らせる画面が表示されました。 これにてインストールは完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/3e42cd4a-a5d6-b3fc-b52e-e9f1ab271d1f.png)
# 動作確認
composer -V コマンドでComposer がインストールされたことを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/fcfa3d25-1431-0042-6c36-ea73e4d36b7f.png)
スループットキャパシティ変更時の落とし穴！SVM個数制限にご注意を！～Amazon FSx for NetApp ONTAP～

# はじめに
こんにちは。ネットアップ合同会社 Specialist SEの月岡です。
皆さん、Amazon FSx for NetApp ONTAP（以降、FSxN）使ってますか？

SMB/NFS/iSCSIのマルチプロトコルに対応し、NetAppストレージの機能を利用できるということで利用ケースは様々かなと思います。
そんなFSxNですが、AWSが提供するファーストパーティーサービスなので、もちろん容量やパフォーマンスを動的に変更することができます。
今回は、スループットキャパシティを変更する際の注意事項をまとめたいと思います。

# そもそもスループットキャパシティって？
簡単に言うと、FSxNが一定時間内にどれくらいのデータ容量を転送処理できるのかということです。
スループットキャパシティが及ぼすパフォーマンスへの影響は、AWS公式マニュアルにも記載がありますのでご参考までに。
https://docs.aws.amazon.com/fsx/latest/ONTAPGuide/performance.html
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2806894/439865f5-7ae3-0f7a-b9ab-e3db93f34940.png)

# スループットキャパシティに紐づく制限を確認してみる
AWS公式マニュアルからFSxNの制限事項を確認してみます。

https://docs.aws.amazon.com/fsx/latest/ONTAPGuide/limits.html

なるほど、スループットキャパシティは最小128MBps、最大2,048MBpsです。
（一部リージョンでは最大4,096MBps）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2806894/b7982ceb-b720-6b60-f62f-519402bfa297.png)

ここで既に皆さんお気付きかと思います。
「Maximum number of SVMs」の欄にスループットキャパシティの記載があります！

そうです。
これは、スループットキャパシティの容量に応じたSVMの個数制限があるという意味です。

SVMについては、以下のAWS公式マニュアルをご参考までにどうぞ。

https://docs.aws.amazon.com/fsx/latest/ONTAPGuide/managing-svms.html

# SVMの個数上限について検証してみる
前置きが長くなりましたが、スループットキャパシティとSVMの個数上限の関係について検証してみました。
（キャプチャデータが昨年のものですが、ご容赦ください）

## FSxNのファイルシステムを作成
- スループットキャパシティ「128MBps」のFSxNを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2806894/ecde2512-f1f5-9194-3b2a-0dcc369f4d5b.png)

- SVMを6台作成（SVM1～SVM6）します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2806894/83bf9f8c-2c21-cda4-7ba7-713da7055541.png)

## 7台以上のSVMを作成しようとするとエラーが表示
- スループットキャパシティが「128MBps」ですので、7台以上はSVMを作成できません。
- マネジメントコンソールで作成しようとすると、以下のキャプチャ画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2806894/c1b0b073-eac7-2d71-ee13-f97bec4c7fbf.png)

## スループットキャパシティを「512MBps」に変更し、7台以上のSVMを作成
- 7台以上のSVMを作成するためには、スループットキャパシティが「512MBps以上」である必要があります。
- 今回は、スループットキャパシティを「512MBps」に変更しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2806894/995f3c9a-bc5b-07c1-2abd-008265fbd707.png)

- 7台以上のSVMを作成してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2806894/ce2adeaf-b910-9c8d-0ad9-680f1764b80d.png)
 問題なく、7台目のSVM7を作成することができました。

## SVMが7台以上ある環境でスループットキャパシティを「256MBps以下」にできるのか
- スループットキャパシティが「256MBps以下」である場合、SVMは6つまでが制限です。
- マネジメントコンソールからFSxNのスループットキャパシティを変更しようとすると、以下のキャプチャ画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2806894/36719358-93d5-272d-6031-d50455a3a530.png)
やはり、スループットキャパシティに紐づくSVMの個数制限に抵触して、変更することができませんでした。

# まとめ
FSxNのスループットキャパシティを変更する際は、スループットキャパシティに紐づくSVMの個数制限があることに注意が必要です。
SVMが7台以上必要な場合は、スループットキャパシティが512MBps以上で構築する必要があります。
また、SVMを7台以上運用している環境では、スループットキャパシティを256MBps以下に変更することはできません。

# 主な参照元
- https://docs.aws.amazon.com/fsx/latest/ONTAPGuide/what-is-fsx-ontap.html
- https://docs.aws.amazon.com/fsx/latest/ONTAPGuide/managing-svms.html
- https://docs.aws.amazon.com/fsx/latest/ONTAPGuide/limits.html
【TOGAF9認証試験のための勉強メモ(5)】受験結果

受験結果です。
結論から回答すると、Level1,2共に合格できました。

スコアは以下の通りでした。
Level 1 :80%(合格基準55%)
Level 2 :70%(合格基準60%)

「TOGAF完全に理解した」という気分になって望んで、実際に問題を見たら急に自信がなくなって焦ったのですが、何とか合格できてよかったです。(思ったよりLevel 2のスコアが低くて悲しかったのですが、まあ合格してたしいいや・・・・・・)

## 受験時の感想
つらつらと書いておきます。
- Level 1は60分、Level 2は90分のテスト時間。どちらも手早く解いていった方がよい。Level 1よりLevel 2のほうが文章量が多いので足りなくなりそうな気がする。
- Level 1について、講師が言っていたことをよく学習していけば何とかなるのではと思っていたが、実際に出題される問題との関連はあまりなかった。講師のアドバイスは、過去問を見るとこういった傾向の問題が出る、くらいに捉えておくのがよいと思われる。
- Level 1のコアはADM. 各フェーズの概要、主な入力/出力、そして主なデリバラブルやアーティファクトがどのフェーズで0.1版を作成し、どのフェーズで1.0版となるかは覚えておくべき。
- Level 2について重要なことは2つ。「(1)問われている状況はどのフェーズなのか？」「(2)そのフェーズにおいて、TOGAFガイドには何をしろと書かれているか？(逆に言うと別フェーズでやることが設問に書かれていないか？)」そこさえ気を付ければ二択まではまず絞れると思われる。
- Level 2では問題文より選択肢を先に読んだ方がいい。簡単な設問であれば、選択肢を読んだだけでほぼ正解が読めることもある。時間の関係もあるので予想がついたらその問題は見当をつけておいて飛ばした方がいいかもしれない。
- Level 2では「TOGAFガイドに書かれていないことをやる選択肢は誤り」と考えればよい。逆に、TOGAFガイドに書かれていることをやる選択肢であれば、0点ではなく最低1点はもらえると思われる。

これから受験される方は頑張ってください。以上です。
【SwiftUI】macOSでウインドウサイズを固定する

# はじめに
[`frame(minWidth:idealWidth:maxWidth:minHeight:idealHeight:maxHeight:alignment:)`](https://developer.apple.com/documentation/swiftui/view/frame(minwidth:idealwidth:maxwidth:minheight:idealheight:maxheight:alignment:))を設定することでウインドウサイズを固定できると思っていたらできなくてつまづいたので記録しておきます。

私の認識では以下のようにすれば1番大きい時で110、1番小さい時で100になると思ってました。
```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
        }
        .frame(minWidth: 100, maxWidth: 110, minHeight: 100, maxHeight: 110)
    }
}
```

しかし、実際は以下のようになります。
![画面収録_2023-01-28_20_53_28_AdobeExpress.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/00bb2ad0-3e83-478a-da14-ebc1164580a9.gif)

`frame`が機能していません

# やりかた
```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
        }
        .frame(minWidth: 100, maxWidth: 110, minHeight: 100, maxHeight: 110)
    }
}
```
```diff_swift
import SwiftUI

@main
struct macos_window_size_sampleApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
+       .windowResizability(.contentSize)
    }
}
```

# おわり
最近macOSアプリを作ることが多いので新たな発見があって楽しいです

# 参考記事
https://developer.apple.com/forums/thread/719389
String型やInt型に直接拡張関数を生やすのはいかがなものか(value classを検討しよう)

## 要約
- プリミティブ型に拡張関数を書くと、必要以上に広いスコープが対象になってしまう
- `value class`を活用するとスコープと用途を限定できて良いかも
  - 絶対こうすべきという強い思想はまったくなく、検討する価値のある方法の1つという意

## よくある場面

🙂<`1500`のようにIntで扱っている値を画面に表示する際に、`1,500円`のようにカンマ区切りにして「円」をつけたStringに変換したいな

```kotlin
val formatedPrice: String = "%,d".format(1500) + "円"
println(formatedPrice)
// -> 1,500円
```

🙂<この変換はいろいろな箇所で使うから`Int.kt`ファイルに拡張関数として追加しておこう

```kotlin Int.kt
fun Int.format(): String = "%,d".format(this) + "円"
```

😊<簡単に呼び出せるようになって、コードもスッキリした
```kotlin
val formatedPrice: String = 1500.format()
println(formatedPrice)
// -> 1,500円
```

## 問題点

- 追加したい拡張関数がこれだけなら問題ない
  - (ほとんどの場合は追加したい処理がどんどん増えていく)
- 用途が限定的なので、Intすべてが使える関数として定義するにはスコープが広すぎる
- 今後同じようなことをやりたい場合`Int.kt`に続々と関数が追加され肥大化する
  - このままいくとIntはグローバルなので、金額の変換、日付の変換などすべてが一同に介してしまう

1ヶ月後...
🤮<`Int.kt`に拡張関数を生やしすぎてが1000行以上あって混沌としている！
```kotlin Int.kt
// 円を末尾につける
fun Int.formatYen(): String = {...}
// ドルを末尾につける
fun Int.formatDoller(): String = {...}
// ユーロを末尾につける
fun Int.formatEuro(): String = {...}
// yyyy/MM/ddの形式に変換する
fun Int.formatYYYYMMDD(): String = {...}
...
...
```

## 解決策 -> value classの利用を検討しよう
### `value class`とは
  - data classとだいたい同じ
  - コンパイル時にプリミティブな値としてバイトコードを生成するので、パフォーマンスはdata classよりも良い
  - 単一のプロパティしか持てない
  - `@JvmInline`をつける必要がある
  - Value Objectとして利用することに適している
  - 参考：https://star-zero.medium.com/kotlin%E3%81%AEvalue-class-27e865696f35
### value classにメソッドを生やすことで、スコープを限定できる
  - `Int`の拡張関数を使うのとパフォーマンス的にもほぼ変わらずにかける
  - `Price`, `Date`のように扱う対象ごとに分けられる
  - プリミティブ値は値の渡し間違いなどがあるため、value classを使うと型安全に扱える(value object)

```kotlin Price.kt
@JvmInline
value class Price(private val value: Int) {
    fun format(): String = "%,d".format(this.value) + "円"
}
val price: Price = Price(1500) // <- オリジナルの型として扱える
val formatedPrice: String = Price(1500).format()
println(formatedPrice)
// -> 1,500円

```

### プリミティブに拡張関数を生やすべきでないか
- まずは`value object`で扱う範囲を限定して汎用関数にする方法を検討するとクリーンなコードになる
- 上記では収まらず本当に汎用的に行う処理であれば、プリミティブ型の拡張関数を作るのは良さそう
  - プリミティブ型の汎用的な関数は、言語仕様として豊富に提供されている
  - 標準の関数で事足りない場合、そのプロジェクト特有の対象(ドメイン)を扱っている可能性が高い
  - であれば、グローバルなプリミティブ型に直接生やすのではなく、value objectを作ってドメインとして扱ったほうがクリーンな気がする
    - 大半の場合はvalue objectに生やす方向で事足りそうなので、一見の価値あり

## 参考文献

https://note.com/navitime_tech/n/n34b8fa9a82b7#f172b567-ae47-4b31-938e-470a1c3e680c

https://star-zero.medium.com/kotlin%E3%81%AEvalue-class-27e865696f35
一部iOSでoverflow-y: scrollが効かない

## ム！この画面、スクロールが効いてないぞ

~~~sample.css
.scroll {
    width: 100%;
    overflow-y: scroll;
}
~~~

自分はiMac Proを使っていますが、Windowsで実装した作業者の画面を見るとスクロールしている。
何なら自サブ機のMacbookは普通にスクロールしとるやんけ！なんなんだこれは

### どうやら一部iOSで起こる固有の現象っぽい

iOS及びSafariでこの手の現象が度々出るっぽい。

https://qiita.com/morikooooo/items/7612c7736ee3fbed8120

>overflow-y: scroll;してるブロックにtransform: translateZ(0); を指定したらRetinaディスプレイでも無事スクロールできるようになりました。

この記事を参考に`transform: translateZ(0);`を追加しましたが、変わらない…
他にも、`height: 100%;`追加で行けたとか色々出てきましたが変わらず。

## 解決

~~~sample.css
.scroll {
    width: 100%;
    height: 100vh;
    overflow-y: scroll;
}
~~~

`height: 100vh;`を追加で解決しました。
100vhだと突き抜ける場合はお好みで数字を指定するスタイル。

他クラスを見てくれないのか何なのか、overflow-yを入れているクラス内で宣言しないとheightを認識してくれないっぽい？
100％だと動かないけど90％を指定すると若干スクロールしたりとかしたので謎すぎる…
あとこの方法だとデザイン崩れやすくなったりするので、もう少しいい解決方法があればコメントで教えていただけるとありがたいです。

### 余談

`overflow: hidden;`も効かなくて`width: 100vw; height: 100vh;`を指定しました。
とりあえずMacでoverflowが効かなかったらwidthとheightを指定しよう（教訓）
公開デザインシステムのまとめ

# デザインシステムとは
「（自分たちが最適と考える）一連のデザイン方針・パーツをまとめたもの」というのがイメージしやすいかと思われます。

### ＜参考定義＞
- 「一貫したデザインや操作性でウェブサイトやアプリを提供するための仕組み」（[デジタル庁](https://www.digital.go.jp/policies/servicedesign/designsystem/)）
- 「良いデザインを一貫性をもって提供するための仕組み」([CONCENT](https://www.concentinc.jp/design_research/2021/04/designsystem/))
- 「企業のビジョンやブランドアイデンティティなどから『良いデザイン』を定義するデザイン原則などのドキュメント、それらを具体的にデザイン・実装するためのUIパターンやコンポーネントなどを備えた一連のリソース」([in-Pocket](https://www.i3design.jp/in-pocket/10230))
- 「デザインにおけるスタイル、UIコンポーネントのライブラリ、そしてその他のルールにまつわるドキュメント」（[CIRCL](https://circl.co.jp/jp/views/design/what-is-design-system/)）

# 公開されているデザインシステム
## 日本国内
### SmartHR
https://smarthr.design/
### CyberAgent:Ameba「Spindle」
https://spindle.ameba.design/
### LINE
https://designsystem.line.me/
### GMOペパボ「Inhouse」
https://design.pepabo.com/inhouse/
### Cookpad「Apron」
https://www.figma.com/community/file/847372282968994272
### Speeda
https://www.figma.com/community/file/1047401907024695662

## 海外
### Material Design (Google)
https://m3.material.io/
### Polaris (Shopify)
https://polaris.shopify.com/
### Human Interface Guidelines (Apple)
https://developer.apple.com/design/human-interface-guidelines/guidelines/overview
### Lightning (Salesforce)
https://www.lightningdesignsystem.com/
### Carbon (IBM)
https://carbondesignsystem.com/
### Primer (GitHub)
https://primer.style/
### Pajamas (GitLab)
https://design.gitlab.com/
### Spectrum (Adobe)
https://spectrum.adobe.com/
### Atlassian
https://atlassian.design/

## 政府レベル
### 日本（デジタル庁）
https://www.figma.com/community/file/1172530831489802410
### アメリカ
https://designsystem.digital.gov/
### イギリス
https://design-system.service.gov.uk/
### カナダ
https://design.gccollab.ca/
### エストニア
https://brand.estonia.ee/?lang=en

## 都市
### フィンランド／ヘルシンキ
https://hds.hel.fi/


## リンク集
https://www.designsystems.com/open-design-systems/
https://platformland.github.io/government-design-systems/data/design-systems/
https://github.com/arielsalminen/design-systems-in-finland
【ArtistでもMELが書きたい】Maya MEL入門(3)【スクリプトエディタ】

# はじめに
この記事は、3DCG業界で働く**Artist向けのMEL入門記事**です。
普段の業務を効率化したいけど、MELの書き方が分からない、調べたけどイマイチ分からなかった、そんな方向けに書きました。
本記事は「スクリプトエディタを使ってMELを実行する」をゴールとします。

# 環境
Autodesk Maya 2022.2

# 前回のあらすじと今回へのつなぎ
[前回](https://qiita.com/Hum9183/private/5cee29b1e227834b2f8e)はコマンドラインを用いて、複数のコマンドを同時に実行しました。
複数のコマンドを同時に実行する方法も覚えたし、もう大丈夫と思うかもしれませんが、実行したいコマンドがもっともっと増えたときはどうなるでしょうか？
例えば、ポリゴンのキューブを10個生成するMELを実行する際、必要なスクリプトはどんなものになるでしょうか。
```
polyCube;polyCube;polyCube;polyCube;polyCube;polyCube;polyCube;polyCube;polyCube;polyCube;
```
![MEL_learning01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121056/613be376-aefc-53c1-8b32-e69672ad0c46.png)
見た目がすごいことになりましたね。
このスクリプトは、**文法的には正しい**ですが、なんというか...もうちょっと良くしたいですよね。

Windowsで手早くテキストを書く際に、皆さんはどんなアプリを使っていますか？
人によっていろいろな好みがあるかと思いますが、真っ先に思いつくのは**メモ帳**ではないでしょうか？
実はMayaには**スクリプトエディタ**というメモ帳のような機能が入っています。

# スクリプトエディタを起動する
コマンドラインの右端に下図のようなアイコンがあります。
![MEL_learning01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121056/6f792a00-11cb-0f10-e559-cdc1abb7abc9.png)
アイコンを押すとスクリプトエディタが起動します。
![MEL_learning02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121056/bcf198fb-08b2-0c90-8607-c5da6d56ea21.png)
こちらがスクリプトエディタです。
たくさんボタンがありますが、すべてを把握する必要はありません。

スクリプトエディタではコマンドラインと同様にコマンドを入力して実行することができます。

# スクリプトエディタでMELコマンドを実行する
スクリプトエディタの下半分はテキストエディタになっています(メモ帳とほぼ同じ機能です)
![MEL_learning04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121056/5ff2645e-349c-ec85-9b79-6752b4b4188e.png)
ためしに`polyCube`コマンドを入力してみましょう。
![MEL_learning03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121056/581f3aea-17da-1582-c47f-bf45256bd414.png)
`polyCube`と入力すると文字が水色にハイライトされました。
スクリプトエディタではコマンドが自動でハイライトされます。見やすくて大変良いですね。

次に実行ですが、Enterを押すと改行されてしまいます。テキストエディタなので当然の挙動と言えます。
スクリプトエディタでは下図のアイコンのボタンを押すことで実行できます。
![MEL_learning05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121056/3f5a2be2-175a-549b-2e74-b7c63b96bb77.png)
![MEL_learning06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121056/948a9eb6-9cdf-fb85-9744-229828f4b9cd.png)
無事にキューブが生成されました。
スクリプトエディタもコマンドラインと同様に、
1. コマンドを記述する
2. 実行する

の流れでMELを実行できることがわかりました。

# 改行してみる
スクリプトエディタではメモ帳同様に改行ができます。
試しに、
```
polyCube;polyCube;polyCube;polyCube;polyCube;polyCube;polyCube;polyCube;polyCube;polyCube;
```
上記のコマンドを`;`ごとに改行してみましょう。
![MEL_learning07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121056/d9d00402-9b6c-0424-be00-ac94ecbedebb.png)
スッキリしましたね。

実行もしてみましょう。
![MEL_learning08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121056/5117f3a5-69ea-05e3-a942-6214189bcd9f.png)
バッチリキューブが10個生成されています。

MELでは一般的に`;`で改行する書き方が良いとされています。
必ずしも守る必要はないですが、文章のわかりやすさが大切という考えは、プログラミングに限らず共感できる内容かと思います。

# 終わりに
MEL開発をする際に、大きな手助けとなってくれるであろうスクリプトエディタをご紹介しました。
基本的にMELを書く際は、コマンドラインではなくスクリプトエディタを推奨します。
効率化のための開発が非効率では馬鹿らしいですからね。

次回はこちら→[【ArtistでもMELが書きたい】Maya MEL入門(4)](https://qiita.com/Hum9183/private/1fce41d94092676f4003)

# 参考
https://knowledge.autodesk.com/ja/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2020/JPN/Maya-Scripting/files/GUID-7C861047-C7E0-4780-ACB5-752CD22AB02E-htm.html
【Address already in use】ポートが被ってる時の対処法

# はじめに
サーバとローカルを`jupyter`で繋げようとした時に前のプロセスが残っていて`Address already in use`とエラーが出る時の対処法

# 解決方法
```
lsof -i :[ポート番号] -t | xargs kill -9
#lsof -i :8888 -t | xargs kill -9
```

#### lsof

|  オプション  |  説明  |
| ---- | ---- |
|  -i  |  待機ポートを確認する(ネットワークソケットファイルを表示する)  |
|  -t  |  プロセスIDの表示 

#### xargs
標準入力やファイルからリストを読み込み、コマンドラインを作成して実行するコマンド
```
#例
#コマンドAの実行結果を引数にしてコマンドBを実行
コマンドA | xargs コマンドB
```
#### kill
実行中のプロセスを終了
|  オプション  |  説明  |
| ---- | ---- |
|  -9  |  強制終了  |

#### lsof -i :8888 -t | xargs kill -9
`lsof -i :8888 -t`:
8888番ポートで起動しているプロセスを探してプロセスIDを渡す

`xargs kill -9`:
受け取ったプロセスIDを用いてプロセスを強制終了

#### 参考
https://qiita.com/toyoyuto618/items/7c281587ea66824c1233
[xargs](https://atmarkit.itmedia.co.jp/ait/articles/1801/19/news014.html)
【GAS】全角英数字、スペースなどを半角に置換する

# 概要
環境: V8 ランタイム

備忘録。

全角英数字を絶対に許さないスクリプトです。書籍APIで取ってきた情報が全角と半角の混合で美しくなかったので、どちらかに統一してしまおうという試み。スペースとコンマはreplaceに渡して半角に置換。

全角文字列を引数に渡せば半角文字列を戻り値で返してくれます。

# コード

```js
// 英数字を全角から半角に変換
function convertCharacters(original) {
  let converted = ""; // 空の変数
  const pattern = /[Ａ-Ｚａ-ｚ０-９]/; // 全角英数のパターンを用意
  for (let i = 0; i < original.length; i++) { // 受け取った文字列の数だけ繰り返し
    if (pattern.test(original[i])) { // 文字が全角英数のとき
      const half = String.fromCharCode(original[i].charCodeAt(0) - 65248); // 半角英数に変換
      converted += half;
    } else {
      converted += original[i];
    }
  }
  converted = converted.replace(/　/g, ' ').replace(/．/g, '.'); // gオプションで該当文字列をすべて置換
  // Logger.log(converted);
  return converted;
}
```
【ArtistでもMELが書きたい】Maya MEL入門(2)【;】

# はじめに
この記事は、3DCG業界で働く**Artist向けのMEL入門記事**です。
普段の業務を効率化したいけど、MELの書き方が分からない、調べたけどイマイチ分からなかった、そんな方向けに書きました。
本記事は「複数のMELコマンドを同時に実行する」をゴールとします。

# 環境
Autodesk Maya 2022.2

# 前回のあらすじと今回へのつなぎ
[前回](https://qiita.com/Hum9183/private/ab5cc907734737b508b4)はコマンドラインを用いて、`nurbsCube`や`polyCube`コマンドを実行しました。
MELコマンドが実行できたのはいいのですが、**一回の実行**で**一つのコマンド**しか実行できないというのは少々不便です。
例えば、一回の実行でNURBSのキューブとポリゴンのキューブの二つを生成するとしたら？現状はできませんよね。

少なくとも、有志の方がネット上で配布されているMELはワンクリックで様々な自動処理がすべて実行される類のものが多いかと思います。

# 複数のコマンドを同時に実行するには？
ものは試しということで、コマンドラインに二つのコマンドを一緒に入れて実行してみましょう。
```
nurbsCube polyCube
```
![MEL_learning01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121056/0390f9fd-0147-6deb-7d96-363c99eb3bb6.png)
![MEL_learning02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121056/bacf98e7-4dd6-474b-d248-8a544607df9b.png)
コマンドラインの右側に赤いエラーが表示されました。

実はMELを書く際には守らなければいけない**文法**が存在します。
今の書き方はMELの文法に反しているのです。

# 間話 文章の読みやすさ
ここで一つ例え話をします。
>私は今日パンを食べましたお腹が膨れたら眠くなったので仮眠をとりました30分後に起きて明日の宿題をやり始めました

上記の文章を読んでなにか感じることはありますか？

そうです。読みにくいですね。
読みにくい原因は様々あると思いますが、一番の要因は句点(。)がないことだと思います。

>私は今日パンを食べました。お腹が膨れたら眠くなったので仮眠をとりました。30分後に起きて明日の宿題をやり始めました。

句点を入れると上記のようになります。
多少は読みやすくなりましたね。

ということで、
文章は**意味の区切りで分割する**ことでより認識しやすくなる事がわかるかと思います。

**意味の区切りで分割する**という概念はMELにも存在します。

# MELで意味の区切りを分割するには
MELでは意味の区切りを`;`(セミコロン)で表現します。
たとえば
```
nurbsCube;polyCube;
```
上記のテキストは`nurbsCube;`と`polyCube;`の二つに分割できていることになります。

なので、端的に言ってしまえば、
```
nurbsCube polyCube
```
は二つのコマンドが**分割されていなかった**ので、文法として違反しているよというエラーが出たというわけです。

# 正しい文法で再度実行してみる
![MEL_learning03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121056/db175e86-1cec-850c-1abf-3772bcc2e38e.png)
シーンビューでは成功しているかが確認しづらいため、アウトライナで確認しましょう。
![MEL_learning04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121056/31ac28b6-ab2c-25c6-120f-9643b89af58f.png)
NURBSのキューブとポリゴンのキューブがそれぞれ生成されています。成功です。
つまり、
```
nurbsCube;polyCube;
```
は正しい**文法**で書けていたということになります。

# MELで守らなければいけない文法
MELはいくら簡単とはいえプログラムです。
先程の`;`を用いた**意味の分割**のような文法がいくつか存在します。
ここですべてを紹介することはしませんし、把握する必要もありません。

# おわりに
少しプログラミングチックになってきて、めんどくさいなと思った方がいるかもしれません。
ですがそこまで滅入る必要はありません。
最初からすべてのルールを把握している人などいないのです。
大切なのはエラーが起きたときに、原因を見つけ出すことにあります。

最初のうちはあまり深く考えずに、**そういうもの**という認識でMELを書くことをおすすめします。
MELを書くことが嫌いになっては元も子もありませんからね。

次回はこちら→[【ArtistでもMELが書きたい】Maya MEL入門(3)](https://qiita.com/Hum9183/private/f37458ee3730706098aa)

# 参考
https://knowledge.autodesk.com/ja/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2020/JPN/Maya-Scripting/files/GUID-20F702F9-8A4A-4961-83FC-F231841EF92B-htm.html
esp-idf の使い方

Ubuntu 24.10 で使いました。
デバイスは、M5Stack Core2 を使いました。

## インストール
詳しい説明はこちら
[Standard Toolchain Setup for Linux and macOS](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/linux-macos-setup.html)

必要なライブラリーのインストール

```bash
sudo apt-get install git wget flex bison gperf python3 python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0
```

ソースのダウンロード

```bash
mkdir -p ~/esp
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git
```

コンパイル

```bash
cd ~/esp/esp-idf
./install.sh esp32
```

```bash
. ./export.sh
```

バージョンの確認

```text
$ idf.py --version
ESP-IDF v5.5-dev-1655-gc5865270b5
```

## サンプルプロジェクトの作成

```bash
cd ~/esp
cp -r esp-idf/examples/get-started/hello_world .
```

main/hello_world_main.c を改造します。

```c:hello_world_main.c
（省略）
void app_main(void)
{
    printf("Hello world!\n");
    printf("Good Morning!\n");
    printf("Good Afternoon!\n");
    printf("こんにちは\n");

    /* Print chip information */
（省略）
```

コンパイル

```bash
idf.py build
```

デバイスにアップロード

```bash
idf.py -p /dev/ttyUSB0 flash
```

実行結果

```text
$ cu -l /dev/ttyUSB0 -s 115200
Connected.


I (289) app_start: Starting scheduler on CPU0
I (294) app_start: Starting scheduler on CPU1
I (294) main_task: Started on CPU0
I (304) main_task: Calling app_main()
Hello world!
Good Morning!
Good Afternoon!
こんにちは
This is esp32 chip with 2 CPU core(s), WiFi/BT/BLE, silicon revision v3.0, 2MB external flash
Minimum free heap size: 301900 bytes
Restarting in 10 seconds...
Restarting in 9 seconds...
```

## ソースを更に改造

プログラム

```c:main/hello_world_main.c
// -----------------------------------------------------------------------
/*
	main/hello_world_main.c

					Jan/28/2023
*/
// -----------------------------------------------------------------------
#include <stdio.h>
#include <unistd.h>

#define	VERSION	"2023-1-28 PM 20:35"
// -----------------------------------------------------------------------
void loop()
{
	int icount = 0;

	while(1)
	{
	printf("icount = %d\n",icount);
	printf("*** loop *** %s ***\n",VERSION);
	printf("Hello world!\n");
	printf("Good Morning!\n");
	printf("Good Afternoon!\n");
	printf("こんにちは\n");
	printf("\n");
	sleep(5);

	icount++;
	}
}

// -----------------------------------------------------------------------
void app_main(void)
{
	sleep(3);
	printf("*** 開始 *** %s ***\n",VERSION);
	sleep(3);

	loop();
}

// -----------------------------------------------------------------------
```

実行結果

```text
$ cu -l /dev/ttyUSB0 -s 115200
Connected.
*** 開始 *** 2023-1-28 PM 20:35 ***
icount = 0
*** loop *** 2023-1-28 PM 20:35 ***
Hello world!
Good Morning!
Good Afternoon!
こんにちは

icount = 1
*** loop *** 2023-1-28 PM 20:35 ***
Hello world!
Good Morning!
Good Afternoon!
こんにちは

icount = 2
*** loop *** 2023-1-28 PM 20:35 ***
Hello world!
Good Morning!
Good Afternoon!
こんにちは
```

## 関連情報
[esp-idf で c++ を使う](https://qiita.com/ekzemplaro/items/3947e64515491e434459)
[esp-idf: ssid のスキャン](https://qiita.com/ekzemplaro/items/3d8cbc0c22149a742d78)
[esp-idf: http_request の使い方](https://qiita.com/ekzemplaro/items/1a839027b1b6f5dde396)
[esp-idf: https_request の使い方](https://qiita.com/ekzemplaro/items/fb745494bd4f44e141f6)
ArduinoでSTM32L010がサポートされたけどなんも動かん(2023/1/28現在)

x なんかわからん

x STM32L010は、STM32L010F4P6の事


![o_cop369.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/64987178-d370-e308-da1c-37aafa3497d5.jpeg)


![o_cop368.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/88f6540d-84e0-3e93-63b1-21f9d796a7a0.jpeg)


![o_cop367.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/9cdc6f40-0649-8aaf-2691-df7696fb58d8.jpeg)