OmniAICreator/Qiita-1.07M huggingface dataset:
増殖したスタイルをまとめて削除したい

[見つけた情報](https://qiita.com/hkuno/items/87f06368855a9e72b0fe)が自分の環境では動かなかったので、同等のスクリプトを `PowerShell` で動くようにしました。

例によって [batファイルを経由して動く](https://qiita.com/asterisk9101/items/cbc9e5b70d3ca369e9f2) 想定です。

~~試運転では問題なく動いているように見えますが、実際に処理したいファイルでは試していません。試して駄目だったらまた考えます。~~

動きました。

```powershell
$excel = new-object -com excel.application
$excel.visible = $True

foreach ( $xlsx in $Args) {
    Write-Host $("Opening...: " + $xlsx)
    $book = $excel.Workbooks.Open($xlsx)
    $changeflag = $False
    $count = 0
    $book.Styles | Where-Object Builtin -eq $False | ForEach-Object {
        Write-Host $("Style Deleting...: " + $_.Name)
        $_.Delete() > $null
        $changeflag = $True
        
        if($count++ -gt 500){
            Write-Host "Saving...: $xlsx"
            $book.Save()
            $count = 0
        }
    }
    if ($changeflag) {
        Write-Host "Saving...: $xlsx"
        $book.Save()
    }
    $book.Close()
}

$excel.quit()
```

一部消えないスタイルがありましたが、[`style.xml`を修正](https://www.excelsystem.jp/Library/archives/50) したら消せるようになりました。
メディア業界生成AI最前線（2024.08）: AIトレンド全体・基礎編

### 2024年の生成AIの展望とメディア業界への影響

2023年は「生成AIの年」と呼ばれましたが、2024年にはどのような進化が期待されるのでしょう？今日は、生成AIに関する最新トレンドから、ソフトウェア開発やメディア・出版ビジネスへの影響を探ります。

---

### 1. 世界のAI市場の現状

#### AI市場の成長と予測
AI市場は2022年に4,541億ドルと評価され、北米が最大のシェアを占めています。生成AIの開発と採用がこの成長をさらに加速させ、2030年までに年間37.3%の成長率が予測されています。

- **重要なポイント**: マッキンゼーは、AIが年間6.1兆〜7.9兆ドルの経済的影響をもたらすと予測しています。

メディア業界においても、AI技術はコンテンツ制作やデータ分析の効率化を推進し、編集作業の革新に寄与しています。

---

### 2. 主要な生成AIツールとメディアへの応用

#### 使用されるツール
生成AIは、ディープラーニングやニューラルネットワークなどのコア技術に基づいています。以下は、メディアや出版業界において注目される代表的な生成AIツールです。

- **ChatGPT**: 自然言語処理を活用し、記事作成やカスタマーサポートに利用可能。オールマイティなLLMとして使いやすい。
- **DALL-E 2**: テキストから高品質な画像を生成し、ビジュアルコンテンツの作成を支援。本番での利用に十分な検討が必要だが、社内の企画会議であればすぐに実践投入可能。
- **Copilot**: コード生成ツールとして、技術系メディア向けのコーディングサポートに利用可能。社内システムとして会社や情報システム部が管理しやすい。

これらのツールは、メディア業界でのコンテンツ制作の効率化や、新しいクリエイティブプロセスの開拓に大きな影響を与えています。

---

### 3. 生成AIがメディア業界に与える影響

#### 編集プロセスの変革
生成AIは、編集作業の自動化や効率化を推進しています。例えば、AIによる初稿作成や校正が導入されることで、編集者はより高度な企画や構成に集中できるようになります。

- **重要なポイント**: GitHubの調査によれば、生成AIツールの導入により生産性が88%向上しています。

メディア業界では、AIを活用した迅速な記事配信や、パーソナライズされたコンテンツの提供が進んでいます。

---

### 4. 生成AIに関する主要な統計とトレンド

#### AIの導入と信頼
生成AIの導入が急速に進んでおり、特にメディア業界では、その信頼性と効果が注目されています。ChatGPTはリリースから2ヶ月以内に月間アクティブユーザー数が1億人に達し、急速に市場に浸透しました。

- **統計**: 企業の64%がAIを活用して生産性を向上させると考えています。

このトレンドは、メディア業界におけるAI技術の採用を促進し、コンテンツ制作の質と速度を劇的に改善する可能性を示唆しています。

---

### 5. 生成AIが雇用とスキル開発に与える影響

#### 雇用市場の変化
生成AIの普及により、メディア業界でも新しいスキルが求められるようになっています。例えば、AIツールを駆使したデータ分析や、AIが生成したコンテンツの編集スキルが必要とされています。

- **重要なポイント**: LinkedInによると、GPTやChatGPTに関連する求人が2022年11月以降で21倍に増加しています。

この変化に対応するためには、編集者自身がAIリテラシーを高め、新しい技術を取り入れるスキルを磨くことが不可欠です。

---

### 6. 倫理的配慮と規制環境

#### AIの規制と倫理
生成AIの普及に伴い、その倫理的使用や規制の必要性が高まっています。AIが生成するコンテンツにおける偏りや誤情報のリスクをどう管理するかが、メディア業界にとって重要な課題となります。

- **統計**: 世界中の71%の人々がAIの規制を必要と感じています。

メディア編集部では、AIを活用したコンテンツ制作において、信頼性と倫理性を確保するためのガイドライン策定が求められます。

---

### 7. 生成AIの将来展望

#### 今後の見通し
生成AIは今後も進化を続け、メディア業界におけるクリエイティブプロセスや業務効率化に寄与していくでしょう。Goldman Sachsは、生成AIが世界のGDPを7%引き上げると予測しています。

- **重要なポイント**: 生成AIがメディア業界での競争力を強化し、新しいビジネスモデルの創出に寄与する可能性が高いです。

編集者としては、AI技術を効果的に活用し、メディアコンテンツの質を向上させるとともに、業界の変化に柔軟に対応することが求められます。

---

生成AIは、メディア業界を大きく変えています。編集者としては、この技術の動向をしっかり把握し、上手に活用することで、これからのビジネスチャンスをしっかり掴んでいきましょう。
.ps1をダブルクリックで実行したい

今更のネタですが、先日思い出すのが面倒だったので書き留めておこうと思いました。

---

`.ps1` はセキュリティやら何やらの都合で、単純にダブルクリックするだけでは実行できないようになっています。

ただ、実用的にはダブルクリックで実行できた方が使い勝手が良いことも多いです。

直接実行できないのであれば、伝統的な `.bat` から呼び出してやれば良いのです。簡単ですね。

以下のバッチファイルは、同じフォルダの同じファイル名(`%~dpn0`)の `.ps1` ファイルを実行します。

```bat
@echo off
powershell -ExecutionPolicy Bypass -NoProfile -File %~dpn0.ps1 %*

if %errorlevel% neq 0 (
    rem 終了コードが 0 以外の場合は一時停止する
    pause
)
```

また、フォルダの中にいくつも `.ps1` と `.bat` が並ぶと見苦しいので、`.ps1` は別のフォルダにまとめたいときがあります。

例えば `ps1` フォルダにまとめたいときは、パスの部分を以下のように調整します。

```bat
@echo off
rem 暗号のように見える部分について
rem %0 は実行されているバッチファイル自身を表します
rem ~ は書式オプションを使う場合に指定します
rem dp は %0 の設置されているディレクトリパスを示す書式オプションです。
rem n は %0 の拡張子無しのファイル名を示す書式オプションです。
rem powershell -ExecutionPolicy Bypass -NoProfile -File %~dpn0.ps1 %*
    powershell -ExecutionPolicy Bypass -NoProfile -File %~dp0\ps1\%~n0.ps1 %*

if %errorlevel% neq 0 (
    rem 終了コードが 0 以外の場合は一時停止する
    pause
)
```

以上
Protect E2E testing from corruption

E2E Testing の自動化について。

https://www.shoeisha.co.jp/book/detail/9784798172354

こちらの本を読み、どうしたら継続的に自動テストを実践していけるのかについて学んでいる。

```mermaid
flowchart TD
    subgraph release_cycle["Release Cycle"]
        release[Release] --> code_freeze["Code Freeze"] --> staging["Staging"] --> regression_test["Regression Testing"] --> deploy["Deploy"] --> beta_test["β Testing"] --> release
    end
    subgraph a_development_cycle["Development Cycle A"]
        a_requirement_analysis[Requirement Analysis] --> a_implement[Implement] --> a_unit_testing[Unit Testing] --> a_review[Review] --> a_merge[Merge] --> a_requirement_analysis
    end
    subgraph b_development_cycle["Development Cycle B"]
        b_requirement_analysis[Requirement Analysis] --> b_implement[Implement] --> b_unit_testing[Unit Testing] --> b_review[Review] --> b_merge[Merge] --> b_requirement_analysis
    end
    a_merge -.-> code_freeze
    b_merge -.-> code_freeze
```

リグレッション テスト（リリース サイクル）で不具合を見つけた場合、手戻りが多く発生する。

不具合を「開発サイクル」の中で見つけることで開発者にとって手戻りが少なく効果的なテストにできる。

## tl;dr

- Application の実装に依存したテストを書かない。

## 振る舞いをテストする

- どちらも同じように動作する。しかし、前者は Application の内部構造に依存しており、実装方法を変更した場合に、副作用を受ける。
- 著書にも述べられている通り、内部構造をもとにテストを実装することは推奨されない。なぜなら、構造の変化により、Application と テスト コード両方の修正が必要になるから。

### Bad

- テスト コードを見てもどこをテストしているのか判断が難しい。

![ui](/images/7fa6757c6b1e57-a.png)

```typescript
    await page.locator('input[name="supplierName"]').fill('とほほ株式会社');
    await page
      .locator('select[name="billingMethod"]')
      .selectOption('クレジットカード');
    await expect(page.locator('input[name="name"]')).toHaveValue(customerName);
```

### Good

- `getByText` [^1] に変更する。
- 見え方が変わらなければテストは成功する。

```typescript
    await page.getByText(/取引先名/).fill('とほほ株式会社');
    await page.getByText(/^請求方法/).selectOption('クレジットカード');
    await expect(page.getByText(/法人名必須/)).toHaveValue(customerName);
```

## Conclusion

著書のあとがきで述べられていることが一番重要だと思う。

テスト自動化の前に必要なことは、周囲を巻き込むこと。そして、チームがテスト自動化から利益を得られる状態にすること。

当人がテスト自動化の効果や重要性について気付いても、それが利用されなければ、自動化したコード自体が陳腐化し、誰も使わない状態に陥る。

これは個人的にも何度も目にしてきた事象である。

自動テスト以外にも、IaC や CI/CD についても同じことが言えると思う。

今いる環境が DevOps に対する理解が乏しいと思えるのであれば、DevOps に対する理解がある場所を探す必要があると思う。

自分を変えることは出来るが、人を変えることは、費やす労力以上に難しいものであるから。

[^1]: https://playwright.dev/docs/api/class-page#page-get-by-text
解いてみた。「Aランク：ハノイの塔」

# 問題
[「Aランク：ハノイの塔」](https://paiza.jp/works/mondai/real_event/hanoi)

# コード
Javaで解いてみました。

``` Java
import java.util.*;

public class Main {
    
    private static ArrayList<Stack<Integer>> alst;
    private static int nT;
    
    public static void main(String[] args) {
   
        Scanner sc = new Scanner(System.in);
        int nN = sc.nextInt();
        nT = sc.nextInt();
    
        // 初期設定
        alst = new ArrayList<Stack<Integer>>();
        for (int i = 0; i < 3; i++) {
            alst.add(new Stack<Integer>());
        }
        
        for (int i = nN; i > 0; i--) {
            alst.get(0).push(i);
        }

        // 移動開始
        move(0, 2, nN);

        // 結果出力
        printStack();
    }
    
    private static void printStack() {
        for (int i = 0; i < 3; i++) {
            if (alst.get(i).empty()) {
                System.out.println("-");
            } else {
                Iterator<Integer> it = alst.get(i).iterator();
                boolean bFirst = true;
                while (it.hasNext()) {
                    if (!bFirst) {
                        System.out.print(" ");
                    } else {
                        bFirst = false;
                    }
                    System.out.print(it.next());
                }
                System.out.println("");
            }
        }
    }
    
    private static void move(int a, int b, int n) {
        if (n <= 0) { return; }

        int c = findSpace(a, b);
        
        // a -> c に 盤1 〜 N-1 を移動
        move(a, c, n-1);

        if (nT <= 0) {  // 残り回数チェック
            return;
        }
        
        // a -> b に 盤N を移動 
        int tmp = alst.get(a).pop();
        alst.get(b).push(tmp);
        --nT;   // 回数を -1 する

        // c -> b に 盤1 〜 N-1 を移動        
        move(c, b, n-1);
    }
    
    // a,bと異なる3本目の塔cを返す。
    private static int findSpace(int a, int b) {
        if (a > b) {
            int tmp = a; 
            a = b;
            b = tmp;
        }
        
        if (b == 1) { return 2; }
        if (a == 1) { return 0; }
        return 1;
    }
    
}
```

# 解説
## 標準入力からの数値の読み取り
Scanner インスタンスを作り、nextInt()メソッドで数値を取得しています。

## 解き方
1 〜 N の円盤が積まれている柱を a、移動先を b、残りの柱を c とすると、
1. 1 〜 N-1 の円盤の山を a から c に移動する
2. N番目の円盤を a から b に移動する
3. 1 〜 N-1 の円盤の山を c から b に移動する

これらの処理を、N-1, N-2, ..., 1 について行えば良いことがわかります。これを再帰関数を用いて実現しています。

## メソッドの説明
### printStack()
3本の柱にある円盤のそれぞれの状態を表示します。
+ 柱（Stack）が空の場合は、"-"を表示しています
+ それ以外の場合は、Stackの中身を順に表示しています。なお、余計な空白を表示させないために。bFirstフラグを設定しています

### move()
再帰処理で円盤の移動を行います。n=0の時、再帰処理を終了しています。

### findSpace()
3本の柱のうち2本を指定すると、残りの1本の番号（0 〜 2）を返します。
【ゲーム開発/C言語/基礎の勉強】#1 環境構築

# 目的
ゲーム開発でよく必要になる環境を構築する。
基礎となるC,C++,C#がコーディングできる環境を構築する

# 必要環境
・Windows

# この記事で構築する環境
・Visual Studio

# 手順

### [手順1] VisualStudioをダウンロード
下記ページからダウンロードを行います
[Visual Studio ダウンロードページ](https://visualstudio.microsoft.com/ja/downloads/)

![visual_studio_download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3863522/953c965e-05ce-5fa2-bb45-dfb49d540082.png)

### [手順2] VisualStudioをインストール
ダウンロードしたexeを実行するとダウンロードする項目が選べるので下記のように選ぶ
・[必須].NETデスクトップ開発 (C#で開発する場合必須)
・[必須]C++によるデスクトップ開発 (C++で開発する場合必須)
・[必須]C++によるゲーム開発 (DirectXやUnrealはよく使用する)
・[任意]Unityによるゲーム開発 (Unityでゲーム開発したい場合必要)
![visual_studio_install.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3863522/8644f7cd-0a65-12c3-58db-a20e436b9477.png)

### [手順3] VisualStudioの設定
VisualStudioのインストールが終わったら起動してください。
VisualStudioはよく使用するのでタスクバーにピン留めしておくと便利です。
Visual Studioが起動したら、「コードなしで続行(W)」をクリックします。

「ツールバー>ツール>オプション」で各種設定を行います。
勝手にテキストが編集される系のものをOffにしていきます。

| 項目 | 値 | 概要 |
|:-|:-|:-|
| テキストエディター>全般><br>マウスクリックを有効にして[定義へ移動]を実行する | Off | CtrlやAltはよく使用するので邪魔になる |
| テキストエディター>C/C++><br>自動かっこ挿入 | Off | 好みの問題 |
| テキストエディター>C/C++><br>コードスタイル>書式設定 | すべてOff | 勝手に編集されたくないのでOff |
| テキストエディター>C#><br>自動かっこ挿入 | Off | 好みの問題 |
| テキストエディター>C#><br>コードスタイル>書式設定 | すべてOff | 勝手に編集されたくないのでOff |
| テキストエディター>C#><br>詳細>貼り付け時に欠落しているusing(ry | Off | 不要なusingが追加されてビルドできなくなる |
Nerves Livebookで取り込んだデータをグラフ表示

# 

MPU6050センサーの値をNervesで取り込みできるようになりました。
測定結果をグラフ表示して正しい値がとれてるか動作を確認してみます。

# Nerves Livebook

Livebookを使えば、簡単にグラフ表示できるので、Nerves Livebookを使ってみます。
はじめて使ってみたので、気になった部分をメモしておきます。

- Mix.installでもモジュールのインストールはできないけど、よく使うモジュールはインストールされている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532235/0540cef4-c282-8898-fee9-635c260da6e1.png)

- Circuits.I2C、Circuits.GPIO、Nxがあるので困る事はなさそう
- VegaLiteでデータをグラフ表示できる
- Nxもつかえる

## ハマりポイント１

GenServerとの通信がTimeoutになってうまくいかない。簡単なGenServerだと問題ない。

原因
デフォルトの5秒のタイムアウトでは足りなかった。GenServer.callのタイムアウトを大きくして実行すればうまくいった。
素のNervesのiexから操作した時は、問題ありませんでしたが、Livebookから使うと時間かかるようです。

## ハマりポイント２

一度、GenServerを起動すると、止められず、Livebookを再起動しないと再実行できない。

原因
普通のセルの中に書いていると、プロセスが終了しないので、起動したGenServerは止まりません。
Reconnect and setupのセルにプログラムを書くとセルの評価で、GenServerが止まった状態になりました。
このセルを評価した時に、新しいプロセスとして起動するのだと理解しました。

# 取得したデータをグラフ表示する

```Elixir
# データをマップに変換
formatted_data = 
  GenServer.call(pid, :get_log, 100000)
  |> Enum.map(fn {yaw, pitch, roll, sampling_number} ->
  %{
    yaw: yaw,
    pitch: pitch,
    roll: roll,
    sampling_number: sampling_number
  }
end)

vl_spec =
  VegaLite.new(
  title: "MPU6050",
  width: 600,
  height: 500
  )
  |> VegaLite.data_from_values(formatted_data)
  |> VegaLite.transform(fold: ["yaw", "pitch", "roll"], as: ["key", "value"])
  |> VegaLite.mark(:line)
  |> VegaLite.encode_field(:x, "sampling_number", type: :quantitative)
  |> VegaLite.encode_field(:y, "value", type: :quantitative)
  |> VegaLite.encode_field(:color, "key", type: :nominal)

    # グラフをLivebookに表示
Kino.VegaLite.new(vl_spec)
```

# 測定結果

roll, pitch方向に傾けてみた時の測定結果です
傾けた後、水平に戻した時に、正確に0に戻っているので、精度もよさそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532235/51d3c4dd-f35d-b58c-2937-3f190d70c1d3.png)

# まとめ

- Raspi zero Wでは、遅いけど、Livebookを使えた
- 取り込んだデータを表示するのに便利
- 初期化が絡むものは、setupのセルに書く

今回の角度の取得は、complementaryフィルタを使ってますが、Nxが使えるので、カルマンフィルターの実装が簡単にできるのかも。カルマンフィルターについてもうちょっと理解できたら、試してみたいです。
初学者Reactプロジェクト作成方法

# はじめに
Reactを勉強しようと思い、動画を参考にプロジェクトを作成してみた。

作成方法が二通りありましたので、まとめてみました。
また動画と変わっている部分があったので参考までに。


# 前提
__Node.jsインストール済み__

まだの方は、下記リンクからダウンロード

https://nodejs.org/en/download/package-manager

# プロジェクト作成手順方法 ①
```
npm create-react-app プロジェクト名
```
###### デメリット
ちょっと作成に時間かかる

# プロジェクト作成手順方法 ②
```
npm create vite@latest

>Project name: プロジェクト名入力
>Package name: プロジェクト名入力
>Select a framework: React選択      (他候補---vite etc..)
>Select a variant: JavaScript選択   (他候補---TypeScript etc..)
```
ここまで入力、選択し終わると
```
Done. Now run:

  cd react-todoList
  npm install
  npm run dev
```
と表示されるので、上記コマンドを実行する。
そうすると、localhostでアクセスできるようになる。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634951/371fe08c-7888-5b9e-e8d0-62c4b4ce67cb.png" width="300"/>


###### メリット
- 選択肢があるので好みなどで選べる
- 作成インストールもそんなかからない


# 参考動画
説明わかりやすくて好きです。
ありがとうございます:blush:

https://youtu.be/nRCNL9T3J98?si=fbk2R6yWIZ24ngiy

https://youtu.be/uuAdVs7sbAs?si=4ClVRV-voMZoFnUp


# 最後に
多少のJapascriptの理解でReact触ると難しい...
ただコンポーネントの概念はLaravelで学べたのでReact学ぶ入り口はスムーズだと感じた。
【合格体験記】Python 3 エンジニア認定実践試験

## はじめに
前回に続き、Python 3 エンジニア認定実践試験の受験所感を記事にしようと思います。
Python 3 エンジニア認定データ分析試験は以下記事にしているので、よろしければ併せてご覧ください。

https://qiita.com/mmm_qiita/items/77f6050acb9254d4d04a

## Python 3 エンジニア認定実践試験とは
概要は以下となります。

:::note warn
記事投稿時の情報となり、内容が変更される可能性がありますので、受験される際はご自身でもお調べいただくことをおすすめいたします。
:::

| 内容 | 詳細 |
| ---- | ---- |
| 主催 | 一般社団法人Pythonエンジニア育成推進協会 |
| 試験内容 | ・より実践的なPython文法を出題<br>　※Python 3 エンジニア認定基礎試験の上位資格 |
| 試験時間 | 75分 |
| 試験形式 | 選択式 |
| 問題数 | 40問 |
| 合格ライン | 70%（28問以上の正解で合格） |
| 受験料金 | 一般: 13,200円（税込）/ 学生: 6,600円（税込） |
| 試験会場 | 全国のオデッセイコミュニケーションズCBTテストセンター |

また教材が用意されており、その中から出題されます。

[Python実践レシピ](https://www.amazon.co.jp/Python%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E8%82%B2%E6%88%90%E6%8E%A8%E9%80%B2%E5%8D%94%E4%BC%9A%E7%9B%A3%E4%BF%AE-Python%E5%AE%9F%E8%B7%B5%E3%83%AC%E3%82%B7%E3%83%94-%E9%88%B4%E6%9C%A8-%E3%81%9F%E3%81%8B%E3%81%AE%E3%82%8A/dp/4297125765)
※出題範囲が公開されていますので、チェックしておくと効率よく学習できます。

## 合格するまでの道のり
前提として、以下を先にお伝えしておきます。

・Pythonの実務経験なし
・データ分析系の業務に従事
・プライベートで触ったことがある程度（AIモデル作成など）
・同資格の"基礎試験"はスキップ
・同資格の"データ分析試験"は取得済み

実践試験は、基礎試験の上位資格ではありますが実務で必要そうな文法知識を学べたので、受験して良かったです。
じっくり基礎から学びたい方は基礎試験から、基礎知識があるor実務で使用する文法をいち早く学びたい方は実務試験からでもいいかもしれません。

資格勉強としてやったことは主に、

①主教材（[Python実践レシピ](https://www.amazon.co.jp/Python%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E8%82%B2%E6%88%90%E6%8E%A8%E9%80%B2%E5%8D%94%E4%BC%9A%E7%9B%A3%E4%BF%AE-Python%E5%AE%9F%E8%B7%B5%E3%83%AC%E3%82%B7%E3%83%94-%E9%88%B4%E6%9C%A8-%E3%81%9F%E3%81%8B%E3%81%AE%E3%82%8A/dp/4297125765)）に目を通す
②模擬試験アプリ（[ExamApp](https://python-basic.com)）を9割正解するまでひたすら解く
③②の模擬試験アプリで疑問が残った箇所は①の主教材で補填する
④見慣れてしまったら他サイトの模擬問題を漁ってひたすら解く

データ分析試験と同様、基本的に模擬試験アプリ⇄主教材を行き来してました。

ですが、データ分析試験と比べて実践試験は他サイトの模擬問題があまりなかったので、④はあまりできませんでした。
とはいえ②の模擬アプリが自分にとって非常に助かったので、安心して試験に挑むことができました！

## 試験の所感
データ分析試験と同様、メモ用紙は配布されなかったです。
頭の中で考えて解く必要があります。
中には「得られる結果はどれか？」のような問題もあったので、メモで整理したいな～と思いながらがんばって解いた記憶があります。

試験時間はデータ分析試験より少々長く、解き終わるのにも20分程だったと思います。
見直しをすればするほど「答えどっちなんだろう？」と迷う部分も多く、合格ライン超えられるかな。。と心配しながら何回も解き直しました。
「もう勢いだ！」と制限時間を待たずに試験終了しました。
無事合格できたのでよかったです。

## 最後に
今回は、Python 3 エンジニア認定実践試験についてお話いたしました。
"Python 3 エンジニア認定データ分析実践試験"という最近できたデータ分析試験の上位資格もあるので、時期を見て受験しようかなと考えています。

最後までお読みいただき、ありがとうございました:snake:
supabaseのテーブルにデータを追加しリロード時に初期表示する際に躓いた話

# 今回記事を書こうと考えた背景について
* supabaseのテーブルにデータを追加して画面に初期表示させるまで時間がかかってしまった
* 登録ボタンをクリックした後の入力欄の初期化がsupabaseのテーブルに追加する処理を実装していた時に動かなくなってしまったから

# うまく動かなかった原因について
* try、catchのtryブロックの中でreturnをしていて処理が終わってしまっていたこと
* 入力したデータをリストに追加する処理に使用していた変数（newRecord）がブロック外にあって参照不可だったこと

# 問題のコード
```App.jsx
const handleRegister = async () => {
    if (!inputs.content || inputs.time === "" || inputs.time === null) {
      setError("入力されていない項目があります。");
    } else {
      const newRecord = {
        title: inputs.content,
        time: parseInt(inputs.time, 10),
      };

      try {
        const { data, error } = await supabase
          .from("study-record")
          .insert({ content: newRecord.title, time: newRecord.time })
          .select();
        if (error) {
          throw error;
        }
        return data;
      } catch (error) {
        console.error("Error insert addData:", error);
        return;
      }
    }
    const newRecords = [...records,newRecord];
    setReCords(newRecords);
    setInputs({content:"", time:""});
    setError("");

    const newTotalTime = newRecords.reduce((sum, record)=> sum + record.time, 0);
    serTotalTime(newTotalTime);
  };

```
# 解決法
* if文の外のブロックからでも変数が参照できるように関数の一番上のところで変数を定義してブロックの外からでも参照できるように変更する
* return dataを削除する
 ⇒returnがあるとそこで処理が終わってしまってそれ以降の処理が走らなくなるから
  ⇒その為入力欄の初期化ができていなかった

# 解決したコード
```App.jsx
const handleRegister = async () => {
    let newRecord;
    if (!inputs.content || inputs.time === "" || inputs.time === null) {
      setError("入力されていない項目があります。");
      return;
    } else {
      newRecord = {
        title: inputs.content,
        time: parseInt(inputs.time, 10),
      };

      try {
        const { error } = await supabase
          .from("study-record")
          .insert({ content: newRecord.title, time: newRecord.time })
          .select();
        if (error) {
          throw error;
        }
      } catch (error) {
        console.error("Error insert addData:", error);
        return;
      }
    }
    const newRecords = [...records, newRecord];
    setReCords(newRecords);
    setInputs({ content: "", time: "" });
    setError("");

    const newTotalTime = newRecords.reduce(
      (sum, record) => sum + record.time,
      0
    );
    serTotalTime(newTotalTime);
  };
```
## 補足
上記の問題のconst { data, error } = await supabaseでdataを入れているが、 
const newRecord = 
{
        title: inputs.content,
        time: parseInt(inputs.time, 10),
      };で学習内容、学習時間をnewRecordというオブジェクトに入れていて次のコードのconst { data, error } のdataには同じものが入っているのでdataは今回いらない
※timestamp等ほかに戻り値として使いたいものもないから
Laravel 学習(サービスプロバイダ)

## 用語

https://qiita.com/_wow_/items/79246b8d8268708dafe7

## サービスプロバイダ

Laravelプロジェクト直下で下記コマンドを実行する。

``` cmd
php artisan make:provider HelloServiceProvider
```

下記ファイルが作成される。
``` php:Laravelプロジェクト\app\Providers\HelloServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class HelloServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap services.
     */
    public function boot(): void
    {
        //
    }
}

```

- register
サービスの登録で使う

- boot
アプリ起動時の処理
ビューコンポーザの利用ができるようになる

下記ファイルに上記プロバイダが追加されているのを確認。
※config/app.phpはいじらない。
``` php:Laravelプロジェクト\bootstrap\providers.php
<?php

return [
    App\Providers\AppServiceProvider::class,
    App\Providers\HelloServiceProvider::class,
];
```

## ビューコンポーザの使用

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604560/853930e4-bf0a-4ac1-23d6-47e9f4232612.png)

/helloにアクセスすると上図のようになる。


``` php:providers.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\View;
use Symfony\Component\CssSelector\Node\FunctionNode;

class HelloServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap services.
     */
    public function boot(): void
    {
        View::composer(
            'hello.index', 'App\Http\Composers\HelloComposer'
        );
    }
}
```

``` php:Laravelプロジェクト\app\Http\Composers\HelloComposer.php
<?php
namespace App\Http\Composers;

use Illuminate\View\View;

class HelloComposer
{
  public function compose(View $view) {
    $view->with('view_msg', 'ComposerのMSG');
  }
}
```

``` php:Laravelプロジェクト\resources\views\hello\index.blade.php
@extends('layouts.helloapp')

@section('title', 'タイトル')

@section('menubar')
   @parent
   showの値
   <li>子</li>
@endsection

@section('content')
   <p>コンテンツ</p>
   <p>何か記述する</p>
   
   <p>msg: {{$msg}}</p>
   <p>view_msg: {{$view_msg}}</p>
@endsection

@section('footer')
   <h2>フッター</h2>
   <p>フッターを記載します。</p>
@endsection
```

``` php:Laravelプロジェクト\resources\views\layouts\helloapp.blade.php
<html>
<head>
  <title>@yield('title')</title>
</head>
<body>
  <h1>@yield('title')</h1>
  <hr size="1">
  @section('menubar')
  <h2 class="menutitle">メニュー</h2>
  <ul>
    <li>親1</li>
    <li>@show</li>
    <li>親2</li>
  </ul>
  <hr size="1">
  <div class="content">
    @yield('content')
  </div>
  <hr size="1">
  <div class="footer">
    @yield('footer')
  </div>
</body>
</html>
```

``` php:Lravelプロジェクト\routes\web.php
Route::get('/hello','App\Http\Controllers\HelloController@index');
```

## 参考

https://qiita.com/hitochan/items/ec3ccfe0c051e8565f4a
React-pdf を使ってみた

# はじめに
この記事では。PDF を生成するライブラリである React-pdf の基本的な使い方について記載します。

https://react-pdf.org/

# 開発環境
開発環境は以下の通りです。

- Windows11
- React 18.3.1
- React-pdf 3.4.4
- TypeScript 5.5.3
- Node.js 20.13.1

# インストール
まずは React-pdf をインストールします。

```powershell
npm install @react-pdf/renderer --save
```

# PDF の生成
React-pdf が提供するコンポーネントや API を利用して PDF のスタイルを定義します。

```PDFDocument.tsx
import {
  Document,
  Page,
  StyleSheet,
  Text,
  View,
} from "@react-pdf/renderer";
import { FC } from "react";

const styles = StyleSheet.create({
  page: {
    flexDirection: "row",
    backgroundColor: "#E4E4E4",
  },
  section: {
    margin: 10,
    padding: 10,
    flexGrow: 1,
  },
});

const PDFDocument: FC = () => (
  <Document>
    <Page size="A4" style={styles.page}>
      <View style={styles.section}>
        <Text>Section #1</Text>
      </View>
      <View style={styles.section}>
        <Text>Section #2</Text>
      </View>
    </Page>
  </Document>
);
```

:::note warn
React-pdf が提供するコンポーネント（タグ）を利用しても表示されません。

```PDFDocument.tsx
export const PDFDocument: FC = () => (
  <Document>
    <Page size="A4" style={styles.page}>
      <View style={styles.section}>
        <Text>Section #1</Text>
        <Text>text</Text>
        <p>paragraph</p>
      </View>
      <View style={styles.section}>
        <Text>Section #2</Text>
      </View>
    </Page>
  </Document>
);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/8490a076-75f8-dcaa-7eb3-a44190b539f3.png)

:::

# PDF のレンダリング
先ほど作成した PDF を `PDFViewe` というコンポーネントを利用してレンダリングします。

```App.tsx
import { PDFViewer } from "@react-pdf/renderer";
import { FC } from "react";
import { PDFDocument } from "../components/PDFDocument";

export const PDF: FC = () => (
  <PDFViewer width="100%" height="100%">
    <PDFDocument />
  </PDFViewer>
);

```

PDF がレンダリングされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/d300bee1-380b-c909-3724-a5371e2eda30.png)

:::note
PDF は iframe タグとして描画されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/71a44459-8b78-da2c-bd07-fe4fbd641402.png)

:::

# 参考
- [React-pdf](https://react-pdf.org/)
投稿 38 Docker 2024/08/07

本日の勉強時間　0.5H

Docker社が開発するコンテナ型の仮想環境の作成・配布・実行に利用するプラットフォーム（コンテナ型アプリケーション実行環境）です。 OSの内部にコンテナと呼ばれる独立したアプリケーションの実行環境を生成でき、異なるOS環境下でも同様の実行環境を構築できます。
ユーザーアクセスポリシーの考慮事項



+ [ユーザーアクセスポリシーの考慮事項](https://help.salesforce.com/s/articleView?id=sf.perm_user_access_policy_considerations.htm&type=5)

**一般情報**
ユーザーアクセスポリシーによって実行されたアクションで別のユーザーアクセスポリシーを開始することはできません。

権限セットライセンスまたは管理パッケージライセンスへのアクセス権を取り消すと、[組織情報] または [インストール済みパッケージ] 設定ページに表示される使用ライセンス数がこれらの更新を反映していない場合があります。

[最近のユーザーアクセスの変更] セクションには、ポリシーで適用された変更のみが表示されます。ポリシーで適用されたアクセス権の変更が、別のユーザーアクセスポリシーまたは手動操作によって上書きされた場合、その変更は [最近のユーザーアクセス権の変更] に表示されなくなります。

ユーザーアクセスポリシーを有効にする場合は、デフォルトで有効になっている拡張インターフェースを使用することをお勧めします。拡張インターフェースを使用してユーザーアクセスポリシーを作成し、その後元のインターフェースに戻った場合、ポリシーのデータを上書きできます。この動作が発生するのは、拡張インターフェースに追加のポリシー項目があるためです。

デフォルトのユーザーアクセスポリシーリストビューを編集して、項目を追加または削除できます。有効なポリシーの管理を容易にするには、[注文] 項目を追加することをお勧めします。

**Active Policies (有効な保険契約)**
一度に 200 件まで有効なユーザーアクセスポリシーを設定できます。パフォーマンスを最適化するために、ビジネス要件に必要なユーザーアクセスポリシーのみを作成することをお勧めします。

有効なユーザーアクセスポリシーに複雑な検索条件や多くの検索条件がある場合、それらを適用するのにより時間がかかる可能性があります。

ユーザーレコードの作成または更新によって複数のユーザーアクセスポリシーがトリガーされると、注文の値が最も小さいポリシーが適用されます。

有効なポリシーは、レコードがポリシーの条件に一致するように更新された場合にのみ既存のユーザーに適用されます。たとえば、ポリシーにユーザーの部署の検索条件が設定されている場合、ポリシーは、部署が条件に一致するように変更されたユーザーにのみ適用されます。このポリシーは、部署がすでに条件に一致するユーザーには適用されません。

有効なユーザーアクセスポリシーでライセンスが割り当てられる場合でも、ユーザーに割り当てる十分なライセンスがない場合、この割り当ての失敗は [最近のユーザーアクセス権の変更] に記録されます。

# 具体的なエラー

+ [最近、2 人のユーザーをプロビジョニングしましたが、アクセスの問題が発生しているという連絡を受けて初めて、2/14 以降、2 つのユーザー アクセス ポリシーが失敗状態になっていることがわかりました。失敗またはレポート時に通知を設定する方法も、失敗が発生したときにどのユーザー レコード/更新が処理中だったかを簡単に判断する方法もわかりません。すべてのユーザーに対して再アクティブ化して再実行しました。他のユーザーはエラーを管理するために何をしていますか?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007ZBmgm)


Spring 24 より前には正常に動作していた同じ UAP が再び安定していることを確認しました。on create と update は失敗していましたが、on create は確実に動作していました。確認したところ、どちらも数週間にわたって問題なく動作しています。
paiza * qiita記事投稿キャンペーンに参加してみた：Dランクスキル「文字の一致 C編」

# はじめに
組み込みソフトエンジニアとして働いているHyonkichiです。最近ではWEBアプリケーションの開発やAIに興味を持ち、Qiitaを触り始めました。今回が初めての記事投稿となります。paizaとQiitaのキャンペーンを見かけた際、ちょうど良い演習の機会だと感じ、挑戦してみることにしました。この記事では、その演習を通して取り組んだ問題について、解答コードや解説をまとめていきます。


# 問題へのリンク
https://paiza.jp/works/mondai/d_rank_skillcheck_sample/diff_str

# 解答コード
```c
#include <stdio.h>
#include <string.h>
int main(void){
    // 自分の得意な言語で
    // Let's チャレンジ！！
    char str[1000];
    char str1[100], str2[100];
    fgets(str, sizeof(str), stdin);
    sscanf(str, "%s\n", str1);
    fgets(str, sizeof(str), stdin);
    sscanf(str, "%s\n", str2);
    
    if( strcmp((char *)&str1[0], (char *)&str2[0]) == 0 )
    {
        printf("OK");
    }
    else
    {
        printf("NG");           
    }
    return 0;
}
```

# 解説
今回の問題では、文字列の一致検出を行うプログラムをC言語で実装しました。具体的には、標準ライブラリのstrcmp関数を使用して、2つの文字列が一致するかどうかを判定しています。
*この手の問題に標準ライブラリを使用することはマナー違反？とも思いましたが、大目に見てください..

strcmp関数は非常に便利ですが、使用する際にはいくつかの注意点があります。例えば、strcmpは一致しているかどうかを判定するために、文字列を先頭から順に比較しますが、1つでも違う文字があるとその時点で比較を終了し、違いを示す値を返します。そのため、完全一致だけでなく、部分一致や大小比較の結果を返すこともあり、意図せず不正確な結果を得る可能性があります。

また、strcmp関数は大文字小文字を区別するため、同じ内容でも文字の大小によっては一致しないと判定されることもあります。このような点を考慮し、使い方には注意が必要です。

# 終わりに
今回の記事投稿を通して、初めてQiitaでの情報発信に挑戦しました。今後も継続的にQiitaを活用していきたいと考えています。Qiitaを通じて他のエンジニアの方々との交流を深めながら、C言語以外の言語も勉強していきたいと思っています。どうぞよろしくお願いいたします。
AWS環境構築時のハマりポイント備忘録①

本記事は私がAWS環境構築をするなかでうっかり忘れてハマってしまうポイントを今後のためにまとめたものです。

## 1. DBを作成する前にサブネットグループを作成すること
サブネットグループは複数のサブネットにまたがるグループであり、サブネットを作成後に別途作成が必要。

例）プライベートサブネット（az-a）と（az-d）があるとした場合、それらをサブネットグループとして事前に作成した上でRDSに紐づける必要がある。

:::note warn
RDS作成時に紐づけるサブネットもしくはサブネットグループを紐づける必要があり、RDS作成後はその設定を変更することができない。
変更したい場合はRDSの再作成が必要（時間がかかる）
:::

## 2．VCP内にLambdaを配置しRDSと内部通信する場合
AWSはLambdaをVPC外に配置することを推奨しているが、LambdaとRDSを内部通信させたい場合はVPC内にLambdaを配置する必要性が出てくる。
サブネットのプライベートIPアドレスを浪費するため、他のAWSリソースに影響が出ないようLambda専用のサブネットを用意すること。（AWS推奨）

:::note warn
RDSのセキュリティグループにてLambdaからのアクセスを許可すること。（Lambda専用のサブネットを作成し、そのサブネットからのアクセスを許可する）
参考URL
https://devlog.arksystems.co.jp/2018/04/04/4807/
:::

1リクエスト1インスタンスとなるので、需要が高まったときには必然的に多くのインスタンスが立ち上がる構成になります。この時、インスタンス が RDS のコネクションを取得している場合、多くのデータベースコネクションを取得することにより、データベース側の負荷が高まってしまう。

:::note warn
Lambda + RDS proxy + RDS構成にしてコネクションのプーリングを行うこと。
:::


## 3. IAMユーザーのNameは吟味してからつけよう
IAMユーザーは一度作成するとNameを変更できない。

:::note warn
IAMユーザーのNameを変更したい場合は再作成が必要となる。
IAMユーザーのNameを正しく設定できているか、見直してから作成したほうがよい。（すぐに作成できるので大した痛手ではないが、手戻りは少ないほうが良い）
:::
## 4．AWS WAFのWeb ACLのNameも吟味してからつけよう
Web ACLは一度作成するとNameを変更できない。

:::note warn
Web ACLを作成し、ruleなど作成した後にNameの変更の必要性が出てきた場合にまた新たに新規作成する必要があるため特に困る。（Web ACLは設定のコピーとかできるのかな？）
:::

以上です。
IAMユーザーにWAFのWeb ACLに、Nameを変更できない仕様なのは何故でしょうね。不便。
またハマりポイントが出てきたら備忘録②としてまとめたいです。
読んでいただきありがとうございました。
Refresh Tokenのまとめ

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめN～Z](https://qiita.com/Keiji_otsubo/items/92f92bb9f668ca9688be)


+ [Amazon AppFlow](https://qiita.com/Keiji_otsubo/items/03bed8ce52e8d1544cf1)
+ [Salesforce OAuth 2.0 JWT Bearer フロー](https://qiita.com/Keiji_otsubo/items/4fedb8a2b2e582baf607)
+ [Named credential 指定ログイン](https://qiita.com/Keiji_otsubo/items/00b5e70f3279df9614b2)
+ [CURLコマンドを使ってfreee APIにアクセスする](https://qiita.com/Keiji_otsubo/items/723a1535cc8babb343b7)
+ [Bad Request](https://qiita.com/Keiji_otsubo/items/2e96872af51294711184)

# エラー

+ [【未解決】Refresh Token gets expired error one time but works right the next time](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007eqko4)

:::note alert
status:400,content:{"error":"invalid_grant","error_description":"expired authorization code"}
:::

+ [【未解決】GAS連携中のアクセストークン切れエラーについて知見ある方お助けください…！](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007cmX4ESAU)

:::note alert
トークンが無効か、有効期限が切れています。もう一度お試しください。
:::

+ [Refresh Token Issue](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007erPLkSAM)

:::note
It's typical for access tokens to expire after two hours, so if you're encountering expiration in a shorter timeframe, it might be due to specific policies in your SF Environment. Check the settings in your connected app's OAuth Policies. 

Also, check the following article links, which might help you resolve this issue.

https://help.salesforce.com/s/articleView?id=sf.connected_app_manage_oauth.htm&type=5
:::
ヨーロッパ中央銀行(ECB)からデータを取得する

ヨーロッパ中央銀行（ECB）は最近、新しいデータポータルを開設しました。これにより、研究者やアナリストは、経済や金融データの宝庫にアクセスできるようになりました。この新しいデータポータルは、旧来の統計データウェアハウスに取って代わり、より使いやすくなっています。


## ステップ1
まず、新たに導入された ecbdata ライブラリを使います。

ecbdata ライブラリは、ECBデータポータルから自動的にデータをダウンロードできるように設計されたPythonパッケージです。ほんの数行のコードで、最新の経済指標や銀行統計などにPython環境から簡単にアクセスできます。

```
pip install ecbdata
```

## ステップ2
下記から取得したいデータのシリーズidを取得
https://data.ecb.europa.eu/data/data-categories#total

## ステップ3
データを取得しグラフにする
コードを実行することで、2010年以降のユーロ圏のインフレ率データを取得し、グラフに表示できます。
```
import pandas as pd
import matplotlib.pyplot as plt
from ecbdata import ecbdata

# インフレ率データを取得
df = ecbdata.get_series('ICP.M.U2.N.000000.4.ANR', start='2010-01')

# データの整形とプロット
df.TIME_PERIOD = pd.to_datetime(df.TIME_PERIOD)
df = df.set_index('TIME_PERIOD')
df.OBS_VALUE.plot()

# グラフを表示
plt.show()
```

## 参照
https://medium.com/@lucamingarelli/easy-access-to-ecb-data-in-python-6015b65dcc0e
【ChatGPT＋Code Interpreter】でサムネイルを作ります。


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

　今回は、サムネイルを作ります。

:::note info
本記事は、ChatGPT（有料版）
で行なっております。画像は
ありません。あしからず。
:::

　ニュースはないので、
　　さっそく本題です。

　サムネイルとは
　　なんでしょうか？

***
***user***
“サムネイル”について教えてください

***GPT-4o***
「サムネイル」（thumbnail）は、主にデジタル画像や動画の世界で使われる用語で、オリジナルの画像やビデオの縮小版を指します。サムネイルは、小さなサイズで表示されることを目的としており、コンテンツを簡単にプレビューしたり、一覧表示したりするために利用されます。

### 主な特徴と用途：
1. **縮小版**: サムネイルはオリジナルのコンテンツよりもはるかに小さなサイズで表示されるため、ユーザーが大きなファイルを開かずに内容を簡単に確認できるようにします。

2. **ナビゲーション**: 画像や動画が多く含まれるウェブサイトやギャラリーで、ユーザーが目的のコンテンツをすばやく見つけるために使われます。

3. **負荷軽減**: サムネイルを表示することで、ウェブページの読み込み速度が向上し、サーバーへの負荷も軽減されます。ユーザーは必要に応じて、フルサイズの画像やビデオをクリックして表示することができます。

4. **エクスペリエンスの向上**: サムネイルは視覚的に整ったレイアウトを提供し、ユーザーエクスペリエンスを向上させる役割も果たします。

例えば、YouTubeでは、各動画にサムネイルが設定されており、ユーザーがどの動画を再生するか選択する際の決め手の一つになっています。また、写真ギャラリーや電子商取引サイトでも、商品のサムネイルが多用されており、これによりユーザーは商品を選びやすくなっています。

サムネイルは、コンテンツの要点や魅力を視覚的に伝えるための重要な要素と言えます。

***user***
サムネイルのサイズは？

***GPT-4o***
サムネイルのサイズは、使用する目的やプラットフォームによって異なりますが、一般的には次のようなサイズがよく使われます。

### 一般的なサムネイルサイズ:
1. **YouTube**:
   - 推奨サイズ: 1280 x 720 ピクセル
   - 最小幅: 640 ピクセル
   - アスペクト比: 16:9
   - ファイルサイズの上限: 2MB

2. **ウェブページのギャラリーやブログ**:
   - 小サイズ: 150 x 150 ピクセル
   - 中サイズ: 300 x 300 ピクセル
   - 大サイズ: 400 x 400 ピクセル以上

3. **電子商取引サイト（例: Amazon, 楽天）**:
   - サムネイルサイズは通常 150 x 150 ピクセルから 300 x 300 ピクセル程度がよく使われます。

4. **ソーシャルメディア（例: Facebook, Twitter, Instagram）**:
   - サイズはプラットフォームごとに異なりますが、一般的に 400 x 400 ピクセル前後の正方形のサイズが多く使われます。

### 注意点:
- サムネイルはオリジナルの画像や動画よりも小さなサイズで表示されるため、解像度を低くしても視認性が保たれるようにすることが重要です。
- アスペクト比を維持することが重要で、画像が歪んで表示されないように気をつけます。
- サムネイルの最適なサイズは、使うプラットフォームや用途に応じて設定するのが理想的です。

これらのガイドラインを参考にして、コンテンツに最適なサムネイルサイズを選択することができます。
***

　ここでは
　　複数画像を
　　　サムネイル化します。

　手順は
　❶GPT-4oであることを確認
　❷画像をアップロード
　❸Prompt入力
```Text:
CodeInterpreterで、サムネイルを作成してください。
```
　❹送信
　❺ダウンロードリンクが表示

　特にサイズ指定などは
　　していませんが、
　　　上のPromptだと
　　　　600×300で生成されました。

　用途を指定しても
　　いいかもしれませんね。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
100-1：CSS基礎の学習（5/91）

# カリキュラム一覧
- <font color="FireBrick"><strong>レスポンシブウェブデザイン 認定講座　　　　　　　　　　　　　　←　今ココ</font>
- JavaScript アルゴリズムとデータ構造 (ベータ版) 認定講座
- フロントエンド開発ライブラリ 認定講座
- データ可視化 認定講座
- リレーショナルデータベース 認定講座
- バックエンド開発と API 認定講座
- 品質保証 認定講座
- Python を用いた科学計算 (ベータ版) 認定講座
- Python を用いたデータ分析 認定講座
- 情報セキュリティ 認定講座
- Python を用いた機械学習 認定講座
- Python を用いた代数学 認定講座

# 内訳（レスポンシブウェブデザイン　認定講座）
#### コース1
- [x] HTML の学習: 猫の写真アプリを作成する
- [ ] CSS 基礎の学習: カフェメニューを作成する <font color="FireBrick"><strong> ←　進捗：5/91step
- [ ] CSS 色指定の学習: カラーマーカーのセットを作成する
- [ ] HTML フォームの学習: 登録フォームを作成する
- [ ] 認定プロジェクト

#### コース2
- [ ] CSS ボックスモデルの学習: ロスコの絵画を作成する
- [ ] CSS フレックスボックスの学習: フォトギャラリーを作成する
- [ ] タイポグラフィの学習: 栄養成分表示ラベルを作成する
- [ ] アクセシビリティの学習: クイズを作成する
- [ ] 認定プロジェクト

#### コース3
- [ ] CSS 疑似セレクターの学習: バランスシートを作成する
- [ ] CSS 中級の学習: 猫のイラストを作成する
- [ ] レスポンシブウェブデザインの学習: ピアノを作成する
- [ ] 認定プロジェクト

#### コース4
- [ ] 技術ドキュメントページ認定プロジェクト
- [ ] CSS 変数の学習: 都市のスカイラインを作成する
- [ ] CSS グリッドの学習: 雑誌を作成する
- [ ] 認定プロジェクト

#### コース5
- [ ] CSS アニメーションの学習: 観覧車を作成する
- [ ] CSS Transform の学習: ペンギンを作成する
- [ ] 認定プロジェクト

# メモ
- スマホアプリでもできるのはよい
- 言語設定英語のままなら、少しは英語の勉強になるかも
【セッションレポート】「ABEMA を支える AlloyDB ベクトル検索で構築するレコメンド システム」に参加しました

# はじめに
本記事はGoogle Cloud Next Tokyo 2024 のDay2(8/2)において AbemaTV 菅 俊弥 氏 が講演された「ABEMA を支える AlloyDB ベクトル検索で構築するレコメンド システム」のレポートです。

# 公式セッション紹介
> アプリケーション開発者を対象に、動画配信サービス「ABEMA」の番組レコメンド機能の一部を担う、AlloyDB を用いたベクトル検索機能の活用方法について解説します。AlloyDB を採用した理由やベクトル検索機能を用いたレコメンド システムの構築手法や運用上の考慮点、そして課題とその実践的な解決策について詳しく説明します。

# 発表資料
- アーカイブ動画は9月に公開されるとのこと(Google Cloud Next Tokyo 2024として)

# 概要／おすすめポイント
AbemaTVにおいて、コンテンツが入稿されてからのレコメンドにおいて幾つかの方式を元々持っていたが、自動のものは新規のコンテンツに対して弱かったり、手動やルールベースのものは鮮度が高いコンテンツ(ニュースとか)に対して弱かったりと課題があったことに対して、ベクトル検索を利用して自動でレコメンドが行えるのでは、というアイデアをもとに開発されたそうです。

セッションでは AlloyDB 上でベクトル検索を行うための具体的なTipsも含まれていたので、AlloyDBを利用してベクトル検索を行ってみたい、という方にマッチすると思いました。

なお、Google Cloudでのベクトル検索については 2023年の DB Tech Showcase で佐藤さんが講演されていたセッション(今さら聞けない！ベクトル検索超⼊⾨])の [レポート](https://inthecloud.withgoogle.com/introduction-vectorsearch-ebook-jp-24/introduction_vectorsearch.pdf) や [動画](https://cloudonair.withgoogle.com/events/next-tokyo/watch?talk=d1-db-01) をおさらいしておくと良いと思います。

# セッション内容の紹介

1. なぜベクトル検索を利用したのか
1. AlloyDBを採用した理由
1. 実際に展開して見えてきたこと

#### 1. なぜベクトル検索を利用したのか

概要でも述べていますが、従来のレコメンドシステムには「コールドスタートとレコメンドのリードタイムを両立させる仕組みがない」という課題がありました。
ベクトル検索を利用することで、上記を両立させることができるのでは？というアイデアがうまれ、検証を行うことになったという事です。

#### 2. AlloyDBを採用した理由

大きな理由としてはコンテンツのデータがAlloyDBに移行されており、且つAlloyDB AI機能でVertex AIモデルがすでに実装されていた、という点になります。身も蓋もない話に思えるかもしれませんが、データを移動することなくベクトル検索が利用できる、というのはいくつかの事例でも同じような話があり、比較的気軽にトライできることは大きなメリットだといえそうです。
その他にも、AlloyDBのSCaNN索引の性能面や、pg_cronやpgvectorなどの拡張機能を始めベクトル検索用の専用レプリカを利用できることなど総合的に判断されたとのことでした。

#### 3. 実際に展開して見えてきたこと

どちらかというとコンテンツの内容との関連になりますが、以下のような調整を行ったという話がありました。
- 消費サイクルが早いニュースなどのコンテンツには古いコンテンツがノイズとして乗ってしまうためpg_cronを活用して検索対象から外す
- 最新のコンテンツはAIモデルが知らない場合もあるため、AIモデルに渡すタイミングで情報を調整

# まとめ

AlloyDB自体が拡張性や耐久性に優れるマネージドなデータベースですが、ベクトル検索を利用してみたい、というときにも問題なく利用できますよ、という点が1番のポイントかなと思います。
ベクトル検索自体は、最近はどのリレーショナルデータベースでも標準で利用できるようになってきていますが(MySQLは標準では未実装)、AlloyDBは Vertex AIとの統合含めて利用しやすくなっているのがよくわかる発表でした。

実際のセッションではどうやって性能問題を解決したのかや、実際のEmbeddingについても触れられていたので、興味ある方はアーカイブが発表されたらぜひ見てみてください。
Reactで簡単な学習記録アプリを作った

# 学習記録アプリをReactで作ってみました

## 作成物


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853126/e0df732e-1bee-f249-4d64-e1755818878f.png)

## 工夫したところ

・学習時間の入力フォームは数値しか入力できないようにした
・無駄なState変数を作らなくても動くようにした（合計時間を計算するときにreduce関数を使用した）

## つまづいたところ

・時間の入力フォームのところで数値しか入力できないようにしたら残り一文字のときにバックスペースを押しても消せなくなってしまった点　→onchangeに設定したイベントハンドラは入力内容が反映されたものが渡されるのだとわかった
Ubuntu + Apple フルキーボードにおいて、xmodmap で「テンキーのカンマ」を入力できるようにする

## やりたいこと

「[Ubuntu + Apple フルキーボードにおいて、udev + xremap + xdotool で「テンキーのカンマ」を入力できるようにする](https://qiita.com/jidaikobo-shibata/items/be318ca855cd0bab8652)」と同じ。Appleの日本語フルキーボードで「テンキーのカンマ」を入力できるようにしたい。

上記記事でも実現できるが、そうとう捻じくれた方法なのと、xdotoolを介するので、少々打鍵がもたつく。

そういえば、xmodmapもあったな、とxmodmapで「テンキーのカンマ」を実装する。

Ubuntu 22.04および24.04で確認した。

## xmodmapの準備

```terminal
vi ~/.xmodmap
```

```vim:~/.xmodmap
keycode 129 = KP_Separator
```
以下で確認。
```terminal
xmodmap ~/.xmodmap
```
## xmodmap.desktopで永続化

ファイルに実行権限を与える。

```terminal
chmod +x ~/.xmodmap
```
autostartディレクトリがなかったら作る。

```terminal
vi ~/.config/autostart/xmodmap.desktop
```
`USERNAME`の部分は自分の環境に合わせること。

```ini:~/.config/autostart/xmodmap.desktop
[Desktop Entry]
Name=run xmodmap at startup
Exec=xmodmap /home/USERNAME/.xmodmap
Type=Application
```

再起動して確認。

## xmodmap.desktopで永続化がうまく行かない場合

理由はよくわからないのだけど、試行錯誤しても.config/autostartでうまく行かない場合がある。その場合は、Ubuntuの「自動起動するアプリケーション」を使う。

```terminal
vi ~/.xmodmap.autostart.sh
```

```vim:~/.xmodmap.autostart.sh
#!/bin/bash           
sleep 3;
xmodmap ~/.xmodmap
```
ファイルに実行権限を与える。
```
chmod +x ~/.xmodmap.autostart.sh
```
Ubuntuの「自動起動するアプリケーション」に`/home/YOURUSERNAME/.xmodmap.autostart.sh`を登録する。

再起動して確認。

:::note info
マシンスペックによるのかもしれないけど、これでもうまく行かない場合は、sleepの長さを増やすとうまく行くことがある。

どうやら、Ubuntuの起動プロセスでxmodmapがibusの起動より早いとibusがxmodmapを上書きしてしまうらしい（詳しくは未確認）。ので、sleepでもろもろ起動しあとにxmodmapが動くようにすると良いらしい。
:::
インスタンスやクラスにどういうメソッドがあるか調べる方法

# はじめに

実務でrubyを書いているのですが、インスタンスやクラスにどういうメソッドがあるか調べる方法を調べてみました。

環境
```
❯ ruby -v                 
ruby 3.2.0
```

# クラスにメソッドが定義されているか調べる

クラスオブジェクトに対してinstance_methodsメソッドを使うと調べられます。
さらにgrepを使って絞り込みました。

instance_methodsメソッドの戻り値はarrayなのでgrepメソッドが使えます
https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/grep.html

```rb
irb(main):017> Range.instance_methods.grep(/each/)
=> 
[:each,
 :each_cons,
 :each_with_object,
 :each_with_index,
 :reverse_each,
 :each_entry,
 :each_slice]
```

## 用途

対象クラスでどんなメソッドが使えるか調べられます。

しかし、公式ドキュメントを探しに行った方が早いかもしれません
https://docs.ruby-lang.org/ja/latest/class/Range.html

## インスタンスに対してはmethodsメソッドで調べられる

インスタンスに対してはmethodsメソッドで利用できるメソッド一覧を調べられる。
同じく戻り値は配列なので、grepで絞り込める

```rb
irb(main):027> [].methods.grep /each/
=> 
[:each_index,
 :reverse_each,
 :each,
 :each_cons,
 :each_with_object,
 :each_with_index,
 :each_entry,
 :each_slice]
 ```

grepメソッドは部分一致検索なので、[メタ文字列](https://docs.ruby-lang.org/ja/latest/doc/spec=2fregexp.html#metachar)を使用しなくてもサクッと調べられるのが良い

 ```rb
 irb(main):030> [].methods.grep /.*each.*/
=> 
[:each_index,
 :reverse_each,
 :each,
 :each_cons,
 :each_with_object,
 :each_with_index,
 :each_entry,
 :each_slice]
```
【AWS】S3バケットの削除手順

## S3バケットの削除
1). S3を開き作成したバケットを選択し「空にする」を押します。
![1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3817084/62660d79-796a-3ecb-ef36-58b143cb5ddc.jpeg)


2). バケット～削除しますか？に「完全に削除」と入力し、「空にする」を押します。
![2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3817084/5542b3e6-9aa1-b8c5-305e-71aa5db9f0c8.jpeg)

3). もう一度バケットを選択し、「削除」を押します。
バケット～削除しますか？にバケット名を入力し、「バケットを削除」を押します。
![4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3817084/2fd161fa-680a-662b-1400-6d232397ca4a.jpeg)

4). 削除されたことを確認して削除作業完了です。
![5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3817084/1a7fcf0b-4fbb-65ab-5ea5-ad6b5d8f354c.jpeg)
【AWS】ディストリビューションの削除手順

## ディストリビューションの削除
1). CloudFrontを開いて作成したディストリビューションを選択し、「無効」を押します。
![1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3817084/a198d892-d868-6eb5-53ad-314be92c90cc.jpeg)


2). 「無効」を押します。
![2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3817084/88ffee66-9621-cf70-35d5-da1ad641c6ac.jpeg)

3). 最終変更日が「デプロイ」から具体的な日時に更新されるまで待ちます。数分かかる場合があります。
![3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3817084/142f521e-e55b-8c29-4f7d-103596dfc264.jpeg)
日時が更新されたら「削除」を押します。
![5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3817084/b65ac885-3fee-9244-41b0-4918b890ed96.jpeg)

4). 「削除」を押し、ディストリビューションが消えてることを確認して完了です。
![6.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3817084/1c78be9e-378f-de55-3374-545f3192f70f.jpeg)
![7.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3817084/c3b03ca5-0767-1730-bc0d-2f93277a4133.jpeg)
【サーブレット/JSP/JDBC】初心者の404エラー原因メモ

初心者が初めてサーブレット/JSP/JDBCを使ってWebアプリケーションを制作する際、404などのエラーで上手く表示されないことがあったので備忘録として残します。

# 使用環境
PC：MacBook Air 2018
OS：macOS Sonoma 14.3.1
IDE：Eclipse 2023
Webコンテナ：Tomcat 10.1.18
RDBMS：MySQL 8.3.0

# 404エラーとは？
404エラー（404 not found）とは、存在しないWebページにアクセスしようとした際に表示されるエラーです。

## web.xmlのservletタグ、servlet-mappingタグのサーブレット名違い
Eclipseでサーブレットを作成した際にweb.xmlにservletタグ、servlet-mappingタグが作成されます。
しかし、サーブレットを右クリック→リファクタリング→名前の変更でサーブレット名を変更してもservletタグ、servlet-mappingタグ内のサーブレット名は変更されず、404エラーが表示されてしまいます。
なので、サーブレット名を後から変更した際はweb.xmlのservletタグ、servlet-mappingタグ内のサーブレット名も修正するようにしています。

 ## servletタグ、servlet-mappingタグが見つからない
 Eclispseでサーブレットを作成する際、「サーブレット」ではなく通常の「クラス」から作成するとservletタグ、servlet-mappingタグが作成されないので404エラーが表示されました。

## JSPファイルのpageディレクティブ内のスペルミス
JSPファイルのpageディレクティブ内にスペルミスがあった場合も、404エラーが表示されました（正：pageEncoding="UTF-8"、誤：pageEncording="UTF-8"など）。

# その他のエラー

## No suitable driver found for
JDBCドライバの準備（Tomcatのlibディレクトリに配置）をせずにJDBCでデータベースに接続しようとしたら、エラー（No suitable driver found for）が表示されました。

## java.lang.IllegalArgumentException
サーブレットの情報をweb.xmlのservletタグ、servlet-mappingタグで指定して、なおかつアノテーションでURLを指定したらjava.lang.IllegalArgumentExceptionのエラー（サーブレット[サーブレット名]と[パッケージ名.サーブレット名]を同じurl-pattern[/サーブレット名] にマッピングすることはできません。）が表示されました。
plotlyで好きなフォントで画像に出力する

plotlyでpngやjpgなどに出力するとき、日本語が豆腐になることがあります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665792/e00bc61f-a0f4-5da1-a19d-5dffea2307be.png" alt="説明" width="500">



matplotlibだと [japanize-matplotlib](https://pypi.org/project/japanize-matplotlib/) をimportして解決する方法が簡便です。plotlyはhtmlに出力するだけなら特に指定せずに日本語を出してくれますが、画像に `write_image` する場合は、豆腐になるのを直す必要があります。

ということで、本記事では画像出力を**好きなフォントにする**方法について紹介します。

※なお、Google colabで実行してます。ほかの環境でも同じことはできるはずなので、ChatGPT先生にでも聞いてください。

# 手順１．install
plotlyの出力に [kaleido](https://github.com/plotly/Kaleido) を使うので、installしておく。
```sh
pip install -U kaleido
```

# 手順２．フォントのダウンロード
ttfファイルをダウンロードする。

Google Font にいろいろある。

https://fonts.google.com/specimen/Zen+Kaku+Gothic+New?preview.text=IPF%20%E3%81%9D%E3%81%AE%E4%BB%96%E7%96%BE%E6%82%A3

https://yutowebdesign.hatenablog.com/entry/2024/02/29/200000

 
游ゴシックの場合これが参考になりそう。

https://note.com/smoo_aran/n/n6546d00a5084

 

# 手順３．フォントの配置
Google colabの場合、uploadしてここに配置すればいけた。

```sh
cp /content/ZenKakuGothicNew-Black.ttf /usr/share/fonts/truetype/ZenKakuGothicNew-Black.ttf
cp /content/NotoSansJP-ExtraBold.ttf /usr/share/fonts/truetype/NotoSansJP-ExtraBold.ttf
cp /content/yugothib.ttf /usr/share/fonts/truetype/yugothib.ttf
```


# 手順４．フォントの反映
これで反映される。
```sh
fc-cache -f -v
```

反映できたかは、以下で確認できる。

```sh
fc-list :lang=ja
```
https://qiita.com/aosho235/items/6dc59b0f3dba373f3564
 

# 手順５．グラフ作成・保存

`update_layout` などでfontを指定できる。

```python
import plotly.graph_objects as go

# グラフデータとレイアウトの設定
fig = go.Figure()

fig.add_trace(go.Scatter(x=[1, 2, 3], y=[4, 5, 6], mode='lines+markers'))

fig.update_layout(
    title='カスタムフォントを使用したグラフ',
    font=dict(size=18, color='black', family='Yu Gothic Heavy'),
    # font=dict(size=18, color='black', family='Zen Kaku Gothic New Black'),
    # font=dict(size=18, color='black', family='Noto Sans JP ExtraBold'),
)

fig.update_layout(
    xaxis_title='X軸',
    yaxis_title='Y軸'
)

# グラフをPNGとして保存
fig.write_image('/content/plot_with_custom_font.png', engine='kaleido')
fig.show()
```


# 結果
なんか微妙に違うのですが、まあ出力したいものに関しては出せてそうなので一旦これで許してください。

| フォント           | notebook       | png                |
|--------------------|-----------------|--------------------|
| Yu Gothic Heavy   | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665792/d6778fd1-9371-feab-4d50-1fb6701920c1.png)| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665792/e0e45f04-25f5-4a23-4a05-a629853659c4.png)）|
| Zen Kaku Gothic New Black   | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665792/50b2e5bb-5c99-abee-eb24-70632d9f1918.png)| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665792/b0644507-ee75-a825-b488-b57943563387.png)|
|Noto Sans JP ExtraBold        |  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665792/36d891bc-458b-be7a-a71a-ce4e8bfe3d12.png)| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665792/52315c23-77dd-d14d-3255-0d627e33d6c1.png)

※notebookのほうはスクショなので範囲は適当
Next.jsでつくったアプリをnetlifyへデプロイする

# 記事概要
[Next.jsの公式チュートリアル](https://nextjs.org/learn-pages-router/basics/create-nextjs-app/setup)をもとに、知人とアプリを作成しています
それをネット上にリリースしたいなぁと思ったところ、netlifyならお手軽にできそうだということで試してみました
その時の作業メモです
（本当はVercel使いたかった...でもGithub organizationとの連携だと有料なんですよね...)

# 環境情報
・next.js 14.2.5
・以下コマンドでプロジェクトを作成済み
```
npx create-next-app@latest {プロジェクト名} --use-npm --example "https://github.com/vercel/next-learn/tree/main/dashboard/starter-example" 
```
※公式チュートリアルは未完了

# デプロイ手順
1 ) [netlify](https://app.netlify.com/login)にログイン


2 )  Add new Site > Import an Existing Project
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771526/0ca77f0a-cbb4-32f0-3404-1d6031e6deca.png)

3 )  インポート元を選択（自分はGithubリポジトリからインポートするので、Github選択）
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771526/3c35156e-c0fe-7a28-3545-a485f7fa2a9a.png)
 

4 )  インポートしたいリポジトリを選択

5 )  デプロイ設定を行い、deploy押下
<table>
  <thead>
    <tr>
      <th>項目名</th> <th>説明</th>
    </tr>
  </thead>
  <tr>
    <td> SiteName </td> <td>サイト名、リリースした際のURLになる</td>
  </tr>
  <tr>
    <td> Branch to deploy </td> <td>デプロイしたいブランチ</td>
  </tr>
  <tr>
    <td> Base directory </td> <td>プロジェクトルート、.nextやappディレクトリの一つ上のディレクトリ名</td>
  </tr>
  <tr>
    <td> Build command </td> <td>"npm run build" ※1</td>
  </tr>
  <tr>
    <td> Publish directory </td> <td>"{プロジェクトルート}/.next"</td>
  </tr>
  <tr>
    <td> Function directory </td> <td>自動挿入される値をそのまま</td>
  </tr>
</table>

デプロイ成功時の自分のアプリのデプロイ設定はこのようになっている
(Site configuration > Build Settings)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771526/2b37214f-5c49-0107-a793-a26939d252a1.png)

※1 事前にローカルでnpm run buildが成功するか確認しておくこと
公式チュートリアルのプロジェクト生成コマンドを流用している場合、以下の通りコンパイルで怒られることがある
```
 Linting and checking validity of types  ..Failed to compile.

./app/ui/acme-logo.tsx:2:26
Type error: Cannot find module '@/app/ui/fonts' or its corresponding type declarations.

  1 | import { GlobeAltIcon } from '@heroicons/react/24/outline';
> 2 | import { lusitana } from '@/app/ui/fonts';
    |                          ^
  3 |
  4 | export default function AcmeLogo() {
  5 |   return (
```
これはfont.tsファイルが不足していることが原因（本当はチュートリアル内で追加するもの）
なので以下にファイルを追加してあげる
> {プロジェクトルート}\app\ui\fonts.ts
```typescript:font.ts
import { Inter,Lusitana } from 'next/font/google';

 
export const inter = Inter({ subsets: ['latin'] });

export const lusitana = Lusitana({
    weight: ['400', '700'],
    subsets: ['latin'],
  })
```
# 環境変数の設定
サイトで利用するシークレットキーなどはリポジトリに上げてしまうのは抵抗があると思います。
なので、そういった機密情報はNetlifyに直接登録します。

１）Site Configuration > Environment Variables > Add a variable
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771526/96b1067b-099b-0232-0cb4-13ba54171737.png)

一つ一つの値を打ち込んで登録する場合は"Add a single variable"
すでにあるenvファイルなどの内容をまとめて登録するには"Import from .env file"を押下し、登録できます