OmniAICreator/Qiita-1.07M huggingface dataset:
transformers向け系列ラベリングクラスRwkvForTokenClassificationを書いてみた

RWKVのトークナイザで[イライラしていた](https://qiita.com/KoichiYasuoka/items/bb5ff11b3e26c5475770)はずなのに、イキオイ余ってRwkvForTokenClassificationを書いてしまった。

```
from typing import List, Optional, Tuple, Union
import torch
from torch import nn
from transformers.modeling_outputs import TokenClassifierOutput
from transformers.models.rwkv.modeling_rwkv import RwkvModel, RwkvPreTrainedModel

class RwkvForTokenClassification(RwkvPreTrainedModel):
    def __init__(self, config):
        super().__init__(config)
        self.num_labels = config.num_labels
        self.rwkv = RwkvModel(config)
        if getattr(config, "classifier_dropout", None) is not None:
            classifier_dropout = config.classifier_dropout
        elif getattr(config, "hidden_dropout", None) is not None:
            classifier_dropout = config.hidden_dropout
        else:
            classifier_dropout = 0.1
        self.dropout = nn.Dropout(classifier_dropout)
        self.score = nn.Linear(config.hidden_size, config.num_labels)

        # Initialize weights and apply final processing
        self.post_init()

    def get_input_embeddings(self):
        return self.rwkv.embeddings

    def set_input_embeddings(self, new_embeddings):
        self.rwkv.embeddings = new_embeddings

    def forward(
        self,
        input_ids: Optional[torch.LongTensor] = None,
        attention_mask: Optional[torch.LongTensor] = None,  # noqa
        inputs_embeds: Optional[torch.FloatTensor] = None,
        state: Optional[List[torch.FloatTensor]] = None,
        labels: Optional[torch.LongTensor] = None,
        use_cache: Optional[bool] = None,
        output_attentions: Optional[bool] = None,
        output_hidden_states: Optional[bool] = None,
        return_dict: Optional[bool] = None,
    ) -> Union[Tuple, TokenClassifierOutput]:
        return_dict = return_dict if return_dict is not None else self.config.use_return_dict

        rwkv_outputs = self.rwkv(
            input_ids,
            inputs_embeds=inputs_embeds,
            state=state,
            use_cache=use_cache,
            output_attentions=output_attentions,
            output_hidden_states=output_hidden_states,
            return_dict=return_dict,
        )
        sequence_output = rwkv_outputs[0]
        sequence_output = self.dropout(sequence_output)
        logits = self.score(sequence_output)

        loss = None
        if labels is not None:
            labels = labels.to(logits.device)
            loss_fct = nn.CrossEntropyLoss()
            loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1))

        if not return_dict:
            output = (logits,) + rwkv_outputs[1:]
            return ((loss,) + output) if loss is not None else output

        return TokenClassifierOutput(
            loss=loss,
            logits=logits,
            hidden_states=rwkv_outputs.hidden_states,
            attentions=rwkv_outputs.attentions,
        )
```

基本的なところは、半年前の[Pull Request](https://github.com/huggingface/transformers/pull/29878)を踏襲している。ただ、RWKVが固有表現抽出や品詞付与に向いているのかどうか、正直あまり自信がない。私(安岡孝一)個人としても、RwkvLinearAttentionまわりをちゃんとファインチューニングできるかどうか、はなはだ心もとない。まあ、ちょっと悩んでみようかな。
ActiveRecordってなに？

Ruby on Railsでアプリケーションを作成していると、度々ActiveRecordという仕組みが出てきます。
Tweet.allやTweet.saveなど、モデルに対してメソッドを使ってテーブルを操作できるものという解釈で使用しており、あまり詳しく踏み込んでいなかったので少し学んでみました。

## ActiveRecordとは
Railsガイドによると

:::note
ActiveRecordとは、MVCで言うところのM、つまりモデルの一部であり、データとビジネスロジックを表現するシステムの階層です。ActiveRecordは、データベースに恒久的に保存される必要のあるビジネスオブジェクトの作成と利用を円滑に行えるようにします。
:::

ちょっと難しいですが、モデルに搭載されていて、データベースとのやり取りを可能にしているシステムですということ。

本来、SQL文を書かないとデータベースのデータが扱えないところ、ActiveRecordというシステムによってTweet.allでtweetsテーブルのレコードが全て取得できる。

このActiveRecordのような仕組みをORM(オブジェクト/リレーショナルマッピング)と言う。
ORMの仕組みがない言語はSQL文でのデータベース操作が必要となる。

Tweet.saveやTweet.allなどイメージしやすく、Ruby on RailsはSQL文を知らなくても扱えるので初心者も学びやすいフレームワークである。

## ActiveRecordでできること
テーブルデータのCRUDだけでなく、マイグレーションやテーブル間のアソシエーションが組めるのもActiveRecordの機能によるもの。

命名規則などもActiveRecordの規約となっている。

## ActiveRecordを使うには
Railsアプリケーションを作成し、モデルファイルを生成した時点で利用できるようになっている。

モデルファイルを作成すると一番上に
```ruby
class Tweet(モデル名) < ApplicationRecord
```
と書かれている。これはTweetクラスをApplicationRecordの機能を受け継いだ子クラスとしている。
ApplicationRecordとは、Railsアプリケーションを新規作成した際にapp/models/application_record.rbと言うファイルが生成されている。
これを見ると、一番上に
```ruby
class ApplicationRecord < ActiveRecord::Base
```
と書かれて、ActiveRecord::Baseを継承している。
ActiveRecord::BaseはRailsが提供する基本機能を持ったクラスで、ActiveRecordが利用できるのも、このクラスがあるおかげである。

全ての機能をActiveRecord::Baseが持っている、そのクラスを継承したApplicationRecordが各モデルにActiveRecordの機能を提供している。

## データの保存がない場合
FormオブジェクトパターンやActiveHashを使用する場合は、ファイル上部にApplicationRecordを継承する記述は書かない。

Railsガイドの説明にも、**ActiveRecordは、データベースに恒久的に保存される必要のあるビジネスオブジェクトの作成と利用を円滑に行えるようにします。** とあるように、ActiveRecordはデータベースを作成するものに対してのみ使用する。

## まとめ
Railsアプリケーションはモデルが処理の根幹を担うため、ActiveRecordの機能の恩恵を受けているのだなと気付きました。
最終課題頑張ります！
Alma Linux 9.5にwine9.0をインストール

本記事ではAlma Linux 9.5にWine9.0を入れた備忘録として作成いたしました。

# 導入準備
### Wineをビルドするためのツールをインストール
#### リポジトリを有効化
```
# yum -y install epel-release
# yum config-manager --set-enabled crb
```

#### パッケージをインストール
```
# yum install -y samba-winbind-clients
# yum groupinstall 'Development Tools' -y
# yum install -y libxslt-devel libpng-devel libX11-devel zlib-devel libtiff-devel freetype-devel libxcb-devel  libxml2-devel libgcrypt-devel dbus-devel libjpeg-turbo-devel  fontconfig-devel gnutls-devel gstreamer1-devel libXcursor-devel libXi-devel libXrandr-devel libXfixes-devel libXinerama-devel libXcomposite-devel mesa-libOSMesa-devel libpcap-devel libusb-devel libv4l-devel libgphoto2-devel gstreamer1-devel libgudev SDL2-devel gsm-devel libvkd3d-devel libudev-devel wget
```

### 導入
#### wineのソースを入手して展開
```
# cd /usr/src
# wget https://dl.winehq.org/wine/source/9.0/wine-9.0.tar.xz
# tar xvf wine-9.0.tar.xz
```

### ビルド
```
# cd wine-*
# mkdir -p wine32 wine64

64ビット版をビルド
# cd wine64
# ../configure --enable-win64
# make

32ビット版をビルド
# cd ../wine32
# ../configure --with-wine64=../wine64
# make

32ビット版をインストール
# make install

64ビット版をインストール
# cd ../wine64/
# make install
```
【不正アクセス対策】NGINXのレート制限機能「limit_req_zone」

NGINXのレート制限は、サーバーのリソースを保護し、悪意のあるリクエストや過剰なトラフィックによるサービスの影響を防ぐために使用される機能です。以下は、NGINXのレート制限の主な特徴です：

---

### 1. **リクエストのレート制限**

- 特定の条件に基づいてリクエスト数を制限します。たとえば、IPアドレスごとに1秒あたりのリクエスト数を制限するなどが可能です。
- `limit_req_zone`ディレクティブを使って、リクエストレートを設定します。
  ```
  limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
  ```
  - `$binary_remote_addr`: クライアントIPをキーとして使用。
  - `zone=one:10m`: 制限のための共有メモリゾーンを定義。
  - `rate=1r/s`: 1秒あたり1リクエストを許可。

---

### 2. **バーストの許容**

- バースト（突発的なリクエストの増加）を許容する設定が可能です。
- バーストの値を指定することで、一時的な超過を許容しつつ、平滑化された処理が行われます。
  ```
  limit_req zone=one burst=5;
  ```
  - この例では、最大5件のリクエストを許容しますが、それを超えるとリクエストは制限されます。

---

### 3. **遅延処理（Delay）**

- バーストが許容される範囲内で遅延をかけることも可能です。
  ```
  limit_req zone=one burst=5 delay=3;
  ```
  - 遅延設定により、リクエストがスムーズに処理され、突然のトラフィック増加による影響を軽減できます。

---

### 4. **帯域幅の制限**

- レート制限だけでなく、帯域幅（転送速度）の制限も可能です。
- `limit_rate`ディレクティブを使用します。
  ```
  location /downloads/ { limit_rate 50k; # 50KB/sに制限 }
  ```

---

### 5. **HTTPレスポンスコードで通知**

- 制限を超えたリクエストには、デフォルトでHTTP 503（Service Temporarily Unavailable）を返します。
- `limit_req_status`ディレクティブでカスタムステータスコードを設定できます。
  ```
  limit_req_status 429; # Too Many Requests
  ```

---

### 6. **複数ゾーンの設定**

- 複数のゾーンを作成して、異なる条件でレート制限を適用することが可能です。
  ```
  limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=5r/s; limit_req_zone $server_name zone=server_limit:10m rate=10r/s;
  ```

---

### 7. **動的条件の適用**

- `$binary_remote_addr`や`$server_name`などの変数を利用して、動的に条件を定義できます。
- IPアドレスやリファラーヘッダー、特定のURLパスごとに異なる制限を適用できます。

---

### 8. **使いやすい拡張性**

- NGINX Plusでは、ダッシュボードを使ってリアルタイムで制限状況を監視したり、より詳細なカスタマイズが可能です。

---

### 注意点

- レート制限を過剰に設定すると、正当なユーザーの利用が妨げられる場合があります。
- 適切なリクエストレートやバースト値を設定するには、アプリケーションやトラフィックパターンを十分に理解する必要があります。

NGINXのレート制限は、柔軟性と高いパフォーマンスを提供し、セキュリティと安定性を強化する重要な機能です。
Entity Frameworkを使ってみた


## はじめに
Entity Framework（EF）を使ってデータベース操作を行う方法について紹介します。今回は、ユーザー情報を管理する簡単なサービスをSampleとして作成しました。

## コードの概要
以下に、ユーザー情報を管理するためのサービスクラス`UserInfoService`のコードを示します。

### モデルクラス
まず、ユーザー情報を表すモデルクラスを定義します。

```csharp
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace UserCreator.Models
{
    [Table("UserInfo")]
    public class UserInfo
    {
        [Key]
        public string UserId { get; set; }
        public string Status { get; set; }
        public DateTime CreatedDate { get; set; }
        public DateTime UpdatedDate { get; set; }
    }
}
```

### DbContextクラス
次に、`DbContext`クラスを定義します。

```csharp
using System.Data.Entity;

namespace UserCreator.Models
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext() : base("DBConnectionString")
        {
            Database.SetInitializer(null); // Disable automatic migration
        }

        public DbSet<UserInfo> UserInfos { get; set; }
    }
}
```

### サービスクラス
最後に、ユーザー情報を管理するサービスクラスを定義します。

```csharp
using System;
using System.Data.SqlClient;
using System.Linq;

namespace UserCreator.Models
{
    public class UserInfoService
    {
        private readonly ApplicationDbContext _context;

        public UserInfoService(ApplicationDbContext context)
        {
            _context = context;
        }

        public void UpdateUserInfoByFile(SampleUserCode sampleUserCode)
        {
            var user = _context.UserInfos.SingleOrDefault(u => u.UserId == sampleUserCode.UserId);
            if (user != null)
            {
                user.Status = "Active";
                user.UpdatedDate = DateTime.Now;
                _context.SaveChanges();
            }
        }

        public void InsertUserInfoByFile(SampleUserCode sampleUserCode)
        {
            var newUser = new UserInfo
            {
                UserId = sampleUserCode.UserId,
                Status = "Inactive",
                CreatedDate = DateTime.Now,
                UpdatedDate = DateTime.Now
            };
            _context.UserInfos.Add(newUser);
            _context.SaveChanges();
        }

        public UserInfo GetUserInfoWithNoLock(string userId)
        {
            var query = "SELECT TOP 1 * FROM [UserInfo] WITH(NOLOCK) WHERE UserId = @UserId";
            var userIdParam = new SqlParameter("@UserId", userId);

            return _context.UserInfos
                           .SqlQuery(query, userIdParam)
                           .SingleOrDefault();
        }
    }
}
```

## ポイント
`WITH(NOLOCK)`を使用する場合、生のSQLを書く必要があります。Entity FrameworkのLINQクエリでは`WITH(NOLOCK)`を直接指定することができないため、SQLクエリを直接記述して実行する必要があります。

## まとめ
Entity Frameworkを使用することで、データベース操作が簡単に行えるようになります。今回の例では、ユーザー情報の挿入、更新、および取得を行う方法を紹介しました。この記事が参考になれば幸いです。
GitHub基本操作

GitHubの基本操作を3つほど記載します。
私のような入門者の方がスムーズに操作できるよう、参考にしていただければ幸いです。

### 1. 新しい変更をリポジトリに追加してプッシュする手順
以下の手順で変更をステージングし、コミットして、リモートリポジトリに反映します。

```bash
git add .
git commit -m "コミットメッセージ"
git push origin "ブランチ名"
```

:sunny:解説
`git add .`
すべての変更ファイルをステージングエリアに追加します。
　※「.」はカレントディレクトリ以下のすべてのファイルを対象にします。

`git commit -m "コミットメッセージ"`
ステージングエリアに追加された変更をコミットします。
-mでコミットメッセージを指定できます。

`git push origin "ブランチ名"`
変更をリモートリポジトリの指定されたブランチにプッシュします。

### 2. 既存のコミットを修正して上書きプッシュする方法
既存のコミットを上書きしたい場合の手順です。
たとえば、誤ったコミットを修正したり、コミットメッセージを変更したいときに使います。

```bash
git add .
git commit --amend
git push origin -f "ブランチ名"
```

:sunny:解説
`git add .`
変更をステージングエリアに追加します（1の場合と同じ）。

`git commit --amend`
直前のコミットを修正します。
コマンド実行後、デフォルトのエディタが開き、コミットメッセージを編集できます。
ステージングした新しい変更も、このコミットに含めることができます。

`git push origin -f "ブランチ名"`
-f（フォースプッシュ）を指定して、リモートリポジトリの内容を上書きします。


### 3. develop ブランチを最新にする際の競合対処法
作業中のブランチで develop ブランチの最新状態を取り込みたいが、競合や作業内容が未コミットでPullできない場合の対処法です。

```bash
git stash
git checkout develop
git pull origin develop
git checkout "元のブランチ名"
git merge develop
git stash pop
```

:sunny:解説
`git stash`
現在の変更を一時的に退避させます。これにより、ブランチを移動しても作業内容が失われません。

`git checkout develop`
developブランチに移動します。

`git pull origin develop`
リモートリポジトリからdevelopブランチの最新状態を取得します。

`git checkout "元いたブランチ"`
元いた作業ブランチに戻ります。

`git merge develop`
developブランチの最新状態を作業ブランチにマージします。

`git stash pop`
一時的に保存していた変更を元に戻します。
※マージ後に競合が発生した場合は、手動で解決する必要があります。
Excelファイルを納品する

# はじめに
人様に収めるExcelファイルは特別な理由がない限り、全シートカーソルをA1にして先頭のシートを選択した状態にするかと思います。
また、外部ファイルの参照も値にしておく必要があります。

単純作業ではありますが、ファイル数、シート数が多いと地味に時間がかかります。
『フォルダ配下のファイルを一括で』は意図しないファイルが更新されるので追々作るとして、まずはアドインにしてみました。

# 全シートA1セルに移動する
```vb
Sub 全シートA1セルに移動()
    Dim wBook As Workbook
    Dim wSheet As Worksheet
    
    Set wBook = ActiveWorkbook
    
    For Each wSheet In wBook.Worksheets
        wSheet.Activate
        'カーソルをA1に移動
        Range("A1").Select
        
        'スクロールをA1に移動
        ActiveWindow.ScrollRow = 1
        ActiveWindow.ScrollColumn = 1
        
        '倍率を100%
        'ActiveWindow.Zoom = 100
    Next
    
    '先頭のシートに移動
    wBook.Worksheets(1).Activate
    
    Set wBook = Nothing
End Sub
```

# 外部ファイルの参照を値にする
```vb
Sub 外部ファイルの参照を値にする()
    Dim wBook As Workbook
    Dim objLink As Variant
    
    Set wBook = ActiveWorkbook
    
    'リンク箇所を取得
    objLink = wBook.LinkSources(xlExcelLinks)
    
    'リンクがある場合のみ処理する
    If IsArray(objLink) Then
        For i = 1 To UBound(objLink)
            'リンクを値に変更
            wBook.BreakLink Name:=objLink(i), Type:=xlLinkTypeExcelLinks
        Next
    End If
    
    Set wBook = Nothing
End Sub
```
30秒であなたの英語力を測定するサイトを作りました

## 概要
好きなトピックを選んで話すだけであなたの英語力を測定するサイトを作ってみました！
試してみてください🙏🙏

下記で技術的な構成の話をしています🙏🙏

https://www.rate-your-english.com/

![](https://storage.googleapis.com/zenn-user-upload/087937a90c34-20241108.png)

## 技術的な話

### 全体構成

情報量少なめになりますが、ざっくり下記のような全体構成で作成しております。
サーバーレスなサービスたちで大体やりたいことはできるので便利ですね！

![](https://storage.googleapis.com/zenn-user-upload/820559a83373-20241108.png)

### フレームワーク(Next.js)

仕事でも使い慣れているNextを使用しましたが初めてAppRouterを活用しての実装となりました。こちらもある程度概念を理解してからであれば問題なく開発することができました。



https://nextjs.org

### デザイン(Tailwind)

なかなか重い腰が降りなかったのですが、初めてtailwindを使用してみました。
意外と慣れると抵抗なくサクサクデザインができたので今後の個人開発ではどんどん活用していこうと思います！


https://tailwindui.com/

### V0

Vercelの出しているv0をデザインのアイデアに使用しました！
ちょっとあまりに画期的すぎて泣きました。

https://v0.dev/
11/16 tecHub（LT&トークセッション＋懇親会）を開催しました！

![image_241116_03.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670233/e2f1fb2e-890f-ed50-f37d-ee3d9b661360.jpeg)

今回のtecHubはLTだけでなく、キャリアアップとフリーランスについてトークセッションを行いました。
実際に異業種からシステムエンジニアへ転職経験談や、フリーランスへ転向した話など、今後エンジニアとしてどう働いていくか参考になる話が盛り沢山でした。

**目次▼**
<INS>[2024年11月のtecHubを開催しました！](#2024年11月のtechubを開催しました)</INS>
<INS>[キャリアを考えるトークセッション](#キャリアを考えるトークセッション)</INS>
<INS>[tecHubは毎月イベント開催しています！](#techubは毎月イベント開催しています)</INS>
<INS>[参加者の声](#参加者の声)</INS>
<INS>[次回の開催](#次回の開催)</INS>

<h3>2024年11月のtecHubを開催しました！</h3>

![image_241116_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670233/3d05650c-69d5-861b-c2b7-8db5e8b266ce.png)

11/16にtecHubを赤坂見附で開催しました。
参加者は64名となり、大盛況でした。

日付：11/16(土)　14:00～17:00
場所：SOCIAL SPACE 赤坂
参加者：64名
内容：LT&トークセッション、懇親会

<h3>キャリアを考えるトークセッション</h3>

![image_241116_03.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670233/e2f1fb2e-890f-ed50-f37d-ee3d9b661360.jpeg)

今回初めての試みだったトークセッション。
会社員で経験を積み、フリーランス、そして法人化までしているエンジニアの体験談は、お互いに刺激し合う会になりました！

**次の5つのトークテーマからキャリアアップとフリーランスについての話が盛り上がりました。**
将来のキャリアを考えるエンジニアなら、誰もが聞きたい内容でした。

1.キャリアアップについて

2.収入アップについて

3.フリーランスのメリットデメリット

4.フリーランスのなり方と案件獲得

5.キャリアビジョンの描き方

**フリーランスになり収入がアップした話、会社員の間に経験しておくべき業務、フリーランスのメリットだけでなくデメリットを感じた体験談など、他では聞けない話ばかりでした。**

また、今後プログラミングでAIに勝つことはできない。
しかし、AIと上手く共存していくことと、AIにできないリアルなコミュニケーションが大事だと、プログラミング歴約40年の熟練エンジニアが話していました。

<h3>tecHubは毎月イベント開催しています！</h3>

毎月60〜80名ほどの方が参加している人気のイベントです。

3ヶ月に1度：LT（ライトニングトーク）と懇親会の2部構成イベント
その他：リアルでIT交流会イベント

LT＋懇親会では、前半は「働き方」をテーマにLT、プレゼンテーションを、後半は懇親会で自由に交流の時間を設けています。
LTでは、外部スピーカーをゲストに招くこともあります。

懇親会にはスピーカーも参加し、発表内容をさらに掘り下げてディスカッションすることも可能です！
色々な方が自由に意見・情報交換をできる場となっています。

<h3>参加者の声</h3>

![image_241116_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670233/def380f4-9e47-5ba8-7ea3-e9f2aa1a594d.png)

今回も幅広い分野のIT関係者が集まり、会社員からフリーランス、法人化まで様々なエンジニアが参加していました。

懇親会では参加者一人一人の実体験から来る仕事の話で盛り上がり、参考になる話を聞ける時間でした。
「今後のキャリアをどうするか？」考えている話も多かったです。
幅広い分野と様々なキャリアの話は、異なる視点や考え方を知る機会になっているようでした。

参加者からは、
**「参加してよかった」
「転職やフリーランス転向などキャリアアップを考えるきっかけになった」
「自分にとって身近な体験談を聞くことができた」**
などの声をいただいています。

tecHubは、今後も毎月イベントを開催していきます。
**他にもITエンジニアがより活躍し、理想のキャリアを切り拓けるように、tecHubはコミュニティサイトも始めました。**
会社員、フリーランス、法人の方向けに、オフラインコンテンツと人脈形成の機会を提供しています。

https://www.navi56.com/communities/tecHub

<h3>次回の開催</h3>

日時：12/14(土)　14:00～16:30
場所：LIFORK 大手町
内容：IT交流会

詳細とお申込みは、上記のコミュニティサイトからご確認お願いします。
※イベントの申込みは、tecHubコミュニティに参加後にサイト内の"イベント検索"から「12/14tecHub (IT交流会)」を検索してお申込みください。
AWS_冗長化(ロードバランサー、S3、CDN等について)

## はじめに

AWSを学び始めて、VPCやサブネット、インターネットゲートウェイの基礎を理解した上で、さらに深堀りし、AWSの他のサービスであるロードバランサーやS3、CDNなどについても学習しました。これらのサービスは、冗長化し負荷分散が可能です。本記事では、これらの内容を詳しく説明し、AWSのインフラ構築における役割を紹介します。

イメージしやすいように構成図を添付します。
![スクリーンショット 2024-11-19 22.19.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3933685/6e7fd0ec-c880-90f0-12bd-880f1fdafcb0.png)


## ロードバランサー (Load Balancer)

ロードバランサーは、トラフィックを複数のサーバー（インスタンス）に分散させ、システム全体の負荷を均等にする役割を持つサービスです。これにより、1つのサーバーに負荷が集中することを防ぎ、システムの可用性とスケーラビリティを高めます。

### ロードバランサーの役割

- **負荷分散**：ユーザーからのリクエストを複数のインスタンスに分散し、システム全体のパフォーマンスを向上させます。
- **冗長化と高可用性**：複数のアベイラビリティゾーンにまたがって配置されたインスタンスにトラフィックをルーティングすることで、1つのゾーンに障害が発生しても他のゾーンでサービスを維持できます。
- **スケーラビリティ**：自動的にトラフィックを処理するインスタンスを追加・削除することで、リクエストの増減に応じて柔軟にスケールします。
- **名前解決**：ロードバランサーはリクエストを適切なターゲットに振り分ける際にDNSを活用し、リソースの名前解決を行います。
- **SSL/TLS終端**：HTTPS通信の暗号化と復号をロードバランサー側で処理し、インスタンス側の負荷を軽減します。

## S3 (Simple Storage Service)

S3は、AWSが提供するオブジェクトストレージサービスで、データの保存と管理に使用されます。大量のデータを冗長化された環境に格納し、可用性と耐久性を備えています。

### S3の特徴

- **高耐久性**：99.999999999%（11 9’s）の耐久性を提供し、データの喪失をほぼ防ぎます。
- **バケットとオブジェクト**：データは「バケット」という単位で管理され、その中に「オブジェクト」として格納されます。
- **アクセス管理**：IAMポリシーやバケットポリシーでアクセス権限を制御可能です。

### 使用例

- **静的ウェブホスティング**：HTMLやJavaScriptファイルをS3に格納し、静的なウェブサイトとして公開できます。
- **バックアップとアーカイブ**：重要なデータのバックアップや長期間の保存に利用されます。

## CDN (Content Delivery Network)

CDNは、コンテンツ配信ネットワークを指し、ウェブコンテンツをユーザーに迅速に届けるための分散型ネットワークです。AWSでは「CloudFront」が代表的なCDNサービスとして提供されています。

### CDNの役割

- **キャッシュ機能**：エッジロケーションにコンテンツをキャッシュし、ユーザーの地理的な位置に応じて最も近いサーバーから配信します。
- **遅延削減**：データの転送距離を短縮することで、ページロード時間を減少させます。
- **負荷分散**：リクエストを複数のエッジロケーションで処理することで、オリジンサーバーの負荷を軽減します。

### 使用例

- **動画ストリーミング**：動画コンテンツを高速で配信し、バッファリングを減らします。
- **静的ファイルの配信**：ウェブサイトの画像やCSS、JavaScriptファイルを効率的に配信します。

## 冗長化と高可用性

冗長化は、システムの一部に障害が発生しても、他の部分がその役割を引き継ぎ、システム全体が稼働し続けるようにする設計です。ロードバランサーとCDNを組み合わせることで、以下のような利点があります：

- **障害時の自動フェイルオーバー**：片方のAZが停止しても、他のAZにあるリソースが自動的にトラフィックを受け入れます。
- **アクセスの高速化**：CDNにより、ユーザーに近いロケーションからコンテンツが提供されるため、遅延を減らすことができます。

## まとめ

AWSのロードバランサー、S3、CDNなどは、冗長化し負荷分散、高可用性を実現するための重要な要素です。これらを組み合わせて利用することで、セキュアかつスケーラブルなシステムを構築することができます。これからのプロジェクトや個人開発でも、これらの知識を生かし、より効率的で信頼性の高いインフラを構築していきたいと思います。

この記事がAWSのインフラ設計を学ぶきっかけになれば幸いです。
HTMLやCSS、JSで要素を透明にする、または非表示にする方法

# はじめに
学んだことを忘れないように備忘録として残しています

Web制作初学者の筆者が要素を透明、または非表示にする方法でよく使うものをご紹介します。


## 1.display: none;
**要素を非表示にし、レイアウトからも削除します。**

【使いどころ】
レスポンシブデザインで、端末の画面サイズや種類に応じて不要なコンテンツを非表示にする

```css
sample {
  display: none;
}
```


## 2.opacity: 0;
**要素を完全に透明にしますが、レイアウトスペースやイベントは保持されます。**

【使いどころ】
- ハンバーガーメニューを取り入れたサイトのheaderのナビゲーション
(スマホサイトはheader-navに**opacity:0**、レスポンシブ対応でPCサイズに**opacity:1**）
- 文字を半透明にする（ホバーアニメーション）


```css
sample {
  opacity: 0;
}
```


## 3.autoAlpha (GSAP)
**GSAPで使用されるプロパティ**

【使いどころ】
フェードイン、アウト効果 非表示状態からスムーズに表示状態へ移行するアニメーションでよく使われます。

```javascript
// フェードアウト
gsap.to(".box", { autoAlpha: 0, duration: 1 });

// フェードイン
gsap.to(".box", { autoAlpha: 1, duration: 1 }
```


## 4.transparent
**要素自体は表示されますが、背景色や文字色を透明にして視覚的に透明に見せます。**

【使いどころ】
背景、文字などの装飾

```css
sample {
  background-color: transparent;
  color: transparent;
}
```

## まとめ
本記事では、要素を透明または非表示にする方法として「display: none;」「opacity: 0;」「autoAlpha」「transparent」の4つを取り上げました。それぞれの特性や使いどころを理解することで、Web制作において柔軟に対応できるようになります。
Entity Frameworkでテーブル名の不一致によるエラーを解決する方法


## はじめに
Entity Framework（EF）を使用している際に、以下の2つの問題が発生しました。

1. 裏で自動マッピング設定されてしまったことに伴うエラー
2. InsertとSelectで異なるテーブルにアクセス

これらの問題を解決するために行った手順を共有します。

## 問題の概要
### 1. 裏で自動マッピング設定されてしまったことに伴うエラー
以下のエラーメッセージが表示されました。

```
The model backing the 'ApplicationDbContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).
```
これは、エラーの内容の通り、自動でマッピング設定がされていたために、DB側の設定が変わっていないのにCode側で変更を加えたというエラーが出てしまっていたということです。DB側の設定を正にしたかったので、勝手に自動でマッピングされる設定をOffにする必要がありました。

### 2. InsertとSelectで異なるテーブルにアクセス
自動でマッピングされてしまっていた結果、Insert操作では`UserInfoes`テーブルにアクセスし、Select操作では`UserInfo`テーブルにアクセスするという問題が発生しました。しかも`UserInfoes`テーブルは既に削除してしまいました。

## 解決方法

### 1. DbContextクラスの修正
まず、`DbContext`クラスを修正し、自動マイグレーションを無効にしました。

```csharp
using System.Data.Entity;

namespace UserCreator.Models
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext() : base("DBConnectionString")
        {
            Database.SetInitializer(null); // Disable automatic migration
        }

        public DbSet<UserInfo> UserInfos { get; set; }
    }
}
```

### 2. モデルクラスの修正
次に、モデルクラスにテーブル名を明示的に指定しました。

```csharp
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace UserCreator.Models
{
    [Table("UserInfo")]
    public class UserInfo
    {
        [Key]
        public string UserId { get; set; }
        public string Status { get; set; }
        public DateTime CreatedDate { get; set; }
        public DateTime UpdatedDate { get; set; }
    }
}
```

## 結果
これらの変更を行ったことで、InsertとSelectの両方の操作が同じテーブルに対して行われるようになり、エラーが解消されました。

## まとめ
Entity Frameworkを使用する際には、モデルクラスとデータベースのマッピング設定が一致していることを確認することが重要です。今回のような問題が発生した場合は、モデルクラスや`DbContext`クラスの設定を見直し、必要に応じて修正することで解決できます。

---
C_TS452_2021 - SAP Certified Application Associate - SAP S/4HANA Sourcing and Procurement対策（19/100）

【19日目】
トピック2：供給元（8/8）

≪問題19≫
品目グループに対して契約明細を登録します。この品目グループに属する特定の品目はこの契約明細を参照して発注されないようにする必要があります。これを行うにはどのようにすればよいですか。
▢仕入先に対して品目固有の供給元一覧を登録し、ブロック済区分を設定する。
▢契約明細に対して品目固有の供給元一覧を登録し、除外区分を設定する。
▢契約の有効期間外で仕入先に対して品目固有の供給元一覧を登録する。
▢契約明細に対して品目固有の供給元一覧を登録し、固定区分を設定する。

≪解答≫
▢仕入先に対して品目固有の供給元一覧を登録し、ブロック済区分を設定する。
█契約明細に対して品目固有の供給元一覧を登録し、除外区分を設定する。
▢契約の有効期間外で仕入先に対して品目固有の供給元一覧を登録する。
▢契約明細に対して品目固有の供給元一覧を登録し、固定区分を設定する。

≪解説≫  
◆購買契約明細の中には、特定の品目ではなく、品目グループに関連するものがあります。この場合、明細カテゴリとして **M（品目未選定）** または **W（品目グループ）** を使用します。  
◆これらの契約明細に対して、品目別の供給元一覧レコードを登録することが可能です。また、供給元一覧を活用することで、該当の品目グループにおける特定の品目を含めるか、または除外するかを設定できます。  
◆品目グループ明細に対する供給元一覧の登録方法は、以下の手順となります：  
1. 購買契約の概要画面で、供給元一覧レコードを入力する明細を選択し、**明細→供給元一覧更新** を選択します。  
2. **除外区分** チェックボックスを選択します。  
3. 除外したい品目コードを、適切な有効期間とともに一覧へ入力します。これにより、該当する購買契約明細が除外する品目の供給元としてブロックされる供給元一覧レコードが生成されます。
【ISUCON】インスタンスへのssh接続コマンドを簡略化しよう

ISUCONでは何度も競技用インスタンスやベンチマーク用インスタンスへssh接続することがありますが、その度に以下のようなコマンドを打つのは面倒くさいですよね。
```bash
ssh -i 秘密鍵ファイルのパス ユーザー名@ホスト名
```
そこで今回は、これを`ssh [インスタンス名]`というシンプルなコマンドで接続できるようにする方法をご紹介します。

### EC2インスタンスのパブリックIPアドレスを調べる
まずはEC2の`インスタンスの概要`ページから、パブリックIPアドレスをチェックします。

![スクリーンショット 2024-11-16 18.08.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1071545/71b60d79-070b-8018-4291-43ffdc34f26f.png)

### 公開鍵を.sshに移動しておく（マストではない）
インスタンスに接続するための公開鍵を`~./ssh`に移動しておきます。
環境によりそうですが、私環境ではまずDownloadsディレクトリに保存されるので以下のコマンドで`~./ssh`ディレクトリへ移動させます。
```
$ cd Downloads
sudo mv private-isu-swing-1116-keys.pem ~/.ssh/
```
### configファイルを作成する
`~/.ssh`ディレクトリの配下に`config`という名称のファイルがなければ新規で作成します。
```bash
cd ~/.ssh
touch config
```
作成したconfigファイルに以下のテキストを追加してください
`iキー`でinsertモードにするのをお忘れなく。
```
# configファイルを編集する（vimを使う場合）
vim ~/.ssh/config
```
```
# configファイルに追記するテキスト
Host isucon1 #[isucon1]は好きな名前でOKです
  HostName xx.xxx.xxx.xxx # ここにインスタンスのパブリックIPアドレスを書く
  IdentityFile ~/.ssh/[秘密鍵のファイル名] # ここに秘密鍵のパスを書く
  User ubuntu # ここにユーザ名を書く
```
ユーザ名は`isucon`にするとPermission denied (publickey).になるので`ubuntu`にしてますが、ssh接続後にisuconユーザに切り替える手間がかかるので初めからisuconユーザでssh接続する方法がないか調査中です。

### おわり
これで、`ssh isucon1`コマンドだけでインスタンスにログインできるようになったはずです！
【TryHackMe】Introduction to OWASP ZAP：Walkthrough

# 概要

TryHackMe「Introduction to OWASP ZAP」のWalkthroughです。

https://tryhackme.com/r/room/learnowaspzap

# Task1

## **Q1**.*What does ZAP stand for?*

**A**.**Zed Attack Proxy**

## **Q2**.*Connect to the TryHackMe network and deploy the machine. Once deployed, wait a few minutes and visit the web application: http://TARGET_MACHINE*

Webページにアクセスします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/fb63becd-4199-6ce0-c5ac-a0ced47c96c1.png)

# Task3

## **Q1**.*Install ZAP on an operating system of your choice!*

Kaliのリポジトリからインストールできます。

https://www.kali.org/tools/zaproxy/

```
$ sudo apt install zaproxy
```

# Task5

## **Q1**.*What IP do we use for the proxy?*

**A**.**127.0.0.1**

# Task6

## **Q1**.*Try scanning the DVWA web application as an authenticated user.*

`Username: admin`,`Password: password`でログインし、`DVWA Security`からレベルを`Low`に設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/44e37381-2227-59c9-1063-c919508e1500.png)

`site`->`attack`->`forced browse site`に遷移し、ディレクトリスキャンを実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/3ac56c22-fdda-06d6-02a6-3bc2335148b7.png)

# Task8

## **Q1**.*Use ZAP to bruteforce the DVWA 'brute-force' page. What's the password?*

`Brute Force`ページに遷移し、GETリクエストパケットをキャプチャします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/73160e77-4fee-3df4-2a16-a22c8665f592.png)

TryHackMeのテキストに従い、ブルートフォースを実行するとレスポンスサイズの差異からパスワードを特定できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/471e5bdd-88f3-5b6e-5e90-5caed452f129.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/a38f9e89-a3e8-4017-3619-9a507b099564.png)

**A**.**password**
rubyのバージョンをアップデートしてcocoaPodsをインストールしてみた

cocoaPodsをインストールしようとした際に以下のエラーが出ました。
```
ERROR:  Error installing cocoapods:
	The last version of drb (>= 0) to support your Ruby & RubyGems was 2.0.6. Try installing it with `gem install drb -v 2.0.6` and then running the current command again
	drb requires Ruby version >= 2.7.0. The current ruby version is 2.6.10.210.
```
このエラーを解消した方法をまとめます。

## 確認環境
XCode Version 15.4
MacOS Sonoma 14.4.1

## エラーの内容
ローカルのrubyのバージョンが2.6.10のため、2.7.0以上にあげてくださいというエラーです。
rubyのバージョンを上げないとcocoapodsがインストールできないようです。

## rubyのアップデート方法

まずはrbenvがインストールされているか確認します。
（rbenvはRubyのバージョン管理を行うツールです）
ターミナルで以下のコマンドを入力します。
```
% rbenv -v
```
```zsh: command not found: rbenv```と表示された場合はインストールされていないので、続けて以下のコマンドを入力します。

```
% brew install rbenv
```
```brew```のコマンドはHomebrewを使用しています。
Homebrewがインストールされていない場合は、以下の記事を参考にインストールしてください。
[Homebrewのインストール方法](https://qiita.com/komkom2/items/3989a6772276108922ff)

以下が表示されればrbenvのインストールは完了です。
```
zsh completions have been installed to:
  /opt/homebrew/share/zsh/site-functions
```
念のため再度バージョン確認のコマンドを入力してインストールされていることを確認します。

```
% rbenv -v
rbenv 1.3.0
```
※上記のバージョンは2024/11時点の最新です。

## rubyをアップデートする

以下のコマンドでrubyの最新の安定版バージョンを確認します。
```
% rbenv install -l
komugi@MBA-m ~ % rbenv install -l
3.1.6
3.2.6
3.3.6
jruby-9.4.9.0
mruby-3.3.0
picoruby-3.0.0
truffleruby-24.1.1
truffleruby+graalvm-24.1.1
```

2024/11時点では3.3.6が最新の安定版のようなので、こちらにアップデートします。

```
% rbenv install 3.3.6
```
アップデート中・・・↓
```
==> Downloading ruby-3.3.6.tar.gz...
```

以下が表示されればアップデート完了です。
```
==> Installed ruby-3.3.6 to /Users/あなたのユーザー名/.rbenv/versions/3.3.6
```

## rubyのバージョンを適用する

現在使用中のrubyを確認します。
```
$ rbenv versions
* system
  3.3.6
```
現在使用しているバージョンに*がついています。
system設定になっている場合は、先ほどアップデートしたバージョンを適用するために以下のコマンドを入力します。
```
$ rbenv global 3.3.6
```
現在のバージョンが適用されているか確認します。
```
$ rbenv versions
  system
* 3.3.6 (set by /Users/あなたのユーザー名/.rbenv/version)
```

*がアップデートしたバージョンになっていればOKです。


## cocoaPodsをインストールする

rubyがアップデートできたらcocoaPodsをインストールします。

以下のコマンドを入力します。
```
% sudo gem install cocoapods
```
パスワードの入力を求められるので、PCのログイン時のパスワードを入力してエンターを押します。
インストール中↓
```
Fetching ...
Fetching ...
Fetching ...
Successfully ...
Successfully ...
```
インストールが完了すると以下のようなメッセージが表示されます。
```
34 gems installed
```
※34の数字は2024年11月時点のものです。

私の場合は以下の推奨メッセージが出ていたので、この後ついでにRubyGemsのアップデートをしました。
```
A new release of RubyGems is available: 3.5.22 → 3.5.23!
Run `gem update --system 3.5.23` to update your installation.
```

```
% gem update --system 3.5.23
.....省略
RubyGems system software updated
```

cocoaPodsのインストールとRubyGemsのアップデートが完了したので、cocoaPodsを適用します。
```
% pod setup
Setup completed
```
上記が表示されれば完了です。

## XCodeのプロジェクトにファイルを反映する

XCode上でpodfileを操作するために、プロジェクトの.xcodeprojファイルがあるフォルダに移動してから以下のコマンドを入力します。
```
% cd プロジェクトの.xcodeprojファイルがあるフォルダへのパス
% pod init
```
cdで移動したフォルダにpodfileが作成されます。

Xcodeで先ほどのフォルダの上で右クリック > 「Add Files to "フォルダ名"...」を押下して、podfileを選択して追加します。

以上で完了です。
Svelteキャッチアップしてみた

## はじめに
今後Svelteを使用する機会があるので、公式チュートリアルを通して学んだことをアウトプットしていきます！
[公式チュートリアル](https://learn.svelte.jp/tutorial/welcome-to-svelte)

#### 目次
1.Svelteってなに？
- 特徴
- 他のフレームワークとの違い

2.メリットとデメリット
3.Svelteの基本構文

## 1. Svelteってなに？
Svelteは、JavaScriptのフレームワークです。   

###### ＜特徴＞
Svelteは開発時にコードをコンパイルして、JavaScript,HTML,CSSを生成します。
そのため、ブラウザ上で余計なランタイム処理が不要になりページの読み込み速度やパフォーマンスが向上します。

###### ＜他のフレームワークとの違い＞

React、Vueはランタイムフレームワークとして動作します。つまり、ブラウザ上でフレームワークのコードが実行されます。また、仮想DOMを使用し、実際のDOMを更新します。

一方で、Svelteは「コンパイラ」ベースのフレームワークであり仮想DOMを使用しません。コードを実行するのではなく、開発時（ビルド）にコンパイルし必要なDOM操作のコードを生成します。
パフォーマンスにおいても、Svelteはランタイムがないため他のフレームワークよりもメモリ使用量が少ないです。

## 2. メリットとデメリット
#### メリット
**1. 軽量で高速**
ランタイムが不要なので、初期読み込みが速く低速のネットワーク環境でも優れたパフォーマンスを発揮します。

**2. コンパイラによる最適化**
Svelteのコンパイラは、コードを解析して「無駄な部分」や「今は使わない部分」を取り除くため軽くて速いコードができる。

**3. シンプルで学びやすい構文**
SvelteではHTML、CSS、JavaScriptを一つのファイルにまとめて記述でき、特殊な構文や概念を覚える負担が少ない。

#### デメリット
**エコシステムの規模が小さい**
Svelteは比較的新しい技術のため、ReactやVueと比べてエコシステム（プラグイン、ツール）がまだ少ないです。そのため必要なツールやライブラリが揃っていない可能性があるため、問題に直面した際に情報やサポートを見つけづらいなどのデメリットがあります。

Svelteのデメリットはそこまでなく、メリットの方が大きなと個人的には感じました。

## 3. Svelteの基本構文
今回キャッチアップを通して学んだ構文をアウトプットできればと思います。

##### 1. 変数とリアクティビティ
Svelteでは変数の値が変更されると自動的に画面が再描画されます。
```javascript: svelte
<script>
  let name = "Svelte"; // 変数を宣言
</script>

<h1>Hello, {name}!</h1>
```
{}で変数を埋め込むと、画面にその値が表示されます

##### 2. リアクティブ文法
リアクティブ文法を使用すると、変数の変更に応じて処理を自動的に実行できます。
```javascript: svelte
<script>
  let count = 0;
  $: doubled = count * 2; // countが変わるたびに再計算
</script>

<p>Count: {count}</p>
<p>Doubled: {doubled}</p>

<button on:click={() => count++}>Increment</button>
```
＄を使用するとcountの値が変更されると自動でdoubleの値を再計算してくれます。

##### 3. 条件付き表示
{#if} ブロックを使って条件によって表示を切り替えます
```javascript:svelte
<script>
  let isLoggedIn = false;
</script>

{#if isLoggedIn}
  <p>Welcome back!</p>
{:else}
  <p>Please log in.</p>
{/if}
```
##### 4. 繰り返し表示
{#each} を使って配列をループ表示します。
```javascript:svelte
<script>
  let fruits = ["Apple", "Banana", "Cherry"];
</script>

<ul>
  {#each fruits as fruit}
    <li>{fruit}</li>
  {/each}
</ul>
```


##### 5. イベント処理
ユーザーの操作に応じて関数を実行できます。
```javascript:svelte
<script>
  function handleClick() {
    alert("Button clicked!");
  }
</script>

<button on:click={handleClick}>Click</button>
```

##### 6. 双方向バインディング
フォーム要素と変数をバインドして、リアルタイムに値を同期できます。
```javascript:svelte
<script>
  let inputText = "";
</script>

<input bind:value={inputText} />
<p>あなたが入力した内容: {inputText}</p>
```
 bind:valueを使用するとimputTextに入力したないようが変数とフォームの内容が連動しそのまま表示されます。

 ##### 7. コンポーネントの分割とプロパティ (Props)
コンポーネントを作成し、親から子にデータを渡すことができます。
```javascript:親コンポーネント
<script>
  import Child from './Child.svelte';
</script>

<Child message="Hello from parent!" />

```
```javascript:子コンポーネント
<script>
  export let message;
</script>

<p>{message}</p>
```
export letを使用親からのデータを受け取ります。

## まとめ
今回はSvelteの基礎中の基礎についてアウトプットしましたが、すでにSvelteの魅力を感じています。チュートリアルのアドバンスも解きつつさらに理解を深めていこうと思います。
【JavaScript】async/awaitについて

今回は「asyncとawait」についての備忘録です。


# 1:「asyncとawait」とは？
・【Promiseを更に「直感的に、簡単に」】記述できるようにしたものです。

## 1-1:「async」について。
⬇︎
・「async」とは、【Promiseを返却する関数】です。


・「関数の先頭にAsync」と付いていた場合には【必ずPromiseが返ってくる】ことが担保されています。

・「Asyncを付けた関数(下記の例ならinit関数)」というのはこのinit関数自体も【Promiseのインスタンスを返します。】 下記の例ではconsole.log(init());とすると、Promiseが入っていることが分かります。

⬇︎

```javascript:async 

//⬇︎asyncで【Promiseを返却する関数】を定義する。
async function init() {
    //ここに処理
}

console.log(init()); //コンソール結果➡︎ これだけでも Promise {<fulfilled>: undefined が格納されている。
//⬆︎つまりこのinit関数自体も【Promiseのインスタンスを返します。】

```

<br>

## 1-2:「await」について。
・「await」はPromiseを返却する関数の【非同期処理が完了するのを待って、次の処理に移行するように制御をかける。】

・【awaitで受け取る】ということ。

⬇︎
```javascript:await

//⬇︎asyncで【Promiseを返却する関数】を定義する。
async function init() {
   await sleep(0); //awaitで受け取る。
}


```

<br>
 
# 2: await が使われてるなら、「asyncを必ず付けよう。」
・例として定義した関数init()の中で、
awaitが使用されている場合には、定義した関数init()は必ず非同期処理されることになる。
⬇︎
・なので呼び出し元の関数init()自体にも、
この関数は、非同期処理されるということを伝えてあげる必要があります。
⬇︎
⭕️【awaitが関数コンテキスト内で使われているなら、asyncを必ず付けよう。】
<br>

```javascript:awaitを使ってるなら,asyncは必ず定義
async function init() {
  await sleep(0); //awaitが付いているなら関数initには、asyncを付ける。
}
```









<br>

# 3: 実際にコードで触れてみる。

__実践1:__  async/awaitを使って【Promiseのチェーンを行ってみます。】
コンソールに0, 1, 2, 3, 4...の結果を表示させる。 
```javascript:main.js
//⬇︎sleep関数（Promiseで非同期処理を定義。）
function sleep(val) {
  return new Promise(function (resolve) {
    //⬇︎1秒後にsetTimeoutでconsoleに数字を表示する非同期処理。
    setTimeout(function () {
      console.log(val++); //コンソール結果: 0,1,2,3...
      resolve(val); // resolveで次の処理に移行するように制御を加えることができます。
      // 次のawaitに「引数val」が渡っていく。 
    }, 1000);
  });
}

//⬇︎asyncで【Promiseを返却する関数】を定義する。
async function init() {
  let val = await sleep(0); //⬅︎await sleep(0);が「実行された結果を、変数valに代入。」
  console.log(val); //⬅︎コンソール結果: 1
  val = await sleep(val); //⬅︎次々とチェーン処理されていく。
  val = await sleep(val);
  val = await sleep(val);
  val = await sleep(val);
}

//⬇︎init関数を実行する。
init();

```
⬇︎
すると「async/awaitを使ってpromiseチェーン」が作成できます。
これがasyncとawait。
⬇︎
個人的に「Promise」と「asyncとawait」はゴチャゴチャになってしまうことがあるので、こうして忘れたとき用に見返すと良い。(人の脳なのでしょうがないですね…)


<br>


__実践2:__ asyncで定義した関数自体にも、Promiseのインスタンスが返却されます。ということはthenで繋げた処理もできる。やってみる。

```javascript:main.js
//⬇︎sleep関数（Promiseで非同期処理を定義。）
function sleep(val) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      console.log(val++); //コンソール結果: 0
      resolve(val);
    }, 1000);
  });
}

//⬇︎asyncで【Promiseを返却する関数】を定義する。
async function init() {
  let val = await sleep(0);
  val = await sleep(val);
  val = await sleep(val);
  val = await sleep(val);
  val = await sleep(val);
  return val; //⬅︎「return val」を設定するとthen(function(val)に「valが渡っていく。」
}

//⬇︎init関数を実行する。
init().then(function (val) {
  console.log('hello ' + val); //⬅︎コンソール結果は、init()の結果0,1,2,3,4が表示されてから【その後に文字列"hello 5"が表示される。】
});

```
⬇︎
・「.then」を繋げてPromiseの非同期処理ができました。
・もちろん「.catch」のエラー処理も可能です。
<br>


# 4: 今回の備忘録でした。
メモ：積極的に使ってawaitとasyncに慣れる！
以上です。
ターミナルからVPNに接続する

## VPNにターミナルから接続できない
macOS（M1、Sequoia環境）でターミナルからVPNを管理しようとしたが、`networksetup`や`scutil`ではVPNの情報が取得できなかった。

しばらくApple Scriptで誤魔化していたが、不安定だしアプデで使えなくなるしでだるかった。

そこで再度調べてみた。どうやらIKEv2だと無理らしい。
[VPNStatus](https://blog.timac.org/2018/0719-vpnstatus/)を導入して解決した。

## VPNStatusの導入
https://github.com/Timac/VPNStatus

## 実行例
接続したいときは
```
vpnutil start "VPN名"
```

切断したいときは
```
vpnutil stop "VPN名"
```
【モデル駆動型アプリ】ビジネスプロセスフローの状態を Power Automate で制御する

# 【モデル駆動型アプリ】ビジネスプロセスフローの状態を Power Automate で制御する

## 概要

ビジネスプロセスフローのフローステップから『フローの実行』で Power Automate フローを実行し、そのアクションで自動的にビジネスプロセスフローを終了させる方法です。
![image-20241119205514047.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111975/47e9fd3c-1752-2483-2929-23d09462f227.png)

## 準備

ビジネスプロセスフローに関連づいているエンティティ (テーブル) を確認します。

1. ビジネスプロセスフローの編集画面で [名前] のリンクをクリックします。
![image-20241119200220376.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111975/c26c9975-797c-e531-5dfc-9c02573d64ff.png)


2. エンティティ (テーブル) の名前を確認しておきます。※例では『Approval_Process』
![image-20241119201010658.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111975/854829ae-ab7d-e29e-55c2-110dd0e27ca9.png)

## Power Automate フローの作成

ビジネスプロセスフローから起動するフローを作成します。
※2024/11 現在 新しいデザイナー非対応

1. 『フローステップから起動する』トリガーでフローを作成します。
![image-20241119204515241.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111975/14b80644-7e79-54bc-9394-3c28c1e08511.png)

1. 『行を更新する』アクションを追加して、先程確認しておいたテーブル名を指定します。
1. [行 ID] のプロパティに、『フロー ステップの実行時』トリガーの [BPF のインスタンス ID] を指定
1. [ステータス] プロパティを『完了』に設定
1. [状態] プロパティを『非アクティブ』に設定
![image-20241119204712195.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111975/b16d8ca1-9913-8dac-f374-559aee79a4ae.png)

## 確認

フローを実行してみて、プロセスフローが『終了』になっていることを確認します。
![image-20241119205133076.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111975/5292cf7b-8a78-dacf-1bb8-d1151546547b.png)


# 参考サイト

https://qiita.com/Rinatamu/items/3132a9fe5441a24ee015
JSTQB FLを取得した時の記録


2024/10/28
# JSTQB FL挑戦

## JSTQBとは？
- ソフトウェアテストに関する資格。日本語試験。国際資格と相互認証。
- 業界の歴史を反映した用語集であり、べしべからず集みたいな感じ。
- 「Foundation Level 資格は、ソフトウェアテストに関与する、または関心を抱いているあらゆる人々を対象にする」ということで、前提条件なしの入門資格。

https://jstqb.jp/

- 試験範囲は公開されているpdf。シラバスと呼ばれる。

https://jstqb.jp/dl/JSTQB-SyllabusFoundation_VersionV40.J02.pdf

- 難易度は、振り返ってみると個人的には1カ月で行けると感じた。

## 目的
- システム一回り入門したかった。今回の観点はソフトウェアテスト。
- 考え方とかフレームワークを手に入れたい。

## 状況
- 文系学部卒、特別なプログラミング経験やソフト、ハードなどの知識、経験なし。
- 社会人で、基本情報FE取得済、セスペSC、ネスペNW取得済。OSSDB gold、LPIC1取得済、デスペ1敗して保留中。CCNA取得済。
- 業務的に何となく色々試験とかしてるけど、過去の流用とか有識者任せ。
- 基本情報とかで何となくディシジョンテーブルとか見たけど使いどころとか良く分かってない。
- 現行試験バージョンが10月で終わるということなので、滑り込み受験。

## 準備
テス友のみ。

https://www.qbook.jp/info-testomo/

ほんと素晴らしいアプリでした。
試験も大体同じような感じで出題されるので試験リハとしても適切でした。
アプリのみ、と言いつつシラバスを確認できるので、
実質ちゃんと公式情報も確認したことになります。
集中したのが9月10月の計2カ月
通勤時間で細々と継続。
2時間/日＊4日/週＊4週/月＊2カ月/今回
＝64時間

アプリで1378問解いたようです。
117回実施して、正答率84%で試験に挑んでいます。
問題解いていた判定の時間は15時間らしいです。
その他の50時間くらいはシラバス確認したり合格者の方のブログ読んだりしてました。
アプリはパソコン、iPhone、androidどれも試しましたが、
個人的にはandroid版のアプリが安定して使いやすかったです。

## 当日
試験時間60分で40問。
フラグ立てて戻れるタイプ。
18分残して1週目終了。
フラグ立てたのは計算必要な3問。
9分残で試験終了。
その場で合否不明なタイプ。

↓　3日後
メール来て、マイページに結果のみ更新されて、合格。
割合や得点は分からないタイプ。

↓　2週間後
認定証が郵送されてきた。

## 振り返り
- 好きな言葉： 「コンピューターの歴史を通して、運用環境にリリースされたソフトウェアやシステムが欠陥を含んでいるために、故障が起きたりステークホルダーのニーズに合致しなかったりすることは一般的である」
→慌てるなって感じで凄く良いなと思いました。
- 「デバッグとテスト」「エラー、欠陥、故障」など、用語、考え方が整理され、業務で使う時に意識できると思った。
- テス友で全く問題なかった。

## お勧めする準備
- テス友：移動時間で可能な最強の対策。シラバスも読める。

## 結果
- 歴史的に見て原則とすべきこと、ソフトウェアテストの基礎的な考え方を整理できた。バグ0とか全部テストとか無理、取捨選択必要だよとか。
- 次はPM系ならPMPなり情報処理のPMなりか。

以上
『ユーザーのための要件定義ガイド第2番』第2章

# 導入
[ユーザーのための要件定義ガイド](https://www.ipa.go.jp/archive/publish/qv6pgp0000000wrt-att/000079352.pdf)

情報技術者試験を主催するIPAが公開している要件定義についての資料。

「ユーザーのための」とあるようにシステム開発を依頼する側に必要な視点だが、ユーザーはそもそもそういう考えに至らない可能性も高いので開発者側も知っておく方が良い。

図など込みで7章に分けて500ぺージ近い資料があるので1章ずつすごく雑に要約していく。

今回は第2章


# 本題
第2章は「要件定義の問題認識」
第1章の焼き直し的な部分もある。
それだけ経営層が要件定義に参加することを強く主張したいのかな、という感じ。


## 経営層が意識すべきこと
### 良き構想なくして良き要件定義はない。
構想が悪かったら全部台無し。
不備があるなら整備する時間をかけるべき。

### プロジェクトの体制
システム部門にお任せ！じゃダメ。

### 経営層の参画
経営層がプロジェクトとして思い描いた構想を業務部門に伝えても、業務部門は実務中心で考えてしまう。
本来の目標を理解している経営層が積極的に要件定義へ参画し、確認する必要がある。
「経営層」は社長とかだけじゃなくて企画担当スタッフとかも含まれるよ。


### 非機能要求
性能や拡張性、および事件や災害時の事業継続性・セキュリティ
企業の社会責任として捉えましょう。

### 要件定義工程で十分な工期、工数を割り当てる
規模が大きくなったら開発期間全体に対して要件定義の比率が小さくなるデータ

要件定義工程で気付いた修正は作業負荷少ない。
設計、実装、総合テスト、稼働後と工程が先に進むほど修正の作業負荷は大きくなる。
要件定義の工数をケチろうとしない方がいい。

### 既存システムの現状認識
ブラックボックス化したシステム
「現行通り」は要件定義ではない
「現行機能」を提示できないなら要件定義は終了できない


### IPAの提示する17個の原理原則
原理原則[1] ユーザとベンダの想いは相反する
原理原則[2] 取り決めは合意と承認によって成り立つ
原理原則[3] プロジェクトの成否を左右する要件確定の先送りは厳禁である
原理原則[4] ステークホルダ間の合意を得ないまま、次工程に入らない
原理原則[5] 多段階の見積りは双方のリスクを低減する
原理原則[6] システム化実現の費用はソフトウェア開発だけではない
原理原則[7] ライフサイクルコストを重視する
原理原則[8] システム化方針・狙いの周知徹底が成功の鍵となる
原理原則[9] 要件定義は発注者の責任である
原理原則[10] 要件定義書はバイブルであり、事あらばここへ立ち返るもの
原理原則[11] 優れた要件定義書とはシステム開発を精緻にあらわしたもの
原理原則[12] 表現されない要件はシステムとして実現されない
原理原則[13] 数値化されない要件は人によって基準が異なる
原理原則[14] 「今と同じ」という要件定義はあり得ない
原理原則[15] 要件定義は「使える」業務システムを定義すること
原理原則[16] 機能要求は膨張する。コスト、納期が抑制する
原理原則[17] 要件定義は説明責任を伴う

経営者「情報システムの問題はよく分からない」
何について、どんな説明が必要か考えて。
• 当社の本質的問題と関係付けて説明せよ
• 英語の 3 文字単語は使用しないで説明せよ
• 開発上のリスクは何か
• 開発、運用の最適責任者は誰か、成功させる信念をもっているか
など具体的に指示して、内容を理解した上で企画の採否を行う努力をして欲しい。


## 業務部門が意識すべきこと
### 経営や業務に貢献する
システムが経営や業務へどう結びついたか。これは業務部門の問題。

### ビジネスプロセス改革・改善
業務プロセス自体が変わらないならITシステムを業務に対するサービスとして捉える。
ビジネスプロセスにシステムを組み込む。

### 業務部門のリーダーシップ
システムからどのような効果を引き出すかは業務部門の責任

### 現行業務、システムの理解
作業を人、機械、システムに分けるときの効率を考える。
「次のシステムへの要望」「使っていない機能」「今の環境にふさわしくない機能」
をあらかじめ整理した方がよい。

もっと顧客に喜んでもらえる機能や仕組みがないかをヒアリングするのもよい。

### 合意形成
ステークホルダ方針・意見・課題
できるできないを切り分けて合意形成へもっていく


### 仕様変更が生じた場合を想定した予算確保
プロジェクトのうち約8割は仕様変更が生じたというデータ
仕様変更予算を10%程度持っていくと円滑になりやすいらしい。


## システム部門が意識すべきこと
### 既存システムの状況の明確化
「システムが動いているならレガシー化していない」と認識する経営層もいる。
システム部門が経営層に課題として認識させる必要がある。

### システム部門のパラダイムシフト
要件定義は業務部門責任が基本ではある。
システム部門が主導してIT技術活用を提案していく姿が理想。

これはベンダ側も同様(営業だけに任せるんじゃないよ)

### プロジェクトマネジメント
要件定義特有のマネジメント
・膨らむ要求のコントロール
・どうなったら要件定義の完了か
・要件定義の品質をどう担保するか

## ベンダ企業の意識すべきこと
### 要件定義の契約基本形は準委任契約
基本としてユーザー企業主体で進める。
請負より準委任になったことで問題が減少したらしい。


### ユーザ企業課題解決貢献
ビジネス変革先行型「ビジネスのためにこんな技術が必要」
IT技術先行型「IT技術で何かできるのでは？」

ユーザの課題は何かを一緒に考える必要

### 見積り
見積りの誤り
・楽観的　(根拠があいまい)
・早期　(作るものが決まっていない)
・目標と見積もりの混同　(営業や顧客の事情)
・一度決まったら修正されない
・時間に余裕がない　(そもそも短すぎる)

実際作り始めたら見積りの精度上がる。都度見直しが必要。
安くすることに力を注ぎ本来あるべき見積りを見失いがち。

### 要求仕様の凍結
要件定義があいまいでプロジェクトに仕損が出ることもある。
要件定義完了時点で凍結させる努力が必要。

よくある契約上の工夫
・要件定義後の変更は仕様変更として費用計上
・期間の延長ありうるものにする
確実に決められるようベンダ側が統制し、コントロールする


## 問題の抽出と整理
ベンダ企業とユーザ企業に要件定義の問題をアンケート

図と表で解決のための勘どころを列挙しているので割愛
ここに関しては原典を読んでほしい。
AWS管理画面のカスタマイズ：Chrome拡張機能『re:Name FavBar』でAWSサービス名を短縮

## はじめに
AWS Management Console を日常的に使用していると、お気に入りバーが長いサービス名で埋まってしまい、視認性や操作性が低下してしまうことがあります。

:::note 
**そんな課題を解決してくれるのが、Chrome 拡張機能「re:Name FavBar」です。**
:::

このツールを利用することで、お気に入りバーのサービス名を短縮し、カスタマイズすることが可能です。

この記事では、「re:Name FavBar」の特徴と使い方を実際に試した結果をご紹介します。

## re:Name FavBarとは
AWS Management Console のお気に入りバーに表示されるサービス名をカスタマイズする Chrome 拡張機能になります。

![スクリーンショット 2024-11-19 20.56.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/f598f2ff-883e-1b81-09f0-16f5a7b41aac.png)

私自身も、複数のサービスをお気に入り登録した結果、バーが横に長くなり、頻繁にスクロールが必要になるという悩みを抱えていました。

![スクリーンショット 2024-11-19 20.30.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/772e489d-0ed6-88b4-cde1-235ee31f3392.png)

機能としては、長いサービス名（例：``Amazon DynamoDB``）を短い略語（例：``DDB`` ）にコンパクトに表示できたり、カスタムマッピングにより独自の略語や非表示設定が可能となります。

:::note warn
- **``DynamoDB, DDB`` → 「DynamoDB」を「DDB」に変更**
- **``DynamoDB,`` → 「DynamoDB」を非表示**
:::

オプションページで以下の形式で入力するだけで、簡単にカスタマイズできます。

```css
original name, new name
```

※1行に1つのルールを記載する形式みたいです。

## インストール方法

Chrome Web StoreまたはGitHubリポジトリから簡単にインストールできます。

https://chromewebstore.google.com/detail/rename-favbar/djibddceopnloddkfmgekaejflcnadli

インストール後、拡張機能のオプションページを開き、変更したいサービス名を入力してカスタマイズします。入力内容がAWS Management Consoleのお気に入りバーに反映されます。

## 実際に使ってみた

Chromeに「re:Name FavBar」をインストールし、AWS Management Console で試してみました。

**Before**

以下は、インストール前のAWS Management Consoleです。サービス名が長いため、お気に入りバーが横に広がり、スクロールが必要な状態でした。

![スクリーンショット 2024-11-19 20.38.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/e7d60d30-3fa6-9704-40e7-c0b912e59569.png)

オプションページに以下のように入力して、サービス名を短縮表示する設定を行いました。

![スクリーンショット 2024-11-19 20.48.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/17e036fb-4a2e-7c76-f526-9667c8396822.png)

**After**

設定後は、お気に入りバーがスッキリとした略称で表示され、視認性が大幅に向上しました！

![スクリーンショット 2024-11-19 20.49.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/eb519533-7658-ab0e-bda6-aafb96ac6d90.png)


## まとめ
「re:Name FavBar」は、AWS Management Console の作業効率を高める便利な拡張機能です。


:::note 
**特に、頻繁に利用するサービスが多い場合や、個人の作業スタイルに合わせてカスタマイズしたい方におすすめです。**
:::

AWSの利用環境をもっと快適にしたい方は、ぜひ試してみてください！

## 参考記事

https://zenn.dev/shimo_s3/articles/493180a784b3f3

https://dev.classmethod.jp/articles/aws-console-rename-favbar/
LeetCodeを1日1題解いてみる (day20)

20日目に取り組んだ問題はこちら！
今回はmediumに挑戦します！

# 55. Jump Game

https://leetcode.com/problems/jump-game/description/

## 問題文
You are given an integer array nums. You are initially positioned at the array's first index, and each element in the array represents your maximum jump length at that position.

Return true if you can reach the last index, or false otherwise.

## 僕の回答 (ヒントなし！)
```py
class Solution:
    def canJump(self, nums: List[int]) -> bool:
        size = len(nums)
        here = size-1
        while here > 0:
            prev = here
            for i in range(here):
                val = nums[i]
                if (i + val) >= here:
                    here = i
                    break
            if prev == here:
                return False
        if here == 0:
            return True
        else:
            return False
```

## より効率の良い回答例

```py
class Solution:
    def canJump(self, nums: List[int]) -> bool:
        goal = len(nums) - 1

        for i in range(len(nums) - 2, -1, -1):
            if i + nums[i] >= goal:
                goal = i
        
        return True if goal == 0 else False
```

### コメント
ヒントなしで自力で考えることができて、実装まで行けたことが嬉しい。考え方も他の回答と似ていたので、自信になった。ただ、二重ループではなく、一重ループで実装できる問題だったので、そこに気づけるくらいまで成長したい。

### 次の問題はこちら!
https://qiita.com/h_y_s_d/items/a80f49f0aeed31c266c8
サクッとクロスアカウントで S3 sync を実施する

## はじめに

S3 バケットの内容を別のバケットに同期したいユースケースで使用する AWS CLI の `s3 sync` ですが、クロスアカウントで実施したいパターンも多々あると思います。
そこで一番簡素な手順と思われサクッと実施するパターンを備忘として残しておきます。

## 1. コピー元のアカウントで実施すること

以下のポリシーを持つ IAM ユーザーまたはロールを作成する。

例: ユーザー `sample-s3-bucket-sync`
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::<コピー元バケット名>",
                "arn:aws:s3:::<コピー元バケット名>/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::<コピー先のバケット名>",
                "arn:aws:s3:::<コピー先のバケット名>/*"
            ]
        }
    ]
}
```

## 2. コピー先のアカウントで実施すること

コピー先バケットのバケットポリシーに以下を設定する。

```json
{
    "Version": "2012-10-17",
    "Id": "S3AccessPolicy",
    "Statement": [
        {
            "Sid": "AllowS3PutObject",
            "Effect": "Allow",
            "Principal": {
                "AWS": "<1で作成したユーザーまたはロールのarn>"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::<コピー先バケット名>/*"
        },
        {
            "Sid": "AllowS3ListBucket",
            "Effect": "Allow",
            "Principal": {
                "AWS": "<1で作成したユーザーまたはロールのarn>"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::<コピー先バケット名>"
        }
    ]
}
```

## 3. sync 実施
`s3 sync` コマンドを実行します。
- １で作成したユーザーにて実行します
- １でロールを作成した場合は、使用ユーザーに assume role してから実施して下さい


```bash
aws s3 sync s3://<コピー元バケット名> s3://<コピー先バケット名> --acl bucket-owner-full-control
```

## Ref

- [AWS CLI Command Reference - s3 sync](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/sync.html)
- [AWS CLI を使用して S3 バケットから別のアカウントとリージョンにデータをコピーする](https://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/copy-data-from-an-s3-bucket-to-another-account-and-region-by-using-the-aws-cli.html)
Flutterの学習 - カスタマイズして理解を深める

こんにちは！

前回までに、以下の記事を書きました。

- [開発環境の構築](https://qiita.com/yam_dev/items/f58dc02260df7aa053ed)
- [簡単なGeminiアプリの起動](https://qiita.com/yam_dev/items/c069680e1deb669c109b)
- [Flutterの学習 - 構成の理解](https://qiita.com/yam_dev/items/82c95e4e7b9373e0bf66)

今回は、構成について理解します。

# 前回までのおさらい
まずは、作ったアプリはこちら。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/3745fb55-e364-abc4-6015-4e52b7d826fd.png" width="300px" />

画像が表示されており、プロンプトに指示を入力して「Go」ボタンをクリックすると、AIからの回答が表示されます。

# 今回カスタマイズする箇所
今回は、以下の2点を見てみます。
- Goボタンの名前を変える
- Goボタンをクリックした際にAIへ送信されるプロンプトをカスタマイズする

### Goボタンの名前を変える
まずは、ボタン名が定義されている場所を探します。

こちらにありました。
![スクリーンショット 2024-11-19 16.00.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/b7c27cc3-c482-0d90-ac89-125244a509ad.png)

`action_go` で設定されているようなので、`Go`を`Send`に変更します。
リビルドすると、ボタンが`Send`に変わりました。

![スクリーンショット 2024-11-19 16.21.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/6f269c98-a057-9ebe-e1de-1beb8cf48a26.png)

### Goボタンをクリックした際にAIへ送信されるプロンプトをカスタマイズする

続いて、プロンプトの送信箇所を探します。

Buttonをクリックしたときに（onClick）、bakingViewModel.sendPrompt(bitmap, prompt)を実行してますね。

![スクリーンショット 2024-11-19 17.25.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/b76bf5cd-0574-a8c5-b45f-d4fd7679e37d.png)

さらにbakingViewModel.sendPrompt(bitmap, prompt)を確認します。

generativeModel（ライブラリ）に渡しているので、その手前で処理したら良さそうです。

![スクリーンショット 2024-11-19 19.31.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/8c68fb9d-1d3a-9002-3cf5-5b021f25421b.png)

画面で入力したプロンプトに加え、「そして、この焼き菓子がメニューにありそうなLAのカフェを教えて。」という旨のプロンプトを付け加えました。

```kotlin

val newPrompt = prompt + "Also, please tell me about a cafe in LA that might have this baked goods on the menu."

```

![スクリーンショット 2024-11-19 19.37.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/7ef3de60-8d4d-8053-b94d-c9e1a3dcefc1.png)

AIからカップケーキのレシピが返され、その続きに追加したプロンプトの回答がありました！

![スクリーンショット 2024-11-19 20.31.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/c996f7f0-547a-f245-2686-78548728a926.png)

特定のお店は教えてもらえなかったものの、追加したプロンプトに対する回答がありました。

# まとめ
今回は、Goボタンの名前を変更し、プロンプトのカスタマイズを行ないました。
簡単なカスタマイズでしたが、どこで何が行われているか、理解が深まりましたね。

実務においても同じで、自分で修正して動きを確かめることで、より理解が深まります。
色々と試して、画面からロジックをイメージできるようになりましょう。

次回は、簡単なゲームを作ってみます。