OmniAICreator/Qiita-1.07M huggingface dataset:
bedrockのprompt flowsを作成したらnetwork errorになった話

# Amazon Bedrock Preview の Prompt Flows を試してみた

Amazon Bedrock のプレビュー機能である **Prompt Flows** を試してみました。  
AWS CDK を使ってリソースを構築し、簡単なフローを動かしてみようとしたのですが、結果として **Network Error** が発生しました。それまでの流れを記載します。
※こちらの検証は10月頃に実施したものとなります



## Prompt Flows の概要

Prompt Flows は、Amazon Bedrock 上で複数のプロンプトやデータフローを定義し、それをワークフローとして実行できる機能です。以下のような構造で、入力データからプロンプトを経由して出力を生成する流れを構築できます。

- **Input Node**: フローに入力データを渡す
- **Prompt Nodes**: プロンプトを使用して LLM を呼び出す
- **Output Node**: プロンプトの結果を出力する


## AWS CDK によるリソース構築

以下は、AWS CDK を使って Prompt Flows を構築したコードの概要です。  
KMS キーの作成から IAM ロールの設定、Prompt ノードやフローの定義まで、一通りの設定を行っています。

### 1. **KMS キーとリソースポリシー**
まず、プロンプトやフローで使用するデータを暗号化するための KMS キーを作成し、適切なリソースポリシーを設定します。

```typescript
const kmsKey = new kms.Key(this, "KmsKeyResource", {
  enableKeyRotation: true,
  alias: "AliasName",
  description: "A KMS key for encryption",
});

kmsKey.addToResourcePolicy(
  new iam.PolicyStatement({
    actions: ["kms:Encrypt", "kms:Decrypt", "kms:GenerateDataKey"],
    principals: [new iam.ServicePrincipal("service.amazonaws.com")],
    resources: ["*"],
  })
);
```

### 2. **IAM ロールとポリシー**
次に、Bedrock の Prompt Flows を実行するためのロールとポリシーを作成します。

```typescript
const executionPolicy = new iam.Policy(this, "ExecutionPolicyResource", {
  document: iam.PolicyDocument.fromJson({
    Version: "2012-10-17",
    Statement: [
      {
        Action: ["kms:Decrypt"],
        Effect: "Allow",
        Resource: [kmsKey.keyArn],
      },
      {
        Action: ["bedrock:InvokeModel", "bedrock:GetPrompt", "bedrock:GetFlow"],
        Effect: "Allow",
        Resource: "*",
      },
    ],
  }),
});

const executionRole = new iam.Role(this, "ExecutionRoleResource", {
  assumedBy: new iam.ServicePrincipal("service.amazonaws.com"),
});
executionRole.attachInlinePolicy(executionPolicy);
```

### 3. **Prompt ノードの作成**
Prompt Flows で使用するプロンプトを作成します。

```typescript
const prompt1 = new bedrock.CfnPrompt(this, "Prompt1Resource", {
  name: "Prompt1",
  customerEncryptionKeyArn: kmsKey.keyArn,
  variants: [
    {
      name: "DefaultVariant",
      modelId: "model-arn-example",
      templateType: "TEXT",
      inferenceConfiguration: {
        text: {
          maxTokens: 4096,
          temperature: 1.0,
          topP: 0.999,
          topK: 250,
        },
      },
      templateConfiguration: {
        text: {
          inputVariables: [{ name: "Variable1" }],
          text: `
            Template example: {{Variable1}}
          `,
        },
      },
    },
  ],
});
```



## 実際にアクセスしてみる

*結果：Network Error の発生*

Prompt Flows をデプロイし、実際にフローを実行しようとしたところ、以下のようなエラーが発生しました。

```
Network Error: Unable to reach the service endpoint.
```

エラーの原因は明確でないですが、推論時間を含めた待機時間が長いとprompt flows側で接続を切っている様でした。

## まとめ
Amazon Bedrock の Prompt Flows を試してみた結果、エラー発生によりフローの実行は完了しませんでしたが、構築プロセスや機能の可能性を確認する良い機会となりました。

Prompt Flows の特長的なポイントとして、プロンプトのアウトプットを次のアウトプットに直接繋げることができる設計は非常に興味深いと感じました。

時間をおいてまた検証してみたいと思います。
MySQLの全テーブル削除するとき外部キー制約...鬱陶しくないですか？

みなさんデータベース操作をするためのSQLをDBMSにはいて操作したことはありますか？
データベース開発やメンテナンスの際，現在のデータベース内のすべてのテーブルを一括で削除する必要が生じることがあるよね？

> こんなことにならないように普段から慎重に開発しましょう．テストやリセットの際は仕方がないですが

本記事では，そのための安全で効率的なSQLスクリプトを詳細に解説します．

SQLわかんない人は以下のSQLチートシートをご覧ください．

https://qiita.com/JavaLangRuntimeException/items/f038fbaccdd92fb0308a

## 全部消すSQLはこれだ
MySQLで実行できるSQLを先にはっちゃいます．これを実行すると全部のデータが消えますわ．

> ガチで全テーブルが消えちゃうので注意

```sql
SET FOREIGN_KEY_CHECKS = 0;
SET GROUP_CONCAT_MAX_LEN=32768;

SELECT GROUP_CONCAT(table_schema, '.', table_name) INTO @tables 
FROM information_schema.tables 
WHERE table_schema = DATABASE();

SET @tables = CONCAT('DROP TABLE IF EXISTS ', @tables);

PREPARE stmt FROM @tables;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET FOREIGN_KEY_CHECKS = 1;
```

### 外部キー制約の一時無効化

まず，外部キー制約を無効化する処理である。`SET FOREIGN_KEY_CHECKS = 0;`により，テーブル間の参照関係に影響を与えることなく，テーブルを安全に削除できる．

### グループ連結の最大長設定

`GROUP_CONCAT`関数で生成される文字列の最大長を設定するステップである。デフォルト値では不十分な場合があるため，`SET GROUP_CONCAT_MAX_LEN=32768;`として32768バイトに拡張している．

### 現在のデータベース内のテーブル名を取得

`information_schema.tables`から現在のデータベースに存在するすべてのテーブル名を取得する処理である．`SELECT GROUP_CONCAT(table_schema, '.', table_name) INTO @tables FROM information_schema.tables WHERE table_schema = DATABASE();`により，各テーブル名は「スキーマ名.テーブル名」の形式で連結される．

### 動的なDROP TABLE文の準備と実行

取得したテーブル名を使用して，動的な`DROP TABLE IF EXISTS`文を生成する。`SET @tables = CONCAT('DROP TABLE IF EXISTS ', @tables);`，`PREPARE stmt FROM @tables;`，`EXECUTE stmt;`，`DEALLOCATE PREPARE stmt;`を使用することで，柔軟で安全なテーブル削除を実現する．

### 外部キー制約の再有効化

最後に，`SET FOREIGN_KEY_CHECKS = 1;`により，外部キー制約を再度有効化する．

このスクリプトは，MySQL環境において，データベース内のすべてのテーブルを効率的かつ安全に削除するための汎用的な方法です．開発初期でテーブルをいじりたい，テスト，リセットなどのシーンで有用なツールとなるのでぜひ活用して欲しい．

それではQiitaアドカレ.24企画の今日のクリスマスツリーです．

> 詳しくは[こちら](https://qiita.com/JavaLangRuntimeException/items/1f4a6febf957f522ba45)の記事から

![Wondershare Uniconverter 15_000006.GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/9a83c578-fb2a-2f11-dee0-2adbde5b61cf.gif)
ラズパイを使ってルーターをとりあえず作る話

みなさんルーターは未知な技術で作られていると思っている方いると思います。なのでルーターの仕組み？を開設しつつiptablesで作ろうと思います。

## 環境
- Ubuntu 24.04

## 必要なもの
今回私はラズパイで作ろうと思っているので、以下の機材を用意してください。
- ラズパイ
- USB - LAN(要するにUSBからLANに変換するもの大体二千円弱で売っています)
- 気力
- スイッチングハブ

## 依存関係をインストール
```sh
sudo apt install iptables-persistent
```

## netplanの設定
```yaml
networks:
  eth0: # グローバルなネットワークに接続している方のNIC
    dhcp4: true # DHCPで今回は自動的に割り当ててもらうようにしたが、固定にしてもよい
  eth1: # ローカル側(スイッチングハブにつなげている方)
    dhcp4: false
    addresses:
    - 172.16.70.254/24
```
これの後反映しましょう
```sh
sudo netplan apply
```

## Iptablesの設定(マスカレード)
```sh
sudo iptables -t nat -A POSTROUTING -s 172.16.70.0/24 -o eth0 -j MASQUERADE
```

`eth0`の部分ですが、グローバルなネットワークに接続しているNICを指定してください。

## iptablesの永続化
再起動が起きた際に今の編集データが消えるので保存しましょう
```sh
sudo iptables-save | sudo tee /etc/iptables/rules.v4
```

## カーネルパラメータで転送を有効にする
デフォルトではipv4のフォワーディングが無効になっているので有効にしてあげてください。
```sh
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
```
このコマンドを実行するだけで反映できます。

## ルーターの完成と早速利用する！
スイッチングハブに手持ちの端末のLANを接続させてください。
次に以下のように設定してください。
IPアドレス: 172.16.70.1/24
サブネットマスク(任意): 255.255.255.0
デフォルトゲートウェイ: 172.16.70.254

## もしも、、、
github.comなどにアクセスができなかった場合、MTU値が最適ではない可能性があります。なのでTCP MSSクランプという技術を用いて解決させてください。
```sh
sudo iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
```

## 最後に
結構簡易的なルーターだと思います。これを発展させる形でDHCPサーバを建てたり、ファイアーウォールを有効にしたりポートフォワードを有効することで本物のルーターに近くなります。

ではまたさようならー
Sequence MakerのExcelの数式を計算して出力する「#EVAL?」コマンドについて

## はじめに
Sequence MakerはExcelから測定器を制御可能にするアドインです。Sequence Makerは様々なシーケンスを自由に組むことができますが、Sequence Maker専用コマンドを組み合わせるとより複雑な処理を行うことができます。この記事ではExcelの数式を計算して結果を出力できる「#EVAL?」コマンドについて解説していきます。なお、Sequence Makerについての詳細は以下の記事を参照ください。

https://qiita.com/sequencemaker/items/8e6a370ab0a793a06a3b

:::note warn
***お断り***
本記事の内容はSequence Maker開発元の公式見解ではなく、あくまでも個人が趣味の範囲内で執筆しているものです。記事の内容について開発元へ問い合わせることはお控えください。ご質問・要望などは各記事のコメント欄へお願いいたします。
:::

## 「#EVAL」コマンド
| 専用コマンド | 機能 |
|:-|:-|
| #EVAL?(数式)	| 数式を計算して結果を出力します。<br>数式はExcelの数式と同じ形式です。|

（https://sequencemaker.hioki.com/manual/ja/#command より引用）

「#EVAL」コマンドは、マニュアルにあるように、Excelの数式を計算してその結果を出力することができるコマンドです。・・・と言ってもイメージがつきませんよね:sweat_smile:実際に試してみるとこんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/df55dd1f-b190-d102-6a0e-1f7d22cc2f47.png)

**=NOW()** というのはExcelの関数で、現在日時を返します。#KF(ON)を先にやっているのは、あらかじめセルに設定しておいた表示フォーマットを勝手に変更されないためです。これをやらないと、結果がシリアル値（45642.8922099537とか）で表示されてしまいます。
ちなみに、表示フォーマットも指定すると以下のような感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/32ac14f8-a05c-07ba-8f95-413011a5409b.png)

## 用途その1：セルをコピーする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/2ad9c474-410d-e508-b2fa-654cb15c7421.png)

こんな感じに書いたら、F3～F7のセルの内容をH5へコピーできるのでは…と思って試してみたところ・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/ffd1f5c0-297e-f973-0d96-0b0816111554.png)

「System.__ComObject」というエラーが表示されてしまいました。これは何のエラーなのでしょうか。。。

これではダメなので、セルの指定の後に「&""」というのを付けて試してみます。「&」は本来文字列を連結させるために使用するのですが、なぜかこれを付けておくと・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/3cc2c6cb-12d7-2a46-4400-db448dd754ee.png)

うまくいきます。こんな感じで、シート上のデータを別の場所に転記したい場合に使えます（セル参照ではなく）。

## 用途その2：セルの計算を行う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/822d2acb-cc2a-fbab-6013-ea001c4ac26d.png)

こんな感じに書くと、F3のセルの値がものすごい勢いでカウントアップしていきます。C4のセルの数式を変更すれば、減算や乗算、除算なんかもできます。何か繰り返し測定時にカウンター変数として使うことができるかもしれません。

## 用途その3：:shinto_shrine:おみくじを作る

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/a0ba748d-0338-5bb3-9f49-39ca95e04ac8.png)

#EVAL?はSequence Makerでおみくじを作るときに便利です。おみくじを作るときは、=RANDBETWEEN(1,5)関数を使って1～5の乱数を発生させます。そして乱数の結果をVLOOKUPでおみくじテーブルから拾ってきます。#EVALを使わずに、D4のセルに直接=RANDBETWEEN(1,5)と書くとどうなるでしょうか。なんと！Excelが再計算するたびにおみくじの結果が変わってしまいます。せっかく「大吉」が出ても、どこかセルを編集した瞬間に結果がコロコロ変わってしまいます。
おみくじに限らず、シーケンス動作中に乱数が欲しい場合は役立ちますね！

## まとめ
今回は「#EVAL」コマンドについて紹介し、3つの用途を紹介しました。他にも工夫次第で便利な使い方があるかもしれません。
XMLのDTDについて

XML自体は順序を保証する形式ではなく、要素の順序がデータの意味や正当性に影響を与えない場合が多い形式です。しかし、DTD (Document Type Definition) や XML Schema などのスキーマ定義がある場合、そのスキーマによって順序を強制することが可能です。

## DTDにおける要素順序の制約
DTDでは、要素の出現順序を定義することで、順序を保証するような構造を指定できます。ただし、これはXMLドキュメントを「バリデート」した場合にのみ有効で、DTDがあるだけでは順序の強制は行われません。

例: DTDで要素の順序を定義
以下のDTDでは、name → age → city の順序で要素が記述されることを要求しています。

DTD例
```xml
<!ELEMENT person (name, age, city)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT city (#PCDATA)>
```
対応するXMLドキュメント
```xml
<person>
    <name>Alice</name>
    <age>30</age>
    <city>New York</city>
</person>
```
上記のDTDに基づいてバリデーションを行った場合、以下のようなXMLは「無効」と判定されます。

無効なXML例
```xml
<person>
    <city>New York</city>
    <name>Alice</name>
    <age>30</age>
</person>
```

## DTDの順序指定の特徴
順序が保証される: DTDで定義した要素順序に違反すると、XMLパーサがエラーを報告します。ただし、順序が保証されるのはDTDを使用してドキュメントをバリデーションした場合のみです。
順序指定の柔軟性: DTDでは次のような順序ルールが設定可能です:
固定順序 ((name, age, city))
任意の順序・繰り返し ((name | age | city)*)

## XML Schemaでの順序制御
XML Schemaでは、DTDよりも柔軟かつ厳密に順序を制御できます。たとえば、<sequence> を使って要素の出現順序を固定できます。

XML Schema例
```xml
<xs:element name="person">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="name" type="xs:string" />
            <xs:element name="age" type="xs:integer" />
            <xs:element name="city" type="xs:string" />
        </xs:sequence>
    </xs:complexType>
</xs:element>
```
対応するXMLドキュメント
```xml
<person>
    <name>Alice</name>
    <age>30</age>
    <city>New York</city>
</person>
```

## DTDやXML Schemaの限界

#### 1. 順序の強制はバリデーション時のみ有効:
XML自体の仕様では順序を保証しません。DTDやSchemaで順序を指定し、それに基づいてバリデーションを行う必要があります。
#### 2. データ操作の順序保証には影響しない:
パース後のデータ構造（例: HashMap）に順序が保持されるわけではありません。パーサやライブラリがデータをどのように格納するかは実装依存です。
順序を保持したい場合は、LinkedHashMapやリストなどを使用する必要があります。

## 結論
DTDやXML Schemaがあれば順序を保証できるのか？
スキーマがある場合、定義された順序を強制できます。ただし、それはバリデーション時に限ります。
順序を保証した操作をしたい場合はどうするか？
バリデーションに加えて、データを順序を保持するデータ構造（例: LinkedHashMap）にパースすることで、順序を完全に制御できます。
DTDやスキーマによって要素順序を強制しつつ、パース後のデータも順序を保持したい場合、ライブラリの選定やカスタム処理が必要です。
【Go言語】newとmakeの違いについて解説

## はじめに
今回、Go言語の`new`関数と`make`関数の違いについて解説していこうと思います。
この2つの関数は似ているので、初学者の方には混乱を招くことがあります。
本記事で、2つの特徴を掴み理解を深めていきましょう。

まずは、それぞれの関数の解説から始めます。
## new関数 について
- **new関数**
    - 指定された型の新しいインスタンスをメモリ上に割り当て、そのポインタを返す関数
    - new関数によって割り当てられた値は、その型のゼロ値で初期化されます

実際にnew関数は以下のように使用できます。
```golang:main.go
package main

import "fmt"

func main() {
	var p *int = new(int)
	fmt.Println(p) //出力：0x1400000e0a8
}
```
アドレスが確保されていることが確認できたかと思われます。
では、`new`関数を使わない場合も考えてみましょう。
```golang:main.go
package main

import "fmt"

func main() {
	var p *int = new(int)
	fmt.Println(p) //出力：0x1400000e0a8

// p2というポインタ型を宣言
	var p2 *int
	fmt.Println(p2) //出力: <nil>
}
```
[The Go Playground](https://go.dev/play/p/QGJQom-QRkH)：実行してみましょう。

上記のことから以下の点がわかります。
- `new`関数はメモリ領域を確保してくれるため、アドレスが返ってくる
- 変数`p2`はメモリを確保していないためnil値が出力された

変数`p`にはデフォルトで「**0**」が入っています。
```golang:main.go
func main() {
	var p *int = new(int)
	fmt.Println(*p)
 // 1インクリメントしてみる
	*p++
	fmt.Println(*p)
}
```
[The Go Playground](https://go.dev/play/p/lgsDU8yVAsG)：実行してみましょう。
実行してみると、デフォルト値「**0**」に+1され「**1**」が返ってきてますね。

こちらの操作を先ほどの変数`p2`にも行ってみましょう。

```golang:main.go
var p2 *int
	*p2++
	fmt.Println(*p2)
```
[The Go Playground](https://go.dev/play/p/6We5NyeNI5f)：実行してみましょう。
こちら実行すると「**panic**」が発生します。
エラー内容を見てみると以下のように書いてあります。
```
invalid memory address or nil pointer dereference
```
まだメモリに値が確保されていないので、その中身にアクセスしようとしたためpanicになったことが確認できます。

:::note warn
- **new関数**と普通の宣言は異なることなので区別しておきましょう！
- 構造体の場合はnew関数を使うよりも、構造体リテラルを使用してインスタンスを直接初期化する方が一般的です
:::

続いて、**make関数**について解説していきます。

## make関数 について
- *slice, map, channel*といったビルトインの参照型のために使用されます
- 新しいインスタンスを作成し、その初期化を行います


### sliceの初期化
- **make関数**を使ってスライスを初期化する際には、スライスの型、長さ、容量を指定する必要があります
- 容量については省略することができますが、その場合は容量には長さと同じ値が設定されます
```golang
//長さ10, 容量15のスライスを作成
s := make([]int, 10, 15)
```
### mapの初期化
- マップを初期化する際は**make関数**にキーとバリューの型を渡す必要があります

```golang
// キーがstring型、バリューがint型のmapを作成
m := make(map[string]int)
```

### channelの初期化
- チャネルは、ゴルーチン間でのデータの受け渡しに使用されます
- チャネルの初期化はチャネルの型とバッファサイズを指定することができます
- バッファサイズを指定しない場合は非バッファチャネルが作成されます

```golang
// int型のバッファサイズ5のchannelを作成
ch := make(chan int, 5) 
```

## new関数とmake関数の違い
まずは以下のコードを見てみましょう。
```golang:main.go
package main

import (
	"fmt"
)

func main() {
	// スライスを作成し、その型を表示
	s := make([]int, 0)
	fmt.Printf("%T\n", s)

	// マップを作成し、その型を表示
	m := make(map[string]int)
	fmt.Printf("%T\n", m)

	// チャネルを作成し、その型を表示
	ch := make(chan int)
	fmt.Printf("%T\n", ch)

	// new関数を使ってゼロ値で初期化されたインスタンスのポインタを返却
	var st = new(int)
	fmt.Printf("%T\n", st)

	// ポインタを作成し、その型を表示
	var p *int = new(int)
	fmt.Printf("%T\n", p)
}
```
[The Go Playground](https://go.dev/play/p/7sS_Vr0_CRt)：実行してみましょう。

実行してみると `struct`と変数 `p` だけが、ポインタ型で返ってきていることがわかるかと思います。

つまり、
**「ポインタが返ってくる返り値のものには`new関数`を使い、そうでない場合はmakeを使います」**

より詳細に説明すると、以下のように言えます。

:::note
- **make関数**：初期化済みのインスタンスを直接返却
- **new関数**：ゼロ値で初期化された指定された型の新しいインスタンスのポインタを返却
:::

## さいごに
本記事では、Go言語の**new関数**と**make関数**の違いについて詳しく解説しました。これらの関数の特徴や使用方法を正しく理解することで、より効果的なコードを書いていきましょう！

## 参考

https://www.oreilly.co.jp/books/9784873119694/

https://go.dev/ref/spec#Making_slices_maps_and_channels

https://go.dev/doc/effective_go#allocation_new
生成AI ゼミ　〜Chromeのアドインと、Advanced Voice〜

1.
・新規タブをクリックするとperplexityを立ち上げたかった。
・AIを検索エンジンに加えたかった

2.
・有料と無料の差がなくなるため、利用の上限か課せられる

3.
・Google Chrom→①設定→②検索エンジン→③サイト内検索追加
◎加える内容
・名前(任意の文字列でOK)：　
・PerplexityAI
・ショートカット(任意の文字列でOK)：
・pa
・URL(最後の「?q=%s」を忘れずに)：
・https://www.perplexity.ai/?q=%s
①https://gyazo.com/321a1bb685f6276ba4c30eafee1564b6
②https://gyazo.com/ba6335c04f46f1c10e312db1dc40baac
③https://gyazo.com/49ebd5cd84d5e2514a3bbc4b0f9f5774

・参考サイト：https://zenn.dev/acntechjp/articles/87b9c8ffb318e3
他は、Chat GPTで英会話の方法を調べた。
・Advanced voiceを使って、英会話がスムーズにできる。ただしそれは有料版にしかないことがわかった。
for、if、switch、defer

## はじめに
A Tour of Goについて勉強になった箇所をまとめる。


### For

初期化、条件式、後処理を括る括弧 ( ) はない。中括弧 { } は必要。
```Go
package main

import "fmt"

func main() {
	sum := 0
	for i := 0; i < 10; i++ {
		sum += i
	}
	fmt.Println(sum)
}
```

初期化と後処理の記述は任意。
```Go
package main

import "fmt"

func main() {
	sum := 1
	for ; sum < 1000; {
		sum += sum
	}
	fmt.Println(sum)
}
```

セミコロンの省略可能。
```Go
package main

import "fmt"

func main() {
	sum := 1
	for sum < 1000 {
		sum += sum
	}
	fmt.Println(sum)
}
```

### If

括弧 ( ) は不要で、中括弧 { } は必要。

```Go
package main

import (
	"fmt"
	"math"
)

func sqrt(x float64) string {
	if x < 0 {
		return sqrt(-x) + "i"
	}
	return fmt.Sprint(math.Sqrt(x))
}

func main() {
	fmt.Println(sqrt(2), sqrt(-4))
}
// 1.4142135623730951 2i
```

条件の前に、評価するための簡単なステートメントを書ける。

```Go
package main

import (
	"fmt"
	"math"
)

func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
		return v
	}
	return lim
}

func main() {
	fmt.Println(
		pow(3, 2, 10),
		pow(3, 3, 20),
	)
}
// 9 20
```

```if```で宣言された変数は、```else```でも使える。

```Go
package main

import (
	"fmt"
	"math"
)

func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
		return v
	} else {
		fmt.Printf("%g >= %g\n", v, lim)
	}
	// can't use v here, though
	return lim
}

func main() {
	fmt.Println(
		pow(3, 2, 10),
		pow(3, 3, 20),
	)
}
// 27 >= 20
// 9 20
```

### Switch

選択された```case```だけ実行しその後の全ての case は実行されない。 PHP等の ```break```が Go だと自動的に実行される。

また```switch```の```case```は定数である必要がなく、 関係する値は整数である必要はない。

```Go
package main

import (
	"fmt"
	"runtime"
)

func main() {
	fmt.Print("Go runs on ")
	switch os := runtime.GOOS; os {
	case "darwin":
		fmt.Println("OS X.")
	case "linux":
		fmt.Println("Linux.")
	default:
		// freebsd, openbsd,
		// plan9, windows...
		fmt.Printf("%s.\n", os)
	}
}
// Go runs on Linux.
```

条件のないswitchは、switch trueと書くことと同じ。

```Go
package main

import (
    "fmt"
    "time"
)

func main() {
    t := time.Now()
    switch {
    case t.Hour() < 12:
        fmt.Println("Good morning!")
    case t.Hour() < 17:
        fmt.Println("Good afternoon.")
    default:
        fmt.Println("Good evening.")
    }
}
```

次のcaseブロックを続けて実行したい場合は、明示的に```fallthrough```をキーワードを使う。

```Go
switch num := 3; num {
case 1:
    println("One")
case 2:
    println("Two")
case 3:
    println("Three")
    fallthrough
case 4:
    println("Four")
default:
    println("Unknown number")
}
```

### Defer

```defer```へ渡した関数の実行を、呼び出し元の関数の終わり(returnする)まで遅延させる。
```defer```へ渡した関数の引数はすぐに評価されるが、その関数自体は呼び出し元の関数がreturnするまで実行されない。

```Go
package main

import "fmt"

func main() {
	defer fmt.Println("world")

	fmt.Println("hello")
}
// hello
// world
```

```defer```へ渡した関数が複数ある場合、その呼び出しはスタックされる。 呼び出し元の関数がreturnするとき、 ```defer```へ渡した関数はLIFO(last-in-first-out)の順で実行される。

```Go
package main

import "fmt"

func main() {
	fmt.Println("counting")

	for i := 0; i < 10; i++ {
		defer fmt.Println(i)
	}

	fmt.Println("done")
}
//
// counting
// done
// 9
// 8
// 7
// 6
// 5
// 4
// 3
// 2
// 1
// 0
```
QAの研究会を運営・外部発信をしてみて

◆この記事を読むのにかかる時間：約5分程度
◆この記事の主な対象者：ゲームQAの業界を主体的に盛り上げていきたい方

## 1.はじめに
みなさま今年もお疲れ様でした。あっという間に年末ですね。
今年もアドベントカレンダーの時期がやってきました。

自身の1年を振り返ると、
社外に向けた発信の取り組みに携わる機会が例年よりも増えました。
特に、自身が中心となって運営しているQAの研究会にちなんだ内容が多かったため、
今回はQAの研究会についての紹介や、
発信をおこなってみての気づきなどについてお話していこうかと思います。

## 2.QA研究会とは？
QA研究会とは、ゲームQA業界への貢献・活性化を目的として、
業界に関連する企業を中心に、各社の有志で共通の課題感などに対してテーマを決め、
横断でチームを組成して研究を行う取り組みです。

現在はオンラインで開催しており、今期で7期目になりました。

直近は約10社〜13社程度のゲームに携わる会社さまが研究に参加してくださっており、
扱うテーマは自動化・効率化、人材育成などの王道な内容から、
品質改善の取り組みや、魅力的品質を模索してのアイトラッキングの活用方法の検討など、
様々な領域について研究の取り組みをすすめています。

## 3.おこなってきた取り組み
研究会の活動として、1年かけて各テーマについての研究を推進しつつ、
外部への情報発信としては、
会自体の紹介や、会のなかであがったテーマをもとにしたCEDECなどでの発信、
本研究会としても研究発表のウェビナーなども開催しており、
ゲームQA業界の活性化に向けて情報発信を積極的にすすめています。

ウェビナーの開催は今年で3回目でしたが、毎年約200名前後の参加申込があり、
同じようなお悩みを持った皆さまに、興味関心を持って参加いただいていると感じております。

発信実績（一例）：
* [13社合同！ゲームQA技術研究報告会 - connpass](https://gree.connpass.com/event/325978/)
* [会社を超えて品質を高める！他社と連携したオンラインQA技術研究会のつくりかた](https://cedil.cesa.or.jp/cedil_sessions/view/2450)
* [ゲームQA業界の技術向上を目指す！ 会社を超えた研究会の取り組み](https://techcon.gree.jp/2024/session/TrackA-2)

## 4.会の運営や情報発信を経て
会の運営や情報発信を経て、よかった点・今後改善すべき点をまとめてみました。

#### よかった点
__1.知見の交換により各人の業務の質や効率を高めることができた__
各社間で情報をやり取りすることで、自社でやっていない取り組みや、
既におこなっている取り組みについても、質を高めつつ業務に活かすことができています。

__各チームでの取り組みを実務に反映した事例__
* PFガイドラインに準じたリジェクトリスク低減用のチェックリストの作成と確認を実施
    * 各社連携して過去事例などをもとにしつつリストの作成をおこなえた
* 各社で連携して海外翻訳のQA周りの観点リストを作成し、開発チームとの検証についての認識合わせができた

__2.会社間を跨いだコミュニティの形成に役立っている__
現場での業務だけではなかなか他社の方との繋がりを形成するのが難しいことが多く、
こういった場を利用して繋がりが形成でき、気軽に話ができる関係の構築にも役立っているとの声が参加者からもあがっています。

#### 今後に向けて
__1.研究会の規模の拡大__
より多くの方へ情報や技術を得ていただけるよう、発信機会の増加・規模の拡大を図っていきたいと考えています。

__2.更なる技術水準の向上への貢献__
トレンドも取り入れつつ、発信する技術や知見の水準をさらに上げ、
業界全体の技術レベルの向上にも貢献をしていきます。

__3.若手メンバーが様々な経験を積める場の用意__
専門的な技術・知識はもちろんのこと、資料作成や発表といった、ビジネススキルなども含めた若手メンバーの成長の場としても会を存続させたいと思っております。

## 5.まとめ
いかがだったでしょうか。

この記事の取り組みをみて興味を持たれた方は、ぜひ外向けの発信も意識してやってみていただけると幸いです。
一緒にQAの業界を盛り上げていきましょう！

もし研究会に参加してみたい方がいれば[こちら](https://speakerdeck.com/gree_tech/greetechcon2024-session-a2?slide=46)から。
詳細などご案内します。

それでは皆さま、よい年末をお過ごしください。
後輩のためのgit講座（基本編）

# Git講座

- Gitコマンド一覧
- 使い方
- まとめ

# Gitコマンド一覧

- ステージング　：　`git add .`
- コミット　　　：　`git commit -m "コメント"`
- プッシュ　　　：　`git push origin ブランチ名`
- ブランチ一覧　：　`git branch`
- ブランチ移動　：　`git checkout ブランチ名` 
- ブランチ削除　：　`git branch -d ブランチ名`
- クローン　　　：　`git clone "url"`
- プル　　　　　：　`git pull origin ブランチ名`

# 使い方

### clone（クローン）する方法

##### Step1 作りたい場所に移動する
##### Step2 `git clone "url"`

<br/>

### 新しいブランチを切る

##### Step1 `git checkout 中央のブランチ名`
中央ブランチに移動する
##### Step2 `git pull origin リモートの中央ブランチ名`
最新の状態をリモートから取得する
##### Step3 `git checkout -b 新しいブランチ名`
新しいブランチに移動する

<br/>

### 作業中に保存

##### Step1 `git add.`
変更されたファイルをステージングする
##### Step2 `git commit -m "コメント"`
ステージングしたファイルをコミットする

<br/>

### 新しいブランチを切る

##### Step1 `git checkout 中央のブランチ名`
中央ブランチに移動する
##### Step2 `git pull origin リモートの中央ブランチ名`
最新の状態をリモートから取得する
##### Step3 `git checkout -b 新しいブランチ名`
新しいブランチに移動する

<br/>

### 作業中に最新を取り込む

##### Step1 `git add.`
変更されたファイルをステージングする
##### Step2 `git commit -m "コメント"`
ステージングしたファイルをコミットする
##### Step3 `git checkout 中央ブランチ名`
中央ブランチに移動する
##### Step4 `git pull origin リモートの中央ブランチ名`
最新の状態をリモートから取得する
##### Step5 `git checkout 作業ブランチ名`
作業ブランチに戻る
##### Step6 `git merge 中央ブランチ名`
最新を作業ブランチに取り込む

<br/>

### 作業中に最新を取り込む

##### Step1 `git add.`
変更されたファイルをステージングする
##### Step2 `git commit -m "コメント"`
ステージングしたファイルをコミットする
##### Step3 `git push 作業ブランチ`
コミットした内容をプッシュする

<br/>

### プルリクエストする


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3950744/d04d7bdd-1519-83ea-491c-34f8f5bddd00.png)

- 左上の部分で、マージ先を選択
- 右の上側で、assign(担当者)を選択
- 右の下側で、label（編集部分）を選択

# まとめ
今回は、初心者に向けてGitのコマンドや使い方をまとめました。
ハッカソンに向けたGitの使い方のため、細かい使い方は省きました。
応用編ではチーム開発でのGitの使い方やブランチ構造などをまとめたので、チーム開発のリーダーなどをする際は参考にしてみてください
【ML初心者アドベントカレンダー】AWS Certified AI Practitionerを受験してきました



# 概要

先日 AWS Certified AI Practitioner を受験しましたので、規約に触れない程度に感想を書こうと思います。

https://aws.amazon.com/jp/certification/certified-ai-practitioner/

# 何はともあれ結果

受験時は以下の状態でした。

* AWS自体の知識については多少あるかなという程度。（既存資格はMLSとANS以外保有しています。）
* 機械学習については初心者中の初心者。そもそも機械学習とAIって何が違うの？というレベル

そんな状態で受けた結果が以下です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3944443/9e02e96d-aac8-9d2e-d5ae-ac4ab54da02b.png)

笑ってしまうくらいギリギリですが、合格できました。


# 感想

**めちゃめちゃ難しかったです。**

もう一つのクラウドプラクティショナーはSAP取得後に受験したというのもあり、ほとんど勉強せずで合格できたのですが、そちらと同じ感覚で行くと絶対に無理だったなと思いました。
https://aws.amazon.com/jp/certification/certified-cloud-practitioner/

「あれ？これってAWSの資格だよね…？」と首を傾げつつ、試験中は事前に学習した機械学習用語たちに助けられました。過去の敵が味方になって駆け付けてくれたような感覚です。

これからこちらの資格を受験しようと考えている方がいらっしゃれば、以下の点を意識すると良いかもしれません。
 * 試験ガイドをとにかく読み込む
 * SageMaker の機能やAWSサービスについて、試験ガイドに記載されている物についてはどんな時にどういう目的で使うのかを説明をできるようにしておく
 * 基本的な機械学習用語について、意味をきちんと整理しておく
 * モデルのトレーニング方法、推論方法について、基本的なものは名前を聞いたときに内容が浮かぶくらいにしておく

最後まで目を通していただきありがとうございました。
Ubuntu 24.04の docker-compose で No module named 'distutils'エラーをaptで治す方法

* pip install の方法ばかり出てきたので投稿

## エラー内容

```sh
$ docker-compose
Traceback (most recent call last):
  File "/usr/bin/docker-compose", line 33, in <module>
    sys.exit(load_entry_point('docker-compose==1.29.2', 'console_scripts', 'docker-compose')())
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/bin/docker-compose", line 25, in importlib_load_entry_point
    return next(matches).load()
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/importlib/metadata/__init__.py", line 205, in load
    module = import_module(match.group('module'))
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/importlib/__init__.py", line 90, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 995, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "/usr/lib/python3/dist-packages/compose/cli/main.py", line 9, in <module>
    from distutils.spawn import find_executable
ModuleNotFoundError: No module named 'distutils'
```

## 解決方法

```sh
sudo apt install -y python3-setuptools
```

参考

* [docker-compose が 'distutils' モジュールがないために失敗する ·問題 #32 ·rashadphz/farfalle ·GitHubの](https://github.com/rashadphz/farfalle/issues/32)
アーキテクチャカンファレンス2024①

# 分散アーキテクチャにおける現代のトレードオフ分析と今後のソフトウェアアーキテクチャの展望

## 概要
アーキテクチャメトリクスの話はほぼなく、ハードパーツの話がメインで取り上げられていました。
複数のシナリオを想定し、モノリスのままでいるのか？
それともマイクロサービスにするのか？
マイクロサービスにしたとしてもどのような粒度感で分割するのか？
について、書籍の内容のざっくりした考え方についてお話しされていました。

## 分割の粒度感
マイクロサービスは、DDDでもよく語られている【境界付けられたコンテキスト】の考え方
を用いて、その境界内でトランザクションの範囲が完了することや、
変更頻度・変更理由がそのサービス内のものに関しては同じであるという
コンポーネントの凝集原則の１つ、CCPを意識した考え方をベースとして分けたくなる。

https://qiita.com/Kudo_panda/items/e143e6186bd840060d1c

要はサービス粒度での単一責務てやつだ。
高度に物理的に分割され、疎結合を満たすことによって、スケーラビリティやアジリティを高めることができる。
しかしながら、それ以外の品質特性軸によるビジネスドライバによって、安易に単一責務のその単位で分けると判断してはならない。



## 繰り返し述べられていたこと
トレードオフ分析は継続的に行うものであるという、至極当たり前なことだけど、
難しいことを述べていました。
これはつまり、環境変化などによって、トレードオフ要素間の重みの比重が変化するからです。

<img width=300 alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781175/1a3989c9-e750-93fb-f818-337a3f03d5ec.png">

ある瞬間上図のように、品質特性A(天秤の左側)、B(天秤の右側)の重みが定義されていたとする。
しかしそれは時間経過に伴うステークホルダーの要求の変化や、市場の変化などによって
天秤の傾き具合が変化してしまいます。
それを事実データを使ったりして、客観的にいまどのくらいのトレードオフ関係なのか？
それとも抜本的技術が登場したことによって、トレードオフ関係が解消されたのか？
などを継続的にモニタリングしろ、ということになります。

同時にそれは、大前提であるステークホルダーの要求の変化や関心の強さの変化にも
目を光らせなくてはなりません。

## 落とし穴
本にあるいくつかの非機能項目での評価マトリクスにおいて、
たとえば【セキュリティ】【パフォーマンス】などが重要な特性であり、
その軸でアーキテクチャを評価しなくてはならないとした場合に、
〇△×という３種類の定性評価だけでは、間違った意思決定になるということ。
なぜなら２つの特性の重みが同じである保証はないからである。

:::note warn
下図はハードパーツにおいて取り上げられていた、
再利用パターンのうち、共有ライブラリを使って静的な結合にするケースか、
共有サービスとして分離した上であとから動的に通信で結合させるケースを
7つの評価軸で比較検討している様子である。
:::

![スクリーンショット (183).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781175/6321c3d6-f9b2-dd01-498f-1c82f0b48f02.png)


たとえばわかりやすくするために、10段階の定性的な重みのうち、
めちゃくちゃ強く求められる特性であるほど10に近づくという場合を想定し、
セキュリティが10、パフォーマンスが4程度であったとする。
この場合、明らかにセキュリティの方が比重が重いため、
単純な〇△×という３種類の定性評価だけでなく、重みも意識した評価が必要。

たとえば重みポイントが10で〇なら、10×3で30　の評価ポイント
重みポイントが5で△なら、5×2 で10　の評価ポイント
といったようにしなくてはならない。

:::note warn
必ずしもこの計算方法が絶対的ではないので、そこだけ注意。
:::

## 所感
今回のテーマであるハードパーツの書籍を私はグループディスカッション形式に
計３回ほど行ったことがあるが、何度読んでも前提となるステークホルダーマネジメント
をアーキテクト自身が行い、アーキテクチャを決める品質の軸の優先度がわかっている
必要があると感じています。

匠メソッドによるプラスの価値の考察と、脅威モデリングによるマイナスからの
両方による考察が必要であると感じます。

# 組織を支えるアーキテクチャの過去と未来
## 背景説明
登壇者の方の組織では、4年前に1チーム5名であった状態から、
今にかけて直線的に組織の人数とそれに伴うチーム数が増加したらしい。

図

組織の拡大に伴って、生産性を下げないようにするために、
またアーキテクチャの方針として、チームごとのマイクロサービスに分割することで、
各チームごとに素早く自律分散して開発ができるようにしたそう。

本来は、初期からのマイクロサービスに分割するのは、
アンチパターンとされているが、たまたま条件がそろって、初期からマイクロサービスで割と成功を収めた事例としてのお話であった。


## 設計方針
業務ドメインごとにサービスを分割し、マイクロサービスごとにデータも分割。
主要なマイクロサービスに対しては、同期的な通信による蜜結合状態を避け、
非同期通信による疎結合の徹底。

フロントエンドからは、BFFを経由してのアクセス。

## 当初のアーキテクチャと現在の比較
共有ライブラリを作成せずに、あえてサービス間でコードを重複しても、
DRY原則に反していてもいいとする方針であった。

重複コード部分を共有ライブラリに分けることによって、
不要な結合を排除して、サービスごとのコンテキスト境界　独立性を重視したかった
ために、あえてそのような設計にしたそう。

このあたりのお話は、以下の共有ライブラリのパターンに参考情報があります。

https://qiita.com/Kudo_panda/items/e8bad3a20b9e9c2c350b#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88-1

しかしながら、現在は共有ライブラリパターンを適用しているとのこと。
というのも、重複コード部分において、データベース周りやWeBフレームワーク、ユーティリティなどなど、共通で使いまわしたいものが固まってきたからだそう。

:::note warn
恐らく共有サービスパターンを使用しなかったのは、
動的に連携した際に、ランタイムエラーが起きる可能性が読めないことなどの
懸念事項が背後にあったからだと思われる。
:::


## 感想
そもそもチームの境界を正しく発見するためには、
データのプロセスの両方の側面からLeSS的な組織一致団結活動によるモデリングによって
チームの責任境界などを継続的に議論しないと無理ゲーではと感じた。

ただし、BFFやら非同期通信を基本とした設計によって、疎結合を徹底されているのには非常に感心をしました。
Pythonでファイル書き込み

# 1.ファイル書き込みの基本

```python:file_open.py
f = open('myfile.txt', 'w')
f = open('myfile.txt', 'a')
f = open('myfile.txt', 'x') 
```
「w」
・対象ファイルが存在しない場合はファイル作成し書き込み。　
・ファイルが存在する場合は元の内容をクリアして書き込み。

「a」
・対象ファイルが存在しない場合はファイル作成し書き込み。　
・ファイルが存在する場合は元の内容に追加してして書き込み。

「x」
・対象ファイルが存在しない場合はファイル作成し書き込み。　
ファイルが存在する場合はエラー。

# 2.エンコーディング指定
```python:file_encoding.py
f = open('myfile.txt', 'w', encoding='UTF-8') 
```
ここでは「utf-8」を指定。
# 3.ファイル書き込みから保存までの流れ
```python:file_open_close.py
f = open('myfile.txt', 'w')
f.write('やっほー\n')
f.close()
```
# 4.複数行を一度に書き込み
```python:file_open_list.py
f = open('myfile.txt', 'w')
datalist = ['やっほー\n', '調子どう？\n', ではまた\n']
f.writelines(datalist)
f.close() 
```
datalistにリスト形式でデータを追加して一度の書き込みで複数行を対応

# 5.closeの省略
```python:with.py
with open('myfile.txt', 'w') as f:
    f.write('やっほー\n')
```
with構文を使うとインデント内の処理が完了後に自動でクローズ処理が行われます。明示的なクローズ処理が不要になります。
DjangoのLANGUAGE_CODEとTIME_ZONEを日本に適応させる

前回の作業

https://qiita.com/ruruchan_nanodesu/items/04967d09791ac1eb31fa

---

### 1.ローカルサーバーが立ち上がっていることを確認する
terminalに下のコマンドを打ち込みます。

```
python manage.py runserver
```
ローカルサーバーが立ち上がっていれば、ロケットの画面が表示されるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1386677/a8320cd6-ed92-f800-6ae0-7a11b3616ffa.png)

確認できない場合は、前回の作業を見直してください。

https://qiita.com/ruruchan_nanodesu/items/04967d09791ac1eb31fa

### 2.settings.pyを編集する
yourproject>yourproject>settings.pyを開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1386677/d934d230-6eb0-3260-e10c-24db21cbc078.png)


105行目あたりに言語と時間の設定があります。
```python
LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'
```
言語を日本語、タイムゾーンを東京に設定しましょう。
```python
LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'
```

### 3.変更が反映されていることを確認する
キーボードのcontrolキーとSキーを押し、変更を保存してください。
次に、terminalをクリックします。controlキーを押しながらCキーを押し、接続を切ります。
そして、もう一度下のコマンドを打ち込み、サーバーを立ち上げてください。

```
python manage.py runserver
```

成功していれば、日本語のメッセージがロケット画面で表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1386677/ff5c434f-8706-3176-f98d-337f38654db9.png)

うまくいかない場合
　1. yourprojectの中でコマンドをうっていることを確認してください。
control+Cをおして下のようなメッセージが表示されていますか？

```
 作成したプロジェクトまでのパス\yourproject> 
```

---
次の作業

https://qiita.com/ruruchan_nanodesu/items/32d13d80015085d58621
GodotEngineで手っ取り早くアイコンボタンを作る

# はじめに

今回は特に重要なテクニックでもないが、地味に効きそうなTipsをまとめた。
UIなどでアイコンボタンを用意するのに、わざわざ画像を作る必要はない。このやり方を知っていれば手軽にアイコンボタンをたくさん作れるというものだ。

# 手順

## Google Fontsで好みのアイコンを探す

[Google Fonts](https://fonts.google.com/icons) をまず開く。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/fe30d9b7-9a71-bdd5-5b45-9dcc9db86cb8.png)

ここではマテリアルデザインのアイコンが沢山紹介されている。いずれも一度はスマホ上で見たことあるデザインなので馴染みがあるはず。

## アイコンを見つけたらクリックして概要パネルを開く

一覧上のアイコンをクリックすると、右側にアイコンを解説する概要パネルが開く。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/7466ae37-9bf4-1b7b-8211-337a4afecab5.png)

ここで色やサイズを指定できる。気に入った設定になったら、プレビュー右下のコピーボタンを押す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/fc90ea52-7551-f0eb-793d-c3b4a9504d42.png)

これでまずは下準備はOKだ。

## テキストエディタでSVGファイルとして保存する

クリップボードにコピーした内容をテキストエディタを開いて貼り付けよう。するとこのようなコードが貼り付けられる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/578d9379-1257-5b06-f1c4-86e4a62a275f.png)

SVGの形式になっているので、さきほどのアイコンはテキストエディタで扱える。これを拡張子 .svg で保存する。


## Godotのプロジェクト内にSVGファイルを配置する

SVGファイルとして保存する際に、直接Godotのプロジェクトフォルダ内に保存してもよい。
Godot側でインポート処理が走り、すぐに使用可能になる。

:::note info
エディタの設定 - ファイルシステム - 外部のプログラムのベクター画像エディタを設定しておこう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/1e4f7ec6-8be0-cd02-8309-cdd0a5282133.png)

たとえばinkscapeの実行ファイルのパスを設定すれば、Godotから直接該当のプログラムを呼び出してすぐ編集可能になる。
:::


## UIのボタンを用意する

SVGファイルはGodot上だと `CompressedTexture2D` になる。
このノード形式を設定可能なノードであればどこでも使えるが、今回はUIのButtonで使う例を紹介する。

## ButtonノードのIconプロパティに設定する

ファイルシステムのパネルからドラッグしてくればOKだ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/f66f6ab8-503c-fd82-244c-6ba62f1672fb.png)

SVGのアイコンが設定される。

ちなみにデバッグ実行で実際に表示するとこのようになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/efe58f30-d16c-6e46-5239-675f9caabd7d.png)

色などのボタンの直接的な見た目は別途テーマファイル(*.theme)を設定すればいくらでも変更可能だ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/7ceaab06-da70-2c60-143d-d15d72feadde.png)

このテーマファイルは設定したいボタンに直接でもいいし、親ノードのパネルに設定してもいい。親ノードで設定すれば子はまとめてそのテーマになる。

# 終わりに

本来であればUIの解説を先にするべきだが、今回はUIのボタン関係に絞って紹介した。自分はツール系のアプリを作っているが、きっとゲームとしてもUIに用意するボタンにアイコンを手軽に使いたいと思う人はいるはず。

通常であればペイント系アプリでボタンの画像を作る必要があるが、GodotではSVGファイルを手軽に扱えるのでSVGファイルを使うのがオススメだ。

SVGならとりあえずテキストに大量にコピーしておいて、後で分けて保存してGodotのプロジェクトに取り込む、といったこともしやすい。中身がテキストなのでgitとかで履歴管理もしやすい。

SVGファイルをもっと扱いやすくなるアドオンの作成も考えているので完成したら改めて紹介したい。
【Advent Calendar 2024 #11日目】AWS学習〜生成AI/ML編〜 Amazon SageMaker

# はじめに
本記事は、「初めての一人アドベンドカレンダー2024 by hohe」の10日目の記事となります。
Advent Calendar 期間中は、AWSの生成AI/ML関連を中心に記事を投稿していきます。
11日目は昨日に引き続き、Amazon SageMakerについてまとめます。

# Amazon SageMaker
あらゆるユースケースで高性能で低コストの機械学習 (ML) を実現する幅広いツールを統合した完全マネージド型サービス

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

## Amazon SageMakerの組み込みアルゴリズム
Amazon SageMakerでは、AWSが提供するアルゴリズムを使った最⼩限のコードで機械学習を利⽤可能とする組み込みアルゴリズムが用意されている

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

|アルゴリズム名|教師あり/なし|詳細|
|---|---|---|
|Linear Learner|教師あり|分類や回帰の問題を解決するために使用する|
|XGBoost|教師あり|決定木に基づき、ランダム フォレストや勾配ブーストなどの他の手法を改善したもの|
|LightGBM|教師あり|XGBoostと同じ決定木の勾配ブースティングアルゴリズムであり，XGBoostに比べ高速(軽量)|
|Seq2Seq|教師あり|時系列データを別の時系列データに変換する|
|DeepAR|教師あり|反復ニューラルネットワークを使用してスカラー時系列を予測する|
|BlazingText|教師あり|Word2vec アルゴリズムとテキスト分類アルゴリズムの高度に最適化された実装を提供|
|Object2Vec|教師あり|高度にカスタマイズ可能な汎用ニューラル埋め込みアルゴリズムで、高次元オブジェクトの低次元高密度埋め込みを学習する|
|Object Detection|教師あり|既知のオブジェクトカテゴリの集合から、イメージ内のオブジェクトのすべてのインスタンスを識別し、特定する|
|Image Classification|教師あり|入力として画像を取得し、その画像に割り当てられた 1 つ以上のラベルを出力する|
|Semantic Segmentation|教師あり|イメージ内のすべてのピクセルを分類するため、イメージに含まれるオブジェクトの形状に関する情報を提供する|
|Random Cut Forest (RCF)|教師なし|データセット内の異常なデータポイントを検出|
|Neural Topic Model|教師なし|統計分布に基づいて単語のグループ化を含むトピックにドキュメントのコーパスを整理するために使用する|
|Latent Dirichlet Allocation (LDA)|教師なし|一連の観測値を異なるカテゴリの混合として記述しようとする|
|k-nearest neighbors (k-NN)|教師あり|インデックスベースのアルゴリズム|
|K-Means|教師なし|データ内の個別のグループを見つける|
|Principal Component Analysis (PCA)|教師なし|可能な限り多くの情報を保持しながら、データセット内の次元 (特徴量の数) を減少させようとする|
|Factorization Machines|教師あり|分類タスクと回帰タスクの両方に使用できるアルゴリズム|
|IP Insights|教師あり|IPv4 アドレスの使用パターンを学習するアルゴリズム|
String::Secretのご紹介

Perl Advent Calenderなんと2024年になってもやってます。本当にめでたいですね！

さて、掲題のString::Secretは2020年にリリースしたっきりのCPANモジュールですが、（たぶん）そういえば紹介してなかったなと思ったのでこの機会に紹介しようと思います。~~完全に忘れていてネタがなかったんです。~~

https://metacpan.org/pod/String::Secret

## SYNOPSIS

なにしてくれるやつなのよということでSYNOPSIS。

```perl
use String::Secret;
use String::Compare::ConstantTime;
use JSON::PP ();
my $secret = String::Secret->new('mysecret');
# safe secret for logging
MyLogger->warn("invalid secret: $secret"); # oops! but the secret is hidden: "invalid secret: ********"
# and safe secret for serialization
# MyLogger->warn("invalid secret: ".JSON::PP->new->convert_blessed->encode({ secret => $secret })); # oops! but the secret is hidden: invalid secret: {"secret":"********"}
unless (String::Compare::ConstantTime::equals($secret->unwrap, SECRET)) {
    die "secret mis-match";
}
# and can it convert to serializable
MyDB->credentials->new(
    id     => 'some id',
    secret => $secret->to_serializable, # or $secret->unwrap
)->save();
```

要はパスワードとかメールアドレスとか下手にうっかり永続化されてほしくないシークレットな情報を扱うとき、それらがうっかりログなどに残らないようサポートしてくれるくんです。

`"password: $password"`みたいにしちゃったとき、`$password`がString::Secretのインスタンスだったら`"password: ********"`相当にマスクしてくれます。

同様に、JSONに埋めてエンコードしちゃったときに`convert_blessed`をつけてたら`{ secret => $secret }`を`{"secret":"********"}`にしてくれるし、同様に`allow_blessed`なら`{"secret":null}`にしてくれます。`allow_tags`でも`{"secret":("String::Secret")[********]}`と同様にマスクしてくれるので安心安全です。

同様に、CBOR、Serial、Storableに対してもマスクした値をシリアライズするため安全です。

もちろん、Data::DumperやData::Printer(DDP)に対しても安全です。たとえば、`Dumper $secret` は `$VAR1 = bless( do{\(my $o = '********')}, 'String::Secret' );` になります。

こんな感じで、出力に絡むだいたいのものに対して対応しています。

なお、`$secret->unwrap`のように`unwrap`メソッドを呼び出すことで本当の中身を取り出すことができます。

## 仕組み

インサイドアウトオブジェクト、演算子オーバーロードというテクニックを使います。

### インサイドアウトオブジェクト

この記事が詳しいので説明を譲ります。

https://tech.mobilefactory.jp/entry/2018/12/09/074155

要は、このテクニックを使うと外側からは特殊な黒魔術を駆使したりでもしない限りはアクセスできない領域にインスタンスの持つ値を保存することができるので、Data::Dumperとかでも中身が漏れない。という感じです。

### 演算子オーバーロード

Perlの演算子オーバーロードではblessされたオブジェクトを特定のコンテキストで評価したときに、任意のメソッドを呼び出すといった処理が記述できます。

```perl
use overload
    '""' => 'to_string',
    fallback => 1;
```

こんな感じで記述することによって文字列コンテキストで評価されると`to_string`メソッドが呼び出されるようになります。

あとは`to_string`で`"********"`を返してあげれば文字列展開されてもマスクされてる感のあるテキストになってくれて安心というわけです。

## 永続化層のサポート

いうて永続化層に保存したいときまでマスクされては困る。という場面もあるでしょう。
そんなときのために `String::Secret::Serializable` というやつも用意しています。

これは中身を保ったままシリアライズできるという点だけが異なります。Data::Dumperや文字列展開に対しては同様に保護ができます。

それぞれ、`$secret->to_serializable`あるいは`String::Secret->from_serializable($secret)`というような感じで相互変換ができます。

たとえば永続化層への保存をする場面で`to_serializable`して、永続化層から取り出したら`from_serializable`するといった使い方が可能です。

## まとめ

Perlはこういうの簡単に作れて便利！明日は @mackee_w さんです！
レポートの紐づくセマンティックモデル切り替えで Power BI プロジェクトファイルの構造を学んでみる

## はじめに

Power BI プロジェクトファイルを使いこなすためにセマンティックモデルの参照を変更してみる：https://learn.microsoft.com/ja-jp/power-bi/developer/projects/projects-overview

### 補足

なお、単純に切り替える場合は、

-  [rebind report - semantic lab](https://semantic-link-labs.readthedocs.io/en/stable/sempy_labs.report.html#sempy_labs.report.report_rebind) や、データソース設定からも可能

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/2d435efb-90a7-68ca-b45d-e361ade953cc.png)

## シナリオ

[売上と返品のサンプル.pbix ファイル](https://learn.microsoft.com/ja-jp/power-bi/create-reports/sample-datasets#sales--returns-sample-pbix-file)　を Power BI プロジェクト形式で保存、コード編集することで、Power BI Service 上のセマンティックモデルを参照するようにしてみる

### 準備

あらかじめレポートを発行する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/3438e4e8-7a0d-aca4-a2f7-0de15e10a868.png)

モデルの編集をして、名前を変えておく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/591eec11-063c-8f93-ff56-1ba6867b7063.png)


### 手順

1. pbix ファイルをpbip 形式で保存する
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/008a3a68-82f6-cf88-05e2-5f3ccb1040c4.png)
2. このようなファイル構造となる
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/9fdc9510-6a48-fc39-c187-59121cf526a5.png)
    セマンティックモデルの参照はdifinition.pbir 内に格納されている。ローカルパスを使っている場合、同プロジェクトのセマンティックモデルが使用される
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/cc8624fd-cce1-ce2f-b236-c18df05a4fc3.png)
    プロパティ構造は以下の通り
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/0f13bf65-beff-8f61-c900-0168d7a9fdf7.png)
    引用：https://learn.microsoft.com/ja-jp/power-bi/developer/projects/projects-report#definitionpbir

3. 変更したいセマンティックモデルのあるワークスペースに移動し、URLからセマンティックモデルのIDなどを確認
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/b98d84a4-f743-dfc3-60f2-37c0626c1759.png)
4. Power BI を閉じた状態で、pbir ファイルを編集してやる。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/a228da48-2d9c-d9dc-a904-257935f4a530.png)
5. 再度 pbip ファイルを開くと、リモートセマンティックモデルに接続したレポートとして開かれる
    ※わかりづらいが、テーブルビューがないことで判断
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/8e3f010c-e3c7-82dd-4ab6-6c307c768c09.png)
6. 名前を変更して発行するとわかりやすい
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/e2dadb8f-058c-0b22-9620-85179ad55e17.png)
Flutter プロジェクトで使用する java のバージョンを管理する

あるプロジェクトで Android アプリのビルドをした際、Java のバージョン関連のエラーが出たため、これを機に java のバージョンを管理するようにした方が良いのではと思い、jenv を導入しました。

その手順について備忘録として残しておきます。

使用している環境は、MacBook Air(M2)です。

1. Homebrew を使用して、[公式サイト](https://formulae.brew.sh/formula/jenv) のinstall コマンドでインストール 
    - `brew install jenv`
1. `echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.zshrc`
1. `echo 'eval "$(jenv init -)"' >> ~/.zshrc`
1. `jenv enable-plugin export`
1. シェルを再起動 `exec $SHELL -l`
1. brew でインストールした openJDK を追加する
    1. `jenv add /opt/homebrew/Cellar/openjdk@17/17.0.13/libexec/openjdk.jdk/Contents/Home
`  
※ `openjdk@17/17.0.13` のところはインストールした java のバージョンに合わせる  
※ brew でインストールしたパッケージの保存先は `brew ls [パッケージ名]` 等で確認可能。パッケージ一覧は、`brew list` で確認可。
1. Flutter プロジェクトのルートディレクトリにて、`jenv local 17.0.13` を実行。
    1. プロジェクトのルートディレクトリに .java-version というファイルが生成される。
    1. プロジェクトのルートディレクトリで `java --version` を実行して、指定したバージョンが表示されたらOK。

以上です。
Windows11のキーボードの言語設定が上手くいかなかったときに試してほしいこと

#概要（蛇足）

PCを最近買い換え、元のPCからの引き継ぎをしているとき、すごく使いづらかった最初windowsの設定の部分でキーボードの設定を特に考えずに「はい」ばっかり連打して設定を進めていたからだと思う。
他の記事やサイトに乗っている日本語設定にするなどを試しても解決しなかった人だけ試してほしい。

#試してほしいこと

１．最初に時刻と言語を選ぶ
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962985/cf5cfdae-6530-fc00-9518-98d7143ef662.png)

２．次に言語と地域を選び、日本語・・・の部分を押して言語のオプションを押す
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962985/72e3eb00-9cf3-c1d7-8fdc-10971d8e5dc1.png)


３．下にスクロールして黄色マーカーのところが英語になっていないか確認する。
　　自分はここが英語になっていたため、言語設定を日本語にしても上手く行きませんでした。
![2.5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962985/9e1db62f-f253-1c9d-d501-4c42343aea38.png)



４．日本語に変更して再起動すれば、いつのも日本語キーボードに戻りました！
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962985/48b84ff8-c1c7-2203-d36b-730f67eefe37.png)
Recordクラスとは？

Javaを勉強中に「レコードクラス」を学んだので、この記事では、レコードクラスの特徴や使い方を、簡単に説明します！

## 1. 概要
レコードクラスとは、「**データを運ぶための専用クラス**」です。例えば、名前や年齢などの情報をまとめて扱いたい場合に便利です。
ポイントは、「作ったあとに中身を変更できない不変なクラス」であること。

## 2. 特徴
### 1. クラスの特性
レコードクラスは、他のクラスを継承（サブクラス化）することができません。
クラス自体が「シンプルなデータのまとまり」を目的としているため、拡張は不要だからです。
### 2. フィールド（クラス内のデータ）
レコードクラスのフィールドは、インスタンスを作るとき（newで生成するとき）に必ず初期化されます。
初期化後は変更できません（private finalというキーワードが自動的につきます）。
ただし、レコードクラスの中でstaticな変数（全体で共有される変数）を明示的に定義することは可能です。
### 3. コンストラクタ（初期化処理）
レコードクラスには、以下の3種類のコンストラクタが使えます。

1. 標準コンストラクタ
自動的に生成されるもので、特に書かなくても使えます。
2. 代替コンストラクタ
開発者が明示的に定義するもので、オーバーロード（引数のパターンを増やすこと）もできます。
3. コンパクトコンストラクタ
こちらも開発者が定義します。主に引数のチェックを行うときに使います。
### 4. 自動生成されるメソッド
レコードクラスでは、次のメソッドが自動的に作られます。

・getter（フィールド名と同じ名前のメソッド）
・equals（オブジェクト同士を比較するメソッド）
・hashCode（データのハッシュ値を計算するメソッド）
・toString（データ内容を文字列として出力するメソッド）
これらを自分で書かなくても、自動で生成されるのがとても便利です！

## 3. まとめ
今回学んだレコードクラスは、シンプルな構造のおかげで、使い方次第では開発の効率を大きく向上させられそうです。特に、DTO（データ転送オブジェクト）として活用できる場面が多い気がする（予想）。
これから資格勉強を進めながら、さらに深く学び、実際の活用方法についても理解を深めたいと思います。また新たに気づいたことがあれば、この記事のようにわかりやすくまとめて紹介しますので、ぜひお楽しみに！
AWS Outpostsとオンプレミスの接続について

## はじめに
プロジェクトでOutpostsを構築することがあり、オンプレミスとの接続方法やルーティング設定について勉強する機会となりました。
個人環境では中々触ることがない大規模なサービスを扱う経験を得たため、調べた内容や構築にあたって得た知見等をまとめます。

## この記事でわかること
- Outpostsとオンプレ間の接続について
- LGW、Outpostsサブネットのルートテーブル設定について


## Outpostsとは
はじめに、主題のOutpostsを一言で説明すると、AWS Regionのサービスをオンプレミス上で実行できるサービスです。
AWS Regionを自社環境まで拡張（または延伸）して利用できるようなイメージを持っていただくとわかりやすいかと思います。

データを自社内で保管する要件や、ローカルのコンピューティングリソースとの低レイテンシー接続などの要件に応えるサービスとなっています。

OutpostsにはOutpostsラックとOutpostsサーバの2種類がありますが、今回はOutpostsラックを対象とします。

## AWS Region・オンプレミスとの接続
前述の通り、Outpostsラックは自社環境にサーバラックを配置しながらAWSサービスを提供します。そのため、AWS Regionとの接続を確立する必要があります。
OutpostsはAWS Regionやオンプレミスの環境とローカルネットワークを介して接続されるので、ローカルネットワークはAWS RegionにもどるWANのアクセスと、オンプレ環境へのLAN（またはWAN）のアクセスを提供する必要があります。  
 

本記事では、特にオンプレ環境との接続をピックアップして内容を記載しています。

## Outpostsとオンプレ間の接続設定
Outpostsラックを利用する場合、デフォルトで構成されるLocal Gateway（LGW）を用いてオンプレミスのネットワークと接続します。
1つのOutpostsラックにつき、1つのLGWが構成されます。

ユーザ側では、LGWルートテーブルの作成、LGWルートテーブルとVPCとの関連付け、LGWルートテーブルとVIFグループの関連付けの操作を実施する必要があります。
各操作はAWSマネジメントコンソールのOutpostsサービスの画面から実施可能です。

上記の設定を行うことで、Outpostsラックとオンプレミスの通信が可能となります。
ここからは、Outposts上のサブネットとオンプレミスの通信方式の詳細について確認していきます。

## Outpostsサブネットとオンプレミス間の通信方法

Outpostsサブネットがオンプレミスと通信する際には、デフォルトで「ダイレクトVPCルーティング」と呼ばれる通信方式が適用されます。
ダイレクトVPCルーティングでは、サブネットやインスタンスのプライベートIPアドレスをそのまま利用してオンプレミスのネットワークと接続します。


また、ダイレクトVPCルーティングでは、ルーティングプロトコルにBGPを使用してオンプレとOutpostsの経路情報をアドバタイズ（広告・広報）しています。
BGP（Border Gateway Protocol）とは、組織（ASと呼ばれるネットワークの集まり）間での経路情報交換を行うルーティングプロトコルの一種です。
ここでは、オンプレミスのローカルネットワークと、Outpostsという異なる組織で経路情報の交換を行っています。

BGPへのアドバタイズの対象となるのはOupostsサブネットに属するプライベートIPアドレスのみとなります。
BGP で交換される経路情報について、プレフィックス等をクライアント側でフィルタリングすることは不可となっています。

このような通信方式において、Outpostsサブネット上のインスタンスとオンプレミスのコンピューティングリソースが通信するには具体的にどのようなルートテーブルを設定すればよいのかについて見ていきます。

## ルートテーブルの設定
### Outpostsサブネットのルートテーブル

まず、Outpostsサブネットのルートテーブル設定についてです。

Outpostsに作成したサブネットのルートテーブルでは、LGWを指定することができます。
例えば、オンプレミス環境（例として 172.16.100.0/24）を宛先、ターゲットにLGWを指定して下記のようなルートを指定することができます。

| Destination | Target |
|:-:|:-:|
| 172.16.100.0/24  | lgw-id  |

LGWをターゲットとしたルートを追加することにより、ローカルのコンピューティングリソースへEC2インスタンスからの低レイテンシな接続が実現可能となります。



### LGWルートテーブル

続いて、LGWのルートテーブルについてです。
基本的には、先のダイレクトVPCルーティングによってOutpostsサブネットのCIDRがアドバタイズされるため、サブネット向けのルート設定は不要です。

ただし注意点として、ダイレクトVPCルーティングではインスタンスのENIへのルーティングのみをサポートしており、VPCエンドポイントなどのプライベートIPアドレスにはオンプレミスから直接アクセスすることはできません。


また、LGWのルートテーブルには、ローカルネットワークと接続するためのデフォルトルートが必要となります。このルートは、VIFとLGWのルートテーブルを紐づけした時点で作成される下表のようなルールとなっています。

| Destination | Target |
|:-:|:-:|
| 0.0.0.0/0  | LGW-VIF-GRP  |

オンプレミス側の経路情報もBGPへアドバタイズされますが、経路情報が追加されたことをLGWのルートテーブル上などユーザ側で確認することはできないようです。



## まとめ
以上、Outpostsラックのオンプレミスとの通信方式と、Outpostsサブネット・LGWのルートテーブル設定について説明しました。
Outpostsを通じて、普段マネジメントコンソールから利用している際にはあまり意識することのないネットワークやルーティングについて学ぶ良いきっかけとなりました。


## 参考
- [User guide for Outposts racks](https://docs.aws.amazon.com/outposts/latest/userguide/what-is-outposts.html "User guide for Outposts racks")
- [Deploying Local Gateway Ingress Routing on AWS Outposts](https://aws.amazon.com/jp/blogs/compute/deploying-local-gateway-ingress-routing-on-aws-outposts/ "Deploying Local Gateway Ingress Routing on AWS Outposts")
MCTへの道：MCT（マイクロソフト認定トレーナー）手動登録

趣味でMCTを目指しています。今回は新規登録について書こうと思います。
前回の研修編はこちら…。

https://qiita.com/ponponmikankan/items/14d77c56e85a71326817

## MCTになるには

MCT（マイクロソフト認定トレーナー）になるには2024年12月現在：
 * AssociateかExpertのMCP資格を1つ以上保有
 * 認定のプロバイダーで指導スキル研修を受講済みのこと
 * 1年以上の指導歴（証明不要）

が必須となっています。
指導スキル研修受講後、MCT登録希望の場合は認定プロバイダーからマイクロソフト社へ受講歴を送ってもらう必要があるようです。

https://learn.microsoft.com/ja-jp/credentials/certifications/mct-enrollment

## MCT登録ツールはアップデート中

通常はMCT登録ツールを用いて自分でオンライン申請を行います。しかし、現在は登録ツールが更新中のため使うことができません。（当初2024年10月再開となっていたものが→2025年1月再開→2025年3月末再開と何度もリスケとなっているため正式な再開時期はだいぶ先になる可能性があります）

以下に最新情報が掲載されておりますが、全然Coming Soon…じゃない…。どんだけ難航してんねん…。

https://techcommunity.microsoft.com/blog/mctnews/update-on-mct-enrollment-tool/4355162

## 代替として手動登録が可能

認定プロバイダー（私の場合はトレノケートさん）に依頼をすると、認定プロバイダー経由で登録ツールを用いない手動登録を行うことが可能です。

認定プロバイダー経由で登録してもらうと、マイクロソフト社からちょっと時間をおいて英語のメールがきます。

英語のメールには
 * MCTの規約
 * MCTの規約への同意書
 * MCT手動登録申請書
 * 面談の登録

について書かれています。それぞれ記入し、面談の登録をします。面談、わりとワールドワイドな時間で予約できるので、日本時間に合わせたほうがよいかもです。

## いざ面談

面談について情報がなさすぎて、そもそも何語で対応するのか謎だったんですが手動登録のために必要なものでした。言語は英語でした。先方2名、面談と聞いてなんとなくカメラオンにしちゃったけど、オンにする必要は全くありませんでした(笑)
何を聞かれるかと思いきや、Learnに登録されている資格の確認や、メールアドレス、MCIDなどを画面共有しながらきかれます。

「はい、ここ押して、それコピーして、はい、それチャットに貼って」と、とりあえず言われるので従いましょう。そんなに高度なことは言われませんが、英語アレルギーの人は結構つらいかも。

10分くらいで面談は終了。

最後にMCTの登録自体は2－3営業日でおわるけど、MCTの特典の利用は2－3か月後と言われました。これは登録ツールがダウンしているからだそうです…。くそうAzureで遊ぼうと思ったのに…。。。

またいろいろわかってきたら記事を書こうと思います。