OmniAICreator/Qiita-1.07M huggingface dataset:
「うるさいえほん」の つかいかた

# １．「ひとコマアニメ」について

「ひとコマアニメ」は、４さいから、おとなまでつかえる、コンピュータアニメーションです。２０１８ねん、キッズプラザおおさかでうまれました。
（[こちらをみてみよう](https://9vae.blogspot.com/p/blog-page_15.html)）


# ２．うるさいえほん　をつくってみよう
さて、そんな　ひとコマアニメ　の　すごいやつ
 [ **うるさいえほん** ](http://web1.kcn.jp/minor/to_onep.html)　（　←　くりっく　してね！）の　しょうかい　だよ！

 **（みんなの　すごい　さくひんを　はやく　みたい　ひとは　[５．にすすんで　ください。](https://qiita.com/uminor/items/885a0c33be4552038418#%EF%BC%95%E3%81%BF%E3%82%93%E3%81%AA%E3%81%AE%E3%81%95%E3%81%8F%E3%81%B2%E3%82%93%E3%82%92%E3%81%BF%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86)）**


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216556/1751b0b3-17b1-3fff-3b24-c049e84df9a2.png)


# ３．こえを　いれて　みよう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216556/847d6928-311b-023c-3c95-0de7f05b1d27.png)

# ４．ほぞん　しよう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216556/5b532594-98fe-1268-15c6-a6d69f0604b4.png)


# ５．みんなの　さくひんを　みてみよう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216556/3b54e428-a61b-faba-f21a-04b90a502f98.png)

ここで　はんのう　しなくなったときは　したの「ひじょうぐち」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216556/718f94a8-d42f-5eef-809a-3636ce594dbc.png)
をおして「はっぴょう」から　やりなおして　ください。（すみません、、ばぐ　みたい・・）

きにいった　さくひんが　あれば　このぺーじの　したに　こめんと　してください。


# ６．じぶんの　さくひんを　おくってみよう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216556/924a129a-55e7-9c4e-bb0a-105eaab16227.png)

「じぶんのなまえ」は、ニックネーム　でもいいよ。
「みんなのさくひん」に　はいると、せかいじゅうの　ひとから　みてもらえるよ。

だけど、さくひんが　たくさんに　なると、ときどき「やみの　しはいしゃ」が　けしてしまうことが　あります。<!-- (※1) -->
あんまり　たくさん　おいておけないので　ごめんなさい。

# さんこうに　したもの
- 本アプリは、[ひとコマアニメーション（書き順アニメ） by Danjiro Daiwa 氏](https://qiita.com/danjiro/items/8dd0d7c7263f62189437
)の JavaScript 実装です。

- 「[ひとコマアニメーションはアニメーションの革命か？！](https://dnjiro.hatenablog.com/entry/2018/03/22/155249)」に思想的原点が記載されています。
<!--
- そういえば　[JavaScript版の初期バージョン](http://www.kinet-tv.ne.jp/~minor/onepager.html)　があった。。
-->
- 音声合成については 「[フリーソフト9VAeきゅうべえに音声合成機能をつけた](https://qiita.com/danjiro/items/ab8d42fe4fd969ab13bd)」を参考にしました。

- さらに、データフォーマットは上記 9VAe と一定の互換性を持っています。例えば、本アプリでは後からデータを編集する機能は無いですが、9VAeエディタを用いて編集可能とするポテンシャルを持っています。詳細はお問合せ下さい。
<!--
- ※1 自分の作品が闇の支配者に勝手に消されて困る人は、いーろんさんとかに本アプリを買い取ってもらうように働きかけてください。(なんならQiitaごとでもw)
-->
<!--
# 2023 スペシャルコンテンツ
- Javascript バージョン ( → [PLAY 2023] ボタンを押してね。)
http://web1.kcn.jp/minor/to_onep2023.html
-->
- youtube バージョン
https://www.youtube.com/watch?v=fjjik8fRI4c
ヘリウム原子に対するHartree-Fock方程式ソルバーをGPUで高速化してみた

この記事は，数値計算 Advent Calendar 2022 13日目の記事です．この記事では，[有限要素法で，ヘリウム原子に対するHartree-Fock方程式を解いてみる（Juliaでやってみた）の記事](https://qiita.com/dc1394/items/9444ca19937545b30ea1 "ヘリウム原子に対するHartree-Fock方程式を解いてみる（Juliaでやってみた）")のコードを，GPUで高速化することを考えます．このコードの律速は，一般化固有値問題を解いている箇所

```julia
    # 一般化固有値問題を解く
    eigenval, phi = eigen!(hfem_val.hg, hfem_val.ug)
```

の一行のみであり，この一行の部分に総計算時間の約95％が集中しています．従って，この部分をGPUに任せることで，高速化が期待できます．この部分をGPUに任せるには，上記のコードを以下のように変更します．

```julia
    # 一時配列の生成
    tmpA = zeros(hfem_param.ELE_TOTAL, hfem_param.ELE_TOTAL)
    tmpB = zeros(hfem_param.ELE_TOTAL, hfem_param.ELE_TOTAL)

    # 一時配列にデータをコピー
    copy!(tmpA, hfem_val.hg)
    copy!(tmpB, hfem_val.ug)

    # ホストメモリからデバイスメモリへデータコピー
    A = CuArray(tmpA) 
    B = CuArray(tmpB)

    # 一般化固有値問題を解く
    d_W, d_VA = CUSOLVER.sygvd!(1, 'V', 'L', A, B)
        
    # デバイスメモリからホストメモリへデータコピー
    h_W = collect(d_W)
    h_VA = collect(d_VA)
```

となります．なお，[CUDA.jl](https://cuda.juliagpu.org/stable/ "https://cuda.juliagpu.org/stable/")を使用するため，`using CUDA`が必要です．これだけで，一般化固有値問題がGPUで解けます．簡単ですね．

プログラムの実行時間を，CPUのみ，CPU+GPUの二通りで比較したもの（及び高速化の比率）を以下に表で示します．なお，パフォーマンスを測定した環境は，

* CPU: Intel Core i9-10980XE (Cascade Lake-X, Hyper Threading ON (物理18コア論理36コア), Enhanced Intel SpeedStep Technology OFF, Turbo Mode OFF)
* メモリ: DDR4-3200 32GB (8GB×4)
* GPU: GeForce RTX 3080 10GB (8704 CUDAコア)
* OS: Linux Mint 21 "Vanessa"
* Juliaのバージョン: v1.8.3

であり，CPUのみとCPU+GPUの双方とも，3回計測し平均を取りました（カットオフ$ r_c = 50.0(a.u.) $，$ \left\vert E\_{new}-E\_{old}\right\vert $の閾値$ 5 \times 10^{-12} $）．分割数は100～10000で計測しました．

|分割数|CPU（秒）|CPU+GPU（秒）|高速化の比率（倍）|
|:----:|:------:|:-----------:|:---------------:|
|100|0.4851|3.234|0.150|
|500|2.014|3.842|0.524|
|1000|7.264|5.390|1.348|
|5000|263.4|84.77|3.107|
|10000|2536|496.5|5.108|

また，上記の結果を以下にグラフで示します．

![helium_cpu_vs_cpu+gpu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58457/7be120fe-0148-6230-666e-b2d7f5f99107.png)

分割数が1000以上では，CPUよりCPU+GPUの方が高速になります．分割数10000では，CPUよりCPU+GPUの方が5倍以上高速です．ただし，CPUとCPU+GPUでは，計算の結果に違いが出てしまうことに注意が必要です．たとえば，分割数5000，カットオフ$ r_c = 50.0(a.u.) $，$ \left\vert E\_{new}-E\_{old}\right\vert $の閾値$ 5 \times 10^{-12} $のとき，CPUではenergy = -2.86157824923450だったのに対し，CPU+GPUでは，energy = -2.86157824922418であり，小数点以下11桁以下が異なる結果となりました．また，分割数5000，カットオフ$ r_c = 50.0(a.u.) $，$ \left\vert E\_{new}-E\_{old}\right\vert $の閾値$ 5 \times 10^{-13} $のとき，CPUではSCFの繰り返し回数が23回で収束しましたが，CPU+GPUでは，収束までにSCFの繰り返し回数が68回も必要になりました．ただしこの結果をもって，「CPUよりGPUの方が精度が悪い」とは一概に言えないと思います．

なお，CPU+GPUのコードは，[GitHubのこちら](https://github.com/dc1394/helium_hf_fem_cuda "https://github.com/dc1394/helium_hf_fem_cuda")で公開しています.
MLOPSにおけるツール

MLOPS ツールにはたくさんの種類がありますが、いくつか代表的なものを紹介します。

1. Jenkins: Jenkins は、ビルドやテスト、デプロイなどの作業を自動化するためのオープンソースツールです。Jenkins を使用することで、機械学習モデルの開発プロセスをより効率的に進めることができます。

2. Kubernetes: Kubernetes は、コンテナを管理するためのオープンソースプラットフォームです。Kubernetes を使用することで、機械学習モデルの運用やスケーリングをより簡単に行うことができます。

3. TensorFlow Extended (TFX): TFX は、Google が提供する機械学習用のフレームワークです。TFX を使用することで、機械学習モデルの開発から運用までを一貫して管理することができます。

また、以下のようなツールも MLOPS に活用されることがあります。

MLFlow: MLFlow は、機械学習モデルの開発プロセスを追跡、管理、再現性を確保するためのオープンソースプラットフォームです。

Airflow: Airflow は、ワークフローをスケジュール、監視、管理するためのプラットフォームです。Airflow を使用することで、機械学習モデルのトレーニングや推論を自動化することができます。

AWS SageMaker: SageMaker は、Amazon Web Services (AWS) が提供するクラウドサービスで、機械学習モデルの開発、トレーニング、推論を行うためのプラットフォームです。SageMaker を使用することで、MLOPS の一部を AWS 上で実行することができます。

以上が、MLOPS ツールの一部です。適切なツールを選択することで、機械学習プロジェクトをスムーズかつ効率的に進めることができます。また、異なるツールを組み合わせることで、より複雑な MLOPS ワークフローを構築することも可能です。

ただし、MLOPS には一定のリスクも伴います。例えば、モデルがトレーニングされるたびに異なる結果が生じる場合や、トレーニング中に問題が発生した場合など、適切な対応ができないと、プロジェクトの進捗が妨げられる可能性があります。
【初心者】AWS Wavelengthを使ってみる #8 (iptables 中継サーバによるキャリア網以外からのアクセス)

# 1. はじめに
- AWS Wavelengthはキャリア網(日本ではKDDI網)からのアクセスのみが許可されており、Wavelength Zone内にWebサーバを立てても、インターネットからアクセスすることはできない。検証などの際に不便なため、東京リージョンにiptablesによる中継サーバを立てて、Wavelength ZoneのWebサーバに対してインターネット経由でのアクセスを可能にする。

# 2. やったこと
- 東京リージョンとWavelength Zone(東京)の両方にsubnetを持つVPCを作成する。
- Wavelength Zone (東京) に、Webサーバ(nginx)を立てる。
- 東京リージョンに中継用のサーバ(Amazon Linux 2 のVM内にてiptablesを設定)を立てる。
- 手元のPC - インターネット - 中継サーバ - AWS VPC内ネットワーク - Webサーバ の経路でhttpアクセスを行う。

# 3. 構成図

![iptables構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/e9aa9f26-3c5a-3977-60cd-c904eef8659a.png)



# 4. 手順

東京リージョンに作成する中継サーバ(Amazon Linux 2) の設定内容を記載する。

## 4.1 IPフォワーディングの有効化

- /etc/sysctl.conf に以下を追記する。
``` /etc/sysctl.conf
net.ipv4.ip_forward = 1
```

- networkをrestartして設定を有効化する。
```
[ec2-user@ip-10-0-1-184 etc]$ sudo sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
[ec2-user@ip-10-0-1-184 etc]$ sudo systemctl restart network
[ec2-user@ip-10-0-1-184 etc]$ sudo sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
```

## 4.2 iptablesの設定
- 自分宛てのhttp(80/tcp)のパケットのDSTIPをWavelength上のWebサーバのIPアドレスに書き換える。また、SRCIPを自身のIPアドレスに書き換える。

```
[ec2-user@ip-10-0-1-184 ~]$ sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.0.0.27:80
[ec2-user@ip-10-0-1-184 ~]$ sudo iptables -t nat -A POSTROUTING -p tcp -d 10.0.0.27 --dport 80 -j MASQUERADE
```

- 手元のPCから、インターネット経由で「http\://中継サーバのEIP/」 にアクセスすると、中継サーバからWavelength上のWEBサーバへパケットが転送され、Webの画面を表示することができる。

![iptables01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/76923bbc-ed0f-a300-97a0-6553e398d95b.png)


## 4.3 設定の保存
- OS再起動しても設定が維持されるようにする。設定を保存するためのコマンドが使えるようにパッケージをインストールした上で、「service iptables save」で設定を保存する。 

```
[ec2-user@ip-10-0-1-184 ~]$ sudo yum install iptables-services
[ec2-user@ip-10-0-1-184 ~]$ sudo systemctl enable iptables
[ec2-user@ip-10-0-1-184 ~]$ sudo service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[  OK  ]
```
- 設定が保存されていることを確認する。

```
[ec2-user@ip-10-0-1-184 ~]$ sudo cat /etc/sysconfig/iptables
# Generated by iptables-save v1.8.4 on Fri Dec  9 14:53:39 2022
*nat
:PREROUTING ACCEPT [60:3120]
:INPUT ACCEPT [60:3120]
:OUTPUT ACCEPT [135:10974]
:POSTROUTING ACCEPT [135:10974]
-A PREROUTING -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.27:80
-A POSTROUTING -d 10.0.0.27/32 -p tcp -m tcp --dport 80 -j MASQUERADE
COMMIT
# Completed on Fri Dec  9 14:53:39 2022
```

# 5. 参考サイト
- [iptablesを利用してNATサーバを構築](https://techblog.raccoon.ne.jp/archives/47152095.html)
- [service iptables save がCentOS ７で出来ない( ﾟДﾟ)](https://tech.godpress.net/?p=503)

# 6. 所感
- サーバとクライアントを直接通信させることができない環境で中継サーバを立てることはよくありそうなので、今回の使い方以外でもいろいろ使えるように設定を理解していきたい。
MLOPSとは

MLOPS (Machine Learning Operations) とは、機械学習モデルの開発、運用、管理を統合するためのプラクティスやフレームワークのことを指します。MLOPS により、機械学習プロジェクトをスムーズかつ効率的に進めることができます。例えば、自動的にモデルの精度をモニタリングし、問題が発生した場合は自動的に再トレーニングすることができます。
RailsのYAMLファイルに正規表現を書いて使用する

# TR;DR

YAMLファイルから正規表現を読み込むようにするには`!ruby/regexp`に続けて正規表現を記述すればよいです。

# 背景

同じアプリケーションを、複数の国や、いくつかの企業毎に環境を分けて使用したいことがあります。
このように場合の対応策のひとつとして、アプリケーションのコードは同じものを使用しつつ、環境ごとに読み込むYAMLファイルを変えることで細かな設定を調整するやり方があります。

今回もその対応をしてたところ、文字列やフラグの値などはスムーズにYAMLファイルに定義して出し分けができたのですが、URLなどの正規表現を環境ごとに変えたかった際にどうすればいいかわからなかったので少し調べてみました。

# RailsにおけるYAMLファイルの読み込み処理

通常はYAMLファイルの読み込みは下記のように行います。

```ruby
path = # YAMLファイルへのパス
REG = YAML.load_file(path).symbolize_keys
```

しかし、今回はconfigをいうgemを使って`Settings`に読み込んでいました。

https://github.com/rubyconfig/config

```ruby
path = # YAMLファイルへのパス
Settings.add_source!(path)
Settings.reload!
```

# YAMLファイルで正規表現を定義する方法

## YAMLファイルとは

そもそもYAMLについておさらいすると、YAML(YAML Ain't Markup Language)とはどのようなプログラミング言語でも使える、人とって可読性が高くデータをシリアライズする言語です。
配列、ハッシュ、スカラ（文字列、数値、真偽値など）でデータを表現することができます。

## 配列を定義したいとき
`-`を使って定義します
```yml
- array_value1
- array_value2
```

## ハッシュを定義したいときは
`:`を使って定義します
```yml
hash_key: hash_value
```

## スカラを使いたいとき
YAMLでは、以下のデータ型を自動的に判別してくれ、それ以外は文字列として扱われます。
- 整数
- 浮動小数点
- 真偽値 (`true`, `yes`, `false`, `no`)
- Null値 (`null`,`~`)
- 日付 (`yyyy-mm-dd`)
- タイムスタンプ (`yyyy-mm-dd hh:mm:ss [+-]hh:mm`)

## 明示的に型を指定したいとき
`！`を使うことで型を指定することができます。Rubyのシンボルや正規表現も下記のように指定することができます。

```yaml
- !str 123            # 文字列
- !ruby/sym  foo      # Ruby の Symbol
- !ruby/regexp /^$/   # Ruby の Regexp
```

このように、明示的に正規表現の型を指定することで、YAMLファイルから読みだした正規表現をそのままRailsのコードで使用することができます。
```yml
reg:
  sample_regexp: !ruby/regexp /^[a-zA-Z|\s]+$/
```

##　サンプルコード

下記のように型を指定した場合と指定しない2つの値をYAMLファイルに定義してみました。

```yaml
regexp: !ruby/regexp /^$/
string: /^$/
```

こちらをRailsで読み込んだ後にコンソールからそれぞれの値とクラスを参照してみたところ、意図した通り型が指定されていたことがわかりました。

```ruby
[1] pry(main)> Settings.regexp
=> /^$/
[2] pry(main)> Settings.regexp.class
=> Regexp
[3] pry(main)> Settings.string
=> "/^$/"
[4] pry(main)> Settings.string.class
=> String
```

# 参考

https://qiita.com/clbcl226/items/c068f617aa34d552a50a

https://qiita.com/ShotaKameyama/items/4dfd3787faec3d2fb10b

https://magazine.rubyist.net/articles/0009/0009-YAML.html
Githubのプロフィールをカスタマイズしよう

# GitHubのProfileとは
この記事は<a href="https://qiita.com/advent-calendar/2022/n-s-highschool">N・S高等学校 Advent Calendar 2022</a>の11日目です。
オンラインTAしています。

みなさんは自分のprofileをカスタマイズしていますか?
https://github.com/{username} で最初にみれる画面のやつです {username}は自身のユーザネームにしてください
カスタマイズすることによって自分がどんな人なのか一目で分かるようになります



# 私のGitHub Profile
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2994704/c9960aaf-33a0-b635-8715-1167bd415dfe.png)


# カスタマイズの方法

https://docs.github.com/ja/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/managing-your-profile-readme
こちらを参考にしながら作成していきましょう

1. 自身の名前がついたリポジトリを作成
2. レイアウトを決める。
3. レイアウトに沿ったgithub apiを用いて  {username}/Readme.md  を編集する
4. [option] .github/workflows を用いて定期更新していく

以上の手順に沿っていけば完成します
最後の4はオプションなので時間があれば追記します。

## 1. 自身の名前がついたリポジトリを作成
そのままの意味です

## 2. レイアウトを決める
私は特に決めずに作成してしまったのでレイアウトがぐちゃぐちゃです
Githubアカウントの統計情報をとってきて円グラフにしたりContributionsをグラフ化したりすることができます
私は作っていないですがスキル一覧のようなものをつくれるらしいです。

## 3. レイアウトに沿ったgithub apiを用いて  {username}/Readme.md  を編集する

### GitHub Readme Stats を使う

これを使うとこの様な画像が作成できます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2994704/399fb521-641b-aa41-300e-f87682baf9ab.png)

```
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username={username}
)](https://github.com/anuraghazra/github-readme-stats)
```

#### Top Languages Card

下のものを書くと左のものが作成できます

```
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username={username}
)](https://github.com/anuraghazra/github-readme-stats)
```

#### GitHub Stats Card

これは右のものが作成できます
```
[![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username={username})]
(https://github.com/anuraghazra/github-readme-stats)
```
### Github Profile Trophy　を使う

これを使うとトロフィーをつけることができます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2994704/3136382e-1ac0-c01e-c531-e151351ef19c.png)

以下のものを張ってusernameのところを書き換えるだけです
```
[![trophy](https://github-profile-trophy.vercel.app/?username={username})](https://github.com/ryo-ma/github-profile-trophy)
```

# さいごに
参考文献に便利なサイトを載せておきます
今回使ったものを使ってみなさんのprofileをいじってみましょう
私はこれをつかってMost Used LanguagesをみてJupyter Notebookが使っている言語のほとんどを占めていてとても驚いたのを覚えています

# 参考文献
GitHub Profile Readme Generator
https://rahuldkjain.github.io/gh-profile-readme-generator/

全部無料！GitHubプロフィールの究極カスタマイズツールを厳選してみた！
https://paiza.hatenablog.com/entry/2022/07/06/160000

Awesome GitHub Profile READMEs
https://zzetao.github.io/awesome-github-profile/
strapiとsupabaseをつなぐ (DB編)

[IKEAのサメアイコンが一人で完走を目指す Advent Calendar 2022 2日目](https://qiita.com/ikea_shark_jk/items/2a442738b717cc68fa5e)ではローカルに立てられるheadlessCMSとしてStrapiを紹介しました。
Strapiの良い点の一つにDBを自由にできるという点があるのですが、同時にこれはDBを用意しなければならないという欠点でもあります。

個人にとって、RDSとかCloud SQLとかは著しく高いわけではありませんが、特にお安いわけでもありません。

これが会社なら、予算さえ確保しておけばとりあえず脳死でAWSやGCPを使えばよいですが、個人となるとそうもいきません。
別に会社であれば無尽蔵にお金を使ってよいというわけではないのですが、個人だと可能な限りお金を使いたくないので無料なものを使用したいです。

というわけで、ちょうど[昨日のアドベントカレンダーの記事](https://qiita.com/ikea_shark_jk/items/a65cd6534ad2e9e2cba0)で触ってみたsupabaseが偶然、たまたま、運よくPostgreSQLとして使用できたのでこちらの無料分を使っていきたいと思います。


## SupabaseのDBに直接繋ぐ

まず、Strapi環境を作成します。

```
npx create-strapi-app@latest
```

いつものごとく質問事項が出てくるので、ぺちぺち適当な値を入力します。
DB関連は下手にsupabaseを見に行ったりせず、本当に適当な値を入れていきましょう。

```
? What would you like to name your project? temp_strapi
? Choose your installation type Custom (manual settings)
? Choose your preferred language TypeScript
? Choose your default database client postgres
? Database name: temp_strapi
? Host: 127.0.0.1
? Port: 5432
? Username: pass
? Password: ****
? Enable SSL connection: Yes
```



以前の記事ではAPI経由でDBにつなぎましたが、実は直繋ぎもできたりします。
ダッシュボードから。Setting > Databaseと行くと、接続に必要な各種情報が記載されているページにたどり着くことができます。
そちらに記載されている値を見ながら、先ほど作成したStrapiの`config/database.ts`を見に行きましょう。

```config/database.ts
export default ({ env }) => ({
  connection: {
    client: 'postgres',
    connection: {
      host: env('DATABASE_HOST', '127.0.0.1'),
      port: env.int('DATABASE_PORT', 5432),
      database: env('DATABASE_NAME', 'temp_strapi'),
      user: env('DATABASE_USERNAME', 'pass'),
      password: env('DATABASE_PASSWORD', 'pass'),
      ssl: env.bool('DATABASE_SSL', true),
    },
  },
});

```

するとはい、このように先のCLI上で入力した値が載っています。
ポートとかはかわいいもんですけど、**ホスト先とパスワードここに直書きしてくるの勘弁してほしいですね**。`.env`に吐け。

一通り値を消して、そこに記載されている環境変数に合わせてsupabaseのダッシュボードの内容を`.env`に記載していきましょう。

```.env
//...

DATABASE_HOST=
DATABASE_PORT=
DATABASE_NAME=
DATABASE_USERNAME=
DATABASE_PASSWORD=
DATABASE_SSL=
```

```config/database.ts
export default ({ env }) => ({
  connection: {
    client: "postgres",
    connection: {
      host: env("DATABASE_HOST"),
      port: env.int("DATABASE_PORT"),
      database: env("DATABASE_NAME"),
      user: env("DATABASE_USERNAME"),
      password: env("DATABASE_PASSWORD"),
      ssl: env("DATABASE_SSL", true)
    }
  },
});
```

記入が終わったら、SSLで接続するための証明書を用意します。
supabaseのDatabase settingsにある↓の項目からダウンロードできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532032/65ba1e11-7331-30cf-dba5-2873599e2dd9.png)

ダウンロードしたら、適当な名前を付けて適当な場所に置いておきます。
設置を確認して、そこのパスを指定してreadFileSyncで証明書情報を取得しましょう。
以下は、プロジェクトのルートに置いた際の例です。

```config/database.ts
import { readFileSync } from "node:fs";

// ...
      ssl: env.bool("DATABASE_SSL")
        ? {
            ca: readFileSync(
              `${__dirname}/../../supabase.crt`
            ).toString(),
          }
        : false,
```

正直もうちょっとやり方あった気がするんですがまあいいでしょう。
まじめにやるならbase64変換して環境変数にでも渡してあげた方がよいかもしれません。

これで準備完了です。
developで開発環境を立ち上げて一通り操作したのち、supabaseを見に行くとすごい数のテーブルが作成されていることが確認できるかと思います。


## 終わりに

というわけで、ひとまずはここまでです。
firebaseとは異なり内部でpostgreSQLが動いてるとこういったことができるので便利ですね。
ただ、これだとファイルがstrapi管理になっていて片手落ちなので、近いうちにこれもsupabase管理にする記事を書きたいと思います。
Flutter carousel_sliderでアクティブなcontrollerを表示したい

業務でFlutterを用いる際、簡単にカルーセルを使用するために`carousel_slider`というパッケージを導入しました
`carousel_slider`の機能には、カルーセルそのものを左右にスワイプして動かすほか、独立した他のwidgetに`CarouselController`オブジェクトを操作させて動かすものがあります

pub.devに記載のexampleでは以下のように使用されています

```dart
final CarouselController _controller = CarouselController();

carouselController: _controller,
```

操作widget

```dart
...Iterable<int>.generate(imgList.length).map(
    (int pageIndex) => Flexible(
        child: ElevatedButton(
            onPressed: () => _controller.animateToPage(pageIndex),
            child: Text("$pageIndex"),
        ),
    ),
),
```

このままで操作は可能なのですが、選択されている（アクティブな）操作widgetを明示したい場合があります

その際に以下のように、外部の`state`などで選択されているインデックスを保存しそれが選択されたインデックスと同じか判定することで実装するとします
```dart
int selectedIndex = 0;
void onPressed(int pageIndex) {
    setState(() {
        selectedIndex = pageIndex;
    });
    this._controller.animateToPage(pageIndex);
}

//~~~略~~~

...Iterable<int>.generate(widget.images!.length).map(
    (int pageIndex) => Flexible(
        child: TextButton(
            onPressed: () {
                onPressed(pageIndex);
            },
            child: Container(
                decoration: pageIndex == selectedIndex
                    ? BoxDecoration(border: Border.all(width: 2))
                    : null,
                child: Image.network(
                    widget.images![pageIndex],
                ),
            ),
        ),
    ),
),
//~~~
```
この実装で、controllerを用いてカルーセルを動かした際に選択されたwidgetがアクティブであると表示できました

しかしこのままではcontrollerではなくカルーセル部分をスワイプしてカルーセルを切り替えると`selectedIndex`が切り替わらずアクティブの表示ができない問題が発生します
そこで、カルーセルからの操作を検知してアクティブなインデックスを切り替えるように追記します

`CarouselOptions`の`onPageChanged`を記述することでこのような変更を受け取って実行される関数を指定できます
```dart
CarouselSlider(
    options: CarouselOptions(
        onPageChanged: (index, reason) => {
            onPressed(index)
        },
```
このように書くとカルーセルが動いた際に**動いた直後のインデックス**を引数として更新する関数を実行します
そのため、実際にはこのコードだと
「コントローラーから移動先を指定する」
↓
「指定通りにカルーセルが動き出す」
↓
「カルーセルが動き出したため`onPageChanged`が発火」
↓
「ここでインデックスに渡されるのは動き出した先のカルーセルなので指定に関係なくすぐ横のカルーセルに`pageindex`が更新される」

といった流れで操作すると強制的に次のページになってしまう減少が発生します
これを避けるため、カルーセルが更新されたときの条件として、コントローラー経由の際には自動で更新を行わないよう追記します

`onPageChanged`の第二引数で`reason`というものがあり、具体的には
```dart
enum CarouselPageChangedReason { timed, manual, controller }
```
として３種類の値が定義される`CarouselPageChangedReason`オブジェクトを受け取れます

これを用いて次のように記述すると以上の問題が解決されます
```dart
onPageChanged: (index, reason) => {
    if (reason == CarouselPageChangedReason.timed ||
        reason == CarouselPageChangedReason.manual)
            {onPressed(index)}
},
```
シェルスクリプトに引数を渡す方法

## 引数を渡す方法

以下の内容で`sample.sh`を作成します。  

```sample.sh
echo "引数: $@"

echo "引数1: $1"
echo "引数2: $2"
echo "引数3: $3"
```

ターミナルで次のようにコマンドを実行すると引数を渡せます。  

```terminal
 bash sample.sh arg1 arg2 arg3
```

```terminal
$ bash sample.sh arg1 arg2 arg3
引数: arg1 arg2 arg3
引数1: arg1
引数2: arg2
引数3: arg3
```
Next.js(React)にて絶対パスでimportする方法

Next.js(React)では、デフォルトだとコンポーネントなどを相対パスでimportするようになっています。
本記事では、Next.jsにて絶対パスでimportする方法を解説しています。

## jsconfig.json(tsconfig.json)で設定する

Next.jsの`jsconfig.json`に下記の設定を追加します。（※TypeScriptの場合は`tsconfig.json`です。）

```json:jsconfig.json
{
  "compilerOptions": {
    "baseUrl": "."
  },
}
```
`baseUrl`にオプションを設定することで、絶対パスでimportすることができます。

```tsx:index.tsx
// import Layout from '../components/layout/Layout'
import Layout from 'components/layout/Layout' // 絶対パスで指定

const Home = () => {
  return (
    <>
      <Layout />
    </>
  )
}

export default Home
```
https://nextjs.org/docs/advanced-features/module-path-aliases

## Visual Studio Code(VSCode)にて自動で絶対パスをimportする

VSCodeではコンポーネントなどを記述する際に自動でimportしてくれる機能があります。
自動importを絶対パスにするには、VSCodeの設定を変更します。

設定を開いて下記の画像のように`JavaScript › Preferences: Import Module Specifier`を`non-relative`に設定します。

![next.js絶対パス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/13c8841c-fdff-0e0e-a87b-b4eea720295d.png)

上記の設定をすることで`baseUrl`に基づいてimportをしてくれるようになります。

ちなみにVSCodeではjsonファイルで設定を管理することもできます。
`.vscode`ディレクトリの`settings.json`ファイルで管理します。

![next.js vscode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/bf47011d-bfad-39c1-0dba-7a2ccd448461.png)

```json:settings.json
{
  "javascript.preferences.importModuleSpecifier": "non-relative"
}
```

## 最後に
本記事ではNext.jsにて絶対パスでimportする方法を解説してきました。
プロジェクトが大きくなり、ディレクトリの階層が深くなる場合などは絶対パスの方が便利かなと思います。
Canvas2D ４点グラデーションの実装実験

この記事は [Web グラフィックス Advent Calendar 2022](https://qiita.com/advent-calendar/2022/webgraphics) の11目の記事です。

# 簡単にきれいなグラデーションがしたい

筆者は個人でドロー系のお絵かきツールを作っています。

[前回](https://qiita.com/warotarock/items/8920c23e7daed0013f69)は放射状グラデーション（RadialGradient）を細分割して線をはみ出さないようにしてみましたが、パフォーマンス面で問題がありました。放射状だけで塗ることに限界を感じたため、もっと他のアプローチを考えてみました。

考えてみると、イラストなどの絵を描くために塗りつぶしをする場合、ベタ塗りだけで用が足りるとは限りません。色や濃淡を変えながら塗るわけですが、できるだけ簡単にきれいにグラデーションさせることができたら嬉しいです。また、ドロー系ツールなので、後からデータを変更するのが楽であるという強みを生かしたいです。

# ４点グラデーション(Quad gradient)

で、思い当たったのが、色を持った４つの頂点の間を補間して描画することです。これをここでは「４点グラデーション」と呼ぶことにします。

<details><summary>英語での呼称について</summary>
英語では Four point gradient とか Bilinear gradient とか Quad gradient 等と呼ばれるようです。CG技術の界隈では正方形にかぎらない四角形のことをQuadと呼ぶほうが伝わりやすいため、ここではその言葉を使います。
</details>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59191/2d6a6d12-30a0-8caf-aea5-9f20927a831e.png)

これなら編集データが少なくて楽ですし、頂点の位置をうまく調整すれば線をはみ出さないように塗ることができるかもしれません。また、頂点三つではなく四つなのは、グリッドとして並べることを想定しているからです。

# 描画処理の概要

アルゴリズムとしては、四角形の中のある点(x, y)に対応する正規化座標(t, u)を計算する、そして色の線形補間をする、という考え方で行きます。

まず２辺を決め、その辺上の点をp1(x1, x2)、p2(x2, y2)とします。p1、p2の位置は一つの変数t(0.0～1.0)をパラメータとして線形補間されるものとします。

![20221211_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59191/95722e0d-8c54-c368-8183-2f35927979a1.png)


ここでp1、p2を通る直線を考えると、tがいずれかの値のときに(x, y)を通るはずです。とすると、次の式が成り立ちます。xa1などは２辺を表す直線のパラメータです。

    x1 = xa1 * t + xb1
    y1 = ya1 * t + yb1
    x2 = xa2 * t + xb2
    y2 = ya2 * t + yb2
    y = (y2 - y1) / (x2 - x1) * (x - x1) + y1

最後の式にx1, y1, x2, y2を代入すると次の式が得られます。

    y = (ya2 * t + yb2 - (ya1 * t + yb1)) / (xa2 * t + xb2 - (xa1 * t + xb1)) * (x - (xa1 * t + xb1)) + ya1 * t + yb1

これをtについて解けばいいわけですが、手作業でやるには（やってはみましたけど）難しいので数式ツールにかけて展開します。最終的に二次式になりますので、tの値を求めることができます。残りの２辺について同様に求めれば、uについても計算できます。

あとはtで２辺の色を線形補間して、得られた２色をさらにuで線形補間すれば(x,y)の色を計算することができます。

ついでにtとuが0.0～1.0の間であるかどうかで内外判定もできますので、四角形の中だけを塗りつぶすこともできますね。

ということで、何番煎じか知りませんが実装してみました。

# 実装したもの

Canvas2Dの機能だけではできないため、バイトデータの操作で実装しています。

<p class="codepen" data-height="750" data-default-tab="result" data-slug-hash="xxzevjm" data-user="warotarock" style="height: 750px; 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/warotarock/pen/xxzevjm">
  Canvas2D ４点グラデーションの実装実験</a> by 柏崎ワロタロ (<a href="https://codepen.io/warotarock">@warotarock</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

GPUを使ったCGのサンプルだと最初に虹色の三角形を描画することが多いですけど、四角形というのはわりと少ない気がします。そのためかちょっと新鮮な感じがしました。

# まとめ

- 放射状グラデーションだけでは限界なので別の方法を考えた
- ４点グラデーションのアルゴリズムを考え、実装した
- 三角形のグラデーションと一味違うものを感じた（感想）

実はまだ続きます。次回、４点グラデーションでグリッドを描画します。
カレンダー埋まらないなー(笑)
【Microsoft】C#でリストを作る


```list.cs
//構文
var 変数名 = new List<T> {};
```
var型で定義し、変数名に何のデータ型が入ってくるか、型推論してくれる。
List型なのでList型で定義しても良い。

```lsit.cs
var items = List<string> {"つるぎ", "やくそう", "何かのカギ"};
var level = List<int> {1, 2, 3};
```
このように文字列はstring型で、整数はint型でデータをリストに格納する。

```list.cs
var items = List<string> {"つるぎ", "やくそう", "何かのカギ"};

Console.WriteLine(items[0]);
```
リストの中から選び取ることができる。選び方はインデックス番号と言って、最初が０番目から数値が割り当てられる。


```list.cs
var items = List<string> {"つるぎ", "やくそう", "何かのカギ"};

foreach(var item in items)
{
    Console.WriteLine(item);
}
```
foreach文を使って、リストの長さだけ繰り返して一個ずつ取り出すことができる。

```list.cs
var items = List<string> {"つるぎ", "やくそう", "何かのカギ"};

items.Add("お手紙");

Console.WriteLine(items[3]);
```
また、Add関数を使ってリストにデータを付け加えることもできる。
この場合はすでに0,1,2の順でインデックス番号のリストデータが格納されているので、インデックス番号3に"お手紙"が入ることになる。

```list.cs
var items = List<string> {"つるぎ", "やくそう", "何かのカギ"};

items.Remove("やくそう");

Console.WriteLine(items[1]);
```
Remove関数を使えば、リストからデータを削除することができる。
この場合は、インデックス番号1の"やくそう"が指定されているので、"やくそう"というデータは削除され、"何かのカギ"がインデックス番号1になる。

```list.cs
var items = List<string> {"つるぎ", "やくそう", "何かのカギ"};

Console.WriteLine(items.IndexOf("やくそう")); //結果: 1
Console.WriteLine(items.IndexOf("つるぎ"));  //結果: 0
Console.WriteLine(items.IndexOf("宝石"));   //結果: -1
```
IndexOf関数を使うと、リストの中を検索してそのインデックス番号を返してくれる。
もし探したいものがなければ、-1を返してくれる。
pythonでアルゴリズムトレード開発日誌 1/n

# pythonを用いたアルゴリズムトレードの開発日誌

開発日誌ではありません。（笑）

先日友達から、「pythonからはじめるアルゴリズムトレード」をお勧めされて、
コンテナと機械学習の勉強になればという思いと、
トレードで儲けたいという思いが3:7で勉強を始めることにしました。（笑）

https://amzn.asia/d/9XfPYO0

おそらく、前提知識が足りていないので、環境準備に時間がかかっています。
とりあえず、dockerでJupiterLabを触れるようにしてみたので、備忘録として記事を書きます！

# 環境準備とpythonの実行確認

## 環境
        OS: Windows 10 Pro
    image : python:3.9.7-buster
    docker: 20.10.14

## コンテナの作成
フォルダの構成とコンテナの作成は、以下のサイトを参照。
めちゃくちゃ迷子してたが、このサイトの言うとおりにしたらとりあえず環境は完成した。

https://www.idnet.co.jp/column/page_187.html

`docker-compose up` の部分は `docker-compose up -d` に変更

### コンテナが動いているかの確認
コマンドプロンプトで、
```cmd:cmd
docker ps
```

として、以下のように書かれていたらコンテナが動いてる。

```
(base) PS C:\User\***> docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED       STATUS       PORTS                      NAMES
8d69f508e694   pyalgo_py3   "jupyter-lab --allow…"   3 hours ago   Up 2 hours   127.0.0.1:8888->8888/tcp   pyalgo_py3_1
```

### コンテナの停止
```cmd:cmd
docker stop CONTAINER ID  # コンテナの停止
docker ps     # コンテナの確認
```
とすると消える。
```
(base) PS C:\Users\***> docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
```
`CONTAINER ID`の部分は、この場合、`8d69f508e694`
※ `8d`とかまで打つといける。
この場合、
```cmd:cmd
docker stop 8d
```
でいける。

### コンテナの再開
再開は、
```cmd:cmd
docker start CONTAINER ID  # コンテナの再開
```

### JupyterLabを開く
ブラウザで、`http://localhost:8888/lab`から開ける。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/7658959d-e590-553b-abd4-318c0516944a.png)


## pythonの実行確認

実行確認のために、企業のデータをcsvでダウンロードしてpythonで読み込んでみます。
[Kaggle](https://www.kaggle.com/)というプラットフォームから、2020年4月のApple社の株価を取得します。

https://www.kaggle.com/datasets/khoongweihao/aaplcsv

保存先は、workspace/archive/dataです。

### pythonを使ってデータを読み込む
保存したデータを、pythonを使って読み込みます。
```python:
In [1]: fn = 'data/archive/AAPL.csv'
In [2]: with open(fn, 'r') as f:
         for _ in range(5):
          print(f.readline(), end='')
```
上を実行すると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/ff5304a2-57e3-2dae-e47b-aaf6840ca5e7.png)

**できたー！！！**
これは、データをメモリに取り込んでるわけではないので、これ以上利用できない。
以降は、また今度やる。
【Tips】TFLintのチェックをGit hooksで自動化するときのプラクティス

# 問題点
TFLintのチェックはたしかに強力だが、以下のようなコードでは意図した検査をしてくれないことがある。

```HCL:サンプル1: 三項演算子で通らないルート
locals {
  lambda_function_dev_name = "${var.prefix}-dev-function"
  lambda_function_prd_name = ""
}

resource "aws_lambda_function" "example" {
  function_name = var.environment == "dev" ? local.lambda_function_dev_name : local.lambda_function_prd_name
  filename      = data.archive_file.example.output_path
  # (以下略)
}
```

```HCL:サンプル2: count = 0 になって通らないルート
resource "aws_lambda_function" "example" {
  count = var.environment == "dev" ? 0 : 1

  function_name = ""
  filename      = data.archive_file.example.output_path
  # (以下略)
}
```

いずれのケースでも、

```bash
tflint --var=environment=dev
```

としてもエラーにはならず、```--var=environment=prd```の場合のみエラーとなる

```bash
tflint --var=environment=prd
4 issue(s) found:

Error: "" does not match valid pattern ^(arn:(aws[a-zA-Z-]*)?:lambda:)?([a-z]{2}(-gov)?-[a-z]+-\d{1}:)?(\d{12}:)?(function:)?([a-zA-Z0-9-_]+)(:(\$LATEST|[a-zA-Z0-9-_]+))?$ (aws_lambda_function_invalid_function_name)

  on 13_lambda.tf line 15:
  15:   function_name    = var.environment == "dev" ? local.lambda_function_dev_name : local.lambda_function_prd_name

Error: function_name must be 1 characters or higher (aws_lambda_function_invalid_function_name)

  on 13_lambda.tf line 15:
  15:   function_name    = var.environment == "dev" ? local.lambda_function_dev_name : local.lambda_function_prd_name

Error: "" does not match valid pattern ^[\.\-_/#A-Za-z0-9]+$ (aws_cloudwatch_log_group_invalid_name)

  on 13_lambda.tf line 84:
  84:   name              = ""

Error: name must be 1 characters or higher (aws_cloudwatch_log_group_invalid_name)

  on 13_lambda.tf line 84:
  84:   name              = ""
```

prdにマージしたときや、prdのパイプラインでTFLintを回せばエラーを検知できるだろうが、prdに行こうとした時点でエラーになる時点で、その日にやろうとしていたプロダクション環境の作業が予定通りに進まないだろう。

# 解決策
解決策はシンプルで、結局、Git hookのpre-commitで以下のようにして全ルートを通した時のみCommit可とすべきだろう。
チームで変数利用におけるルールをちゃんと定義して、シンプルに全ルートを通せるようにしておくのが重要だろう(分岐のパターンが増えれば増えるほど検査に必要な数が増える)

```shell:.git/hooks/pre-commit
#!/bin/sh

CMD="tflint --var=environment=dev"
echo ${CMD}
${CMD} || exit 1

CMD="tflint --var=environment=prd"
echo ${CMD}
${CMD} || exit 1

exit 0
```

なお、.git/hooksディレクトリ配下はremoteにpushされないため、作ったスクリプトは、リポジトリ上に配置して以下のコンフィグを入れておこう。--global しない情報は各リポジトリ単位で管理されるので、チームで共有する場合はチェックアウト時に忘れないようにしてもらおう。
※以下の例では、リポジトリのルートディレクトリ配下に```.githooks/pre-commit```を配置している前提とする

```bash
git config core.hooksPath .githooks
```
ほぼ耐久試験？AWS、GCPのMachine Learning認定試験を受験してみた

AWS、GCP (Google Cloud Platform)のMachine Learning認定試験をオンライン受験しました。

- AWS Certified Machine Learning - Specialty （以下AWS ML）
https://aws.amazon.com/certification/certified-machine-learning-specialty/
https://d1.awsstatic.com/training-and-certification/docs-ml/AWS-Certified-Machine-Learning-Specialty_Exam-Guide.pdf
時間: 3時間
受験料：$300
受験日：2022/12/4

- Google Cloud Certified Professional Machine Learning Engineer（以下GCP ML）
https://cloud.google.com/certification/machine-learning-engineer
時間：2時間
受験料：$200
受験日：2022/11/6

私は現職での大半のプロジェクトではオンプレミス環境を使用しており、（DockerイメージをGoogle Container RegistryにPushしてGoogle Kubernetes Engine にデプロイしたことがある以外に）クラウドを使った経験はほとんどなく、クラウドの認定試験は初めてでしたが、付け焼き刃でも何とかなりました。

AWS MLは2年、GCP MLは1年以上の使用経験が推奨されていますが、クラウドを使ったことがなくても一般的なMLの経験がある方であれば、どちらかの受験を検討されてもいいかもしれません。

数えたわけではありませんが、AWS MLは40〜50%程度、GCP MLは20~30％程度の問題で、それぞれのクラウドサービスについての知識が必要だったように記憶しています。（実際に出題された試験問題はシェアできないことになっています。）

### 最大の注意点

AWS MLは3時間、GCP MLは2時間の間、途中休憩はありませんので、特に非人道的に長いAWS MLの場合には、受験前のどのタイミングでどの程度の水分をとってトイレに行っておくかがとても重要になります。（死にかけました）

### オンライン受験特有の注意点

両方とも、オンライン受験のためのアプリはmacOSも対応していますが、Windows のほうが無難のようです。
AWS ML では、 MacBook Pro上でPearson OnVUEの事前テストアプリがシングルクリックで反応せず、なぜかトリプルクリックしないといけなかったので、Windows 10のPCを使用しました。

オンライン受験する場合、ウェブカメラで監視されます。周囲に物があると受験を許可されないことになっています。

自分の場合は、机の上は片付けて、視界に入る棚にはレジャーシートをかけて物が見えないようにしました。

### 認定ページ

AWS MLは翌日、GCP MLは5日後に、以下の認定ページが発行されました。

AWS Certified Machine Learning - Specialty
https://www.credly.com/badges/5662bdee-e49d-4d08-9426-37c73420f708

Google Cloud Certified Professional Machine Learning Engineer
https://www.credential.net/00bd4a92-90bb-4145-b236-e6d80031b300?key=aa1ffc9adbf75f06d330ec520fb45f540aa033c6a9c5112d9bea7399cb1de912


### 参考リソース
（アフィリエイトではありません）

- AWS
  - https://www.amazon.co.jp/AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8-%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3-%E5%B7%9D%E7%95%91-%E5%85%89%E5%B9%B3-ebook/dp/B0B81PZY8H

  - https://docs.aws.amazon.com/sagemaker/latest/dg/algos.html

- GCP
  - https://www.amazon.co.jp/Google-Cloud-Platform-%E3%82%A8%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%97%E3%83%A9%E3%82%A4%E3%82%BA%E8%A8%AD%E8%A8%88%E3%82%AC%E3%82%A4%E3%83%89-%E9%81%A0%E5%B1%B1-%E9%99%BD%E4%BB%8B-ebook/dp/B07C85YMCW/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=21R8D815MMT87&keywords=Google+Cloud+Platform+%E3%82%A8%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%97%E3%83%A9%E3%82%A4%E3%82%BA%E8%A8%AD%E8%A8%88%E3%82%AC%E3%82%A4%E3%83%89+Kindle%E7%89%88&qid=1670760655&s=digital-text&sprefix=google+cloud+platform+%E3%82%A8%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%97%E3%83%A9%E3%82%A4%E3%82%BA%E8%A8%AD%E8%A8%88%E3%82%AC%E3%82%A4%E3%83%89+kindle%E7%89%88%2Cdigital-text%2C245&sr=1-1
Javaで何か作ってみる(2022/12/11 Day52)

## 今日やった事
- オブジェクト指向の動画教材を見た。（**J2-06_static** まで見た。）
## 参考にしたもの
- [Spring 入門 ～ SpringBoot 2 を使ってお問い合わせアプリとToDoアプリを作る ～](https://www.udemy.com/course/java_spring_beginner/)  
- [【超初心者も必見】Javaプログラミングの「オブジェクト指向」が絶対理解できる講座【プロ講師が丁寧解説】](https://www.udemy.com/course/uz-java-obj/)  
## 所感
- staticは、必要な時だけ使用するようにする（メモリ食うからねー）
## 明日の予定
- 引き続き、動画教材を進めていく。
Javaで何か作ってみる(2022/12/10 Day51)

## 今日やった事
- オブジェクト指向の動画教材を見た。（**J2-05_継承②** まで見た。）
## 参考にしたもの
- [Spring 入門 ～ SpringBoot 2 を使ってお問い合わせアプリとToDoアプリを作る ～](https://www.udemy.com/course/java_spring_beginner/)  
- [【超初心者も必見】Javaプログラミングの「オブジェクト指向」が絶対理解できる講座【プロ講師が丁寧解説】](https://www.udemy.com/course/uz-java-obj/)  
## 所感
- 継承については理解出来たと思う。
## 明日の予定
- 引き続き、動画教材を進めていく。
Javaで何か作ってみる(2022/12/9 Day50)

## 今日やった事
- オブジェクト指向の動画教材を見た。（**J2-04_継承①** まで見た。）
## 参考にしたもの
- [Spring 入門 ～ SpringBoot 2 を使ってお問い合わせアプリとToDoアプリを作る ～](https://www.udemy.com/course/java_spring_beginner/)  
- [【超初心者も必見】Javaプログラミングの「オブジェクト指向」が絶対理解できる講座【プロ講師が丁寧解説】](https://www.udemy.com/course/uz-java-obj/)  
## 所感
- 継承については理解出来たと思う。
## 明日の予定
- 引き続き、動画教材を進めていく。
TypeError: __call__() missing 1 required positional argument: 'image'

diffusersのインターフェースが0.10.0でまた変わりました（やめてくれ）。

https://github.com/huggingface/diffusers

名前付き引数が`init_image`から`image`に変更されています。

```python:
pipe = StableDiffusionImg2ImgPipeline.from_pretrained(
    model_id_or_path,
    revision="fp16", 
    torch_dtype=torch.float16,
).to("cuda")
images = pipe(prompt=prompt, image=init_image, strength=0.75, guidance_scale=7.5).images
```
【GMC-4】爆弾ゲーム

学研の4ビットマイコンGMC-4で爆弾ゲームを作ってみた。

# 爆弾ゲーム

爆弾の前にスイッチが何個か並んでいる。
そのうち1個だけ、押すと爆弾が爆発するスイッチがある。

* 複数人で遊ぶ場合
  * まだ押されていないスイッチを順番に1個ずつ押していく。
  * 爆弾を爆発させた人が負け。
* 1人で遊ぶ場合
  * スイッチを押していく。
  * 爆弾を爆発させたらゲームオーバー。
  * 爆弾を爆発させずに押していないスイッチを1個だけにできたらクリア。

# 仕様

実行開始後、何かキーを押すとゲームが開始し、2進LEDが全て点灯する。
ゲーム中、点灯している2進LEDがまだ押されていないスイッチを表す。
0～6の数字キーを押すことで、スイッチを押す。
まだ押されていないスイッチを押したとき、それが爆弾を爆発させるスイッチではなかった場合は、短い音を鳴らす。
爆弾を爆発させるスイッチだった場合は、7セグメントLEDにそのスイッチの番号を表示し、エラー音を鳴らす。

# プログラム

以下のプログラムは、[MikeAssembler](https://mikecat.github.io/mike_assembler/) でアセンブルできる。

```
target gmc4

	; 爆発スイッチの位置をランダムで選ぶため、スタートボタン待機
	TIY 6
start_wait_loop:
	AIY -1
	JUMP random_no_return
	TIY 6
random_no_return:
	KA
	JUMP start_wait_loop
start_release_wait_loop:
	KA
	JUMP start_release_wait_loop_end
	JUMP start_release_wait_loop
start_release_wait_loop_end:
	; 爆発スイッチの位置を[7]に格納する
	CY
	TIY 7
	AM
	; [0]～[6]を「押されていない」に設定し、2進LEDを点灯する
	; (爆発スイッチの位置0～6は、2倍してキャリーが出ない)
led_init_loop:
	AIY -1
	AM
	CAL SETR
	CIY 0
	JUMP led_init_loop
	; メインループ
game_loop:
	KA
	; 範囲外や既に押された所なら、再入力させる
	; 1回押されたら押された所になるので、押し待ち・離し待ちは不要
	; …と思ったが、FX-マイコン シミュレータでは押してなくてもAレジスタが前回入力値になってしまう
	JUMP game_loop
	AIA 0x10 - 7
	JUMP game_loop
	AIA 7
	CY
	MA
	; 0～6(押されていない)の時は飛ばない、F(押された)の時は飛ぶ
	M+
	JUMP game_loop
	; 新しいスイッチが押された
	CY
	TIY 7
	M-
	CIA 0
	JUMP safe_process
	; 押されたのは爆発スイッチだった
	M-
	AO
	CAL ERRS
game_end:
	JUMP game_end
safe_process:
	; 押されたことを記録し、2進LEDを消灯する
	M-
	CY
	TIA 0xF
	AM
	CAL RSTR
	CAL SHTS
	JUMP game_loop
```

以下は、このプログラムの機械語表現である。

```
  | 0 1 2 3  4 5 6 7  8 9 A B  C D E F
--+-----------------------------------
0 | A 6 B F  F 0 9 A  6 0 F 0  2 0 F 1
1 | 4 F 0 D  3 A 7 4  B F 4 E  1 D 0 F
2 | 1 8 0 F  2 2 9 9  F 2 2 9  7 3 5 6
3 | F 2 2 3  A 7 7 C  0 F 4 3  7 1 E 8
4 | F 4 0 7  3 8 F 4  E 2 E 9  F 2 2
```

# 実行結果

<iframe width="560" height="315" src="https://www.youtube.com/embed/7hZZ3g6nB3c" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
【Laravel + ajax】画面遷移しないでフォームに入力した内容を表示する

## サンプル
![qiita.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218398/ea89e25e-f5f7-c14e-db9f-15504814ad85.gif)

## コード

### ルーティング処理

```\routes\web.php
// 表示するメイン画面
Route::get('/splite_blade/','SpliteBlade\SpliteBladeController@index')->name('splite_blade.index');
// フォームの内容を受け取って、処理をして返す
Route::post('/splite_blade/ajax/','SpliteBlade\SpliteBladeController@ajax')->name('splite_blade.ajax');
```

### コントローラー

```\app\Http\Controllers\SpliteBlade\SpliteBladeController.php
<?php

namespace App\Http\Controllers\SpliteBlade;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class SpliteBladeController extends Controller
{
    // 入力画面を表示する処理
    public function index()
    {
        return view('/splite_blade/index');
    }

    // ajaxを利用して受け取った値を処理して返す
    public function ajax(Request $request)
    {
        // 受け取った値の処理
        $ajax_form = "入力された値は".$request->input('ajax_input')."です。";

        // ajaxで受け取ってviewを表示できるようにレンダリング
        return response()->json([
            'form' => view('/splite_blade/ajax')->with(['input_data' => $ajax_form])->render()
        ]);
    }
}
```

### View

```\resources\views\splite_blade\index(.blade).php
<script 
  src="https://code.jquery.com/jquery-3.6.1.js"
  integrity="sha256-3zlB5s2uwoUzrXK3BT7AX3FyvojsraNFxCc2vC/7pNI="
  crossorigin="anonymous"></script>
<script>
$(function(){
    $('#ajax_submit').on('click', function(){

        // 入力する値の取得
        var input_value = document.getElementById('ajax_input');

        $.ajax({
            headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},  // CSRFトークンの設定
            url: "{{ route('splite_blade.ajax') }}",
            type: 'POST',
            data: {"ajax_input" : input_value.value},
        })
        .done(function(data){
            // 通信に成功したら、指定したIDにhtmlデータを挿入
            $('#ajax_result').html(data['form']);
        })
        .fail(function(){
            alert('error');
        })

    });
});
</script>


<div>
    <div>ajaxで渡すデータを入力する</div>
    <div>
        <h2>入力画面</h2>
        <div>
            <input id="ajax_input" name="ajax_form" type="text">
            <button id="ajax_submit" type="submit">送信する</button>
        </div>
    </div>
    <div id="ajax_result"></div>
    </div>
</div>
```

```\resources\views\splite_blade\ajax(.blade).php
<div>{{ $input_data }}</div>
```


## 参考記事
- [Laravel7 ajaxでviewを返す方法 – 半力投球](https://halfpower.work/2020/12/12/laravel7-ajax%E3%81%A7view%E3%82%92%E8%BF%94%E3%81%99%E6%96%B9%E6%B3%95/)
- [jQuery CDN](https://releases.jquery.com/)
- [【Laravel】Ajax通信をするときはCSRFトークンをヘッダーに追加しよう！ | あきぞらてっく](https://akizora.tech/laravel-ajax-csrf-4263)
ネットワークエンジニアとは？（通信キャリア）

大学の学生へ通信キャリアのお仕事について話をしに行くのですが、その際に業界地図などがいい感じのが見つからないので、整理用の記事です。

## ネットワークエンジニアとは？
カテゴリとしては大きく二つかなと想定しています。
### 社内ネットワークエンジニア
社内のネットワークを構築するエンジニアです。
LANや、LANとWANの接続に関する業務となります。
よく聞くネットワークエンジニアのイメージはこちらかなと思います。
### キャリアネットワークエンジニア
電気通信事業者として回線を提供するためのエンジニアです。
WANにかかわる業務となります。

# 今回のターゲット
電気通信事業に特化するので、キャリアネットワークエンジニアについて解説します。


# 業界地図
地図のような絵を描きたいけど、いったんスキップします。（気が向いたら作ります）
会社としては以下の4つに大きく区分されると思います。
### 電気通信事業者
NTTを筆頭に電気通信事業サービスを提供する会社です。
[Wiki 電気通信事業者](https://ja.wikipedia.org/wiki/%E9%9B%BB%E6%B0%97%E9%80%9A%E4%BF%A1%E4%BA%8B%E6%A5%AD%E8%80%85)
### ベンダー
通信機器導入をサポートする会社。
メーカがベンダーの役割を兼ねていることが多い。
以下の記事が国内の携帯電話事業者についてはわかりやすく記載されている。

[各キャリアが採用する5Gベンダーは基本4Gを踏襲も、中国系は採用見送り](https://k-tai.watch.impress.co.jp/docs/column/mca/1247403.html)
### メーカー
機器そのものを製造しているメーカ。
有名どころは、cisco、NOKIA、Hauwei、fujitsuといったところかな。。。
国内のメーカはOEMのところも増えている印象です。
### 通信建設会社
機器の設置工事などを行う会社。保守業務を担っている場合もある。
[電気通信工事業界の動向、ランキング、現状など](https://gyokai-search.com/3-koji.html#:~:text=%E9%9B%BB%E6%B0%97%E9%80%9A%E4%BF%A1%E5%B7%A5%E4%BA%8B%E6%A5%AD%E7%95%8C%20%E5%A3%B2%E4%B8%8A%E3%83%88%E3%83%83%E3%83%975%EF%BC%882021%2D2022%E5%B9%B4%EF%BC%89&text=2021%2D2022%E5%B9%B4%E3%81%AE%E9%9B%BB%E6%B0%97,%E6%A8%AA%E3%81%B0%E3%81%84%E3%81%A8%E3%81%AA%E3%81%A3%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82)
# 仕事の流れ
計画、設計、施工、設定、保守という流れが多いと思います。

作ることがあれば当然撤去するための作業も発生するので、それぞれで上記の流れで作業をしていきます。

# 推奨される資格
- 工事担任者
- 電気通信主任技術者
- 基本情報処理
- CCNA系


# まとめ
話をするために必要そうな情報をとりあえずまとめてみました。
作業が途中になっている記事  覚え


# あきらかに作業途中の記事

2022年５月下旬　いいねをいただいた記事　16

https://qiita.com/kaizen_nagoya/items/a68b0c9a6c1fcbce5ff8

2022年6月上旬　いいねをいただいた記事　16

https://qiita.com/kaizen_nagoya/items/e99ae995d22a04ea9373

Drivetrain(駆動系),ボッシュ自動車handbook(英語)11版A.C.まとめ<10>

https://qiita.com/kaizen_nagoya/items/e3d8affd5ebf096c891a

AdvencCalendar2022 報告

https://qiita.com/kaizen_nagoya/items/5b4b99cb9ad571f4094b

# 作業途中の記事　

 
<この項は書きかけです。順次追記します。>


# Advent Calendar 2022

今年企画した４つのAdvent Calendarと、それぞれの記事一つをご紹介します。

AUTOSAR Advent Calendar 2022

https://qiita.com/advent-calendar/2022/autosar

AUTOSAR References to ISO, IEC, ITU, IEEE, RFC and SEA etc.

https://qiita.com/kaizen_nagoya/items/d7d252211e10a79516df

Automotive Handbook Advent Calendar 2022

https://qiita.com/advent-calendar/2022/automotivehandbook

Basic principles, ボッシュ自動車handbook(英語)11版まとめ<2>

https://qiita.com/kaizen_nagoya/items/24a1ba5da3d09b2a95d1


2022 いいねをいただいた記事ランキング(O.K.版) Advent Calendar 2022

https://qiita.com/advent-calendar/2022/goods

2022年１月下旬　いいねをいただいた記事　16

https://qiita.com/kaizen_nagoya/items/0ee589a8edaeab24fd2a

AdCale(O.K.) Advent Calendar 2022

https://qiita.com/advent-calendar/2022/adventcalendar2022

「会議は15分未満」に。小耳にはさんだ話。

https://qiita.com/kaizen_nagoya/items/510c47c5d1e8d03145db

AdvencCalendar2022 報告

https://qiita.com/kaizen_nagoya/items/5b4b99cb9ad571f4094b


誤差の評価が苦手（専門分野以外）

https://qiita.com/kaizen_nagoya/items/cc3a50827b24ab80985f





 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞


# 文書履歴(document history)
ver. 0.01 初稿 20221211
gitのブランチ戦略について調べてみた(git-flow)


# ブランチ概要
|ブランチ名|概要|分岐元|マージ先|
|---|---|---|---|
|master|本番環境にリリースしたソースを管理、一般的にタグでバージョンを管理する。|-|-|
|develop|開発用、実際の開発作業は`featuer`で実施する。|master|release|
|feature|機能開発用。`develop`にマージ後は削除する。|develop|develop|
|hotfix|`master`の緊急対応用。|master|master, develop|
|release|リリース準備用。|develop|master, develop|

- メインとなるブランチは、`master`と`develop`
- 上記をサポートするために、`featuer`、`hotfix`、`release`が存在する

# 特徴
- 本番環境にリリースしたソースと、開発中のソースの区別が明確
- 修正や機能追加といった異なる作業を並行して進められる
- あとから開発が行われた流れを確認しやすい

# 参考サイト
https://nvie.com/posts/a-successful-git-branching-model/

https://cloudsmith.co.jp/blog/efficient/2020/08/1534208.html

https://rfs.jp/server/git/03git/outline-git-flow.html
STM32H743ZI2でLチカ「なぜか?理系フリマ(浅草)で1000円で手に入れたので」


目的

動作テスト


![o_cop243.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/067353d6-6e24-58c9-6144-7830f48fcbc9.jpeg)



```c++



// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(PB0, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(PB0, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(PB0, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}



```
[Golang] OSコマンドを実行する

## OSコマンドを実行する

### 環境
- macOS Monterey : 12.6.1
- iproute2macをbrewでインストール済み

### コード実行

``` package.go
package main

import (
	"fmt"
	"os/exec"
)

const defaultGw = "172.22.0.1"

func main() {
	pingCmd(defaultGw)
	fmt.Println("-----")
	catCmd("golang.txt")
	fmt.Println("-----")
	lsCmd()
	fmt.Println("-----")
	ipAddr()
}

func pingCmd(addr string) {
	result, err := exec.Command("ping", addr, "-c3", "-i0.5").CombinedOutput()
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(string(result))
}

func catCmd(f string) {
	result, err := exec.Command("cat", f).CombinedOutput()
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(string(result))
}

func lsCmd() {
	result, err := exec.Command("ls", "-al").CombinedOutput()
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(string(result))
}

func ipAddr() {
	result, _ := exec.Command("ip", "addr").CombinedOutput()
	fmt.Println(string(result))
}

```

### 実行結果
```
% go run ./execCmd.go 
PING 172.22.0.1 (172.22.0.1): 56 data bytes
64 bytes from 172.22.0.1: icmp_seq=0 ttl=64 time=19.265 ms
64 bytes from 172.22.0.1: icmp_seq=1 ttl=64 time=3.376 ms
64 bytes from 172.22.0.1: icmp_seq=2 ttl=64 time=197.188 ms

--- 172.22.0.1 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 3.376/73.276/197.188/87.859 ms

-----
Go is an open source programming language that makes it simple to build secure, scalable systems.

 - An open-source programming language supported by Google
 - Easy to learn and great for teams
 - Built-in concurrency and a robust standard library
 - Large ecosystem of partners, communities, and tools

-----
total 32
drwxr-xr-x  6 masashi  staff  192 12 11 20:01 .
drwxr-xr-x  9 masashi  staff  288 12 11 20:01 ..
-rw-r--r--  1 masashi  staff  620 12 11 20:01 calculation.go
-rw-r--r--  1 masashi  staff  796 12 11 20:01 execCmd.go
-rw-r--r--  1 masashi  staff  304 12 11 20:01 golang.txt

-----
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
        inet 127.0.0.1/8 lo0
        inet6 ::1/128
        inet6 fe80::1/64 scopeid 0x1
＊省略

```
NFTの所有情報を使ったプロダクト「ReCone」について


これは[no plan inc.の Advent Calendar 2022](https://qiita.com/advent-calendar/2022/noplan_inc)の11日目の記事です。

no plan株式会社ではNFTホルダー限定のコミュニティサイト「[ReCone](https://recone.app)」を開発しています！
今日はその中身の技術の話しなどさせていただきます！

# ReConeとは
![A2CD8425-2C1D-45A4-AF8F-DDDD4B003ED4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62822/e7568530-e4a9-48f5-b09e-c36e1867b3a8.png)


[ReCone](https://recone.app)（リコーン）とは、NFTホルダー限定の半クローズコミュニティプラットフォームです。
NFTを持っている人が世界中から集まり、限定ライブや限定投稿、限定チャットなどによって、クリエイターやファン同士の交流が促進され、NFTの価値を向上することができます。

![FireShot Capture 023 - 投稿一覧 - ReCone🦄 - www.recone.app.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62822/3b5cbc63-322c-80a5-dc9e-733fd45346e2.png)

このように、NFTを持っている人に特別な情報を届けることができます。

# NFTの所有判定について

**ReConeでは、あらゆるNFT規格、あらゆるNFTのネットワークに対応するべく、NFTの所有判定の実装を行なっています。**

現在対応しているNFTの規格としては
- ERC-721
- ERC-1155

また対応しているネットワークとしては
- Ethereum
- Polygon
- Shiden

になります。しかしながら、
**NFTの所有者情報を使ったサービスで特有のつらみが発生することがわかりました**

# NFTの所有者情報を使ったサービスでのつらみ

### 1: ERC-721でNFT所有者を把握する
以前ReConeでは、「Alchemy」というサービスでノードをレンタルしNFTのOwnerOf関数を叩いてこのNFT誰が持っているのかを実装していました。

### 2: ERC-1155にはownerOf関数がないことに気づく
ERC-1155のドキュメントを見るとownerOf関数がありませんでした。

### 3: 2の解決案としてownerOf関数の代わりにbalanceOf関数 と balanceOfBatch関数を利用
- balanceOf関数は誰が何個持っているかがわかる関数になります
- しかしbalanceOf関数は引数にウォレットアドレスを取るため、目的であるNFT所有者を把握したい場合には使用できません
- 対策としては、BatchTransferとSingleTransferという関数を呼び出し、Transaction履歴を追跡すると所有者情報を取得するようにしました

### 4: 3の解決策をしても、SingleとBatchの2つを気にする必要がある
- 目的のNFTがBatchでTransferされたのかSingleでTransferされたのかを意識する必要がありました

### 5: 4の解決策をしてもメモリに乗り切れない
- OpenSeaなどの巨大NFTコントラクト(1コントラクトにたくさんのTransaction履歴がある)場合、大体のサーバーではメモリに乗り切れずクラッシュが発生します
- 解決策としては、サーバーで処理できる数でページネーションを行い、分けて処理を記述しましょう

### 6: 5が解決してもマルチチェーン対応でつまる
- 別のネットワークのNFTの情報も欲しくなってバッチが終わらなくなってきます

### 7: 6を解決してもデータ、CPUとメモリを圧迫が激しい
- めちゃめちゃ圧迫されました

# どう解決すべきか
弊社の見解としては、
**「NFTの所有者情報の実装をサービスごとに独自実装するべきでない」**
という見解になりました

# no plan株式会社ではこのつらみを解決するAPIを公開しています
- TIUS API (https://tius.dev)

# TIUS APIについて
このAPIではNFTの判定にこの呼び出しのコードだけで実現でき、上記のつらみを解決することができます

```.ts
import {createClient} from "@urql/core";
import fetch from 'cross-fetch';

const client = createClient({
    url: GRAPHQL_ENDPOINT,
    fetch,
    requestPolicy: 'network-only',
    fetchOptions: () => {
        return { headers: { 'X-API-KEY': GRAPHQL_API_KEY } };
    },
});

const getOwner = async () => {
    const results = await client.query<
    GetOwnerQuery,
    GetOwnerQueryVariables
    >(GetOwnerDocument,
       {
        address: "0xC52d9642260830055c986a97794B7b27393Edf5e"
      }).toPromise();

    results?.data?.erc721ByContractAddress?.tokens
    .forEach(token => {
        console.log(token.tokenId);
        console.log(token.ownerAddress)
    });
}
```

# まとめ
- ReConeはNFTホルダー向けのプラットフォームです
- NFTの所有者情報を使ったプロダクトはつらみがあります
- NFTの所有者情報はTIUS APIで簡単に実現できます

# no plan株式会社について
- no plan株式会社は、ブロックチェーン技術、Webサイト開発、ネイティブアプリ開発、チーム育成、などWebサービス全般の開発から運用や教育、支援などを行っています。よくわからない、ふわふわしたノープラン状態でも大丈夫！ご一緒にプランを立てていきましょう！
- [no plan株式会社について](https://noplan-inc.com)
- [no plan株式会社 | ブロックチェーン実績](https://noplan-inc.com/blockchain)
- [no plan株式会社 | ブログ一覧](https://noplan-inc.com/blog)
- [お問合せはこちら](https://noplan-inc.com/contact)