OmniAICreator/Qiita-1.07M huggingface dataset:
NginxでUser-Agentによる条件分岐を用いたアクセス制御を実装する

## 概要
* 特定のUser-Agentを含むリクエストだったら無条件でアクセスを許可する
* それ以外はBasic認証をかける

上記の要件が提示されたので、Nginxで設定してみた。

## 注意点
なお、そもそもNginxにおけるlocationコンテキスト内でのifディレクティブの利用は**非推奨とされているので注意**。
(予期せぬ動作が起きるなど、意図通りに制御できない場合が多い)
https://mogile.web.fc2.com/nginx_wiki/start/topics/depth/ifisevil/

今回の環境は短期利用の想定であること、かつ検証用であることから許容している。

## 実装例
```
        location / {
                set $target_ua 0;
                if ($http_user_agent = "<TARGET-USER-AGENT>"){
                        set $target_ua 1;
                }


                if ($target_ua = 1){
                        set $auth_basic off; #対象のUAならBASIC認証オフ
                }
                if ($target_ua = 0){
                        set $auth_basic "Restricted"; #それ以外ならBASIC認証有効化
                }

                auth_basic $auth_basic;
                auth_basic_user_file /etc/nginx/.htpasswd;
        }
```
## 結果
User-Agentを含まないリクエストにはBasic認証がかかる。
```
$ curl -I <URL>
HTTP/2 401 
中略
www-authenticate: Basic realm="Restricted"
```
対象のUser-Agentを含むリクエストには認証なし。
```
$ curl -H "User-Agent: <TARGET-USER-AGENT>" -I <URL>
HTTP/2 200 
以下略
```
対象ではないUser-Agentを含むリクエストにはBasic認証がかかる。
```
$ curl -H "User-Agent: <UNTARGET-USER-AGENT>" -I <URL>
HTTP/2 401 
中略
www-authenticate: Basic realm="Restricted"
```

---
参考文献
* [nginxでIPもしくはuseragentでアクセス制限をする](https://sumito.jp/2018/11/22/nginx-ip-useragent-restriction/)
イベントソーシングを知ろう ~ステートソーシングとの比較とGoでの簡単な実装例つき~

イベントソーシングとは、データベースに保存するデータをイベントの形式で保存することです。イベントソーシングを使うことで、データベースの状態をイベントの履歴から再現することができます。


CRUDのようにデータベースの状態を直接変更するのではなく、イベントを発行してデータベースの状態を変更します。イベントソーシングを使うことで、データベースの状態を変更する操作をイベントの履歴として保存することができます。


ステートソーシングとイベントソーシングの違いは、データベースの状態を直接変更するのではなく、イベントを発行してデータベースの状態を変更する点です。イベントソーシングを使うことで、データベースの状態を変更する操作をイベントの履歴として保存することができます。

ステートソーシングにおいて履歴をトレースするためには、データベースの状態を保存するためのテーブルを作成したりロギングを行って時系列で解析する必要があります

この特徴から、イベントソーシングは、データベースの状態を変更する操作をイベントの履歴として保存することができるため特定の時点でのデータベースの状態を再現することが容易です。


## イベントソーシングの利点

イベントソーシングの利点は以下の通りです。

- データベースの状態をイベントの履歴から再現することができる
- データベースの状態を変更する操作をイベントの履歴として保存することができる
- 更新履歴があるため特定のタイミングのステートを再現することが容易

## イベントソーシングのデメリット

イベントソーシングのデメリットは以下の通りです。

- データベースの状態を変更する操作をイベントの履歴として保存するため、データベースの状態を再現するためにはイベントの履歴を再生する必要がある
- イベントの履歴を再生するためには、イベントの履歴を保存するためのストレージが必要

特に最新の状況を取得するためには、イベントの履歴を再生する必要があるため、データベースの状態を再現するためにはイベントの履歴を再生する必要があります。

一方でステートソーシングでは最新の状態はデータベースに保存されているため、データベースの状態を再現するためにはデータベースの状態を取得するだけで済みます。

## イベントソーシングの実装

ここからGoを使ってイベントソーシングを実装する方法を説明します。

イベントソーシングを実装するためには、以下の手順が必要です。

1. イベントを発行する
2. イベントを保存する
3. イベントを再生する

イベントを発行するためには、イベントを発行するための関数を定義します。イベントを保存するためには、イベントを保存するためのストレージを定義します。イベントを再生するためには、イベントを再生するための関数を定義します。

以下にイベントソーシングを実装するためのGoのコードを示します。

```go

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "os"
)

type Event struct {
    Type string `json:"type"`
    Data string `json:"data"`
}

func main() {
    // イベントを発行する
    event := Event{
        Type: "user_created",
        Data: "user_id: 1, user_name: alice",
    }

    // イベントを保存する
    saveEvent(event)

    // イベントを再生する
    replayEvents()
}

func saveEvent(event Event) {
    file, err := os.OpenFile("events.json", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    encoder := json.NewEncoder(file)
    if err := encoder.Encode(event); err != nil {
        log.Fatal(err)
    }
}

func replayEvents() {
    file, err := os.Open("events.json")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    decoder := json.NewDecoder(file)
    for {
        var event Event
        if err := decoder.Decode(&event); err != nil {
            break
        }
        fmt.Printf("replay event: %+v\n", event)
    }
}

```

このコードでは、`Event`構造体を定義し、`main`関数でイベントを発行して保存し、再生する処理を行っています。

イベントを発行のためには、`Event`構造体を使ってイベントを作成し、`saveEvent`関数でイベントを保存します。イベントを保存するためには、`os.OpenFile`関数を使ってファイルを開き、`json.NewEncoder`を使ってイベントをエンコードしてファイルに書き込みます。

イベントを再生のためには、`replayEvents`関数でファイルを開き、`json.NewDecoder`を使ってイベントをデコードして再生します。

このように、イベントソーシングを実装することで、データベースの状態をイベントの履歴から再現することができます。
asdfでnodejsのバージョンが変わらない

## はじめに
asdfで新しいバーションのnodejsを入れてもバーションが更新されない問題に

## エラーの内容
```
$ asdf global nodejs 22.3.0

$ node -v
No preset version installed for command node
Please install a version by running one of the following:

asdf install nodejs 18.15.0

or add one of the following versions in your config file at /Users/.user/src/.tool-versions
nodejs 18.16.0
nodejs 21.6.1
nodejs 22.3.0
```

asdf global nodejs でバーションを指定してもnode -vでNo preset versionと言われてしまう。

## 原因
エラーで出ていたこのファイルがおかしい
```add one of the following versions in your config file at /Users/.user/src/.tool-versions```
このディレクトリの.tool-versionを消してみるとバージョンが確認できた
```
$ node -v
v22.3.0
```
確認できました。

## 最後に
asdf globalでsetした場合は$HOME/.tool-versionsが参照され、
asdf localでsetした場合は$PWD/.tool-versionsのバージョンが参照されるようです。

私の手元の$PWD/.tool-versionsが悪さをしていたので今回はファイル削除で直りました。

読んでいただきありがとうございました。
Reactでブラウザの翻訳機能を使ったらFailed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.ってエラーが出た対応

Reactユーザーのみなさんこんにちは。

普段はGoを書いていてあるタイミングでReactのプログラムを保守することになり、その時に出くわしたエラーと原因について書いていきます。

## 事件はブラウザの翻訳機能で起きた

皆さんが使うブラウザでは自動翻訳機能があると思います。

翻訳の仕組みとしては仕組みとしては翻訳機能をOnにするとブラウザ内の文をサーバーに送ってレスポンスからDOMの置き換えを実行しているような感じでした。

（しっかりとは調べていません）

そんな中でDOM操作をしまくっていたところ、翻訳機能をOnにした状態で操作したときに以下のエラーが発生しました。

`Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.`

## 解消方法の模索

とりあえずググってみたところ近い問題を持っている人はいたようだった。

https://github.com/facebook/react/issues/11538#issuecomment-390386520

このissueではdivタグ内に直接文字列を書くことに起因してエラーが起きるようだった。

うちのコードそんなの無いんだけど？？？

## もう少し読んでみた

上記のリンクのissueにも書いてあるがもう少し説明を見ているがエラーをスローする/しないは以下の条件となっていた。

```
テキストノードの条件レンダリング: テキストノードが親要素の子要素として単独で存在せず、かつ条件レンダリングされていた場合にReactはエラーを発生させます。これは、テキストノードが削除される際に、親要素から子要素を削除する処理 (parent.removeChild(textNode)) が実行されますが、既にテキストノードは親要素の子要素ではないためエラーが発生してしまうためです。

唯一の子要素のテキストノード: もし、条件レンダリングされるテキストノードが親要素の唯一の子要素であれば、Reactはエラーを発生させません。

テキストノードの前方のノードの条件レンダリング: テキストノードの前方に位置するノードが条件レンダリングされていた場合にも、Reactはエラーを発生させます。このケースでは、新しいノードが挿入される際に、親要素に対して挿入処理 (parent.insertBefore(someNode, textNode)) が実行されますが、テキストノードは既に親要素の子要素ではないためエラーが発生してしまいます。
```


一方で我々が書いた個所は以下のようなコードだった。

```tsx
const Component = () => {
  return (
    <button>
        {condition && 'Welcome'}
        <span>Something</span>
    </button>
  )
}
```

このコードは上記の条件の中で「テキストノードが親要素の子要素として単独で存在せず、かつ条件レンダリングされていた場合」に該当していたためエラーが発生していた。

divタグに限らず、buttonタグやでも発生するので注意が必要だった。
Công trình phòng chống sóng thần tại Cầu Vượt Sóng Thần

"Kỳ công kiến tạo - Cầu Vượt Sóng Thần
Chi Tiết Tại: https://topbinhduongaz.com/cau-vuot-song-than/
Xem Thêm: 
https://www.behance.net/gallery/196700501/K-nim-10-nam-sng-Binh-Duong-Cu-Vut-Song-Thn?share=1
https://500px.com/photo/1091078695/ky-niem-10-nam-song-va-lam-viec-tai-binh-duong-cau-vuot-song-than-by-top-binh-duong-az#google_vignette

#Cầu_Vượt_Sóng_Thần, #CầuVượtSóngThần, #Cau_Vuot_Song_Than, #Top_Binh_Duong_AZ, #TopBìnhDươngAZ, #Top_Bình_Dương_AZ, #Binh_Duong, #BìnhDương, #Bình_Dương"![ho-dai-lai_7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3816687/577dde32-e2e8-a3ca-da94-b68e38a3c9df.jpeg)
[SQL]DBから特定のカラムを持つテーブルを検索する

# はじめに
カラムがどこのテーブルにあるか探すためのSQLをコードとして残します。
MySQL、PostgreSQLでも動作します。
# コード
```
SELECT table_name, column_name
FROM information_schema.columns
WHERE column_name LIKE'%カラム名%';
```

# 参考
https://zenn.dev/datchlive/articles/9a8b821fd2486b
ApacheShiroを使用する上での注意点

# 導入
こんにちは。元バックエンドエンジニアのYamaです。

前回、過去のプロジェクトで触ったApacheShiroの概要について記事にしました。
[前回記事はこちら](https://qiita.com/Flowerfy_FuMiSan/items/6713087b693125aa972f "ApacheShiroを使ってみた(遠い過去)")

https://qiita.com/Flowerfy_FuMiSan/items/6713087b693125aa972f

このApacheShiroにおいて重要なShiroFilterについて解説しましたが、フィルタチェーンの順番には注意が必要なので、別途記事にしました。

# フィルタチェーン

フィルタについては前回の記事を参考にしてください。

さて、早速本題ですが、フィルタチェーンの順序は重要です。
**Shiroはフィルタマップを上から順に評価します。**
具体的なパスは一般的なパスよりも前に配置し、詳細なパスのマッチングが適切に行われるようにしなければなりません。

```java
filterMap.put("/login/**", "anon");
filterMap.put("/user/**", "authc");
filterMap.put("/**", "authc");
filterMap.put("/api/**", "noSessionCreation");
```

上記の例では、最後の`noSessionCreation`は適用されません。
なぜならその設定の前に`/**`に対するフィルタの設定が行われており、`/api/**`のパスに対しては、`filterMap.put("/**", "authc");`のフィルタの設定が優先されてしまうからです。

ですので、フィルタマップで`/**`を設定する際は、一番最後に設定し、それ以外のURLマッチングさせたいパスは上に記述することに注意してください。
URLマッチングさせる範囲が狭いものを先に設定し、広いものを後に設定することを忘れなければ問題はないかと思います。

# 最後に
まぁ、ApacheShiro自体、利用するユーザーは少ないと思いますが、いつか特殊なプロジェクト荷携わり、利用する開発者の役に立つことを願っています。
AWSのログインをパスキーにしよう！

# AWSでパスキーを使ってログインができるようになりました！

この神アップデートでいままで面倒くさかったトークンを入力する作業が不要になりました！
地味に6桁の数字を入力するのが大変だった...

## やり方

1. IAMにアクセスして、ユーザーを選択します。　セキュリティ認証情報から MFA デバイスの割り当てを選択します。
![IAM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288957/12b0bf0a-ccb3-7a9e-0a10-ba6e97132651.png)

2. 一番上のパスキーまたはセキュリティキーを選択します。
![Select.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288957/85775fcd-d561-95fe-fb78-67ea5cc413ed.png)

3. するとWindows Helloが立ち上がるので好きな方法で認証します。 
![MakePasskey.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288957/724f22b5-9b09-3e00-feef-19e08de1d5e9.png)

::: note alert
ブラウザの機能のパスワードマネージャーではWindows Helloの認証を求められます。
その時と同じ認証方式をパスキーに設定してはいけません。
同じパスワードでログインとパスキーの認証ができるようにしてはいけません。
:::
Language Server Protocolの仕組みについての概要~Goを例に~

# Language Server Protocolの仕組みについての概要~Goを例に~

コードエディタを使っているときに補完をしてコーディングすることが多いと思います。

例えばGoのコードを書いていてある関数内で`fmt.P`と入力したときには以下のスクショのように
- Print
- Printf
- Println
などがサジェストされます。

![Screenshot 2024-06-09 at 17.29.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655827/dc4d0587-1024-efc2-7a3a-2a70a479510b.png)


この仕組みを支えるLanguage Server Protocol について本記事では解説していきます。

## そもそもLSPとは

Language Server Protocol (以下LSP)はエディタやIDEとプログラミング言語間の通信プロトコルです。

LSPを使用するとエディタは特定のプログラミング言語の詳細を知る必要がなく、代わりにLanguage Serverと通信することで、コード補完、定義へのジャンプ、リファクタリングなどの機能を提供できます。

つまりVSCode、Zed、Vimなどのエディタそれぞれにコード補完用の機能を開発する必要がなく、共通の機能を提供できるようになっています。

## だいたいの動き

LSPがサジェストを提供するまでの流れは以下のようになります。

1. エディタでコードを入力

1. エディタがLanguage Serverに対して補完リクエストを送る。リクエストには、現在のファイルのURIとカーソルの位置情報が含まれる

1. Language Serverがリクエストからファイルのソースコードを解析する（この解析はカーソルの位置情報を元に構文木を構築する）

1. Language Serverが構文木を元に可能な補完候補を計算する

1. 補完候補をエディタに送信する

1. エディタが候補を表示する

## Goでの例

Goではgoplsが公式でサポートしているLSPで、そのサジェストを提供する流れを以下に示します。

1. コードを入力（例えば、`fmt.P`と入力したとする）

1. エディタはgoplsに対して補完リクエストを送信する

1. goplsがカーソルの位置情報を元に構文木を作成してソースコードを解析

1. goplsが構文木を元に、Goの言語仕様と標準ライブラリ、コードを元に可能な補完候補を計算する

1. 計算した補完候補をエディタに送信し、エディタは候補を表示する

以上の流れにより、ユーザーはfmt.Pと入力したときに、Print、Printf、Printlnなどの補完候補を見ることができます。

## AIコード補完ツールとの比較

一方でGitHub CopilotはAIベースのコード補完ツールで、大量の公開コードから学習しています。

Copilotは特定の言語の詳細を理解するのではなく、過去のコードからパターンを学習してそれを元にコード補完を提供します。

| | LSP | AI |
| -- | -- | -- |
| 知識の源泉 | 言語の仕様とその言語のLanguage Server | 公開されているコードベース全体 |
| 動作の仕組み | エディタとLanguage Server間の通信 | AIモデルがユーザーの入力コードを元に補完を生成 |
| 対応言語 | Language Serverが存在する言語 | 学習データに含まれる言語 |

使い分けとしては

- LSPは言語の詳細を深く理解し精度の高いコード補完やリファクタリング
- Copilotは広範なコードベースから学習し新しいパターンや異なるコーディングスタイルの補完

といったところでしょうか。
Spring BootにおけるDI（依存性注入）入門

# 導入
今回は、Spring Bootの基本技術である**DI（依存性注入）** について、初めて学ぶ方でもわかりやすく解説していきます。
DIを使うと、コードの保守がしやすくなったり、テストが楽になったりと、色々良いことがあるんです。

# 依存性注入（DI）ってなに？
## 1. 依存性って...？
まず、「依存性」ってなんだろう？ってところから。
これは、クラス（例えばAクラス）が、他のクラス（例えばBクラス）の機能を利用するために必要なオブジェクトのことを言います。
簡単に言うと、Aが動くためにはBが必要ってことですね。

## 2. DIってどんなもの？
**依存性注入(Dependency Injection, DI)** は、上述のAとBのように依存するオブジェクトを、クラスの中で直接作らずに、外から注入する(つまり、渡してあげる)仕組みです。
これにより、オブジェクトは自身で依存オブジェクトを生成するのではなく、外部から提供されるため、柔軟でテストしやすいコードを書くことができます。

## 3. DIを使うメリット(重要)
DIには、以下の3つのメリットがあります。
このメリットこそがDIを使う意義といっても過言ではありません。

- **疎結合**: クラスが他のクラスに直接依存しないため、変更に強くなります。
- **テストの容易さ**: 依存オブジェクトを簡単にモックに置き換えられるため、単体テストが容易になります。
- **再利用性**: クラスの再利用が容易になります。別の依存関係を持つ別のコンテキストで簡単に使用できます。

# Spring BootでDIを使ってみよう！
## 1. Spring Beanって何？
Springでは、オブジェクトを管理するためにBeanという仕組みを使います。
Springがアプリ全体のBeanを管理してくれるので、開発者はBeanの作成や管理に頭を悩ませる必要がありません。

## 2. Beanをどうやって作るの？
Spring Bootでは、主に2つの方法でBeanを作ります。

### 2.1. アノテーションを使う方法
一番よく使うのが、`@Component`や`@Service`などのアノテーションを使う方法です。
これをクラスにつけると、そのクラスがBeanとして登録されます。

```java:SampleService.java
import org.springframework.stereotype.Service;

@Service
public class SampleService {
    public void sayHello() {
        System.out.println("Hello World!");
    }
}
```

### 2.2. `@Configuration`を使う方法
こちらは、Javaの設定ファイル(Configuration)でBeanを定義するやり方です。

```java:AppConfig.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    @Bean
    public SampleService sampleService() {
        return new SampleService();
    }
}
```

## 3. 依存性をどうやって注入するの？
依存性を注入する方法も、主に2つあります。

### 3.1. コンストラクタ注入
コンストラクタの引数に必要なオブジェクトを受け取るようにして、`@Autowired`を付けてあげます。

```java:UserService.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    private final SampleService sampleService;

    @Autowired
    public UserService(SampleService sampleService) {
        this.sampleService = sampleService;
    }
    
    public void executeServiceSay() {
        sampleService.sayHello();
    }
}
```

### 3.2. フィールド注入
こちらはフィールドに直接`@Autowired`を付けて注入する方法です。
コンストラクタ注入より、一般的ではありますが、テストが難しくなる可能性があります。

```java:UserService.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    @Autowired
    private SampleService sampleService;
    
    public void executeServiceSay() {
        sampleService.sayHello();
    }
}
```

# 最後に
DIを使うと、クラスの依存関係を外から注入できるので、コードがシンプルになって変更にも強くなります。
Spring Bootでは、DIを使ってBeanを簡単に管理できるので、ぜひ活用してみてください！
GPT-4oでAIと楽しく英会話！僕もう一人じゃないもん！

# はじめに
こんにちは、H×Hのセンリツ大好きエンジニアです。（同担OKです😉）
GPT-4oでは音声入力と音声読み上げが爆速になったことによって、とうとう英会話が出来るようになったとのこと。。。進歩早すぎますね。。。😮

先月からスピークバディを契約して英会話学習を始めているので、これは試さねば。。！という思いで挑戦してみました🫣

# 英会話の始め方
ざっくりはこうです
1. ChatGPTのアプリをStoreから入手
1. ログイン
1. **GPT-4o**を選択し、画面右下のヘッドフォンマークを選択!
![gpt4o_screen.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653241/282c7805-4c72-e03f-19b7-aef7f0bb4fcf.jpeg)

UIも分かりやすいので簡単ですね！
では、早速英語学習2ヶ月目の実力を見せちゃいますかあ。。。😎

# GPT-4oとの英会話の所感
は、早い。。。何言ってるか少ししか聞き取れません。。。🥹
まだちゃんとした会話になっていないですね、まだ1ヶ月くらいの学習じゃあ早かったか。。。

![gpt4o_english_conversation_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653241/dc47c2bf-269a-b4c9-41d3-74e55522fbbb.jpeg)

しかも、英会話中は何言ってるかテキストで表示されずに、以下の画面のままなので音を頼りに会話するしかありません。。。（会話中にテキスト表示させるやり方ご存知の方教えて頂きたいです。。。）
![gpt4o_white_talking_screen.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653241/d3caeec6-c19c-2e03-89cb-0da9a5b96c86.jpeg)

ですが、音声認識能力がすごいですね！
自分の拙い英語でも一字一句全て認識して、それに対する答えもすぐ返ってくるので本当に人間と会話してるみたいでした！！

また、「聞き取れなかったのでもう少しゆっくりお話ししていただけませんか？」とお願いすると、ゆっくり話してくれるので少し楽になるのも良いですね！！

正直、ここまでちゃんと会話ができることに驚きました！
ただ、以下の観点から**初学者よりは中級者向け**なのかなあと個人的には感じました
- テキストで表示されない
- ネイティブっぽい早口なので聞き取る力が必要
- 英会話を繋げる語彙力が必要

# 英会話アプリとの比較

自分が契約しているスピークバディとの比較になりますが、こんな感じかなあと思っています。
（個人の主観込みなので一意見としてご覧ください🙈）

|  | GPT-4o | スピークバディ |
| :-: | :-: | :-: |
| **費用** | 約3000円 | 1983円〜3300円<br>（プラン割引による変動） |
| **英語認識精度** | ◎ | ○ |
| **聞き取りやすさ** | △ | ◎ |
| **英語学習のしやすさ** | △ | ◎ |
| **手軽さ** | ◎ | ○ |
| **用途** | 中級者〜向け<br>会話が出来る程度のリスニングとスピーキングをより向上させる | 初学者向け<br>語彙とフレーズ、スピーキング、リスニングを学ぶ |

やっぱりスピークバディは英語学習に特化したアプリという事もあり、全体的に評価は高いです！
対するGPT-4oも、ある程度英会話に慣れてきたらめちゃくちゃ重宝しそうだなと思いました！

初学者の方は、スピークバディみたいな英語学習アプリ -> GPT-4oみたいなロードマップで学習すると良さそうな気がします！（自分も同じように活用します😉）

# おわりに
GPT-4oの会話がスムーズに行えるので、英語学習はもうAIに頼れば良いという時代になりそうですね！
英語を話せるようになって、海外で働きたい or グローバルな日系企業で働いてみたいです。
ここまでご覧いただきありがとうございました！
センリツでした🤓
AWS EKSにNginxを建てよう ~ロードバランサーを添えて~

# 前提条件　

- EKSクラスターを作成している
- kubectl がAWS EKSクラスターに接続されている

まだしていない人は以下の記事を参照してください。

https://qiita.com/Takkesan/items/83ed99a36bca5b105d97

# 本編

## 1. Nginxのデプロイファイルを作成する

以下のようなファイルを作成します。

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
    purpose: serve-web
  annotations:
    description: Deployment for the nginx web server
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      name: nginx-pod
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx-container
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
              protocol: TCP
      restartPolicy: Always
```

このファイルはnginxのイメージを使って2つのポッドを作成します。

## 2. サービスファイルを作成する

以下のようなファイルを作成します。

```yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: nginx
    purpose: expose-nginx
  annotations:
    description: Service to expose the nginx Deployment
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer
```

このファイルによってクラシックロードバランサーが作成され、アクセスがpodに分散されます。

## 3. ファイルを適用する

プロジェクトの中で以下のコマンドでファイルを適用します。

```bash
kubectl apply -f .
```

## 4. サービスの確認

EC2からロードバランサーを見つけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288957/00f074dc-60ae-0ffa-cc89-c73cb6ae0be2.png)
DNS名が表示されているのでこれをコピーしてブラウザに貼り付けます。

すると...
見事表示されました！！
![nginx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288957/7b8b83fb-8d80-3908-0ec9-56cb8fa59831.png)


::: note
ロードバランサーがEC2を認識するまで少し時間がかかることがあります。
:::

# おわりに

以上でEKSにNginxをデプロイする方法を紹介しました。
あとは好きなイメージに置き換えれば何でもできます！
よきEKSライフを！
IT用語集

~2024/06/15 
仕事
・[名前解決](https://wa3.i-3-i.info/word154.html)
・[DNS](https://wa3.i-3-i.info/word1287.html)
・[ドメイン名](https://wa3.i-3-i.info/word1286.html)

2024/06/15 
基本情報　　　
・[排他的論理和](https://wa3.i-3-i.info/word11664.html)　
・[対数](https://www.nli-research.co.jp/report/detail/id=67930?site=nli#:~:text=%E5%AF%BE%E6%95%B0%E3%81%A8%E3%81%AF,b%20%E3%81%AE%E5%AF%BE%E6%95%B0%E3%80%8D%E3%81%A8%E5%91%BC%E3%81%B6%E3%80%82)
・[キャッシュクリア](https://wa3.i-3-i.info/word110199.html)
・[クライアント](https://wa3.i-3-i.info/word145.html)
闘魂Elixir ーー AtCoder Beginner Contest 347(A)をElixirで楽しむ

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>

<b><font color="red">$\huge{闘魂とは己に打ち克つこと。}$</font></b>
<b><font color="red">$\huge{そして闘いを通じて己の魂を磨いていく}$</font></b>
<b><font color="red">$\huge{ことだと思います}$</font></b>


# はじめに

[AtCoder Beginner Contest 347](https://atcoder.jp/contests/abc347)を[Elixir](https://elixir-lang.org/)で解いてみます。

[AtCoder](https://atcoder.jp/)を解くのが趣味で、休憩時間に解いているという若い人がいて、それってすごい意識の高い休憩時間の過ごし方だと思って、私も真似してみることにしました。


# [AtCoderをElixirでやってみる](https://zenn.dev/torifukukaiou/articles/ac84c87736ceebf4da01)

入力の読み取り方や解答の作り方は、別の記事にまとめています。


https://zenn.dev/torifukukaiou/articles/ac84c87736ceebf4da01

ご参照くださいませ。

[Elixir](https://elixir-lang.org/)で[AtCoder](https://atcoder.jp/)を楽しむためには、エントリポイントを`Main.main/0`にする必要があります。つまり`Main`モジュールを作って、その中に`main/0`関数を定義するわけです。

# [A - Divisible](https://atcoder.jp/contests/abc347/tasks/abc347_a)

問題はリンク先をご参照くださいませ。
私の解答を貼っておきます。


<details><summary>私の解答</summary>

_問題文を読んでいることを前提にひとこと解説をしておきます。_

リストの要素のうち条件にあうものを残して、さらに細工をしますので、[Enum.filter/2](https://hexdocs.pm/elixir/Enum.html#filter/2)および[Enum.map/2](https://hexdocs.pm/elixir/Enum.html#map/2)関数を使うとよいでしょう。
使用する関数を少なくするには、[Enum.reduce/3](https://hexdocs.pm/elixir/Enum.html#reduce/3)関数一発で実装できます。


```elixir
defmodule Main do
  def main do
    [_n, k] =
      IO.read(:line) |> String.trim() |> String.split(" ") |> Enum.map(&String.to_integer/1)
    a_list = IO.read(:line) |> String.trim() |> String.split(" ") |> Enum.map(&String.to_integer/1)

    solve(k, a_list)
    |> IO.puts()
  end
  
  def solve(k, a_list) do
    Enum.filter(a_list, & rem(&1, k) == 0)
    |> Enum.map(& div(&1, k))
    |> Enum.join(" ")
  end
end
```




</details>




---

# さいごに

[AtCoder Beginner Contest 347](https://atcoder.jp/contests/abc347)を[Elixir](https://elixir-lang.org/)で解くことを楽しみました。

あなたのお好きなプログラミング言語でお楽しみください。

---


**闘魂**とは、  **「己に打ち克つこと。そして闘いを通じて己の魂を磨いていくことである」** との猪木さんの言葉をそのまま胸に刻み込んでいます。
知っているだけで終わらせることなく、実行する、断行する、一歩を踏み出すことを自らの行動で示していきたいとおもいます。
**アントニオ猪木さんのメッセージから元氣をもらったものとして、それを次代に語り継ぎ、自分自身が「闘魂」を体現するものでありたいとおもいます。**

---

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>
<b><font color="red">$\huge{１、２、３ ぁっダァー！}$</font></b>
ECMAScriptの紹介及びES6とJavaScriptの関係

# ECMAScript 6の紹介

ECMAScript 6.0（以下ES6と呼ばれる）は、2015年6月に公式にリリースされたJavaScript言語の次世代です。その目標は、JavaScript言語を使用して複雑な大規模なアプリケーションを作成し、エンタープライズレベルの開発言語になることです。

## ECMAScriptとJavaScriptの関係

よくある問題は、ECMAScriptとJavaScriptの関係は何ですか？

1996年1996年历史、JavaScript的、决定决定决定决定提交组织组织希望这种种次年、ecma ECMA-262の初版）は、ブラウザスクリプト言語の標準を指定し、この言語はecmascriptと呼ばれます。

この標準は、最初からJavaScript言語のために策定されていますが、JavaScriptと呼ばれる理由は2つあります。 JavaScriptの名前は、Netscapeによって商標として登録されています。

したがって、ECMAScriptとJavaScriptの関係は、前者が後者の仕様であり、後者は前者の実装であるということです（他のECMAScript方言とJScriptとActionScriptは、これら2つの単語を交換できます。

## ES6とECMAScript 2015の関係

ECMAScript 2015（ES2015と呼ばれる）もよく見られます。

2011年に、ECMAScript 5.1のリリース後、6.0を策定し始めました。

ただし、このバージョンでは文法機能が多すぎるため、多くの組織と個人が新しい機能を含めることは不可能になります。従来のアプローチは、最初にバージョン6.0をリリースすることです。

ただし、標準メーカーはこれを行いたくありません。彼らは標準を通常のプロセスにアップグレードしたいと考えています。これらの提案は、多くの会議の後、どのような改善が必要ですか。次に、

標準委員会は、毎年6月に公式にリリースされると判断しました。このようにして、年の新しいバージョンでは、年度マークが使用されている限り、今年の新しいバージョンが必要です。

ES6の最初のバージョンは2016年6月にリリースされました。公式名は、2016年6月に「ES2015」と呼ばれます2つの違いは非常に小さいため、ES6.1と見なすことができます（配列インスタンスのみが追加されます`includes`方法とインデックスオペレーター）、基本的に同じ基準に応じて、ES2017標準は2017年6月にリリースされました。

したがって、ES6は歴史的な名詞であり、ES2015、ES2016、ES2017などをカバーする次世代のJavaScriptを参照しています。しかし、時には「次世代のJavaScript言語」を指します。

## 文法提案の承認プロセス

誰でも標準委員会（TC39委員会とも呼ばれる）に提案できます。これには、言語標準の変更が必要です。

新しい文法は、提案から正式な基準に変更され、各段階の変更をTC39委員会によって承認する必要があります。

- ステージ0- ストローマン（ディスプレイステージ）
- ステージ1- 提案
- ステージ2- ドラフト（ドラフトステージ）
- ステージ3- 候補者（候補段階）
- ステージ4- 終了（最終段階）

提案がステージ2に入ることができる限り、それは将来の正式な基準におけるECMAScriptの現在のすべての提案を間違いなく含めます。これはTC39の公式ウェブサイトにあります[github.com/tc39/ecma262](https://github.com/tc39/ecma262)チェック。 

この本の執筆目標の1つは、ECMAScript言語の最新の進捗状況を追跡することです。

## ECMAScriptの歴史

ES6は、最初から最終リリースから15年間使用されています。

前述のように、ECMAScript 1.0は1997年にリリースされました。今後2年間で、ECMAScript 3.0（1999年12月）が大成功を収めました。 JavaScript言語の文法、およびその後のバージョンは、今日まで完全に継承されていました。

2000年、ECMAScript 4.0は最終的には渡されませんでしたが、そのコンテンツのほとんどはES6によって継承されました。

ES4が合格しないのはなぜですか？このバージョンはあまりにも攻撃的であるため、ES3に完全にアップグレードされているため、Googleおよびその他の大企業の標準委員会のメンバーがいます。

2007年、ECMAScript 4.0ドラフトは、当初8月にリリースされると予想されていましたJavaScriptの作成者Brendan Eichが現在のドラフトを主張しています。

2008年7月、次のバージョンには、すべての関係者の違い、紛争が激しく拡張され、将来のバージョンのために拡大する必要があります。このバージョンは、会議の直後にハーモニーと名付けられました。

2009年12月、ECMAScript 5.0は公式にリリースされました将来のTC39委員会は基本的に互換性があります。 ES7の判断は、ES5が2013年半ばにJavaScriptによって開発された主流の標準になることであり、このポジションは今後5年間で維持されています。

2011年6月、ECMAScript 5.1がリリースされ、ISO国際標準になりました（ISO/IEC 16262：2011）。

2013年3月、ECMAScript 6ドラフトは凍結され、新しい機能はECMAScript 7に追加されなくなりました。

2013年12月、ECMAScript 6ドラフトがリリースされました。

2015年6月、ECMAScript 6は正式に合格し、2000年から15年になりました。

現在、ES6の主要なブラウザのサポートを表示できます[https：// compat-table.github.io/compat-テーブル/es6/](https://compat-table.github.io/compat-table/es6/)次に、

node.jsは、JavaScriptのサーバーの実行環境です。
3DのURPで作成したプロジェクトで2DLight(2DのURPの機能)を使う

# この記事を書いたキッカケ
3Dで作成したプロジェクトで[2DLight](https://www.youtube.com/watch?v=Km_4NQPk59s&t=528s&ab_channel=UnityJapan)を使おうとしたらちょっと引っかかったのでその備忘録として書きます。

# 使用したUnityバージョン
2022.3.33f1

# 2DLightを使えるようにするまでの下準備
まず3DURPでプロジェクトを作成していると思うのでプロジェクトを開きます。
最初の状態では2DLightなどがプロジェクトに含まれていないので2DPackageをPackageManagerからインポートします。
![2D.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654136/2fbd63ab-22d5-3404-5ae1-d395ea7861f9.png)
その後NewSceneで2D用のシーン(Standard(URP))を作成します。
![918187a338d770ebab87e7c83e2d5468.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654136/12870e7a-5bd8-5806-bb83-b3b03e069ff6.png)
そのままだとRendererが3D用のものになっていてうまく2Dのオブジェクトが表示されないので、編集する必要があります。
まずは使用しているURPAssetを探しましょう。
使用しているURPAssetがどれかはEdit->ProjectSettings->Graphicsの一番上を見ることで分かります。
![aa5c2c5f6b59eb4ebc3eeb3191025349.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654136/2d0d58b2-2199-5896-a564-280f08a3c896.png)
使用しているURPAssetがどれかわかったらRendererListに2D用のAssetRendererを追加します。2D用のAssetRendererはこの時点ではないはずなのでCreate->Rendering->URP2DRendererを選択して作成します。
![Create.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654136/e721cdb7-8b97-2719-3aba-a994a72fe9f2.png)
作成したら使用しているURPAssetを選択し、InspecterのRendererListから作成した2DRendererを登録します。
![abc132c0dcf819a238165d14298602f6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654136/8211bb9d-510b-38aa-96fe-b9c3b104cf7f.png)
# 2DLightを使う
2DLightを使うシーンを作成します。作成したシーンでは2D用のRendererを用いるため、カメラのRendererに2DRendererを設定します。
![2920f3f78ded9ff311369252c473e6b9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654136/4dc210b3-5ff9-11dc-e358-baf544074272.png)

:::note warn
シーンビューとGameシーンビューで使われるRendererは必ずしも同じになるわけではありません。シーンビューではURPAssetでデフォルトに設定したRendererが使われ、Gameシーンビューではカメラに適用されているRendererが使われます。これにより、それぞれの画面で映るものが違うことがあります。
:::
設定したらシーン上にライトを設定します。
全体にライトを適用したい場合は、HierarchyからLight->GlobalLightを作成することでできます。
![5780873b678970ee75b3da413a43df5d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654136/92c2d654-a56d-a6df-fcd7-6f44c4cca218.png)
ライトを作成したら明るさを適用するSpriteを設定していきましょう。2DObject->Sprite->Squareで適当なSpriteを設定して画面全体に映るようにします。
デフォルトのマテリアルだと2DLightが反映されないのでマテリアルを作成し、シェーダーにUniversalRenderingPipeline->2D->Sprite-Lit-Defaultを設定します。

# 完成
GlobalLightとFreeformLightを置いたもの
![72f51ca65be27762b321efbbefe039f5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654136/a840df68-0388-4a8c-1606-3e40fd73e312.png)


# 注意点とか
2DRendererにDecal機能を追加するとエラーが出る。
![855a8a95c2c1aef2c35064bc313925b7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654136/02fff265-57db-cb3f-8817-7df7a41d9cd6.png)
Einstein 会話インサイト Einstein Conversation Insights の考察2



+ [Mulesoft を通じて組織に取り込まれた通話録音で Einstein 会話インサイトが生成されない](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007epfyUSAQ)


>営業コールの録音は、Mulesoft を使用して Mitel コール サービスから Salesforce に取り込まれていますが、それらのコールに関する Insights は生成されていません。ECI 統合権限セットは、Mulesoft 統合ユーザーに割り当てられています。組織では Einstein Conversation Insights が有効になっており、Dialer を通じて記録されたコールに関する Insights は生成されていますが、Mulesoft 統合を通じて取り込まれたコールに関する Insights は生成されていません。Mulesoft が取り込んだコール録音に関する Insights を ECI が生成できるようにするために、何をする必要があるかについてのアイデアはありますか? 


保存場所によってEinstein Conversation Insightsができないのかな？

+ [Microsoft Teams と Google Meet での Einstein 会話インサイトの使用](https://help.salesforce.com/s/articleView?id=release-notes.rn_sales_eci_expanded_providers.htm&release=248&type=5)


>チャネルのコンテキスト内で作成された Microsoft Teams 会議はサポートされていません。チャネル会議は SharePoint に保存され、Einstein Conversation Insights によって処理されません。


トランスクリプトとして保存されるとEinstein 会話インサイトで使用できる？

+ [音声通話とビデオ通話のトランスクリプトへのアクセス](https://help.salesforce.com/s/articleView?id=release-notes.rn_sales_eci_transcripts.htm&release=236&type=5)

>音声通話とビデオ通話のトランスクリプトへのアクセス権を持つ営業担当およびマネージャは、通話音声を使用せずに顧客との会話をすばやく解析できます。


+ [録音プロバイダー向けの Einstein Conversation Insights API の設定](https://help.salesforce.com/s/articleView?id=000392584&type=1)

録音プロバイダーを追加する必要がある？


+ [Einstein 会話インサイトの設定に関する考慮事項](https://help.salesforce.com/s/articleView?id=sf.ci_considerations.htm&type=5)

**サブスクリプションに関する考慮事項と制限**

+ Conversation Insights は、Sales Dialer とすぐに使用できるほか、ビデオ通話用の Google Meet、Microsoft Teams、Zoom Meetings とも互換性があります。Zoom Phone はすぐには利用できません。Dialpad、RingCentral、Aircall、Amazon Connect は、追加のセットアップにより利用できます。その他のサポートされているパートナーは、 API 経由で利用できます。**新しい録音プロバイダーを追加するには、顧客による統合作業が必要です。**

**サポートされている機能とファイルの種類**

+ MP3、FLAC、WAV、MP4、M4A ファイル タイプがサポートされています。
+ MP4 ファイルはビデオのみでサポートされます。
+ 各録画は 64 MB に制限されます。
+ Sound eXchang は、MP3、FLAC、WAV ファイルの変換に使用されます。サポートされているコーデックの詳細については、SoX ページを参照してください。
+ FFmpeg は MP4 および M4A ファイルの変換に使用されます。サポートされているコーデックの詳細については、+ FFmpeg ページを参照してください。
+ Shield Platform Encryption はサポートされていません。


+ [Zoom Phone Integration with Salesforce](https://qiita.com/Keiji_otsubo/items/29bcb30d4653865d76cf)


# 資料

+ [Call Coaching リソース](https://developer.salesforce.com/docs/atlas.ja-jp.chatterapi.meta/chatterapi/connect_resources_calls_resources.htm)
+ [CloudTalk で Einstein Conversation Insights を設定する方法](https://help.cloudtalk.io/en/articles/8290842-how-to-setup-einstein-conversation-insights-with-cloudtalk)
+ [Salesforce R2 向け Mitel® MiVoice 統合](https://appexchange.salesforce.com/appxListingDetail?listingId=a0N3000000B4hfaEAB)
+ [Salesforce 向け Mitel (MiCloud Connect)](https://oneview.mitel.com/s/article/Mitel-for-Salesforce-MiCloud-Connect)


# 投稿

+ [Einstein Conversation Insights + Teams Video : r/salesforce](https://www.reddit.com/r/salesforce/comments/1g3rvsz/einstein_conversation_insights_teams_video/?rdt=35622)
[GitHub Projects] 私たちのプロジェクト管理方法を紹介 第3弾

## はじめに

こんにちは。株式会社 Panta Rhei のインフラ構築を担当している岸本です。

[前回](https://qiita.com/Antonnion/items/8e3c24663d8257995a1f)と[前々回](https://qiita.com/Antonnion/items/0b5a2e8f226bd5d9bf9b)に引き続き私たちが採用しているプロジェクト管理方法第3弾をご紹介します。
今回は大項目、中項目、タスクをわかりやすく把握する方法を紹介いたします。


## 完成図
![スクリーンショット 2024-06-15 12.07.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775049/5a5ada9b-f62d-eceb-0a49-4fbd343af11b.png)

## 手順

作成手順は以下のようになっています。

1. チケット作成
2. 大項目、中項目を作成
3. チケット分類
4. ボードの編集

順に見ていきたいと思います。

### チケット作成
今回のプロジェクトのテーマは「人生」で作成します。

:::note info
最後に実運用しているボードのスクリーンショットを載せています。
:::

私は以下のような作成しました。
| チケット名 |
|-----------|
| 朝ごはん作る     |
| 朝犬の散歩行く    | 
| 仕事Aする  | 
| 仕事Bする   | 
| 仕事Cする   | 
| 6/20に自治会出席  | 
| 6/25に~歯医者に行く   | 


### 大項目、中項目を作成
大項目、中項目はカスタムフィールドで作成します。
[第1回](https://qiita.com/Antonnion/items/8e3c24663d8257995a1f)の記事でも作成方法や大項目、中項目以外の項目も紹介していますので参考にしていただければ思います。

以下のように設定します。
[ 大項目 ]
![スクリーンショット 2024-06-15 11.49.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775049/f255aa6c-bf83-73a7-3559-aacd69ad19cc.png)

[ 中項目 ]
![スクリーンショット 2024-06-15 11.57.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775049/25b8338f-19b2-9c98-afe1-9dd4dfeb0b71.png)

これで大項目、中項目が作成できました。

### チケット分類
チケットをクリックし、カスタムフィールドを設定していきます。
以下の設定してみました。

| チケット名 | 大項目 | 中項目|
|:-----------:|:------------:|:------------:|
| 朝ごはん作る       | プライベート   | 家事  |
| 朝犬の散歩行く  | プライベート   |  家事 |
| 仕事Aする | カンパニー  | プロジェクトA|
| 仕事Bする   | カンパニー    | プロジェクトA |
| 仕事Cする   | カンパニー    | プロジェクトB |
| 6/20に自治会出席 | プライベート  | 自分の時間 |
| 6/25に~歯医者に行く  | プライベート  | 自分の時間 |


### ボードの編集
ボードを作成する画面で以下のような設定を行います。
- Layout をTable
- Group by を中項目
- Slice by を大項目



![スクリーンショット 2024-06-15 12.06.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775049/9350859e-cd0d-d841-f755-3caaf89bb307.png)


すると以下のように表示されます。
![スクリーンショット 2024-06-15 12.07.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775049/5a5ada9b-f62d-eceb-0a49-4fbd343af11b.png)
これで大項目、中項目にタスクを分けることができました。

### 実際の運用例
大項目はCategoryと設定しています。
中項目はプロダクト名を使用しています。

![スクリーンショット 2024-06-15 12.09.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775049/5f54ba12-92d4-8e88-a52e-3ef4204189fc.png)


## まとめ
いかがでしたでしょうか。
実際の運用ではこのように大項目は環境、中項目はプロダクト名で分けています。
これに至った経緯はGoogle Cloudで基盤を構築していると
必ずプロダクトに分類される&抽象のレベルが同じになるためです。
ぜひ会社にあった大項目、中項目を分けて運用してみてはいかがでしょうか？
弊社ではアジャイル開発に興味のある方やエンジニアの募集を行っています。
GitHub Projects に関することや、採用に関するお問い合わせも、どうぞお気軽にご連絡ください。
TypeScriptでオブジェクトのプロパティを型定義に利用する場合には`undefined`が含まれる

めちゃくちゃ基本的なことですが…知らないとある時に「え？」となります。

:::note
TypeScriptを書き始めて時間が経っていない人に届くと嬉しいな…
という記事です！
:::

## TypeScriptでオブジェクトのプロパティを型にする時に何故か入ってくる`undefined`はなに？
結論を端的に言うと「予期せぬエラーを防ぐため」です！

:::note alert
[サバイバルTypeScript](https://typescriptbook.jp/)は一読していますが、細かいことまで覚えられてなかったことが発覚したのはいうまでもありません…
:::

TypeScriptは、オブジェクトのプロパティに安全にアクセスでき、存在しない場合にエラーを防ぐことを目的に`undefined`を返すように設計されています！

実際のコードを見ながら説明します。

```typescript
type MyObject = {
  name?: string
  age?: number
}

type Props = {
  firstName: MyObject['name'];
};
```

上記の`firstName`の型は`string`と`undefined`を受け付ける型になります。

:::note
`MyObject`のnameが任意ではなく、必須のプロパティである場合の`firstName`の型は`string`のみを許容する型になります。
:::

## まとめ
TypeScriptを業務で使い始める前に[サバイバルTypeScript](https://typescriptbook.jp/)は一通り確認してますが、漏れているところその時には理解できてなかった部分が多いと感じるこの頃です…。

:::note
これからTypeScriptを始める人や始めたばかりの人にとって「そうだったんだ！」という気づきを与えられる記事を投稿していければと思います！
:::
【GCP】Cloud Tasksのリトライ（再試行）ポリシーについて


業務において、GCPのCloud Tasksにおける設定方法や確認方法を学んだため、備忘として整理します。

## Cloud Tasksとは？
Cloud Tasksは、GCPが提供するフルマネージドサービスで、アプリケーションが非同期タスクを実行・管理できるようにします。これにより、バックグラウンド処理を効果的に行い、システムのスループットと応答性を向上させることができます。

[公式ドキュメント：Cloud Tasks のドキュメント](https://cloud.google.com/tasks/docs?hl=ja)

## リトライポリシーとは？
リトライポリシーは、タスクが失敗した場合に再試行するための定義・設定のことです。具体的な設定内容は以下の通りです。

#### ①最大試行回数（`MAX_ATTEMPTS`）　
- タスクが再試行される最大回数を設定する。
 　例：`MAX_ATTEMPTS`: 5の場合、タスクが失敗すると最大で5回まで再試行される。
    
#### ②最小バックオフ（`MIN_INTERVAL`）
- 再試行の間隔の最小値を設定する。
 　例：`MIN_INTERVAL`: 10の場合、最初の再試行は少なくとも10秒後に行われる。

#### ③最大バックオフ（`MAX_INTERVAL`）
- 再試行の間隔の最大値を設定する。
 　例：`MAX_INTERVAL`: 300の場合、再試行間隔は最大で300秒（5分）まで増加する。

#### ④最大倍増回数（`MAX_DOUBLINGS`）
- 再試行間隔が倍増する最大回数を設定する。
 　例：`MAX_DOUBLINGS`: 5の場合、再試行間隔は5回まで倍増。それ以降は最大バックオフ値に達する。

#### ⑤最大試行時間（`MAX_RETRY_DURATION`）
- タスクが再試行される総時間の上限を設定する。
 　例：`MAX_RETRY_DURATION`:172800s（48時間）の場合、タスクの再試行総時間は48時間となる。

[公式ドキュメント：再試行パラメータの設定](https://cloud.google.com/tasks/docs/configuring-queues?hl=ja#retry)

## 何のためにリトライポリシーを設定するの？

リトライポリシーを設定する主な目的は、以下の通りです。

##### 1. 信頼性の向上
- タスクが一時的なエラーや障害から回復するために再試行を行うことで、システム全体の信頼性を高めることができる。

##### 2. リソースの効率的な利用
- 過剰な再試行を防ぎ、システムリソースの無駄な消費を抑えることで、効率的なリソース管理が可能になる。

##### 3. パフォーマンスの最適化
- 再試行間隔を適切に設定することで、タスクの完了時間を最適化し、システムのパフォーマンスを維持する。

## リトライポリシーの設定方法について
##### queue.yamlファイルの作成
まず、リトライポリシーを設定するために、以下のようなqueue.yamlファイルを作成します。
```
queue:
- name: task-queue
  rate: 1/s
  bucket_size: 10
  retry_parameters:
    max_attempts: 5               # 最大試行回数（MAX_ATTEMPTS）
    min_backoff_seconds: 10       # 最小バックオフ（MIN_INTERVAL）
    max_backoff_seconds: 300      # 最大バックオフ（MAX_INTERVAL）
    max_doublings: 5              # 最大倍増回数（MAX_DOUBLINGS）
    max_retry_duration: 172800s   # 最大試行時間（MAX_RETRY_DURATION）
```
##### 設定項目の反映
queue.yamlファイルを作成した後、以下のコマンドを使用し、設定内容をデプロイします。
```
gcloud app deploy queue.yaml
```

[公式ドキュメント：queue.yaml リファレンス](https://cloud.google.com/appengine/docs/legacy/standard/python/config/queueref?hl=ja)
※[retry_parameters]を設定しない場合のデフォルト値についても上記ドキュメントに記載有
## リトライポリシーの確認方法について
以下の手順に則り、GCPコンソールからリトライポリシーを確認することができます。

##### 1. Google Cloud Consoleにログイン
- Google Cloud Consoleにアクセスしてログイン。

##### 2. Cloud Tasksのページに移動
- ナビゲーションメニューから「Cloud Tasks」を選択。

##### 3. 該当のキューを選択
- 設定を確認したいタスクキューをクリック。
- [構成]タブを押下でリトライポリシーの設定を確認することができる。

## まとめ
- リトライポリシーの設定は、システムの信頼性、効率性、パフォーマンスを向上させるために重要。
- 正しいリトライポリシーを設定することで、タスクが失敗した場合でも適切に再試行され、システムの安定性を保つことができる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762672/19962c08-d429-6ce9-1995-c0f9e74ade7e.png)
AtCoder練習2～白昼夢を様々な方法で～

# 白昼夢の問題
問題：英小文字からなる文字列 `S` が与えられます。 `T`が空文字列である状態から始め、以下の操作を好きな回数繰り返すことで `S=T` とすることができるか判定してください。

- `T` の末尾に `dream dreamer erase eraser` のいずれかを追加する。
-  `S`は英小文字からなる

詳しい詳細は[こちら](https://atcoder.jp/contests/abs/tasks/arc065_a)から

1\. **後ろから順に当てはめていく。**
- この問題のポイントは、Sの文字列を前から調べていくと、複数通りの選択が生じることです。例えば、`dreamer`と言う文字列が続いたときに、コレが`dreamer`の文字列でできているのか、それとも`dream+erase`などの造語かどうかを判断できないところです。それを回避するために、後ろの文字列から当てはめていくことが良さそうです。

```python
S = input()
# 逆順にする
S = S[::-1]

target = ["dream", "dreamer", "erase", "eraser"]
# 逆順にする['maerd', 'remaerd', 'esare', 'resare']
target = [x[::-1] for x in target]

index = 0
while(index < len(S)):
    found = False
    for t in target:
        if S[index:index+len(t)] == t:
            found = True
            index += len(t)
    if not found:
        break
if index == len(S):
    print("YES")
else:
    print("NO")
```
- found変数で途中で一致しないと分かったら、for文を抜け出すところがポイントです。途中で一致しないと分かったら、それ以降は無駄な計算です。

:::note warn
しかし、この問題は逆順に並び替えるとたまたま紛らわしさが消えるために実行できる方法です。他の手法を考えてみましょう。
:::

2\.  **動的計画法の利用**
# 動的計画法とは

動的計画法（どうてきけいかくほう、Dynamic Programming、略してDP）は、複雑な問題を解くためのアルゴリズムの一つです。初心者でも理解しやすいように、以下にその基本的な概念と使い方を説明します。

## 動的計画法の基本概念

1. **問題の分割**:
   - 複雑な問題を、より小さくて解きやすい部分問題に分割します。
   - 部分問題は、元の問題と同じ種類の問題であることが多いです。

2. **部分問題の解を再利用**:
   - 部分問題の解を保存しておき、同じ部分問題が再び現れたときに再計算するのではなく、保存しておいた解を使います。これにより計算量を大幅に削減できます。

3. **再帰的な解法**:
   - 部分問題の解を利用して、元の問題の解を得る方法を見つけます。

## 動的計画法の手順

1. **初期化**:
   - 最も小さな部分問題の解を設定します。これは通常、問題の基本的なケースです。

2. **部分問題の解を計算**:
   - 小さな部分問題から順に、より大きな部分問題の解を計算していきます。

3. **最終的な問題の解を得る**:
   - 全ての部分問題の解を組み合わせて、元の問題の解を求めます。


コレを今回の白昼夢の問題に置き換えてみると、
1．**部分問題の解を保存する**:

-文字列`S`は各位置までの部分文字列が指定された文字列で構成可能かどうかを保存しています。これにより、同じ部分問題を再度計算することを避けます。

2．**最適解を構築する**:

ある配列＝dp配列を使って、文字列全体が指定された文字列で構成可能かを段階的に確認します。

## 実装例 (Python)

```python
S = input()
target = ["dream", "dreamer", "erase", "eraser"]


# dp[i]は、Sの先頭からi文字までが指定された文字列で構成可能かどうかを示す
dp = [False] * (len(S) + 1)
dp[0] = True  # 空文字列は構成可能とする

# 文字列Sの各位置についてチェック
for i in range(len(S)):
    if not dp[i]:
        continue
    # divideリスト内の各文字列について
    for s in target:
        # Sの位置iから始まる部分文字列がsと一致するか確認
        if S[i:i+len(s)] == s:
            dp[i + len(s)] = True

# S全体が構成可能かどうかを返す
print("YES") if dp[len(S)] else print("NO")
```

:::note
無事に動的計画法を用いて実行できました。こちらの方法は、解法１に比べて、計算時間はかかるものの、前から順に文字列の一致を調べることができています。また、間違った文字列の生成をしてしまったとしても、途中で気づけるところにあります。気持ちいいですね。
:::

## こちらを参考にさせていただきました
- https://qiita.com/259_Momone/items/991d31ccc1f830a1d578#%E7%AC%AC-9-%E5%95%8F--abc049c---%E7%99%BD%E6%98%BC%E5%A4%A2--daydream
無知の知を得るのは難しい

# 無知の知って？
「自分が何も知らないことを知っている」という状態のこと。
全く知らないことを私達は検索することはできませんよね？
例えば私達は全く知らない学問について検索することができません。
たまたま目にしたり、誰かが教えてくれることで初めて知ることができます。

# 体験談

## Git
自分はプログラミングを初めたてのころはバージョン管理という概念そのものを知りませんでした。
皆さんの中にも同じような経験を持っている人がいるのではないでしょうか？
なんか使いづらいし... ブランチを切るって何？ そんな状態から、Gitを使いこなせるようになるまでには確かに時間はかかりました。
しかし、今ではGitを使わない開発は考えられません。

# どうやって解決しよう？

## 先輩に聞く
一般的な方法としては*先輩のエンジニアさん*から聞くことです。
その際は具体的な使い方を聞くのはあまり重要ではありません。どんな風使われているかや業界での立ち位置をを知ることが重要です。
あとはそれを知ったら自分で本を読んだり、実際に使ってみましょう。

近くに聞く人がいない場合はChatGPTやWindowsのCopilotなどのAIを使ってみるのもいいかもしれません。

## 本を読む
本を読むことも一つの方法です。
本の中でこの分野についてはこの本も参照されたい、というような記述があることがあります。
これらをはしごすることで、自分の知識を広げることができます。

# 注意点

質問するときは謙虚に、尊敬する気持ちを持って質問しましょう。
せっかく教えてもらえるのですから、感謝の気持ちを忘れずに！
闘魂Elixir ーー AtCoder Beginner Contest 351(B)をElixirで楽しむ

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>

<b><font color="red">$\huge{闘魂とは己に打ち克つこと。}$</font></b>
<b><font color="red">$\huge{そして闘いを通じて己の魂を磨いていく}$</font></b>
<b><font color="red">$\huge{ことだと思います}$</font></b>


# はじめに

[AtCoder Beginner Contest 351](https://atcoder.jp/contests/abc351)を[Elixir](https://elixir-lang.org/)で解いてみます。

[AtCoder](https://atcoder.jp/)を解くのが趣味で、休憩時間に解いているという若い人がいて、それってすごい意識の高い休憩時間の過ごし方だと思って、私も真似してみることにしました。


# [AtCoderをElixirでやってみる](https://zenn.dev/torifukukaiou/articles/ac84c87736ceebf4da01)

入力の読み取り方や解答の作り方は、別の記事にまとめています。


https://zenn.dev/torifukukaiou/articles/ac84c87736ceebf4da01

ご参照くださいませ。

[Elixir](https://elixir-lang.org/)で[AtCoder](https://atcoder.jp/)を楽しむためには、エントリポイントを`Main.main/0`にする必要があります。つまり`Main`モジュールを作って、その中に`main/0`関数を定義するわけです。

# [B - Spot the Difference](https://atcoder.jp/contests/abc351/tasks/abc351_b)

問題はリンク先をご参照くださいませ。
私の解答を貼っておきます。


<details><summary>私の解答</summary>

_問題文を読んでいることを前提にひとこと解説をしておきます。_

条件を満たした場合には計算（評価）を打ち切ってよいので、解法の骨格には、[Enum.reduce_while/3](https://hexdocs.pm/elixir/Enum.html#reduce_while/3)を使えばよいでしょう。


```elixir
defmodule Main do
  def main do
    n = IO.read(:line) |> String.trim() |> String.to_integer()
    
    a_grid = build_grid(n)
    b_grid = build_grid(n)
    
    solve(a_grid, b_grid, n)
    |> IO.puts()
  end
  
  def solve(a_grid, b_grid, n) do
    indexes = for i <- 1..n, j <- 1..n, do: {i, j}
    
    indexes
    |> Enum.reduce_while(nil, fn {i, j}, nil ->
      if a_grid[{i, j}] == b_grid[{i, j}], do: {:cont, nil}, else: {:halt, "#{i} #{j}"}
    end)
  end
  
  defp build_grid(n) do
    for i <- 1..n do
      IO.read(:line)
      |> String.trim()
      |> String.to_charlist()
      |> Enum.with_index(1)
      |> Enum.map(fn {c, j} -> {{i, j}, c} end)
    end
    |> List.flatten()
    |> Map.new()
  end
end
```




</details>




---

# さいごに

[AtCoder Beginner Contest 351](https://atcoder.jp/contests/abc351)を[Elixir](https://elixir-lang.org/)で解くことを楽しみました。

あなたのお好きなプログラミング言語でお楽しみください。

---


**闘魂**とは、  **「己に打ち克つこと。そして闘いを通じて己の魂を磨いていくことである」** との猪木さんの言葉をそのまま胸に刻み込んでいます。
知っているだけで終わらせることなく、実行する、断行する、一歩を踏み出すことを自らの行動で示していきたいとおもいます。
**アントニオ猪木さんのメッセージから元氣をもらったものとして、それを次代に語り継ぎ、自分自身が「闘魂」を体現するものでありたいとおもいます。**

---

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>
<b><font color="red">$\huge{１、２、３ ぁっダァー！}$</font></b>
噂の「DreamMachine」で生成AI動画を無料で作成してみた！

# はじめに
生成AIは様々な分野で活用されています。  
私自身、AWSのBedrockを利用し、LLM（Large Language Models）を用いた生成AIを活用してアプリに画像を表示する機能を実装した経験があります。  
このシステムでは、ユーザーがテキストを入力すると、対応する画像が表示されるというものです。

ITエンジニアがこのような生成AIを駆使することは非常に重要です。  
現場で生成AIを利用したシステムの構築が進んでいる例もあり、常に最新のAI技術情報を把握しておくことが、業務において大きなアドバンテージとなります。


今回は、話題の「DreamMachine」を無料で使ってみました！

https://lumalabs.ai/dream-machine

# 使ってみた
[URL](https://lumalabs.ai/dream-machine)をクリックして「try Now」をクリックした後に、サインアップを行います。  
無料枠なので、数に制限があります。
>Due to high demand, we are temporarily limiting free tiers to 10 generations/day. Paid tiers have no limit and priority in the queue.

![スクリーンショット 2024-06-15 11.25.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263017/de348c97-2e7b-8e19-58f4-abcde183442a.png)

サインアップ後、画像を添付したり、文字を入力することで、動画を生成できます！
![スクリーンショット 2024-06-15 11.28.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263017/7785288d-0d3a-b31d-76ea-b239e40dd99f.png)

生成が完了した後は、下記に表示されます。
![スクリーンショット 2024-06-15 11.35.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263017/62e2c159-5755-a952-2a1f-f23b662848de.png)

生成された動画をご覧ください！添付画像の猫が動いている動画を見て、驚かされました！
![ezgif-4-781cf64164.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263017/85af8ef6-4698-0f3e-bb58-7826276efc4a.gif)

他にも作ってみました！
![ezgif-4-fd128f7634.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263017/bd9d8284-dcd6-8f49-b59e-11caccc5bdd8.gif)

# さいごに
この技術は本当に素晴らしいですね！今後の進展が楽しみです🙌
コマンドでAWS EKS のクラスターを作ろう

# 前提条件

- AWSアカウント
- AWS CLI
- kubectl
- eksctl

# 本編

::: note warn
この記事では料金が発生するので使い終わったらクラスターを削除してください。
その方法を最後に記載しています。
:::

## クラスターを作ってみよう

```Bash
eksctl create cluster --name 好きな名前 --nodes-min=インスタンスの数 --region 好きなリージョン
aws eks --region 好きなリージョン update-kubeconfig --name 好きな名前
```
上記のようなコマンドを実行すると、EKSクラスターが作成されます。


私は以下のようにコマンドを実行しました。
ここでは、クラスター名をsampleService、ノード数を2、リージョンをus-west-2に設定しました。
```Bash
eksctl create cluster --name sampleService --nodes-min=2 --region us-west-2
```
::: note warn
クラスターの作成には15分程度かかります。
クラスターが完成したら次のコマンドを実行してください。
:::


次にこのコマンドでkubectlにEKSクラスターに接続させます。
--region --nameには先ほどと同じ値を入力してください。
```Bash
aws eks --region us-west-2 update-kubeconfig --name sampleService
```

Added new context arn:aws:eks:us-west-2:~~~
このようなメッセージが表示されればOKです。

## ダッシュボードを確認しよう

このようにステータスがアクティブになっていればOKです。
![active.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288957/258a4f14-2a2f-c1f8-34db-ff61b7db6653.png)

## クラスターを消そう

```Bash
eksctl delete cluster --name 好きな名前
```

自分はsampleServiceというクラスターを作成したので、以下のようにコマンドを実行しました。
```Bash
eksctl delete cluster --name sampleService
```
STM32CubeIDEのBuild Analyzerが表示されないことの対策

いつからか...は定かではありませんが、STM32CubeIDEをアップデートしてから`Build Analyzer`のメモリ使用量が表示されなくなりました。

STのコミュニティサイトに対策が記載されていました。
[Build Analyzer does not work after STM32CubeIDE update.](https://community.st.com/t5/stm32cubeide-mcus/build-analyzer-does-not-work-after-stm32cubeide-update/td-p/652218)

アップデート後、手動で更新する設定に変更されるようです。
![スクリーンショット 2024-06-15 11.27.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/60c427b6-37ff-8b6d-d463-f80c955a87e5.png)


これを自動に戻せばいいです。
![スクリーンショット 2024-06-15 11.29.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/966c23c3-705a-52f8-76cd-b496a04c0182.png)
2回目のチーム開発振り返り

## はじめに
[アプレンティス](https://apprentice.jp/)というエンジニアになるための実習に4期生として参加しています。
カリキュラムの中で2回のチーム開発があって、今回はその2回目のチーム開発が終わったので、その振り返りの記事を書きました。

## 作ったもの
![チーム丑のアプリ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547640/5ce3f052-4ed4-6bb3-00d9-57f885b86cad.gif)

今回のテーマは「ワクワクするもの」でした。  
チームで「どうしたらユーザーにワクワクしてもらえるか？」何度も話し合いました。 

「休みの日いつも同じでつまんないな」と思ったことはないですか？  

サイトは情報量多すぎるし、SNSは疲れるし、「もうちょっとシンプルになんかアイデア出してくれるのないかな？」

そんな人向けのアプリです。

今のところは時間指定でアイデアがランダムで出てくるようになっていますが、「MBTI診断の性格ごとにアイデアを出す」とかも考えていました。


## やったこと
おもに環境構築とバックエンドを担当しました。
バックエンドは超シンプルで大したことはやってないです。
Dockerで環境構築したのがいちばん学びが大きかったです。

- アイデア出しでたくさんアイデア考えた。自分が考えたのは自分の書いたコードを説明する練習用のアプリ。チーム内投票で最下位だったので不採用になった😂
- Dockerで環境構築した。docker-composeでrailsコンテナとMySQLコンテナ立ち上げた
- devcotainer使って環境構築した
- 早く終わったら他のチームメンバーの担当を巻き取って行った(フロントのビューにCSS当てる)
- プレゼン前の動作確認で発見したバグを修正した(本来飛ばしたいページに遷移しないので、Javascriptで前のページのドロップダウンメニューで選択した項目ごとに遷移先を変える処理を追加した)
- メインの機能である、休日の過ごし方アイデアを取得する処理を書いた(ideasテーブルからランダムに取得)

## よかったこと
- 他の人が実装したところで理解できないところはわかるまで聞いた。自分の理解が合っているか確認して、足りないところや間違っているところを教えてもらった
- Dockerでの環境構築で書いたコードをチームメンバーに説明して、READMEにドキュメントを残して共有した
- コンテナ内でエラーが起きたときにdocker logsでログ見て解決できた
- Railsのコントローラに自分でメソッドをつくって機能させることができた。ビューからコントローラにデータを受け渡せることもわかった

## もっとやれたら良かったこと
- プロジェクトの進捗管理を他のメンバーに頼ってしまった
- プレゼンが近づいてきて焦ってくると、やや他のメンバーに対して口調がキツくなってしまったので、もっとソフトな伝え方ができればよかった
- 自分が書いたimportmapの部分やdevcontainerで生じたエラーについて聞かれたときに十分な説明ができなかった
- 既存のrailsに途中からBoostrapを導入しようとしたが、どうしてもエラーが解決できず結局rails newのオプションで作り直してうまくいくも、Docker環境のエラーが解決できず断念した。環境構築のスコープにCSS, Javascriptが反映されるところまで含めるべきだった
- エラーが起きたときにGitHubのissueにあげたが、正直あまり機能してなかった

## 課題
- 特にimportmapのところで、そう設定すれば一応Javascriptが動くものの、なんでそうなるのか、何をしているのか説明できない＝理解できてない
- 調べて記事を見つけてきて、そこに書いてあるコードを用いて一応動くが説明できないのがまだまだある。おおよそ何してるのかはわかっても、ひとつひとつが何してるのかがわかってないから、次同じことやるときに何も見ないで書けない。チームメンバーに聞かれたとき説明で詰まる
- 何も見ないで書けるコードが少ない。理解してないのもあるが、他の記事や公式ドキュメント見ないと安心できない

## 振り返り
1回目のチーム開発よりたくさんコミュニケーション取れたのがよかったです。

前回のチームでは必要最小限の時間だけ会議してましたが、今回は雑談もたくさんして、そのおかげか納得いかないところや理解できてないところは流さず何回も聞きました。

Dockerのところは自分が書いたところを説明しました。

雑談したほうが関係性もより深まるし、チームとしての一体感も高まるなと感じました。
【Figma Plugins】Figma Pluginsでページ遷移をする

## はじめに
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/4dc0c595-aa41-8311-6510-7f50f3f0fc28.png)

FigmaのPluginを開発する際、複数のHTMLファイルを用意して、画面遷移させたいなと思ったことはありますか？
そんな時に使うのが「**showUI**」という関数です。

この記事では、そんな「**showUI**」について解説しようとな思います。

 ## showUIとは？
showUI 関数は、Figma側のプラグインに表示されるUIをレンタリングしたり、ブラウザのAPIにアクセスすることができる関数です。

showUI 関数は、以下のように 引数の`html`で指定されたHTMLを`<iframe>`として生成します。

```ts
figma.showUI(html: string, options?: ShowUIOptions)
```

optionsには、以下の指定することができます。

- **visible**：UIがユーザーに表示されるか
    - デフォルト：`true`
    - `figma.ui.show()`と`figma.ui.hide()`を使うと表示を変更することができる
- **width**：UIの幅を決めることができる
    - デフォルト：`300`
    - 最小：`70`
    - `figma.ui.resize(width, height)`を使うと変更することができる
- **height**：UIの高さを決めることができる
    - デフォルト：`200`
    - 最小：`0`
    - `figma.ui.resize(width, height)`を使うと変更することができる
- **title**：UIウィンドウのタイトル
    - デフォルト：プラグインの名前
- **position**：UIウィンドウの位置
    - デフォルト：iframeの最後の位置またはビューポートの中心
- **themeColors**：CSS変数を使うか
    - デフォルト：`false`
    - light theme と dark theme を使うことができる

これらのOptionsを使うと以下のようになります。

```ts
figma.showUI(
    __html__,
    {
        width: 400,
        height: 400,
        title: "sample",
        position: { x: 100, y: 100 },
        themeColors: true,
    }
);
```

## 特定のHTMLファイルを生成する
puluginを生成していると複数のHTMLを作成して、特定のタイミングで、HTMLファイルを表示したいということがあると思います。
このセクションでは、その方法を紹介します。

### ① HTMLファイルを生成する
HTMLファイルを生成する場所は、pluginのフォルダー内であれば、指定はありません。

今回は、uiフォルダを新しく作って、uiフォルダ内にHTMLファイルを作ろうと思います。

イメージは以下の通りです。

```
📁 sample_plugin
　　　　　　┗ 📁 ui
　　　　　　　　　　　　┣ 📄 main.html
　　　　　　　　　　　　┗ 📄 sub.html
```

### ② HTMLファイルを呼び出せるようにする
HTMLファイルを生成したら、HTMLファイルを呼び出せるようにします。
HTMLファイルを呼び出せるようにするには、`manifest.json` を編集します。

```diff_json
{
-  "ui": "ui.html"
+  "ui": {
+    "main": "ui/main.html",
+    "secondary": "ui/secondary.html    
+  }
}
```

`manifest.json`の "ui"の部分を上記のように
`"名前": "呼び出すHTMLファイル・パス"` を記述することで、HTMLファイルを呼び出せるようになります。

### ③ HTMLファイルを表示させる
HTMLファイルを表示させるには、上記で書いたように`showUI`関数を使います。

そして、`__uiFiles__` というGlobal Objectsをつかい以下のように指定することで、HTMLファイルを表示させることができます。

```code.ts
// main を表示したい時
figma.showUI(__uiFiles__.main);

// secondary を表示したい時
figma.showUI(__uiFiles__.secondary);
```

上記のように、`__uiFiles__.〇〇` とすることで、`manifest.json`の "ui"の部分で記述したファイルを生成することができるようになります。

## まとめ
この記事では、「showUI」関数について紹介しました。
「showUI」関数は、FigmaのpluginのHTMLファイルを表示させる関数です。

---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaで記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510