OmniAICreator/Qiita-1.07M huggingface dataset:
[IDMC]Informaticaで出来るデータマスキングのご紹介

この記事は インフォマティカ Advent Calendar 2023 Day 4 の記事として書かれています。

## はじめに
皆様データマスキングしてますか？
データをマスクするとは、データの一部もしくは全部を見えなくすることで機密情報等を他人に判別・認識させなくするような処理となります。
よくありがちなマスキングといえば、アスタリスク等の文字で埋め尽くす置き換え等が想像されやすいですよね。ただ、そのような単純なマスキングを行ってしまうとデータ本来が持つ意味合いが分からなくなり、またデータ間の関連性が消えてしまったりして、そのデータを利用した分析やテストの役に立たなくなってしまう場合があります。

## Informaticaの高度なデータマスキング
Informatcaのクラウドサービス Intelligent Data Management Cloud がデフォルトで持つデータマスキング機能を利用すれば、本来のデータが持つ特徴を損なわずに、またデータ間の関係性を保持したまま、マスキングデータを作成する事が出来ます。
データ特性毎にマスキング方法を選ぶことで、例えばクレジットカード番号や電話番号、生年月日などの意味合いを持たせたままマスクされたデータを生成します。以下に簡単な例を示します。

### 効果的なマスキングの例
|マスキング方法|マスキング前|効果的では無いマスキング結果|効果的なマスキング結果|説明|
|:---|:---|:--|:--|:--|
|クレジットカード番号|5573-5886-7397-8193|1234-5678-9012-3456|5573-5832-0756-8917|クレジットカード会社情報(冒頭4桁)を保持|
|E-Mailアドレス|EM@infabank.com|aaabbbccc|7X@oowgOBR8.5LV|疑似的なメールアドレスを生成|
|電話番号|03-6403-7600|00-0000-0000|03-9357-4374|同一地域の疑似電話番号を生成|
|URL|http://xxx.infa.com/em|http://xxxx.yyyy|http://tCY.ab.dOt/mI|URL形式を保持|
|生年月日などの日付|1995-02-28|9999-99-99|1995-03-15|前後数ヶ月の範囲のランダム日付を生成し年齢情報を保持|


## マスキングの種類
以下のマスキング方法が用意されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985453/040fd3fe-cc65-ab5d-76fd-69da7b4cf847.png)

## マスキングの実装方法

データ統合機能のマッピングにて「マスキングトランスフォーメーション」を配置し、設定する事で利用可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985453/c8e75d3b-97fa-4611-636f-5601d7f8ce9c.png)

以下のデータマスキングトランスフォーメーションをマッピングに配置して利用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985453/72c484b2-e99d-c903-88b7-cbb43efead93.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985453/953d620c-8ef5-bbab-ee5d-af1fed89d10d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985453/2ef2f106-62a3-deb2-6611-24ef58f70113.png)

尚、過去の記事でこの機能を利用した実装例を紹介しておりますので、参考にして頂ければと思います。

[IICS（Informatica Intelligent Cloud Services）CDI(Cloud Data Integration）Masking Transformationの依存マスキング使い方](https://qiita.com/Takumi248/items/815483c4d006afb3251c)

マスキング機能詳細は以下のマニュアルを参照ください。

[データマスキングトランスフォーメーション](https://docs.informatica.com/ja_jp/integration-cloud/data-integration/current-version/_transformations_cloud-data-integration_current-version_ditamap/GUID-30C5C27F-A698-4DED-8D72-27AE129B9991.html)

## おわりに
本記事はほぼマニュアルの情報のみ、基本的な情報のみの紹介となりますが、ぜひ皆様に知って頂きたいので記事にしてみました。便利ですのでどしどしご利用ください！
border-radius 長方形+半円の作り方

```css
.rectangle {
    border-radius: 9999px;
}
```
こちらはiOS Safariでもスタイルが当たってくれることはテスト済み。

~~上記でもいいが、9999pxというのは嫌なので、
以下書き方でも長方形+半円のデザインが実現可能。~~
<font color="red">注意: iOS Safariだと効かないことが判明 2024.6.18現在</font>

```css
.rectangle {
    border-radius: calc(Infinity * 1px);　// calc(1px / 0)
}
```
iOS Safari以外ならスタイルが当たる。
オーバーロードとオーバーライドごっちゃにならん？

「世の中いろいろ興奮することあるけど、一番興奮するのは、オーバーロードとオーバーライドがどっちがどっちか分からなくなった時だよな」
　
『間違いないね』

 ## 目次
1. [オーバーロードってなんだっけ](#オーバーロードってなんだっけ)
2. [オーバーライドってなんだっけ](#オーバーライドってなんだっけ)
3. [間違えないようにしよう](#間違えないようにしよう)
4. [さいごに](#さいごに)

## オーバーロードってなんだっけ
　**「オーバーロード」（Overloading）** は、同一クラス内で**同じ名前のメソッドまたは関数を**、異なる引数の型や数で**複数定義**することを指します。オーバーロードにより、同一のメソッド名で異なる操作を実現することが可能になります。
![オーバーロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3601651/e322389b-ad2d-e758-b64f-81e94ccb438e.png)


 
## オーバーライドってなんだっけ
　**オーバーライド（Override）** は、オブジェクト指向プログラミングにおいて、子クラス（サブクラス）が親クラス（スーパークラス）から **継承したメソッドを新しい実装で再定義する**処理です。オーバーライドの主な目的は、継承されたメソッドの動作を派生クラスに適した形に変更することです。

 ![オーバーライド.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3601651/204d2e5f-005b-31b8-82a6-9a3446fe27f1.png)

## 間違えないようにしよう
### オーバーロードの覚え方
「Overload」の「 **load** 」は「 **荷物を積む** 」という意味です。関数やメソッドに「荷物（引数）を多く積み込む」ことから、異なる引数の組み合わせで同じ名前の関数やメソッドを多く「 **積み込む** 」と覚えます。

**たくさん積み込む = 同じ名前の関数を増やす**


### オーバーライドの覚え方
 「Override」の「 **ride** 」は「 **乗る** 」という意味です。派生クラスが基底クラスのメソッドの「 **上に乗ってそれを覆う** 」イメージで覚えます。

 **上に乗る ＝ 関数を上書きする**

 ## さいごに
  
  引数の違う同じ名前の関数を実装するのはどっちだっけ？
 <details><summary>オーバーロード</summary><div>

正解です！ 
えらい

</div></details>

 <details><summary>オーバーライド</summary><div>

『ちょっと何言ってるかわからない...』

</div></details>
Streamlitで遊んでみよう

この記事は タダの2年目 Advent Calendar 2023 の2日目の記事です。

n番煎じ甚だしいですが、streamlitをちょこちょこっと触ってみました！



# Document

https://docs.streamlit.io/

# はじめに

とっとと使ってみましょう。ターミナルから以下実行するだけで、streamlitが立ち上がります。

```
$ pip install streamlit
$ streamlit hello
```
![スクリーンショット 2023-11-24 11.47.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656439/a2afce99-1a9b-525a-aefe-a05a46a7b439.png)

すごい...!

左側のサイドバーから、デモを選択し、そのコードを確認することができます。
例えば、DataFrame Demo をクリックすると、次のように表示され、ページ下部にはコードも記載されます。

![スクリーンショット 2023-11-24 12.13.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656439/6ec87170-7e48-9f97-fe55-677c51d07690.png)

コード部分

![スクリーンショット 2023-11-24 12.14.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656439/2c2ce523-3bf0-653b-f0bf-97c31f78b36b.png)


# 書いてみた

雑にベタ書きするだけで、動くものを作ることが可能です。

```python:app_init.py
'''
Run Command: streamlit run ./article_streamlit/app_init.py 
'''
import streamlit as st
import datetime

st.title('たいとる')

textbox=st.text_input('入力を受け付けられます', '')
st.write('自由にテキストかけますよ')
st.sidebar.title('サイドバーのタイトル')

if st.button('面白かったら いいね してください！'):
    st.write('いいね ありがとう！')
```

ターミナルから以下実行すると、localhostで実行されます。

```
$ streamlit run ./app_init.py
```

じゃーん

![スクリーンショット 2023-11-24 13.43.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656439/abc075fa-2c65-d79d-f13b-a1c7ef917444.png)


# 用途

### 一般的な用途: PoCやモック作成

> 最終的なゴール例: streamlitを使う予定はないが、PoCとしてstreamlit上で検証を行う

→ ローカルでstreamlitを立てればOKです。

検証アイテムに応じてpythonコードを記載し、期待しているものがきちんと価値を生み出しそうか検証しましょう。以下実行して、期待値や認識を確認しPoCを進めれば、十分ワークするように感じました。

(これほどフロントエンドを考えずに、アイデアを形にできるのは本当にすごい...!)




### 社内ページ等の簡易的なwebページ

> 最終的なゴール例: streamlitを使って、webアプリを一般/限定公開する

→ どこでホストし、どのようにアクセスコントロールを行うかが重要になりそうな気がしています。あとお金。

* ホストの手段

[Streamlit Community Cloud](https://docs.streamlit.io/streamlit-community-cloud)? EC2 (AWS) 等のインスタンスでホストする？→ 公開範囲で議論がきちんと進みそう

* アクセスコントロール (ログイン認証等必要か？)

FYI: 

https://tech.revisio.co.jp/entry/2023/09/27/121859

### Streamlit in Snowflake

StreamlitでSnowflakeを語らないわけにはいかないでしょう！ Streamlitの買収により、SnowflakeはIntegrated platformへまた一歩進んだ気がしています。

使用例はClassMethodさんが1番わかりやすい: 

https://dev.classmethod.jp/articles/try-streamlit-on-snowflake-from-snowsight/

ただし、アプリ起動中にwarehouseのクレジットが継続して消費される点は注意しなくちゃいけないようです。

https://docs.snowflake.com/en/developer-guide/streamlit/about-streamlit#billing-considerations-for-sis

# 感想

* PoC目的としてのstreamlit: 最強
* 最終成果物のwebアプリとしてのstreamlit: なんだか中途半端

こんなイメージが1番いいのかなあと思いました。

1. アイデアレベルでまずはフロントエンドの形をつくってみる
1. 機能面も作り、ローカルでホストしてPoCを進める
1. 機能のPoC完了後、実際に業務上利用するために、VPC内でホストして社内公開する
1. きちんと価値を生み出せた場合、社内Webサイトの要件を固めて、きちんとWebアプリを作る (=streamlitを捨てる)

<br>

もちろん、上記step3で「十分うまくいくじゃん！わざわざアプリ作り直さなくてもいいよ！」となる気もするのですが、streamlit上でコンバージョンやユーザー動線を辿れないような気がしていて、最終的なゴールとしてのwebアプリのユースケースが想像つかなかったからです。

ただし、とにかく価値を早く生み出すという観点では、streamlitは本当にすごい存在だなと感じました。

<br>

これからstreamlitで色々遊んでいくのが楽しみです！
内定者アルバイト1日目を終えて

ツルマキと愉快な仲間たち Advent Calendar 1日目です。ゆるく書きます。

今日は来年春から就職する会社の内定者アルバイトの受け入れの日でした！

受け入れの際に感じたことや勉強になったことを忘れないように書いておこうと思います。

# 入社ガイダンス
ここでは各種ソフトウェアのログインやセキュリティの話などを聞きました。
作業中は常にVPNを繋げておくようで、さすがしっかりしているなと。

zoomで社員さんの画面を見ながら進めていくのですが、少しでも詰まったら言って待ってもらうのが良いと思います。(ログインでパスワード間違えちゃったとかでも)

# チーム受け入れ
受け入れはほぼOJTと同時に行われた感じでした。Androidチームでの夕礼が毎日あり、自己紹介をしていただきました。暖かかった☺️

# OJT(On the Job Training)
OJTではメンターさんに1対1でついてもらって、ジョインするプロジェクトの説明や、github-enterpriseのアカウント作成、作業環境構築などなどをしました。

## OJTでつまづいた場所
ジョインするプロジェクトが`Kotlin Multiplatform(KMP)`を使っているもので、Android Studioだけではなく、Xcodeの環境構築も必要だったため、そのあたりでつまづきました。

### JAVA_HOMEの設定
環境変数JAVA_HOMEの設定方法がわからなかった。
#### JAVA_HOMEとは
JAVA_HOMEは、Javaの環境変数の一つです。
Javaを使用するアプリケーションでは、どこの場所にJavaがインストールされているかを把握する必要があり、"JAVA_HOMEという環境変数にJavaがインストールされている場所が設定されている"と判断する。
今回はJava17を使うのでこれでOK
```
export JAVA_HOME=`/usr/libexec/java_home -v 17`
```
:::note info
JavaのLTS
JavaにはLTS(Long Time support)バージョンというものがあり、これは特定のバージョンが長期間に渡ってサポート(セキュリティアップデートやバグ修正など)を受けるバージョンです。
Java21, Java17, Java11, Java8などが当てはまります。
:::

## Xcodeのコマンドラインツールのバージョン指定
Xcodeの開発環境構築のために、Terminalでスクリプトを実行した結果、以下のエラーが出ました。
```
error: terminated(72): /usr/bin/xcrun --sdk macosx --find xctest output:
    xcrun: error: unable to find utility "xtest", not a developer tool or in PATH
```
※業務用PCを今確認できないので、一言一句あっているかわからないがこんなエラー

原因はXcodeのコマンドラインツールで指定しているバージョンが違うことでした。

#### 対策
以下のコマンドでコマンドラインツールの指定先を確認します
```
xcode-select -p
```
出力結果
`/Applications/Xcode_13.3.1.app/Contents/Developer`
※忘れちゃったけどこんな感じ

次に、使用したいXcodeのコマンドラインツールのバー本を更新する。
```
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
```
今回はこれでOKでした。

## 他にも色々教えていただいた
- vimの基本操作
- コマンドプロンプト
    - 環境変数設定後、`source .zshrc`と`exec $SHELL -l`をする

 ここらへんは入社する前におさらいしといたほうが良いなと思う

# ガイダンス中に心がけていたこと
- 読めない単語が出てきたら読み方を聞く
    - 単語の読み方がわからないと聞くときに恥ずかしくなっちゃうので
    - 例.) Bitrise(ビットライズ)
　
- 知らないソフトウェアが出てきたら何ができるものなのか聞く
    - タスクで詰まったときに、「あれを使えばできるのでは？」という推測ができるので
    - 例.)このDataDogってやつは何に使うんですか？
　
- READMEとコードはMAX理解する努力をする
    - 新しいプロジェクトにジョインするに当たって、先輩方が残してくれたドキュメントを理解するのはすごく大事なことだなと
    - KMPを使ってるからコード量が多くて複雑😵‍💫

 内定者アルバイトとか新卒1年目のアドバンテージは沢山質問できることだと思っているので、沢山質問して覚えていきましょう✊
【新人教育】新人との振り返りミーティングで見えた自身の課題

# はじめに
### お疲れ様です！兼業主夫SESの@yone051319です！
この度、4ヶ月間のプロジェクトが無事に終了し一息ついたところです。
新入社員とプロジェクトにジョインしまして、教える側（？）の立場となり試行錯誤しながらあっという間の4ヶ月でした。

先日、新人君とプロジェクトの振り返りを1on1ミーティングした際に気づいたこと、自分自身の反省をまとめました。

# 登場人物とプロジェクト
1　 筆者
* 非情報系卒のエンジニア歴3年
* プログラミングよりもオムツ交換の方が得意

2　 新人君
* 情報系卒
* JavaSilverを半月で取得するポテンシャルの持ち主
* コミュニケーションがかなり苦手

３ その他のメンバー
* 客先常駐先のPL
* 客先常駐先の新卒メンバー（２人）

WEBアプリケーションのエンハンスプロジェクトに基本設計フェーズの8月から参画し、11月末にリリースを目指す。
筆者と新人君で主に新規画面（4画面）の追加と既存画面（2画面）の改修を担当する。
新人君のフォローは筆者が主に担当し、作業状況の報告は個別でPLに報告を行う。


# プロジェクトの振り返り
1on1ミーティングを実施しました。その内容を箇条書きで書いていきます。

## 1.目標の振り返り
**目標**
「自分からコミュニケーションをとりにいく姿勢を持つこと」
=>　達成率は60%

・特にPLに対してのアプローチが遅れてしまった。
=>　自信がなくて報告や相談が遅れることが多かった。

## 2.作業プロセスの自己評価
**プロジェクトの進捗**
「設計/製造フェーズでは遅れたが、テストフェーズではオンスケで作業を完遂できた」
=>　プロジェクトの後半のテストフェーズでは、スケジュールを意識して作業を行うことができた。

**問題発生時の対応について**
「ドキュメントの書き方から、基本的なプログラミングまで先輩（筆者）に聞くことで解決していた」
=>　少しでも自分で調べてから聞くべきであった。

## 3.コミュニケーションとチームワーク
**チームメンバーとの協力について**
「先行してモンキーテスト実施した際に、製造担当者に仕様の詳細をヒアリングする事ができた」
=>　機能面や動作内容、前提条件を理解する事ができ、単体テストで網羅できてなさそうなテスト内容を実施する事ができた。

「自分の聞きたいことが相手に伝わらない事があった」
=>　質問内容をもっと具体的にするべきであった。聞きたい内容に対しての状況説明が曖昧であったため、回答者への負担が多くなってしまう事があった。

## 4.技術的な挑戦
**Java、javascriptでの開発について**
「自信が無いため、毎回先輩（筆者）に確認してもらう状況であった」
=>　もう少し自分の裁量で実装できたのではと考えている。

「フロント実装については、知識不足で実装が難しかった」
=>　何が分からないかも分からない状況、苦手意識がある。

「SQLについて勉強しなければならない」
=>　データの取得方法を工夫すれば、Javaのロジックが簡単になる場面が多くあった。使いこなせるようになりたい。

## 5.自己評価
**自身の役割や業務について**
「4割くらいはできた」
=>　テストフェーズにおいてはスケジュールを守る事ができた。

「製造フェーズでは力になれていなかった」
=>　PLからの「日々の業務で成長して欲しい」が達成できていない。期待された役割を全うできていないと考える。

「メンバーとのコミュニケーションは成長できた」
=>　聞きたい事があったときに即座に聞く動きができるようになった。

## 6.その他
**プロジェクト全体**
「あまりの不甲斐なさに2回泣いた」
=>　仕様を誤解したままテストを実施し、半日を無駄にしてしまった事があった。
=>　他の新卒メンバーと自身を比較して、チームに貢献できていない自分自身を情けなく思った事があった。


## 7.筆者から新人君へのフィードバック
**プロジェクト全体を通じて80点**
「コミュニケーションが苦手ではあるが、成長を感じた」
=>　プロジェクトの初期ではコミュニケーションロスによる遅延が発生した。この時に二人で話し合って、朝会1on1ミーティングの開催やペアプログラミングを施策した。その結果、コミュニケーションロスを解消する事ができた。また、新人君が他のメンバーとコミュニケーションを取る練習をすることもでき、非常に良かった。

「他にもたくさんいい所あったよ」
+ 業務に対して真摯に取り組み、やり遂げようとする姿勢が凄い
+ テストを淡々とコツコツ消化するのは凄い（作業実績に波が無い） 
+ 自分で発見した過去の参考資料を全体チャットで共有するなど、チームに貢献できていて非常に良かった

「理想の自分に対しては【ステップ】を踏もう」
=>　例えば、山登り未経験の人が富士山に挑戦するのは難しいから、近所の山を散策することから始めるように、目標に向けて段階を踏もう。

「コミュニケーションのハードルを下げよう」
=>　仕事におけるコミュニケーションは「報連相」ができれば100点です。質問するときのテンプレートを作り、コミュニケーションの1歩目のハードルを下げよう。

## 8.次のプロジェクトに向けて

「継続すること」
+ 自分から聞きにいく姿勢を続ける
+ 与えられた業務を全うする努力を続ける

「課題」
+ 特に技術面。製造フェーズで力になれていない
+ 自分自身の与えられる業務への理解が曖昧

「挑戦すること」
+ 説明内容を理解した上で作業に取り掛かることを意識すること
+ SQL文を操れるようになること 
+ 自分の意見や考えを言えるようになること

# 最後に
今回のプロジェクトで初めて新卒をフォローしながら業務を行いました。
反省点としては、下記の4点です。
1. タスクの細分化を筆者が行ったこと
1. 手段ではなく答えを教える事が多かったこと
1. 新人君のフォローに回りすぎて、残業が増えてしまったこと
1. 新人君のメンタル不調に気が付けなかったこと

設計/製造フェーズにおいてコミュニケーションロスによる遅延が発生してから、新人君が自身の裁量で考える余地を狭めてしまっていたことが挙げられます。遅れを取り戻すことはできましたが、**新人君の成長を阻害していた**ことは反省しなければなりません。
また、新人君へのフィードバックの回数を増やすべきでした。新人君が気が付いていない良い面を指摘し、伸ばしていく事ができればメンタル的な不調も回避できた事が考えられます。

新人君の成長のためを思った振り返り1on1ミーティングでしたが、結果として筆者の力のなさを痛感した結果となりましたが、実施して本当に良かったなと思います。
エンジニアとして技術をつけることはもちろんですが、組織の人間として、後輩育成のスキルを身につけていけるように努力します。

最後までお読みいただき、誠にありがとうございました！
頑張ります！！
ChatGPT API使用時に[Error code: 429]がでた時の確認事項

**注意**
未経験から転職した、一年目のエンジニアが、作成したものになります。
そのため、至らぬ表現や、誤った表現をしている場合があります。

経験豊富な先輩エンジニアの方々へ
もし、誤った情報を記載していた際は、大変お手数をおかけしますが、ご指摘いただけますと幸いです。

少しでも、皆様のお役に立てれば幸いです。

# 記事の内容

-   生じたエラー
-   エラーの意味
-   エラーの原因
-   対処方法

## 生じたエラー
![スクリーンショット 2023-12-02 13.02.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2963171/f3b1cd06-e345-9279-bb94-926ad0162c29.png)


## エラーの意味

例外が発生しました: RateLimitError
Error code: 429 - {'error': {'message': 'You exceeded your current quota, please check your plan and billing details.', 'type': 'insufficient_quota', 'param': None, 'code': 'insufficient_quota'}}

ChatGPT の API を初めて利用するのに、既に使用量を超過している...

## エラーの原因

アカウントを作成して 3 ヶ月経つと、無料で利用できる期間が終了する。

## 対処方法

無料期間が終了しているため、試しに API を叩くのにも少量のクレジットが必要に
そのため、先にクレジットの登録をしないといけない。

コードや、環境変数の問題ではありませんでした。
この記事が、少しでも皆様のお役に立てば幸いです。
Go言語の環境構築～HelloWorld出力（Windows）

## はじめに
WindowsでGo言語の開発環境を構築し、`HelloWorld`を出力する方法を説明する

## Goのインストール
1. https://go.dev/dl/ にアクセスして`go1.21.4.windows-amd64.msi`をダウンロードする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/a36570e9-0a89-74c1-2eaa-f82746f0b532.png)

1. ダウンロードが完了したら、`go1.21.4.windows-amd64.msi`をダブルクリック
1. `Next`をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/5f5ae292-b661-eb49-d36a-0e2b4feac0f2.png)
1. `Next`をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/b16b9c33-b4ad-ec9f-fd24-c72259539b30.png)
1. `Next`をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/c72284c5-5437-b5cc-5888-1a668ce54bc7.png)
1. `Install`をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/5b4c9acd-8921-4816-f16a-c35937e6ad22.png)
1. `Finish`をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/ac799f9c-1ecb-fb58-f43e-27e98e74cea3.png)
## インストールの確認
コマンドプロンプトでGoのバージョン表示して、インストールが確認されていることを確認する
```cmd
> go version
go version go1.21.4 windows/amd64
```
:::note warn
**表示されない場合**
環境変数の設定を確認する
参考：[**Go言語の環境変数を設定する方法**](https://zenn.dev/atsushifx/articles/golang-win-install#2.2.-%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%E3%81%AE%E8%A8%AD%E5%AE%9A)
:::

## `HelloWorld`出力
### `go.mod`の作成
空のフォルダを作成し、以下のコマンドを実行する
```cmd
go mod init helloworld
```
コマンドを実行すると`go.mod`ファイルが作成される
> 【**補足**】Go言語のアプリケーションやライブラリは「**モジュール**」という塊になっている
`go mod`コマンドによってプロジェクトの中心となる`go.mod`ファイルを作成する

### `main.go`の作成
同じフォルダ内で`main.go`を作成する
```go
package main

import "fmt"

func main() {
	fmt.Println("Hello World")
}

```
### コンパイル＆実行
以下のコマンドを実行する
#### コンパイル
```cmd
go build
```
#### 実行
```cmd
.\helloworld.exe
```

#### 確認
`Hello World`が出力されることを確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/388176cb-22a1-5e27-db36-fddb00f3a874.png)


## 参考
https://www.oreilly.co.jp/books/9784873119694/

https://qiita.com/suke_masa/items/0c45c92934b9a2807ddb

https://qiita.com/ryome/items/8bc5d7c8cd51a351d016

https://zenn.dev/atsushifx/articles/golang-win-install
【Flutter】リスト表示とルーティング

[chatGPT に立ててもらったスケジュール](ceecf4a987d3f75b6d93)に準じてFlutterの状態管理を勉強。
> Day 6: リスト表示とルーティング
>    - リスト表示を作成する方法を学ぶ
>    - Flutterのルーティングシステムを理解する
# リスト表示を作成
`ListView`というコンストラクタを使用するとリスト表示を作成できる。
``` dart
ListView( // ul
  children: const <Widget>[
    ListTile( // li
      title: Text('タイトル文字のみ'),
    ),
    ListTile(
      leading: Icon(Icons.map), // 先頭に来るアイコン
      title: Text('タイトル文字'),
      subtitle: Text('サブタイトル文字'),
      trailing: Icon(Icons.more_vert), // 末尾に来るアイコン wrap(spacing: 【アイコン同士の余白】,children: [Icon(),Icon()] /) で複数使うことも可能
    ),
  ],
),
```

<details><summary>chatGPTが作ったサンプルソース</summary>

``` dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  final List<String> items = ['Item 1', 'Item 2', 'Item 3'];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Dynamic List Example'),
        ),
        body: ListView.builder(
          itemCount: items.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(items[index]),
            );
          },
        ),
      ),
    );
  }
}

```
</details>

# Flutterのルーティングシステム
## ルーティングシステム とは
画面遷移のこと
## 導入方法
1. 遷移先の`.dart`ファイルを作成する。例では`detail_page.dart`とした。
   ``` dart
    // detail_page.dart
    import 'package:flutter/material.dart';
    class DetailPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Detail Page'),
          ),
          body: Center(
            child: ElevatedButton(
              onPressed: () {
                Navigator.pop(context); // 前の画面に戻る
              },
              child: Text('戻る'),
            ),
          ),
        );
      }
    }
   ```
2. `Navigator`で遷移先を指定
   例はボタンを押して遷移
   ``` dart
    child: ElevatedButton(
      onPressed: () {
        Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => DetailPage()),
        );
      },
      child: Text('Go to Detail Page'),
    ),
   ```
3. ルートを設定
   ``` dart
   import 'detail_page.dart';
   ```
# 参考

## 公式

### list

https://docs.flutter.dev/cookbook/lists/basic-list

#### 例が多くておすすめ

https://api.flutter.dev/flutter/material/ListTile-class.html

### ルーティング

https://api.flutter.dev/flutter/services/SystemNavigator/pop.html


## Zenn

### list

https://zenn.dev/koheii/articles/531d3f113f794f
WebAR SDK Onirixを使ってみよう

# 概要
[ちゅらデータ Advent Calendar 2023](https://qiita.com/advent-calendar/2023/churadata)の2日目の記事です。
WebARを実装する際にiOS Safariが[WebXR Device API](https://caniuse.com/?search=WebXR%20Device%20API)に対応していないため工夫が必要になります。よくある方法としては、`WebXR Device API`を使わずに実装したり、[8th Wall](https://www.8thwall.com/)を使ったりすると思います。
今回は、解決策の一つとして、あまり知られていないWebAR SDK [Onirix](https://www.onirix.com/)を使って開発する方法について取り上げます。OnirixのSDKを使えば、iOS SafariでもSLAMを使った6DoFを実装できるようになります。

# Onirix
Webブラウザ上で動作するWebARをWebブラウザ上で作成、公開できるサービスを提供([Onirix Studio](https://www.onirix.com/creative-studio/))しています。さらに、WebARに必要な機能をSDKとして[NPMパッケージ](https://www.npmjs.com/package/@onirix/ar-engine-sdk)提供までしてくれています。同様のサービスとしては、[8th Wall](https://www.8thwall.com/)が有名かと思います。が、純粋にローカルで開発するだけなら、無料で使えるOnirixのSDKを使った方がいきなりお金がかかる8th Wallを使うより低コストなところが嬉しいポイントの一つですね。


### 互換性とブラウザのサポート
| OS        | Version   | Supported browsers |
|-----------|-----------|-----------|
| iOS       | iOS 11+   | Safari, Safari view controller (SFViewController): iOS 13+, Safari web views (WKWebView): iOS 14.3+     |
| Android   | Any※     | Chrome, Firefox, Samsung Internet, Edge, native android web views (Android 4.4+)|

※ 下記の性能を有するハードウェアである必要あり
- リアカメラが少なくとも VGA 解像度 (640x480px) 
- ジャイロセンサー搭載
- 2GB以上のRAM




# Three.js × Onirix SDKをローカルで動かす
今回は、ViteとDocker環境で公式のサンプルを動くようにした[リポジトリ](https://github.com/yoshiyasugimoto/onirix-sample)を用意しました。
```bash
git clone https://github.com/yoshiyasugimoto/onirix-sample
```

- [Onirix](https://www.onirix.com/)にログインして SDK の Token を取得してください。([参考 URL](https://docs.onirix.com/onirix-sdk/web-ar#onirix-studio-configurati))

```bash
echo VITE_ONIRIX_TOKEN={取得したSDK Token} > .env
```
- コンテナ起動しましょう。
```bash
docker compose up
```
- OnirixのSDKはOnirixと契約したドメイン以外はアクセス制限がかけられています。ただし、開発用に`localhost`や`*.ngrok.io`が[ホワイトリスト](https://docs.onirix.com/onirix-sdk/web-ar#local-development-and-tes)に登録されています。また、WebARはカメラ映像([getUserMedia](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia))やデバイスの方向([deviceOrientatation](https://developer.mozilla.org/en-US/docs/Web/API/Window/deviceorientation_event))を取得するために`https`でアクセスする必要があります。ここでは、ngrokを使います。（※ngrokを立ち上げるとアプリケーションが公開されるので、扱いにはよくよく注意）
```bash
 ngrok http 8000
```

- ngrokから発行されたURLにスマホでアクセスしてカメラを平面にかざして画面をタップするとクマが踊り始めましたね!
![onirix.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417336/bf9b500e-5356-b95f-f8fc-18376b181c31.gif)

# まとめ
本記事では、Onirix SDKを使って6DoFを行ってみました。正直な感想としては、6DoFの完成度に関しては、まだまだ8th Wallが圧倒しているので、もう少し精度が良くなれば、簡単なデモの開発をOnirix SDKを使うことのはアリですね！
[ちゅらデータ Advent Calendar 2023](https://qiita.com/advent-calendar/2023/churadata)の明日は @takumanken さんの「SnowflakeでORDER BYする話」です！
SwiftDataをUIKitで利用する

# 概要
SwiftDataに関する記事でほとんどがSwiftUIで書かれていたので、
UIKitでサンプルアプリを作りました。
テキストフィールドに入力した値をテーブルビューに表示するシンプルなアプリです。

```swift
import UIKit
import SwiftData

class ViewController: UIViewController {
    var container: ModelContainer?
    var dataSource: UITableViewDiffableDataSource<Section, User>?
    
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var textField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        container = try? ModelContainer(for: User.self)
        tableView.delegate = self
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "User")
        createTableViewDatasource()
        loadUsers()
    }
    
    func loadUsers() {
        let descriptor = FetchDescriptor<User>()
        let users = (try? container?.mainContext.fetch(descriptor)) ?? []

        var snapshot = NSDiffableDataSourceSnapshot<Section, User>()
        snapshot.appendSections([.users])
        snapshot.appendItems(users)
        dataSource?.apply(snapshot, animatingDifferences: false)
    }
    
    @objc func addSamples(name: String) {
        container?.mainContext.insert(User(name: name))
        loadUsers()
        textField.text = ""
    }
    
    private func createTableViewDatasource() {
        dataSource = UITableViewDiffableDataSource<Section, User>(tableView: tableView) { tableView, indexPath, user in
            let cell = tableView.dequeueReusableCell(withIdentifier: "User", for: indexPath)
            var content = cell.defaultContentConfiguration()
            content.text = "\(user.name)"
            cell.contentConfiguration = content
            return cell
        }
    }
    
    @IBAction func addButtonDidTap(_ sender: UIButton) {
        if let name = textField.text {
            addSamples(name: name)
        }
    }
}

extension ViewController: UITableViewDelegate {
    
}

@Model
class User {
    var name: String

    init(name: String) {
        self.name = name
    }
}

enum Section {
    case users
}

```

![simulator_screenshot_B694886B-E656-462D-B3AF-62972C668EC6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314423/0652bd89-41a4-6efc-a198-64fd27799fee.png)
Gem作者が開発するときに考えていること

私は、 [ruby-duckdb](https://github.com/suketa/ruby-duckdb) という gem を開発しています。普段、 gem を開発する上で考えていることを書いてみたいと思います。

## 複数のRubyのバージョンで動作する

普段、業務で開発している Rails アプリケーションとは違い、 gem を使うユーザーは、 どのバージョンの Ruby を使うかわかりません。
なので、広く使われるように、複数の Ruby で使えるようにしたいと考えてます。
とはいえ、古いバージョンのサポートを続けるのは、労力がかかるので、 Ruby が公式にメンテしているバージョンに限定しています。

手元で全バージョンを確認するのも手間なので、CI (GitHub Actions) を使って自動テストを実行して動作確認しています。
なお、CIで実行するときは、head や preview バージョン (2023年11月26日時点では、 3.3.0-preview2)でもテストしています。

私は、開発するときは、最新のバージョンを使っています。
たまに、Ruby 3.2 では、テストが通って、 Ruby 2.7 ではテストが通らないことがあり、その都度、どちらでも動作する書き方に変更しています。

例えば、 Ruby 3.2 では、

```ruby
def foo(*args, **kwargs)
  ...
end

def bar(*, **)
  foo(*, **)
end
```

と書くことができますが、 Ruby 2.7 では `SyntaxError` になるため、


```ruby
def foo(*args, **kwargs)
  ...
end

def bar(*args, **kwargs)
  foo(*args, **kwargs)
end
```

と修正する必要がありました。
場合によっては、 `RUBY_VERSION` でコードを分岐させる必要がありますが、コードが複雑になってしまうので、極力、そういった書き方は避けるようにしてます。

gem ユーザーの立場では、なんでこのバージョンのRubyで動作しないのとか、思ったりすることもありますが、
gem 作者の立場では、複数バージョンをサポートするのは面倒なので、オフィシャルでサポートされているバージョンに限定しています。

## 複数のバージョンの duckdb で動作する

duckdb は、LTS なバージョンは存在しないと思ってます。
ですが、将来、LTS なバージョンが出てくることが予想されます。
その時、慌てることがないように、複数バージョンの duckdb でも動作するようにしようと意識して開発してます。
2023年11月26日現在では、最新バージョン (0.9.x) と1つ前のバージョン (0.8.x) のどちらでも動作するようにしています。
ただし、最新版でのみ使える機能の場合、 最新版の duckdb と組み合わせたときは使えるが、1つ前のバージョンと組合せたときは、その機能だけが使えないといったことがあります。

例えば、

- duckdb 0.9.2 と組み合わせた場合に `DuckDB::Connection#interrupt` というメソッドが使える。
- duckdb 0.8.1 と組み合わせた場合に `DuckDB::Connection#interrupt` というメソッドは定義されない。

といった違いが発生しますが、どちらの duckdb のバージョンでも使える機能は同じように使えるように開発してます。

## 複数のOSで動作する

ruby-duckdb は、 duckdb に依存しているのですが、 duckdb が動作する OS では、 ruby-duckdb も動作するのが理想だと考えています。
ですので、 GitHub Actions でサポートされているOSでテストするようにしています。

例えば、 Windows で CI が失敗することがあったので、 `duckdb` にPRを取り込んでもらったこともあります。

ちなみに私は、 Mac と Linux で duckdb を動かしたことがあるのですが、 Windows では一度も動かしたことがありません。

## C 少な目、Ruby 多め

ruby-duckdb は C言語で書かれている部分と、Ruby で書かれている部分があるのですが、極力 C言語を少くして、Rubyで書ける部分を多くするようにしてます。
Ruby で書いた方がメンテナンスしやすいためです。
あと、 Rubyユーザーなら、 Ruby で書かれたコードが多い方がとっつきやすく、 PR とかも出してもらいやすいんじゃないかと考えているからです。

C言語の部分は duckdb の薄いラッパーにして極力単純に duckdb の C API を呼び出すだけにしています。
C言語部分では、duckdb の C API の関数を元にメソッドを定義してます。
Ruby のコードでは、ruby-duckdb ユーザーが使いやすいメソッドを定義して、メソッド内部でラッパーを呼び出すように実装しています。
最近では、Copilot が推測しやすいようなメソッド名やメソッドの別名を定義したりすることもあります。

例えば、薄いラッパーを使うと

```ruby
prepared_statement = DuckDB::PreparedStatement.new(
    db_connection,
    'SELECT * FROM users WHERE name = $name'
)
i = prepared_statement.bind_parameter_index('name')
prepared_statement.bind_varchar(i, 'Bob')
result = prepared_statement.execute
```

となりますが、 Ruby 側で `DuckDB::Connection#query` を定義していて

```ruby
result = db_connection.query(
    'SELECT * FROM users WHERE name = $name',
    name: 'Bob',
)
```

と簡単に書くこともできるようになってます。

## まとめ

gem 作者としては、より多くの場面で、より多くの人に gem を使ってもらえるように、それなりに色々と考えているんだということがわかっていただけると幸いです。
Amazon Inspectorで脆弱性をらくらく検出　　概要と初回セットアップ

# Amazon Inspectorとは？
Amazon Inspectorは、自動脆弱性管理サービスで、EC2インスタンス/Lambda関数/コンテナイメージ毎の「脆弱性」と「意図しないインターネット公開」をリアルタイムに自動検出し、脆弱性を視える化することができます。
脆弱性毎の対処の優先順位やスコア、CVE（共通脆弱性識別子）番号も表示され、
システム管理者は、OSの詳細情報を手作業で調査せずとも網羅的に具体的な脆弱性情報を自動収集でき、対処を進めるための情報も併せて得ることができます。

### 脆弱性の検出結果一覧の例
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141348/417628c4-457a-dd35-8e8a-1541ee21bfb3.png" width=80%>


### 自分用に手順をメモっておきます。

# Inspectorの初回セットアップ

### Inspectorをアクティブ化する
補足：
リージョンサービスなので、リージョン毎にアクティブ化が必要。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141348/f5c7841f-1300-6e4e-75e2-09b42903fd03.png" width=70%>


### 最初のスキャンが開始される
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141348/4907142d-da32-2eb8-75d1-cdc0580b0a05.png" width=80%>

### 最初のスキャンが終わっても、（IAMロール設定が不足しているため）実はスキャンされていない
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141348/d99ffe3b-8718-c643-5e29-64c89c28faf1.png" width=80%>

### スキャンされるためには、マネージドインスタンス化が必要
ステータスが「**アン**マネージドEC2インスタンス」の場合、スキャン対象外
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141348/03ce90e4-c01e-2d70-a52d-a6bdfcb02fe7.png" width=80%>



### マネージドインスタンス化にするための、IAMロール作成
＜仕組み、IAMロールの必要性メモ＞
EC2インスタンス内のOS(windowsやlinuxなど)にインストールされているSSMエージェントからSSMに連携するため、EC2にSSMへのアクセス許可を付与しなければならない。
その許可を付与するために、このIAMロールが必要となる。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141348/541d462e-40c4-cff3-6fe5-ee9670b58529.png" width=80%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141348/e4eb7c95-663d-c52a-48f8-799f746af0d5.png" width=80%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141348/8551ee73-879c-0077-ae34-c509bbd01f4c.png" width=80%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141348/34409b72-da8a-f9fe-84e9-25ad9608c8d6.png" width=80%>


### マネージドインスタンス化のため、EC2インスタンスのIAMロールで「AmazonSSMManagedInstanceCore」を付与する
これにより、EC2にSSMへのアクセス許可が付与され、OS上のSSMエージェントとSSMの連携が始まる
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141348/763d94d4-39e0-082d-6846-f1c607ecf551.png" width=80%>

### マネージドインスタンス化され、ステータスが「アクティブにモニタリング中」に変わった
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141348/90fb6ab6-1edb-e88c-b918-00bea678a06f.png" width=80%>


#### 補足メモ
今回、SSMエージェントをインストールせずとも、マネージドインスタンス化された。
どうやら最近のAMIには、SSMエージェントが初期インストールされている模様。
古いAMIの場合、インストールされていなかったり古いバージョンだったりするらしい。
その際は手動インストール・最新版へのアップデートが必要となる


# 脆弱性の詳細表示例

### 「インターネットからこのEC2インスタンスのポート番号22に到達可能」と自動検出（右上あたり）
また、この脆弱性への対策が記載されており、「セキュリティグループまたはACLを変更することで、インスタンスへのアクセスを制限できます」とのこと。（右下あたり）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141348/89ece0da-3456-8637-869d-40051d42e179.png" width=80%>


### このEC2インスタンスのセキュリティグループを確認したところ、下記設定でした
たしかに、インバウンドルールでポート番号22が許可されていました。
ソースIPは私が使用しているグローバルIPアドレスを/32で指定していますが、ちゃんと自動検出されました
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141348/a9809cbb-9f85-6556-5578-d91546316d96.png" width=80%>


# その２につづく
次回は、Amazon Inspectorを使って最近のOSと古いOSを比較して、脆弱性の差分をみてみようと思います。
【ChatGPTなどの生成AIを使わん宣言してる人に向けて思うこと】


　どうも、カーブミラーです。

　今回は、生成AIを使わん宣言してる人への文句です。独り言と思ってくださいw

:::note info
本記事は、
　ChatGPTは未使用です。
　　あしからず。
:::
　ChatGPTなどの生成AIに限らず、
　　新しいものは拒否られる傾向に
　　　あります。

　自動車、機関車、飛行機。
　　電卓、マイコン、パソコン。
　　　などなどなどなど。
　
　でも、
　　新しもの好きさんが
　　　飛びつき、それに続けと、
　　　　興味を持った人が続き、
　　　　　それが流行だと思った人が
　　　　　　流行に遅れるな、と
　　　　　　　流れていく。

　そうなると、使わん宣言した人も
　　会社で、強制的に扱わねば
　　　ならなくなり、渋々使う。
***
　でも、
　　生成AIに限っては、
　　　少しようすが違う気がします。

　なぜなら、
　　そこに言葉が介在するから。

　生成AIとの会話を
　　する必要があり、
　　　それなりの成果を
　　　　出すためには、
　　　　　ポイントを知る
　　　　　　必要がある。

　つまり、
　　コミュニケーション能力が
　　　問われるわけです。

　そして、
　　やらせたいことを
　　　的確に指示するには、
　　　　知識も必要になります。

　例えば、
　　ChatGPTに
　　　Excelマクロの作成を
　　　　頼むとしましょう。

　相手は、Excelがどういうものかを
　　知っていますし、マクロも
　　　組めます。

　でも、目的のセルに
　　合計を計算して、
　　　入れて欲しい、と
　　　　きちんと説明しなければ
　　　　　目的のマクロの作成が
　　　　　　できないわけです。

　Excelのマクロは組めなくても
　　Excelの各名称と役目は、必要。

　ほかも然りです。

　ChatGPTなどの生成AIとの
　　コミュニケーションは、
　　　いまだに、“これが正解”という
　　　　答えが出てきていません。

　言葉ひとつで
　　千差万別の結果が
　　　出てきて、右往左往するのは
　　　　我々、ユーザーです。
***
　それなのに
　　“やらない”という人がいる。

　今、“やらない”ということは
　　将来的にやるハメになったとき、
　　　ほかの人間が全員やっていて
　　　　自分ひとりだけが知らない、
　　　　　そんな場面を想像して
　　　　　　いないのでしょうね。

　そんな状況で、
　　“人に聞ける”と思いますか？

　おそらく、知ったかぶりして、
　　“これ、やっとけ”みたいに
　　　部下に投げるんでしょう。
　　　　“簡単だよな”とか言いそう
　　　　　ではありませんか？

　そんなときの部下の心の中は、
　　こんな感じでしょうか。
![DALL·E 2023-12-02 11.46.39 - An office scene where a female employee is throwing work documents at her boss in frustration. The boss is a man with a balding head and a noticeable .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/b67ce743-e0f8-f6ac-b703-e233ad5b4945.png)


　まぁ、今回は、
　　このくらいにしといたるわw
CloudFront オリジンサーバーがダウンしたときにsorryページを表示する方法

## はじめに
今回の構成はcloudfrontからオリジンサーバー（alb+ec2）にアクセスしたときに500番台のエラーが返ってきたときにsorryページを表示させる方法について記載します。

## 構成
今回の構成は下記になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/16e66c50-cefa-1e74-900d-b8d2a8110080.png)

## 手順
前提として上記構成がすでにあるものとします。
①cloudfrontの設定
②S3にファイルの配置

### ①cloudfrontの設定
・パスパターンを __/sorry/*__ として設定する。その他は任意で。
・エラーページで500番台すべてでカスタムエラーレスポンスを作成する。
・レスポンスページのパスは __/sorry/index.html__ とする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/872cdea8-6162-292e-2991-f5ceab6f9841.png)

### ②S3にファイルの配置
指定のS3バケットのsorryオブジェクトにindex.htmlファイルを配置。

以上で設定完了。

## まとめ

オリジングループでsorryページを表示するように設計していたがうまくいかなかったのでこちらの方法で行うことにしました。時間があったらオリジングループについてもっと詳しく調べていきたい。
【Unity】eventというオブジェクトを含むJsonをパースする

UnityのJsonUtilityを使って以下のようなJsonをパースしようとして詰まった。

```
{
    "id": 1,
    "event": {
        "broadcaster_user_id": "1337",
        "broadcaster_user_name": "Cool_User",
        "broadcaster_user_login": "cool_user"
    }
} 
```

Jsonのeventキー部分をパースするには、以下のようなクラスを書く必要があります。
```
[System.Serializable]
public class Hoge
{
    public int id;
    public event event;
}

[System.Serializable]
public class event 
{
    public string broadcaster_user_id;
    public string broadcaster_user_name;
    public string broadcaster_user_login;
}
```

が、これだとエラーとなります。
eventはC#で使われているキーワードなので、識別子に使う事ができません。
ではどうするか。

# 結論
識別子の頭に@をつけることで解決できました。

```
[System.Serializable]
public class Hoge
{
    public int id;
    public @event @event;
}

[System.Serializable]
public class @event
{
    public string broadcaster_user_id;
    public string broadcaster_user_name;
    public string broadcaster_user_login;
}
```

これでeventが無事パースできました。
この頭に@がついた識別子は、逐語的識別子と呼ぶらしいです。

参考
https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/250identifier/identifier.html

ちなみに、@を抜いた識別子も逐語的識別子として定義したものと同一とみなされるようです。
前述のような既にキーワードで使用されているケースでなければ、普通に使えます。

```
int @foo = 10;
foo += 15; // @fooとして定義した変数に代入される
Debug.Log(@foo); // 結果は25
```
CodeIQ:「タワー・ビルディング」問題の解答

Kawazoe(@riverplus)さんのCodeIQの問題です。
問題とテストケースはこちらにお世話になりました。解答もあります。
~~->https://blog.goo.ne.jp/r-de-r/e/e574b768cca193ed96af1b5f7a74d7c7~~
(リンクが切れていました。2025.5.2)
URLが変わっていましたが見つかりました。(2025.5.3追加)
->https://sangaku0418.hatenablog.com/entry/2018/01/04/100100

こちらにも情報があります。
->https://togetter.com/li/1179955

ーーー2025.5.2追加
Aを一辺が1の立方体のブロックとし、
Bを縦が1、横が1、高さが2の直方体のブロックとします。
自然数n,a,b に対し、Aを最大a個、Bを最大b個使って、
縦が1、横が1、高さがnの直方体の塔を作ります。
このときの積み上げ方の場合の数をF(n,a,b)としたとき、
1≦n≦500, 0≦a≦n, 0≦b≦nなる自然数n,a,bに対し、
F(n,a,b)を1000003で割った余りを求める問題です。
ーーー

前回Kawazoeさんの問題は難しいと書きましたが、難しくないものもあります。
漸化式とメモ化で解く方針を立てました。
タワーなのに横に並べて考えたため混乱したのでざっと式変形してみました。
nCrを組み合わせの数として
f(n,a,b)＝Σ(ai+bi)Cai　ただしai+2*bi=n
(ai+bi)Cai=(ai+bi-1)C(ai-1)+(ai+bi-1)Cai=(ai+bi-1)C(ai-1)+(ai+bi-1)C(bi-1)
Σ(ai+bi-1)C(ai-1)+(ai+bi-1)C(bi-1)=f(n-1,a-1,b)+f(n-2,a,b-1)
漸化式はf(n,a,b)=f(n-1,a-1,b)+f(n-2,a,b-1)という~~当然の~~結果になりました。
この右辺はタワーの一番上にAを乗せるかBを乗せるかに対応しています。(12月3日)

```Julia
#julia ver 1.41,1.53,1.73

function solve3(n,a,b,r)
  dic=Dict()
  function f(n,a,b)
    key=string(n)*":"*string(a)*":"*string(b)
    if haskey(dic,key)
      re=dic[key]
    elseif n <0 || a<0 || b<0
      re=0
    elseif n == 0
      re=1
    else
      re=mod(f(n-1,a-1,b)+f(n-2,a,b-1),1000003)
      dic[key]=re
    end
    return re
  end
  ret=mod(f(n,a,b),1000003)
  s = r==ret ? "ok " : "no "
  println(s,ret)
end

solve3(6, 4, 2,11)
solve3(100, 50, 50,765461)
solve3(7, 5, 2,16)
solve3(29, 10, 10,92378)
solve3(500, 249, 125,0)
solve3(123, 81, 82,475012)
solve3(436, 400, 212,544100)
solve3(497, 490, 399,663760)
```
Juliaでは漸化式で解く方針を立ててましたので式の変形を続けましたがが、
nCrを計算するだけでよいのが明瞭です。prologは遅いしメモ化が面倒なので、
題意に合うaiとbiに対して、(ai+bi)Cbiの合計を計算します。

```Prolog
%Swi-Prolog v 7.4.2,7.6.4

%:-initialization(start).
%start.

ncr(_,0,1).
ncr(N,1,R):-R is N.
ncr(N,M,R):-N1 is N-1,M1 is M-1,ncr(N1,M1,R1),R is R1*N div M,!.

res1(N,A,B,R,R):-
    N>A+2*B,!.
res1(N,A,B,R1,R):- %　N=<A+2*Bの間(N-2*B+B)C(B)を計算してたしていく
    N=<A+2*B,!,X is N-2*B+B,ncr(X,B,R2),R3 is (R1+R2) mod 1000003,
    B1 is B-1,res1(N,A,B1,R3,R).

solve1(A,B,C,D):-
    (res1(A,B,C,0,R)->(R==D->Str=" ok  ";Str=" no  ");
    write(fail)),write(" "),write(Str),writeln(R),!.

start:-f1(A,B,C,D),solve1(A,B,C,D),fail.
start.

f1(6, 4, 2,11).
f1(100, 50, 50,765461).
f1(7, 5, 2,16).
f1(29, 10, 10,92378).
f1(500, 249, 125,0).
f1(123, 81, 82,475012).
f1(436, 400, 212,544100).
f1(497, 490, 399,663760).
```
【7日目】OSS連携してみたい！(5)PythonでHelloWorld

この記事は筆者オンリーの[Advent Calendar 2023](https://qiita.com/advent-calendar/2023/aichallenge_racing_for_mas)7日目の記事です。  

# 前回までのあらすじ
OSS連携を試みるため、C++でROS2の簡単なモジュールを作りました。
今回はpythonrobotics等のPython製OSSとの連携を見据えPythonで自作ROSモジュールがAutoware上で動くか確認してみたいと思います

# ROS2でモジュール作成
[ROSのチュートリアル](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Creating-Your-First-ROS2-Package.html)を参考にまずはAutowareでHelloWorld的なことができるようにカスタマイズしてみようと思います。

# Autowareのカスタマイズ
## パッケージの作成
Autowareをカスタマイズする方法ですが、[公式ページ](https://github.com/AutomotiveAIChallenge/aichallenge2023-racing/blob/main/documentation/docfx_project/customize/index.md)にちょっとだけ記載されております。

まずは[ROSのチュートリアル](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Publisher-And-Subscriber.html)を見ながら、簡単なパブリッシャーとサブスクライバーを作ります。

[公式サイト](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Publisher-And-Subscriber.html)の通り、ROS2のパッケージを作成します。

```
$ cd ~/aichallenge2023-racing/docker/aichallenge/aichallenge_ws/src/aichallenge_submit/
$ ros2 pkg create --build-type ament_python py_pubsub
```

[ROSチュートリアル](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html)に従って、package.xmlとCMakeLists.txtを変更します。

## パッケージのビルド
次に、Dockerを起動してコードをビルドします。
```
$ cd /aichallenge/
$ bash clean_build.sh 
```
以下のようにビルドエラーが発生してしましました
![Screenshot from 2023-12-02 10-52-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3154772/fc3ed946-7d7d-2095-ed0b-f155b0f884c4.png)
[こちら](https://answers.ros.org/question/396439/setuptoolsdeprecationwarning-setuppy-install-is-deprecated-use-build-and-pip-and-other-standards-based-tools/)を参考にダウングレードしてビルドしたら成功しました。

```
pip install setuptools==58.2.0
cd /aichallenge/
bash clean_build.sh 
```

以下のようにcpp_pubsubのビルドができれば成功です。
![Screenshot from 2023-12-02 10-56-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3154772/f5acf658-2193-640f-678d-2595d30c8acf.png)

## パッケージの実行
参考記事同様、launchファイルから実行します。本大会ではAutoware-Microを使用しており、autoware_micro_awsim.launch.xmlを変更します。

```autoware_micro_awsim.launch.xml
<!-- lane_driving -->
〜割愛〜
<group>
    <node pkg="python_pubsub" exec="talker"/>
    <node pkg="python_pubsub" exec="listener"/>
</group> <!-- Simple Pub Sub -->
</group> <!-- lane_driving -->
```
実行してみます。今回は併せてAWSIMも実行してみます。
```
$ bash run_autoware.sh
$ bash run_awsim.sh
```
![Screenshot from 2023-12-03 09-50-44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3154772/efd62f0e-b144-fbf9-4ce7-ad8416ea44a9.png)
PythonでもHello Worldできることを確認しました。


# 今後の予定
1.Autowareのメッセージをサブスクライブできるようにする。
2.Autowareのメッセージをパブリッシュし、既存のAutowareがサブスクライブするようにする。
3.OSS連携もできるように変更する。
という流れで行きたいと思います。
私の強い思想を聞いてくれLTという勉強会のログ

# LT開催の背景
* 人にはそれぞれ想い(強い思想)があり、それはとても面白く、共有されること自体に価値があると思っている
* 昨今のXを見ていて、何か発信するとお気持ちが沢山飛んできて発信自体に心理的負荷が高いと感じている
* 結果、globalに発信する内容は、多数が共感・正しいと思う内容でないと発信しづらい、勇気がいる行為になっている気がしている

# LTの目的
* globalには発信しづらい・しなくても良いくらいの思想をシェアしてもらう
* 5分1テーマという制限を設けて、主張したいことの濃さを上げる
* 限られた時間で伝えたいことをまとめる能力も練習してほしい(内緒)
* 私が強い思想を感じたい(利己)


# LT発表者のルール
* 1人5分
* 強い(と思われる)思想ならなんでもOK
* テーマは1つに絞る
* 発表タイトル固定「いいから黙ってxxxはxxxしておけ」


# LT進行スライド
https://gamma.app/public/LT-b5pogmrancps45n?mode=doc


# 結果
* 最大30名集まりました
![slack のスクリーンショット： スレッド「私の強い思想を聞いてくれLT会メインスレッド。ハドルもここでやります。」 33 件の返信  スレッド「いいから黙ってwsでソケット通信しとけ」14件の返信 スレッド「いいから黙って代替テキストは入れておけ」50件の返信  スレッド「いいから黙ってpropsのコールバックはonから始めておけ」27 件の返信 スレッド「いいから黙ってアニメーションはCSSで書いておけ」40件の返信 スレッド「いいから黙ってAPI通信はRPCでしとけ」23 件の返信 スレッド「いいから黙って抽象的なコンポーネントはコンポジションにしておけ」29件の返信 スレッド「いいから黙って例外処理にはResult型を使っておけ」48 件の返信 スレッド「いいから黙ってCSS設計は Every Layoutにしておけ」31 件の返信](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147882/3ce0eacd-ff2a-8c1b-0cac-edd94fb1ef04.png)

## 公開されている発表内容
* @ygkn 
    * [いいから黙って代替テキストは入れておけ](https://scrapbox.io/ygkn/%E3%81%84%E3%81%84%E3%81%8B%E3%82%89%E9%BB%99%E3%81%A3%E3%81%A6%E4%BB%A3%E6%9B%BF%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%81%AF%E5%85%A5%E3%82%8C%E3%81%A6%E3%81%8A%E3%81%91)
* @totto2727
    * [とりあえずTypeScriptの例外処理にはResult型を使っておけ](https://qiita.com/totto2727/items/14dc358b71b791a44dbd?a)
* @282Haniwa 
    * [いいから黙ってpropsのコールバックは`on`から始めておけ](https://qiita.com/282Haniwa/items/46c01c9a8e2acc130d89)

# このLT開催に向けて意識したこと
* 60分枠を時間通り終わらせること
* 時間オーバーすることが多いのでバッファを持たせておくこと
* 主役は発表者で進行役は黒子で良い状態にすること
* 発表者の心理的安全性を担保すること
* 発表者も含めた参加者の学びになること
* 時間が不足する可能性が高いので、補完ができる仕組みを作ること
* 参加できなかった人にも大体伝わるようにすること
* 私の負担も最小限にすること


# このLTの勘所
## 発表タイトルのテンプレ固定
* 同じフォーマットにすることで、LTの目的を達成しやすくする
* タイトルに悩むコスト削減

## 1人5分
* 主張したいことの濃度を上げる
* LT全体のテンポも上がる

## 心理的安全性の担保
* このLTの場をどのような場にしたいのかLT最初に目的を伝えておく
* 私が検閲者となるよと宣言

## 補完の仕組みを作る
* 発表内容ごとにあとで質問とかも出る可能性があるので、スレッドを分けて情報集約しコメント・質問・追加情報などを書きやすくした

## LTが見れなかった人でも後でログを見やすくする
* 発表者ごとのスレッドを用意してそこにコメントしてもらった
* 発表者のスライドスクショを貼っていき、何の話の時にどんなコメントがあったのか分かりやすくした


# 感想
* やってよかった
* 2回目もありそう
* 今年は1記事も書いてないことに気づいたので安心した


# ここまで読んでくれた人向け
* このLTが面白そうと思ったら是非同じような枠でLTをやってみて感想教えてくれると私が喜びます
    * ~~いいから黙って同じLTやって感想をコメントしておけ~~


いつもQiitaにはお世話になってます
Apache ActiveMQ ArtemisをWindows11で立ち上げる


# 1. はじめに
* メッセージキューサービスをwindowsで試してみたい
* Apache Active MQ Artemisのサービスを起動して使ってみたい

# 2. 開発環境
* Apache ActiveMQ artemis 2.31.2
* Windows 11

# 3. Active MQのダウンロード
* 以下サイトよりzipファイルをダウンロードする。

https://activemq.apache.org/components/artemis/download/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/69cf1eaa-1412-5dda-34bc-03be3a33655a.png)

* 任意のフォルダに保存して展開しておく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/8904b59f-13ec-71e9-b8e9-40b83b629614.png)

# 4. Active MQのインストール
## 4.1. コマンドプロンプトを起動して、```${ARTEMIS_HOME}/bin```へ移動する
* サンプルではworkフォルダ内へ展開している
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/fda67261-55cf-d7f4-5878-b800b2e18ced.png)

## 4.2. artemis createコマンドを実行する
* サンプルでは```mybroker```を指定
```
artemis create mybroker
```
* 任意のユーザー名を入力する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/397d0f35-3df4-5f96-6a90-ee06bba85c53.png)

* 任意のパスワードを入力する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/51edc128-368b-b28a-13ab-ab1dd96cb83a.png)

* 任意のanonymousの設定をする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/16a4e636-5301-4e94-923d-2c547c1061df.png)

## 4.3. インストール完了後のURLを確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/f2b71c40-c30f-d715-0c14-6f9a9e2f08a6.png)

## 4.4. URLにアクセスし、ユーザ名、パスワードを入力してログインする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/c8d1a380-f822-73a5-fd8d-465c7ba8d27e.png)

## 4.5. トップページが表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/29e5d83c-0330-1a6e-e0bf-59399de3b15d.png)

# 5. 参考文献

https://activemq.apache.org/components/artemis/documentation/

https://zenn.dev/yuulab/articles/ea3a67e956a0f2
BIツールで使いやすいオープンデータのノーコード自動取得方法を紹介するぜ！

#　この記事は以下の人を対象にしています。

:::note
- プログラミングはできない。
- グーグルのスプレッドシートは使える。
- 関数の書き方はわかる。
- メールアドレスを持っている。
- オープンデータを自動取得したい。
:::

最初にネタバレ、結論から書く！

1. 総務省統計局の統計ポータルサイトe-statでユーザー登録する。
1. ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/5cf1d4d1-2092-e4c3-a111-7266efa7f976.png)マイページのトップページにある`API機能(アプリケーションID発行)`を押して、リンク先から登録してください。無料で3つまで登録できます。
1. ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/ed390a00-4593-7f21-6210-262931e1c4eb.png)


1. Googleスプレッドシートを開く。
1. どこでもいいから以下の式を書く。

```
=IMPORTDATA("http://api.e-stat.go.jp/rest/3.0/app/getSimpleStatsData?appId=0123456789abcdefghijklmnopqrstuvwxyz&lang=J&statsDataId=0003410420&metaGetFlg=Y&cntGetFlg=N&explanationGetFlg=Y&annotationGetFlg=Y&sectionHeaderFlg=1&replaceSpChars=0")
```
:::note alert
`0123456789abcdefghijklmnopqrstuvwxyz`
の部分を、e-statで取得したapiIDの文字列に変えてください。
:::

これでスプレッドシートに以下のようなデータが出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/8a17db0e-3c1e-2bfb-3355-45273a34529e.png)


e-statからはjson形式とcsv形式でデータを取得できるものがあります。
※全部とれるかどうかはよくわかんない。

urlの`getSimpleStatsData?`の部分がcsvを指定していると思われ。


# そうはいっても無尽蔵にとれるわけじゃない。
スプレッドシートの制限があるので、なんぼでもとれるわけじゃないっす。
なので、urlを構成している要素をいろいろ工夫して、制限の範囲内でデータが取れるようにチャレンジしてみてください。

tableau public使って練習してるとね、いろんなデータとってきたくなるけど、違う環境下で利用したい、人に教えたいのにcsvで毎回読み込むのはちょっとね、というわけで、スプレッドシートに自動更新されるデータを反映させられる方法の一つを紹介しました！
読書感想：「技術書」の読書術

# 情報
書籍名「技術書の読書術」
著者：IPUSIRON 増井敏克


# 読もうと思った動機
今まで我流で読書をしていたため。
他の人の良い読書習慣を取り込むため

# 印象に残った部分

## 本を読む目的　1-1
### １．体系的に学ぶため
実務で必要な場合該当する。

### ２．概要を把握するため

実務で使わない場合が該当する。

## 入門書、専門書、逆引きの３通りを読む
入門書の役割：その分野の概要を知る。（教科書）
専門書の役割：実務で使う知識（参考書）
逆引き：似たような事例がないか調べるときに使う。（ドリル）

個人的な疑問点：
公式ドキュメントはどれに該当するのか気になった。
本は二次情報、公式ドキュメントは一次情報だから棲み分けができてるって解釈か？

## 読書の工夫

### 1.読書管理アプリを使う
(a)忘備録としての役割
(b)積み重ねが目に見えるからモチベーション維持ができる。

### 2.マーキング読書法-紙の本に印をつける
(a)知識の吸収率が変わる
(b)短時間でできる。

### 3.書見台を使う
(a)両手を使わないで読書できる
　　→両手が疲れない　and PC作業と並行してできる。
  　　　分厚い本読むとき効果絶大



# 実践できること or 感想
・マーキング読書法を試す
・書見台で本を読む
・Qiitaに感想を投稿する
・入門書、専門書、逆引きの３通りを読む
・Notionで読書記録を取る。

読書を楽しむための工夫が多数紹介されていて　良い本でした。
読む前より読書習慣が改善されたので満足ですね。
[Next.js]LayoutとTemplateの違い

# はじめに
LayoutとTemplateの違いについてまとめてみました。

# 大きな違い
2つの大きな違いとしては、画面遷移時にLayoutは再レンダリングがされませんが、Templateはされます。

# 実際に確かめてみる
実際にコードを書いて確かめてみようと思います。
以下のコードを用意します。

```dashboard/layout.tsx
"use client";

import React, { useEffect } from "react";

export default function Layout({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    console.log("Layoutレンダリング");
  }, []);
  return (
    <div>
      <h2>Layout Header</h2>
      {children}
    </div>
  );
}

```

```dashboard/template.tsx
"use client";

import React, { useEffect } from "react";

export default function Template({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    console.log("Templateレンダリング");
  }, []);
  return (
    <div>
      <h2>Template Header</h2>
      {children}
    </div>
  );
}


```

以下のような画面になります。
![スクリーンショット 2023-12-02 10.48.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613586/da080de9-d01d-2f7c-6487-01504c7378dd.png)

画面を開いた時は、どちらもレンダリングされていることがわかります。
続いて、以下のコードを用意します。
```dashboard/[slug]/page.tsx
"use client";

import Link from "next/link";

export default function Page({ params }: { params: { slug: string } }) {
  return (
    <>
      <div>dashboard: {params.slug}</div>
      <Link href={`/dashboard/${Number(params.slug) + 1}`}>Go to next page</Link>
    </>
  );
}

```
これは、dashboardの詳細ページを用意し、ページ遷移することができるリンクを設置したコードです。
表示画面とコンソールは以下のようになります。
![スクリーンショット 2023-12-02 10.52.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613586/332a2153-cb38-57f5-9a7a-eb8bab07af36.png)

コンソール↓
![スクリーンショット 2023-12-02 10.52.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613586/0ed7d112-db94-6f6a-ceb0-25ec71f262d2.png)

リンクを押して画面遷移してみます。
![スクリーンショット 2023-12-02 10.55.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613586/bb9c480c-aa2b-9fc0-c68b-330a9a7ff366.png)

コンソールを確認します。
![スクリーンショット 2023-12-02 10.54.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613586/2e9cc93d-4d87-61dc-342f-70488143d625.png)
すると、templateはレンダリングされましたが、Layoutはレンダリングされていないことが確認できました。

　# 感想
基本的には、パフォーマンスの最適化の観点から、Layoutを使用するのがいいと思います。
ですが、例として、画面遷移時に何かしらのイベント(アニメーションをつけたい場合など)はTemplateを使用してもいいのかなと思いました。

# 最後に
他にも色々な記事を書いているので、よければ読んでいってください、、、

https://qiita.com/hukuryo/items/97797a91d7e2ee0bcabc

https://qiita.com/hukuryo/items/265c676d17fe21e75242

https://qiita.com/hukuryo/items/ebeb26823f944f143b11
App EngineからCloud Runに移行したら、サーバー費用が98%削減出来た話

# はじめに
先日、費用削減の一環として、弊社で運用しているAPIサーバーをApp EngineからCloud Runへと移行したところ、表題の通り98% (サーバーあたり月間2万円 -> 450円)の費用削減を達成することが出来ました。何故サービスを移行しただけでこれほどの違いが出たのか、そのカラクリについて調べてみました。

# 基本料金
2023年12月現在、両者の料金体系は以下の通りです。App Engineにはスタンダードとフレキシブルの２つの環境がありますが、今回はフレキシブル環境を前提としています。

|App Engine|Cloud Run(下側)|
|---|---|
|![Pricing  _  App Engine  _  Google Cloud - Google Chrome 2023_10_10 13_49_02 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2147470/563b2256-bcd7-eb78-a349-8788d9609ef2.png)|![Pricing  _  App Engine  _  Google Cloud - Google Chrome 2023_10_10 13_49_42 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2147470/4721fcb1-b3c7-9f2a-92ee-0d3c3cce13c9.png)|

例えば`CPU: 2コア, Memory: 4GB`で運用した場合の、１日当たりの料金を算出すると...
```
App Engine
  ($0.0666 x 2vCPU + $0.0089 x 4GB) x 24時間 = 約4ドル

Cloud Run
  ($0.000024 x 2vCPU + $0.0000025 x 4GB) x 60秒 x 60分 x 24時間 = 約5ドル
```
**基本料金はほとんど同じっぽいです。**

# インスタンスの状態遷移
両者の基本料金に大きな差はありませんでしたが、一方で課金システムに違いがあります。課金システムはサーバーインスタンスの状態遷移と密接に関係しているため、ここで整理しておきます。

インスタンスには『Active・Idle・Terminated』の３つの状態があります。

- Active (処理中)
リクエストを受けてからレスポンスを返すまでの時間を指します。

- Idle (待機中)
リクエストの処理が完了した後、インスタンスはすぐに破棄されるのではなく待機状態へ移行します。待機状態のインスタンスは、新規リクエストに対し迅速にレスポンスを返すことが出来ます。車のアイドリングストップなどと似た概念だと思います。

- Terminated (終了)
インスタンスが破棄された状態のことです。待機状態がApp Engineでは15分、Cloud Runでは5~15分続くと、自動で終了状態へと移行します。

# インスタンスの課金対象
![graph_price.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2147470/951d02cf-b9b2-ce5f-3c6c-e258ef352793.png)

ここが大切なポイントなのですが、**App EngineはActiveとIdleの時間が課金対象になります。一方、Cloud RunではActiveの時間のみが課金対象です。ですので、Idleの時間が長いほどCloud Runの方がお得ということになります。** 

Idleの時間が長くなるユースケースとしては、ユーザーからのリクエスト頻度が少ないAPIであったり、バッチ処理などの用途で定期的にしか呼ばれないAPIなどが考えられます。

今回移行の対象となったAPIサーバーもバッチ処理で呼ばれるAPIだったのですが、メトリクスを確認したところ**１日の中でActiveな時間はわずか20分ほどであり、残りの23時間40分は何もしていないのに無駄に費用が発生している状態だっだ**と判明しました。この無駄遣いをカットしたことが今回の成果に繋がっています。

# まとめ
App EngineとCloud Runのどちらでも良いユースケースにおいては、Cloud Runを使用することで費用を大きく抑えられる可能性があります。ただし、App Engineでしか実現できない機能もあるので、そこだけ注意しましょう。

# 参考
https://cloud.google.com/appengine/pricing?hl=ja

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