OmniAICreator/Qiita-1.07M huggingface dataset:
AWS Lambdaの「アプリケーション」と「関数」って違うの？

## はじめに

しばらく、Lambdaのよくわかんないことを調べていく記事を書いていきます。

最初の記事は下記`アプリケーション`と`関数`の違いについてです。

![スクリーンショット 2024-12-31 5.24.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894042/3358501f-2c3b-2320-0758-e15129401174.png)

なんか二つあるなぁ。と思ってましたが深く調べたことなかったので調べてみます。

## 関数（Functions）

関数から見ていきます！

Google先生にいろいろ定義を聞いてみても、納得いく答えがなかったのですが、マネコンのヘルプパネルに普通に定義が書いてました。

![スクリーンショット 2024-12-31 5.41.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894042/7095236c-23a6-106c-c898-a2a04be790ae.png)

> [Functions (関数)] ページには、現在の AWS リージョンにあるすべての関数が一覧表示されます。

なので、「関数」は作ったLambdaがそのまま一覧表示されています。

## アプリケーション(Applications)

こちらの定義は以下のようになっていました。

> AWS CloudFormation または他のツール (AWS Serverless Application Model など) を使用してデプロイされたアプリケーションのリストが表示されます。

以前、AWS SAMで作ったツールも以下のようになってました。

`AWSWhatsNewFeeder`がStack名。スタックの中に定義したリソース群のうち、Lambdaに関するものがリソース欄に表示されている模様です。

![スクリーンショット 2025-01-02 5.42.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894042/fc8d4599-c7ac-7dec-f48c-fe85c86c69df.png)

### トリガーや通知先との組み合わせをアプリケーションっていうのでは？

マネコン上で、アプリケーションを作ろうとすると、以下のような画面が出て、アプリケーションの定義が書いてました。

![スクリーンショット 2025-01-02 5.51.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894042/106482cb-694d-f425-fc95-941097f086f5.png)

念のためトリガー、通知先をマネコンから設定しても、やはりアプリケーション側には表示されません。

![スクリーンショット 2025-01-02 6.22.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894042/728b570b-8ef0-4cc3-a008-1ef20a69cd35.png)

アプリケーションに表示される一覧はやはり、どのような構成なのか？ではなく、どうやって作ったのか？が影響してそうです。

## マネコンからアプリケーションの新規作成できるけど？

マネコンから新規作成も可能です。

![スクリーンショット 2025-01-02 6.25.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894042/c2fad75b-e4a1-5d7f-614b-16f1cc09ce09.png)

が、結局はCloudFormation経由での作成となっていそうです。

![スクリーンショット 2025-01-02 6.26.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894042/7cb5d378-7f6e-4571-a189-10a1012aee51.png)

![スクリーンショット 2025-01-02 6.27.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894042/a71d3207-034b-2497-bb40-c27cfeac909c.png)

## まとめ

ということで、「アプリケーション」と「関数」はどうやってLambdaを作ったかで、二分されるみたいです。

が、分けて表示する意図がはっきりわかりませんでした。
もし、わかる人いれば教えていただきたいです！
量子コンパイラを作る。 その13

# 概要
量子コンパイラを作る。
古典論理回路を論理回路アセンブラで書いてみた。

# 半加算器

https://embed.plnkr.co/plunk/Mn4hhEiae2Ixu6ME

```
make 4
in 0 1
out 2 3
xor 0 1 2
and 0 1 3
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/ff23ae81-584f-cf56-886c-c4ee90c747e1.png)


# 全加算器

https://embed.plnkr.co/plunk/pgBqrgcN4L3iwPBw

```
make 8
in 0 2
wire 3 5
xor 1 2 3
and 1 2 4
xor 0 3 7
and 0 3 5
or 4 5 6
out 6 7
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/66f6aab5-7682-6021-d076-4d9f893642ce.png)

#  2bit multiplier　2×2ビットの乗算器


https://embed.plnkr.co/plunk/cnQm2JpfH7kOozKj


```
make 12
in 0 3
and 0 2 4
and 1 2 5
and 1 3 11
and 0 3 6
xor 5 6 10
and 5 6 7
xor 4 7 9
and 4 7 8
out 9 11
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/73ea99bd-5c6d-c068-39c5-7b6b83484281.png)


# 3bit adder　３×３ビットの加算器


https://embed.plnkr.co/plunk/Lvw8FtpmrWm4PMAe


```
make 18
in 0 5
wire 6 13
xor 0 3 14
and 0 3 6
xor 1 4 7
and 1 4 8
xor 6 7 15
and 6 7 9
or 8 9 10
xor 2 5 11
and 2 5 12
xor 10 11 16
and 10 11 13
or 12 13 17
out 14 17
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/d442756a-7fee-fe49-386b-e67e9f5a2d41.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/32112182-3cdc-6530-ac13-4e63ae536e93.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/c2035e0c-6334-b3bb-eb52-ce2e37732333.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/ddfabdf8-a952-6004-d1f7-37ddea9a6f85.png)

以上。
JavaScript_Salesforceのカスタム表示ラベルが数値か判定

JavaScriptで数値か判定するコードだよ！
基本、カスタム表示ラベルは、文字列で渡されるから判定が出来ないんだけど、JavaScriptで判定するメソッド作成したから、応用して使用してみてね！

以下、サンプルコード！
```isStrictNumeric.js
function isStrictNumeric(value) {
    // falsyチェック（空文字、null、undefinedなどはfalse）
    if (!value) {
        return false;
    }
    const pattern = /^-?\d+(\.\d+)?$/;
    
    return pattern.test(value);
}
```


```実行結果.
console.log(isStrictNumeric("123"));        // true   (整数)
console.log(isStrictNumeric("-123"));       // true   (負の整数)
console.log(isStrictNumeric("123.456"));    // true   (小数)
console.log(isStrictNumeric("-123.456"));   // true   (負の小数)
console.log(isStrictNumeric(""));           // false  (空文字)
console.log(isStrictNumeric("Hello"));      // false  (文字)
console.log(isStrictNumeric("123."));       // false  (小数点後に数字なし)
console.log(isStrictNumeric("12.34.56"));   // false  (小数点が2回)
console.log(isStrictNumeric("--123"));      // false  (マイナス記号が2回)
console.log(isStrictNumeric(" 123"));       // false  (先頭にスペースあり)
```


<h1>数値の形式を厳格にチェックするための正規表現</h1>
<dt>const pattern = /^-?\d+(\.\d+)?$/;
    <dd>^ … 文字列の先頭にマッチ<br/>
    -? … マイナス記号 - が0回または1回 (任意、オプション)<br/>
    \d+ … 1桁以上の数字 (整数部分)<br/>
    (\.\d+)? … 小数点 . + 1桁以上の数字 のセットが0回または1回<br/>
    $ … 文字列の末尾にマッチ</dd><br/>
</dt>

つまり・・・
「先頭に一度だけ - をつけられる」
「数字部分を少なくとも1桁入れる」
「小数点は0回または1回」
「小数点がある場合は最低1桁の数字を続ける」
ことを指定しているよ！！！
<br/><br/>

参考になると嬉しいな！！！
LWC_Lightning-pillの動作(削除など)

LWCのLightning-pillの削除などの動作のLWCだよ！
検索などで使用するよね！


以下、完全サンプルコード！

```pill.html
<template>
    <template for:each={labelItems} for:item="pillItem" for:index="index">
        <lightning-pill label={pillItem.label} onremove={removePillItem} key={pillItem.label} name={index}></lightning-pill>
    </template>
</template>
```

```pill.js
import { LightningElement } from 'lwc';

export default class Basic extends LightningElement {
    labelItems = [
        {
            label: 'Pill 1'
        }, 
        {
            label: 'Pill 2'
        }, 
        {
            label: 'Pill 3'
        },
        {
            label: 'Pill 4'
        }
    ];

    removePillItem(event) {
        // `name` 属性を使用してピルのインデックスを取得
        const pillIndex = event.detail.name;
        // ピルアイテムを削除
        this.labelItems.splice(pillIndex, 1);       
        // スプレッド演算子を使用して配列を更新
        this.labelItems = [...this.labelItems];
    }
}
```

<h1>実行結果</h1>
<dt>初期表示:
    <dd>Salesforce LWC、Aura Lightning、Integration、W3web Tutorial の4つのピルが並んで表示されてるよ！</dd>
    <dd>いずれかのピルの “X” アイコンをクリックすると、onremove イベントが発生し、removePillItem メソッドが呼ばれて･･･</dd>
    <dd>removePillItem で、該当ピルを配列から削除し、配列を更新して削除したピルが画面上から消えるよん！</dd>
</dt>

<h1>HTML解説</h1>
<dt>
template for:each={labelItems} for:item="pillItem" for:index="index"
    <dd>labelItems という配列をループさせ、それぞれを pillItem という変数として扱う<br/>
    for:index でループの順番 (0, 1, 2, … ) を取得し、 index として使用</dd>
</dt>
<br/>
<dt>
lightning-pill label={pillItem.label} onremove={removePillItem} key={pillItem.label} name={index}
    <dd>label 属性にはピルに表示する文字列（pillItem.label）をセット<br/>
    onremove 属性には削除イベント（ユーザがピルを消そうとしたとき）をハンドリングするメソッド removePillItem を指定<br/>
    key はループで使われる一意な値で、ここでは単純にピルのラベルを使用<br/>
    name={index} は、削除する際にどのピルが押されたかを識別するため、0, 1, 2,... のインデックスをセット</dd>
</dt>


<h1>JavaScript解説</h1>
<dt>
labelItems (初期配列)
    <dd>ピルとして表示したい文字列を持つオブジェクトの配列</dd>
</dt>
<br/>
<dt>
removePillItem(event)
    <dd>event.detail.name:<br/>
    lightning-pill で name={index} を指定したことで、削除イベント (onremove) には event.detail.name としてインデックス番号が渡ってきます。<br/><br/>
    <dd>this.labelItems.splice(pillIndex, 1):<br/>
    labelItems 配列から、pillIndex 番目の要素を 1件削除。<br/><br/>
    <dd>this.labelItems = [...this.labelItems]:<br/>
    配列をスプレッド構文でコピーし、新しい配列 として代入し直す。<br/><br/>
</dt>

<h3>ポイント: <br/>
ただ splice で削除しただけでは、JavaScript的には同じ配列インスタンスを操作したことになるため、LWC が再レンダリングを検知しない場合があるよ。<br/>
そこで配列をコピーして代入し直すことで、変更を検知→再描画 のトリガーになるよ！</h3>
LWC, Apex_最新の静的リソースをLWCで動的に使用

静的リソースの最新verを、動的に、かつJavaScriptでインポートしないで使用する方法だよ！
<br/>
そもそもLWCで静的リソース使用する場合、importするのが普通だよね！

```Apex.js
import logoImage from '@salesforce/resourceUrl/org1Logo';
```

```Apex.html
// 例: LWC 内で <img> にセット
<img src={logoImage} alt="logo" />
```

ただ、困ったことに静的リソースを更新してみてほしい！最新が反映されないんだよね！<br/><br/>
実は、実行時に実際のURLには静的リソースの「バージョンのタイムスタンプ」が含まれていて、「バージョン更新が頻繁でない」「毎回このコード部分を変更するのが面倒」という場合には、タイムスタンプが入ったURLを直接扱うのが不都合なんだよね。

（例: /resource/1675163571000/org1Logo など）に置き換えらるんだ！
この 数字部分 (1675163571000) は、その静的リソースの「バージョンのタイムスタンプ」を表すよ！

そこでApexでURLを作っちゃおうって訳！！！



まずはサンプルコード！
```MyResourceController.cls
public with sharing class MyResourceController {
    @AuraEnabled(cacheable=true)
    public static String getResourceUrl() {
        StaticResource staticResource = [
            SELECT Name, SystemModStamp 
            FROM StaticResource
            WHERE Name = 'org1Logo'
            LIMIT 1
        ];

        // 動的URLを組み立てて返却
        return '/resource/'
            + String.valueOf(((DateTime)staticResource.SystemModStamp).getTime())
            + '/'
            + staticResource.Name;
    }
}

```


```MyResource.html
<template>
    <img src={urlFileRef} alt="logo" />
</template>
```
           
```MyResource.js
import { LightningElement, api, wire, track } from 'lwc';
import getResourceUrl from '@salesforce/apex/MyResourceController.getResourceUrl';

export default class MyComponent extends LightningElement {
    @track urlFileRef;

    @wire(getResourceUrl)
    wiredUrl({ data, error }) {
        if (data) {
            this.urlFileRef = data; 
        } else if (error) {
            console.error(error);
        }
    }
}
```

<h1>コード解説</h1>
1．JavaScriptのwiredUrl メソッドで Apex側の生成したURLを受け取り、それを urlFileRef に保存<br/>
2．HTML側で {urlFileRef} として <img> の src にセットして常時最新を表示

<br/><br/>
なにか参考になれば嬉しいな！
Apex_一番最上位の取引先名を取得

Apexで取引先階層の一番上の取引先名を、再帰的に取得するコードだよ！

<br/>

まずは、完成形サンプルコードだよ！

```getTopParentAccountName.method
public String getTopParentAccountName(Id accountId) {
    Account acc = [SELECT Id, Name, ParentId FROM Account WHERE Id = :accountId];
    while(acc.ParentId != null) {
        acc = [SELECT Id, Name, ParentId FROM Account WHERE Id = :acc.ParentId];
    }
    return acc.Name;
}
```

<h1>コード解説</h1>
引数の取引先ID(基準)から親Accountを辿り、その親AccountのIdを持って、更に上の親Accountを取得しに行くよ！
最終的に最上位のAccountのNameを返すよ！
説明なんか不要な気がするけど。。。<br/><br/><br/><br/>


なにか力になれれば嬉しいな！
再利用性を高めたWeb Components

Web Componentsを使ってマイクロフロントエンドを実現する方法は多くのプロジェクトで採用されています。

私も仕事でWeb Componentsを扱っていますが、再利用性の部分で課題を感じており、その解決策をこのブログで提案したいと思います。

## 再利用性の課題感

例えば以下のようなコンポーネントを想像します

```html
<h1>My Todo</h1>
<my-todos></my-todos>
```

![スクリーンショット 2024-12-31 14.22.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/c09a9cba-03e6-2732-28c8-1ad59d593554.png)

この`my-todos`コンポーネントは、`todo`の一覧を表示するコンポーネントで、JavaScriptのファイルを読み込むことで、どのサイトでも簡単にこのカスタムエレメントを使用することができます。また、適切にCSSを実装することで、レイアウトも調整できます。

ただ、これは本当に再利用性が高いと言えるのでしょうか？

例えば以下のようなユースケースではどうでしょうか

1. **リストスタイルのデザインではなく、カードタイプのデザインが必要な場合**
1. **リストスタイルはそのままで良いが、個人のTodoではなく、TeamのTodoを表示したい場合**

これらのニーズを満たすために、my-todosコンポーネントにプロパティを追加することを考えるかもしれません。

例えば、

```html
<!-- カードスタイルのデザインということをプロパティで伝える -->
<my-todos design="card"></my-todos>
```

または、

```html
<!-- teamのtodoということをプロパティで伝える -->
<my-todos type="team"></my-todos>
```

これらのアプローチでは、プロパティを増やすことでユースケースに対応しようとしますが、元々のシンプルな再利用性が失われてしまうことになります。
`my-todos`という名前のコンポーネントで、チームのTodoを表示するという矛盾が生じてしまいます。

また、プロパティを追加することを避けて、ゼロから新しいコンポーネントを作る選択肢を取る場合、車輪の再発明が避けられず、開発が非効率になることが多いです。

## 解決策

そこで、今日紹介する解決策というのは、「**slot**に**todo**を表示する**レンダラー**を注入する」というアプローチです。

この方法により、コンポーネント間の柔軟な切り替えが可能になり、再利用性を損なうことなく、異なるデザインやユースケースに対応できます。

### コンポーネントの分割

まず、先ほどの`my-todos`コンポーネントをどう分割するかを考えます。

`my-todos`コンポーネントの主な役割は「自分のTodoの一覧を取得して表示すること」です。この2つの機能を別々のコンポーネントに分けることで、役割ごとに責任を持たせることができます。

|コンポーネント|役割|
|----|----|
|**my-todos**|自分のtodoの一覧を取得し、親コンポーネントに伝える|
|**list-renderer**|材料(todoのid一覧)を受け取り、リストスタイルでtodoを描画する|

### 実装イメージ

`Lit`で実装するイメージとしては以下のような感じです

#### 親コンポーネント（呼び出し側）
親コンポーネントではイベントリスナーを設定し、`my-todos`からtodoのIDの一覧を受け取り、それを`list-renderer`に渡します。

```html
<my-todos  @todo-fetched=${this.handleTodoFetched}>
  <list-renderer .ids=${this.todoIds}></list-renderer>
</my-todos>
```

#### `my-todos`コンポーネント
`my-todos`コンポーネントは、`fetchTodos`関数を使ってTodoの一覧を取得し、そのID一覧を親コンポーネントに渡します。

```typescript
constructor() {
  super()

  fetchTodos().then((data) => {
    const event = new CustomEvent('todo-fetched', {
      detail: {
        ids: data.ids,
      },
    })

    this.dispatchEvent(event)
  })
}

render() {
  return html`
    <div>
      <slot></slot>
    </div>
  `
}
```

#### `list-renderer`コンポーネント

受け取ったTodoのID一覧をもとに、リストスタイルでTodoを描画します。

```typescript
  @property({ type: Array })
  ids = [] as number[]

  render() {
    return html`
      ${this.ids.map((id) => html` <todo-list .todoId=${id}></todo-list>`)}
    `
  }
```

## メリット

このアプローチでは、`list-renderer`を例えば`card-renderer`に置き換えるだけで、カードタイプのデザインに切り替えることができます。また、`my-todos`を`team-todos`に置き換えることで、チームのTodoを表示することができます。

このように、コンポーネントを単一責任で分け、差異だけを変更することで、新しいユースケースに柔軟に対応できるようになります。

## 結論

Web Componentsの再利用性を高めるためには、コンポーネントの責務を分け、柔軟にカスタマイズできる仕組みを提供することが重要。

`slot`とカスタムイベントを活用することで、再利用性を保ちながら、デザインやデータの変更にも簡単に対応できるようになります。

## ソースコードなど

**実装してみたサイト**

https://webcomponent-renderer-play.vercel.app

**ソースコード**

https://github.com/maaaashi/webcomponent-renderer-play
【2025年最新】iosアプリ申請に必要なスクリーンショットの端末サイズについて【 App Store】

## はじめに
iosアプリ制作者の方、app store connectでのアプリ申請時に必要な**スクリーンショットの端末サイズ、いくつ必要なのか**と困ったことはないでしょうか？
私自身も、アプリ申請時に検索したところ古い情報も多く、なんだか情報が錯綜していると感じました。
そこで今回は、2025年最新の情報についてまとめておきたいと思います。


なお、この記事は以下の2つを目的に書いています。
- 【2025年最新】というタイトルで記事を書いてみたかった(1月2日に投稿することで最速を目指す）
- 作ったアプリを宣伝したかった

なので、結論ベースで書いていますし正直中身は薄いです。あらかじめご了承ください。

## 今回作ったアプリについて
ここで記事を閉じずにどうか下記のアプリに触れてくれたら非常に嬉しいです。宣伝です。
今回、flutterを用いて「傾斜割り勘」というiOSアプリを制作しました。

https://apps.apple.com/by/app/%E5%82%BE%E6%96%9C%E5%89%B2%E3%82%8A%E5%8B%98/id6739862582

飲み会において、「1年生だけ1000円にしたいな〜」とか「上司達が10000円くれたから残りの人たちであとは割り勘したいな〜」とか「この人達だけ1000円多めに出して欲しいな〜」て感じで、**均等じゃない割り勘をする場面**に使うアプリです。
とてもシンプルなアプリで、合計金額と人数、そして任意の傾斜をつけたいグループを入力するだけでアプリが自動で割り勘をしてくれます。
また、通常の割り勘ももちろんできて、その場合には割り勘した結果出てくる**端数を0.1~100円単位で切り上げたり切り下げたり**できます。

なかなか文章だけでは良さが伝わりづらいかと思いますので、よかったらぜひインストールしてくださると嬉しいです！

## 結論

#### **6.9インチor6.5インチのどちらか一つあればOK。**  

多くの記事では2つ用意する必要があると記載されていますが、少なくとも2025年1月現在では6.9インチただ1つあれば問題ないです。**現に自分はそれで通りました。（ただしiPadは別）**  

したがって、6.9インチ(16Pro Maxや16Pro,15Pro Max等が該当)１つ用意しましょう。
ただ、これだけだと流石に記事が薄すぎるので、自分がこれ一つあれば良いんじゃね？と判断した根拠を説明していきます。

## 必要なスクリーンショットのサイズについて（公式サイトを解釈）

ここからは、以下の公式情報をもとにした解釈について説明します。

https://developer.apple.com/jp/help/app-store-connect/reference/screenshot-specifications/

ここで、例として6.5インチディスプレイの部分を引用すると、次のように書いてあります。

![スクリーンショット 2025-01-01 23.21.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/702415/8e0fe977-fb60-e9ff-864e-68d73cb1ebbe.png)
(上記公式より抜粋）


この**スクリーンショットのソース**の部分を読めば分かる通り、**6.5インチのスクショは、6.9インチのスクショを提出すれば縮小版を勝手に作ってくれる**んですよね。

同じように読み解いていくと、実はほとんどのサイズのスクショについて縮小版を勝手に作ってくれて、同じようなことが成り立つとわかります。これをわかりやすく表にすると、以下のようになります。

| 端末サイズ | 縮小版を作ってくれるサイズ（自動）
|:-:|:-:|
| 6.9 インチ  | なし（ただし6.5インチで代替可能） | 
| 6.5 インチ | 6.9 インチ |
| 6.3 インチ  | 6.5 インチ |
|  5.8 インチ | 6.5 インチ  |
|  5.5 インチ | 5.8 インチ  |
|  4.7 インチ | 5.5 インチ  |
|  4 インチ | 4.7 インチ  |
|  3.5 インチ | 4 インチ  |

つまり

6.9インチを用意、提出する
↓
用意した6.9インチをもとに、**縮小版の6.5インチが作成**される（自動）
↓
完成した6.5インチをもとに縮小版の6.3インチが作成される（自動）
↓
以下ループ

みたいな感じです。

イメージとしては数学的帰納法みたいな感じですね。1ミリも伝わらなかったらすみません。


もちろん、縮小版を自動で作成せずにそれぞれを作成して提出しても問題ないと思います。スクリーンショットの質にこだわる場合はそれでも良いかもしれません。
今回お伝えしたかったことは、さまざまな情報がありますが**2025年1月現在では一つのサイズだけ用意すれば問題ない**よ、ということです。


## 最後に
今回は私が勝手に読んで解釈して、実際に試してみたら一つで通ったよという話なので、もし解釈が違う！等のご意見があればぜひコメントお願いします。
そして、「傾斜割り勘」も何卒お願いします！
競プロ日記#24/12/31

# アルゴ式-[素数の個数](https://algo-method.com/tasks/234)
- 自然数Nの素数判定について1からNまでforで回したため素数判定時に割り切れた回数を2にして判定してしまった
→2からN-1（その数自身で割らない）ようにすることで単純に割り切れたかどうかだけでflagを切り替えればよい

### この解法に気づけなかった原因
- 前回の1つの数を素数判定問題では平方根を取って素数判定をしていた。そのためその数自身で割るパターンの考慮が必要なかった。また、前回は何故か1ではなく2から割り始めていた

# アルゴ式-[回文の個数](https://algo-method.com/tasks/237)
- reverse()を使うのがどう考えても早いが以下が模範解答
```
bool flag = true;
  int N = x.size();
  for (int i=0; i<N; ++i) {
    if (x[i] != x[(N-1)-i]) {
      flag = false;
    }
  }
  return flag;
  ```
  前と後ろから同時に見ていって一致を確認
初心者がスクラムガイドを読んでみた！

閲覧頂き、ありがとうございます🙇

この記事は、スクラム開発初心者が `スクラムガイド2020` を読んで、
自分なりに解釈した内容になります！

誤釈や補足があればコメントに書いていただけますと幸いです！

## スクラムチーム と 役割

### スクラムチームとは

* 「`プロダクトオーナー`」「`スクラムマスター`」「`開発者`」で構成されたチーム
* 「`1つの目的(プロダクトゴール)`」を持ったチーム
である。

---

下記メンバーの役割は以下となる。
(例はTODOリストを開発する場合、どんなものがあるかを記載)

### プロダクトオーナー(1名)🧑‍💻

* プロダクトゴールの策定
    * 例：TODOリストを開発する
* ゴールに基づき、プロダクトバックログアイテム(タスク)の作成
    * 例：アイテムとして「ログイン機能」「TODO登録機能」を作成する

### スクラムマスター(1名)🧑‍💻

* スクラムイベントや時間の管理
    * 例：イベントスケジュールの決定
* スクラムチームが円滑に開発できるよう支援する
    * 例：スプリント外のタスクが舞い込んできた場合の調整

### 開発者🧑‍💻

* スプリントバックログアイテム(タスク)の作成
    * 例：「ログイン機能」に必要なタスクの細分化し作成する
* 開発をする
    * 例：実際のコードを書いていく

### ステークホルダー🧑‍💼 ※スクラムチーム外

* 開発の依頼や要望の伝達
* 成果物のレビュー

図に表すとこんなイメージです。

![スクラムチーム.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130422/5b01fb7e-ed68-4535-b26b-05aa01f26a1d.png)


## スクラムイベント

### スプリントとは

この後説明する `スクラムイベント` を実行する箱のこと。
スプリントを実行する期間は1ヶ月の以内が望ましい。

実際に行われるイベントは以下となる。

---

### スプリントプランニング📝(1回)

* スクラムチームのみで開催
* そのスプリント内で実行することを計画する
* プロダクトバックログアイテムから選択し、スプリントバックログを作成する
* トピックとして以下の3項目を意識する
    * このスプリントはどのような価値を生むのか
    * このスプリントで何ができるようになるのか
    * このスプリントはどのように成し遂げるのか

### デイリースクラム🏉(毎日)

* スクラムチームのみで開催
* 毎日15分程度で行うイベント(朝会的な)
* スプリントゴールに向けての進捗を共有

### スプリントレビュー🔍(1回)

* スクラムチームとステークホルダーで開催
* このスプリントでの成果物とプロダクトゴールへの進捗を共有する
* その結果からプロダクトバックログの調整が必要となる場合もある

### スプリントレトロスペクティブ✅(1回)

* スクラムチームのみで開催
* このスプリントでの進め方や問題点をレビューする(振り返り会的な)
* その結果からプロダクトバックログの調整が必要となる場合もある

## 最後に

スクラム開発に関するワードはよく耳にしていたものの、
公式のガイドブックを見ることないままの知識だったので知見が深まりました。
実際に実践する機会があれば試していき、
それぞれのスクラムチームにあった運用をしていきたいです！

## 参考資料

* [スクラムガイド2020](https://scrumguides.org/docs/scrumguide/v2020/2020-Scrum-Guide-Japanese.pdf)
Visualforce_画面遷移で値を渡す方法(POST)

VisualforceページからVisualforceページへPOSTで値を渡す一般的な方法だよ！
まず、完成形サンプルコード！

```FirstPage.page
<apex:page controller="FirstPageController" showHeader="true" sidebar="true">
    <!-- ここでは apex:form ではなく、純粋な HTML の form を使う -->
    <form action="/apex/SecondPage" method="POST">
        <!-- 非表示項目（隠しフィールド） -->
        <input type="hidden" name="passValue" value="{!passValue}" />
        
        <!-- 送信ボタン -->
        <input type="submit" value="次のページへ"/>
    </form>
    ・FirstpageからPOSTで渡す隠し文字列：{!passValue}<br/>
    （分かりやすく表示）
</apex:page>
```

```FirstPageController.cls
public with sharing class FirstPageController {
    // 送信したい値を保持するプロパティ
    public String passValue { get; set; }
    
    // 今回はコンストラクタで値をセットしておきます
    public FirstPageController() {
        // ここでは例として固定文字列をセット
        passValue = 'Hidden Text';
    }
}
```






```SecondPage.page
<apex:page controller="SecondPageController" showHeader="true" sidebar="true">
    <h1>SecondPage</h1>
    <p>Firstpageから受け取った値: {!receiveValue}</p>
</apex:page>
```

```SecondPageController.cls
public with sharing class SecondPageController {
    // 受け取る値を表示するためのプロパティ
    public String receiveValue { get; set; }
    
    public SecondPageController() {
        // POSTされてきたフォームのパラメータを取得
        receiveValue = ApexPages.currentPage().getParameters().get('passValue');
    }
}
```

<h1>実装手順（1から順番に作成してください）</h1>
1. Apexクラス：FirstPageController<br/>
2. Apexクラス：SecondPageController<br/>
3. Visualforceページ：SecondPage<br/>
4. Visualforceページ：FirstPage<br/>


<h1>各ページ、コントローラの役割</h1>
<dl>
    <dt>FirstPage:</dt>
    <dd>遷移元となるVisualforceページ。<br/>
    <dd>ここでユーザが「次のページへ」ボタンを押すと、ある値をPOSTで送信します。</dd><br/>
    <dt>SecondPage:</dt>
    <dd>遷移先のVisualforceページ。<br/>
    FirstPageからPOSTで送られた値を受け取り、画面に表示します。</dd><br/>
    <dt>Controller:</dt>
    <dd>値の持ち運びや受け取りを行うApexクラス。</dd>
    <dd>FirstPageController(FirstPage用)</dd>
    <dd>SecondPageController(SecondPage用)</dd>
</dl>

<h1>コードの流れ</h1>
<dl>
    <dt>1．ユーザがFirstPageへアクセス</dt>
    <dd>ブラウザでFirstPageが読み込まれる。<br/>
    FirstPageのController(FirstPageController)が呼び出され、passValue というプロパティに “Hidden Text” が設定される。<br/>
    その値が apex:inputHidden にバインドされ、画面には表示されないが、裏側ではフォーム内に保持されている。</dd><br/>
    <dt>2．「次のページへ」ボタン押下 (フォームのPOST送信)</dt>
    <dd>ユーザがクリックすると、form が POSTリクエスト を行い、SecondPage (/apex/SecondPage) へデータを飛ばす。<br/>
    <dd>送信内容 は画面にあるフォーム要素（今回は apex:inputHidden のみ）が含まれる。<br/>
    そしてSecondPageへのリクエスト到着。</dd><br/>
    <dt>3．SalesforceサーバがSecondPageの処理を受け取り、SecondPageController が呼び出される</dt>
    <dd>SecondPageController のコンストラクタ内などApexPages.currentPage().getParameters() を通じて、POSTで送られてきたパラメータを取得。</dd><br/>
    <dt>4．SecondPageの表示</dt>
    <dd>取得した値(receiveValue) を Visualforceの {!receiveValue} で画面に出力<br/>
これにより、FirstPageで設定された文字列がSecondPageの画面に表示される。</dd>
</dl>

<br/><br/><br/>

URLパラメータに付与して渡す方法もあるけど、クラッキングのリスクもあるのでPOSTで渡す方法を今回は記載したよ。
ヒントになれば幸いです！！
テーブルにおけるインデックスの効果

# 1. 目的
目的の行を早めに見つけ、クエリの処理速度の向上を目的とする。

今回はインデックスの効果を簡易的に確認する。

▪️ DB：MySQL

【用語】
・key：設定したインデックス
・rows：取得される行の見積もり

# 2. テーブル・データ作成
```
CREATE TABLE `test` (
  `id` int NOT NULL,
  `name` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `age` int NOT NULL,
  `is_manager` int NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```
データを10000件用意し、idが10000のデータのageは16で登録する。
<table>
<thead>
<tr>
<th>id</th>	<th>name</th>	<th>age</th>	<th>is_manager</th>	
</tr>
</thead>
<tbody>
<tr>
<td>1</td>	<td>山田太郎</td>	<td>15</td>	<td>1</td>
</tr>
</tbody>
</table>
<br>
・・・・・・・・・・・<br>
・・・・・・・・・・・<br>
・・・・・・・・・・・<br>
・・・・・・・・・・・<br>
<table>
<thead>
<tr>
<th>id</th>	<th>name</th>	<th>age</th>	<th>is_manager</th>	
</tr>
</thead>
<tbody>
<tr>
<td>10000</td>	<td>山田太郎</td>	<td>16</td>	<td>1</td>
</tr>
</tbody>
</table>

#  3. データ検索
ageが16のデータを検索する。
```
EXPLAIN SELECT * FROM test WHERE age = 16;
```

<table>
<thead>
<tr>
<th>id</th>	<th>select_type</th>	<th>table</th>	<th>partitions</th>	<th>type</th>	<th>possible_keys</th>	<th>key</th>	<th>key_len</th>	<th>ref</th>	<th>rows</th>	<th>filtered</th>	<th>Extra</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>	<td>SIMPLE</td>	<td>test</td>	<td>NULL</td>	<td>ALL</td>	<td>NULL</td>	<td>NULL</td>	<td>NULL</td>	<td>NULL</td>	<td>9867</td>	<td>10.00</td>	<td>Using where</td>	
</tr>
</tbody>
</table>

・key：NULL
・rows：9867

# 4. インデックス設定
インデックスをageカラムに設定する。
```
CREATE INDEX index_age ON test(age);
```

# 5. 再度検索
再度検索する。
```
EXPLAIN SELECT * FROM test WHERE age = 16;
```
<table>
<thead>
<tr>
<th>id</th>	<th>select_type</th>	<th>table</th>	<th>partitions</th>	<th>type</th>	<th>possible_keys</th>	<th>key</th>	<th>key_len</th>	<th>ref</th>	<th>rows</th>	<th>filtered</th>	<th>Extra</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>	<td>SIMPLE</td>	<td>test</td>	<td>NULL</td>	<td>ref</td>	<td>index_age</td>	<td>index_age</td>	<td>4</td>	<td>const</td>	<td>1</td>	<td>100.00</td>	<td>NULL</td>
</tr>
</tbody>
</table>

・key：index_age
・rows：1

# 6. 結果
rowsが明らかに減ったことがわかる。

# 7. インデックスが効かない場合
こちらのサイトで解説してくださっています。
https://qiita.com/MURAMASA2470/items/d06cb3b6ad6b43b12a4b

# 8. 記事の参考
・EXPLAINについて
https://qiita.com/chii-08/items/e6a3ff51129ef1167ab6

・インデックスについて
https://qiita.com/masayasviel/items/b4f2fe76235f30270b07
https://supersoftware.jp/tech/20240610/19469/
気象庁サイトのアメダス情報を Node-RED だけで取得する

## ノードと JavaScript だけで実現できるのか？
[気象庁のアメダス情報を取得し、 PHP で1地点だけ情報を抽出する](https://qiita.com/harycurl/items/b3b3b53aef8c26573e0b) の記事では、 PHP を併用しながらアメダス要素を取得、 TC001 で表示させることにした。

しかし、この場合別途 PHP の動く環境を用意しなければならず、煩雑となる。
Node-RED で全部処理できれば、 Node-RED 環境だけを構築すればよいことになるので管理も楽になる。

フローや JavaScript の組み合わせで実現方法を模索する。

## さほど難しくはないが、落とし穴がいくつかある
結論から言うと、問題なく実装することができた。
フロー図は以下の通りである。
![amedas_nodered1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943774/615bf114-af7b-f542-bced-04cb580adb53.png)

### URL の日時処理
1つ目、巻き戻し日時を含めた URL の日時であるが、まずは現在時刻の数値化が必要になる。これは `getTime` を使えばよい。ただし、この数値は単位がミリ秒であることに注意（ハマった）。
あとは7分引いて YYYYMMDDhhmmss の形にしてやればよいが、ここで `toLocaleString` のスウェーデンフォーマットがよいという情報を得る。なかなかトリッキーなやり方だが、一々年月日時分ごとに取り出さなくてよくなったので安堵。

https://zenn.dev/terrierscript/articles/2020-09-19-time-sv-se

スクリプトは以下のようになる。
```javascript: datetime
var getdate = new Date();
var gettime = new Date().getTime() - 7*60*1000;
getdate.setTime(gettime);
var urltime = getdate.toLocaleString("sv-SE", { timeZone: "Asia/Tokyo" }).replace(/[^0-9]/g,"").slice(0,11) + "000"
var url = "https://www.jma.go.jp/bosai/amedas/data/map/" + urltime + ".json";
msg.payload = url;
return msg;
```
### URL を http requrst へ渡す
続いてこの URL を http request にわたす方法だが、公式クックブックにある通り、 change ノードで msg.url に割り当て直せばよい（というか、そもそも function で msg.payload のかわりに msg.url へ代入すればよい）。

https://cookbook.nodered.jp/http/set-request-url

ただし、このクックブックの記述には落とし穴がある。
`msg.URL` と書いてあるが、 url は**大文字にしてはいけない**。
もう一度書くと、 `msg.URL` ではなく **`msg.url` としなければならない**。
![amedas_nodered3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943774/8bee36c9-a2cb-cfe9-77b0-17353e562266.png)

## http request と parse
大文字小文字トラップを乗り越えたらもう一息である。
http request ノードは URL 空欄でよい。

JSON から要素を抜き出すのもさほど難しくはない。
アメダスの地点コードは数値扱いになってしまうが、頭が0の地点がないので問題は起きないだろう（地点コードを文字列で与えようと、数値で与えようと適当に処理してくれる）。

気温を取り出す際の下1桁の扱いが問題になるが、 `toFixed(1)` で有効数字小数第1位まで（.0を付加）とすることができる。

https://zenn.dev/shinkano/articles/0fa71ad65614b6

![amedas_nodered4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943774/19209e8a-64ef-7734-e2a1-ed887eb7936d.png)

## 完成です
あとは mqtt out ノードに繋いでやれば完成（ノードと実行例は省略）。

この方法だと PHP を用いる方法と違って、 JSON ファイルの読み込みは1回だけで、複数地点のアメダスデータを一気に取得することができる。
気象庁サーバーにかける負担も若干減らすことができるので、この方法が本来望ましいだろう。
![amedas_nodered5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943774/7a5e12a8-a127-bf8c-1100-c2b54ddfe8d1.png)
ヘンリーフォードの格言

# 概要
心に刺さる格言を見つけたので記録として記載します

# 内容
“Anyone who stops learning is old, whether at twenty or eighty. Anyone who keeps learning stays young.
The greatest thing in life is to keep your mind young.” –Henry Ford

「20歳だろうが80歳だろうが、学ぶことをやめた者は皆、老人だ。学び続ける者は、若くいられる。」

引用：https://eigojin.com/2021/02/17/henryford/

自動車会社フォードの創設者、ヘンリー・フォードの言葉です。

人生は一生勉強。学びをやめないように生きようと思います。
未経験から新卒でエンジニアになり、3年目で高度試験に合格した

## 前提
筆者は大学では医療系の学部に所属していたが、新卒では大手SIerに入社。
何も武器のない状態でいるのが嫌だったため、1年目の時から続けて資格取得に精を出してきました。
そんな中で3年目である今年度に高度資格である「DBスペシャリスト」に合格したのはなかなかすごいんじゃね？と自分で思っており、自慢するとともに、今後DBスペシャリストを受けるであろう方たちに向けて少しでもためになる情報を提供できればということで、以下にまとめてみました。
どうぞ、うざいと思ってしまった方以外はお付き合いください。

## 実は1回落ちている
小題からもわかるように、2年目の時もDBスペシャリストについては受験してました。
結果は以下の通り。午後Ⅱで3点だけ足りずに不合格。。。（各60点以上で合格）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3931439/e75651e8-2279-38bd-5158-2a320c7e000a.png)
当時、合格発表を自社のオフィスで見たのですが、悔しすぎて椅子から滑り落ちました。

勉強はこんな感じで進めました。
- 試験の約2か月前から、勉強開始。平日毎朝1時間、休日は予定の兼ね合いを見ながら可能な限り時間確保
- 書籍を使って勉強（[データベーススペシャリスト「専門知識＋午後問題」の重点対策](https://www.amazon.co.jp/2023-2024-%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%82%B9%E3%83%9A%E3%82%B7%E3%83%A3%E3%83%AA%E3%82%B9%E3%83%88%E3%80%8C%E5%B0%82%E9%96%80%E7%9F%A5%E8%AD%98%EF%BC%8B%E5%8D%88%E5%BE%8C%E5%95%8F%E9%A1%8C%E3%80%8D%E3%81%AE%E9%87%8D%E7%82%B9%E5%AF%BE%E7%AD%96-%E5%B1%B1%E6%9C%AC-%E6%A3%AE%E6%A8%B9/dp/4865752897)）
- 午前Ⅱ→午後Ⅰ→午後Ⅱの順に勉強
- 午後の選択問題は、DB設計の問題が回答を読んでも理解できないことが多かったため、捨てた

このときの勉強の進め方は、今思えば反省点だらけでしたね。
- 午後Ⅰの対策に時間がかかり、午後Ⅱの対策に十分な時間が取れなかった。（2週間弱くらいしかとれませんでした）
- DB設計の問題を捨てていたが、午後ⅠでDB設計の大問が2つ出てきて、解答用紙を見た瞬間絶望。メンタルに大影響だった。

いびつな勉強の進め方で、過去問演習の中で点数が取れることはあっても根本的に理解できているような実感もあまりなかったです。今思うと、この状態で合格しなくてよかった。

## リベンジマッチに向けての準備
1回目の失敗を経て、自分なりの反省としては、ざっくり勉強の方針が悪かったということです。
やっぱりどんなことでも成功するためには、正しいベクトルの努力を重ねることが重要なんだと学びました。大学受験の時にそれは学んでいたはずなのに、油断すると同じ過ちを繰り返すものです。
リベンジ時の勉強の進め方はこんな感じ
- 試験の約4か月前から勉強開始
- 午後Ⅱ→午後Ⅰの順に勉強
- 午前Ⅱは前の年にやっているから通勤時間に過去問やるだけで何とかするという気合いで乗り切る
- DB設計の問題を選択することを決意。得点源にするつもりで重点的に勉強
- 書籍に加えて、解説用にUdemyの講義を利用（[令和7年：参考書の著者直伝！「データベーススペシャリスト」試験　午後２対策講義](https://www.udemy.com/course/db_specialist_pm2/?srsltid=AfmBOoqs7hTQNzA3732okINq54H0_Db7zrYbVETduv3JlOhDfTUhzfpk)）

中でも、午後Ⅱの対策から始めたのは一番いい選択だったと思っています。
午後Ⅱがやはり試験の最大の関門なので、そこが乗り切れられれば合格率は格段に上がります。さらに、午後Ⅱで合格点が取れるくらいになっておけば、午後Ⅰのうち1つの大問は間違いなく取れます。
これから高度試験の勉強始める方がいれば、午後Ⅱの対策からスタートすることがおススメです。

その他にも、Udemyの動画講義を使って復習したというのもよかったです。
使っていた参考書は、比較的解説が丁寧に書いてあったのですが、どうしても「何でその答えになるのか」という内容の解説がメインで、「どうすればその思考にたどり着くのか」というような観点の解説はありませんでした。その点、Udemyの講義では比較的思考の流れについても解説されていたのでスムーズに復習をすることができました。

## リベンジ成功！
そんなわけで、リベンジに向けて勉強をした結果、出た成果がこのようなものになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3931439/ab0f8d84-a3e1-63e4-edb0-793e734dc72b.png)
合格点の60点をそれぞれ余裕で超えることができてとても満足ですね。
不合格となった1年前に、「次は余裕で合格するんだ！」ということも１つ目標に据えていたので、それも達成できました。

## 振り返って
1回不合格というある種の失敗を味わって、それを活かして今回合格できたというわけですが、途中に書いた通り不合格の経験をしたことは自分にとってプラスの意味があったなと感じてます。
プラスと感じたことは大きくは2つかなと思います。
 1. 知識のキャッチアップをするときのアンチパターンを理解できた気がする
 1. DB設計の知識、あるべき姿を理解することができた

1.に関しては今後も引き続きやっていくであろう技術のキャッチアップをする際に、油断せずに気を付けていきたいと思います。2.に関しては既に業務の中で役に立つ場面が多くあり、これだけでも勉強した価値があったなと思えてます。

今後については、高度試験を取れたので一旦しばらくはIPAの資格試験については放置しようかなと思います。（基本情報技術者、応用情報技術者、DBスペシャリストの資格を取得した、という状態です。）
じゃあ何をやっていくかというと、これまで資格ベースで勉強してきた（上記の資格以外にも認定資格を複数とれている）ので、より業務に直結する知識をつけていきたいなと思ってます。どうやってコードを書いていくべきか、とか、システム開発するならこういうこと頭に入れて気を付けないといけないよね、とか、アーキテクチャのこととか。
自分1人でできることという意味ではまだまだあまりにもできないことが多すぎるので、改めて気合いを入れていろんなこと頑張らないとなと思ってます。できるようになったこと少しずつでもアウトプットしながら、引き続き勉強していこうと思います。

ここまで読んでくれた人と一緒に頑張りたいです。読んでくれてありがとうございました。また会いましょう。
リアルタイムでの会議文字起こし：効率化の鍵とは？

ビジネスの現場では、会議の内容を正確に記録することが欠かせません。しかし、手動でのメモ作成は時間と労力がかかり、重要な情報を見逃してしまうリスクもあります。そこで注目されているのが「リアルタイム会議文字起こし」です。この技術は、AIを活用して会議中の発言をその場で文字化し、効率的な情報共有を可能にします。

## リアルタイム会議文字起こしの仕組みとは？

リアルタイム会議文字起こしは、音声認識AIを用いて、会議中の発言を瞬時にテキストに変換する技術です。これにより、会議中に議事録を作成する手間を省き、内容をリアルタイムで共有できるため、会議の効率が大幅に向上します。特に以下のような場面で活用されています：

- オンライン会議での議事録作成  
- 多国籍メンバーとの会議における言語サポート  
- トレーニングやセミナーの内容記録  

## リアルタイム会議文字起こしのメリット

1. **時間と労力の削減**  
   議事録作成のために会議を振り返る必要がなくなり、その場で内容を記録できます。これにより、後処理の負担を大幅に軽減します。

2. **正確な記録**  
   AIは会話内容をほぼ漏れなく文字化するため、発言の取り違いや重要なポイントの抜け漏れを防ぎます。

3. **即時共有が可能**  
   リアルタイムで文字起こしが行われるため、会議参加者全員がその場で記録を確認でき、議論の透明性が向上します。

## Soro.jp：リアルタイム会議文字起こしのおすすめツール

リアルタイムでの文字起こしを効果的に行うためには、信頼性の高いツールが必要です。その中でも注目されているのが**Soro.jp**です。このツールは、会議中の音声をリアルタイムで正確に文字化し、参加者全員に即座に共有できる機能を提供しています。特に日本語に特化した音声認識技術を採用しているため、日本国内のビジネスシーンにおいて優れたパフォーマンスを発揮します。  

また、[Soro.jp](https://soro.jp/) はシンプルな操作性を重視しており、専門知識がなくても誰でも簡単に利用できます。これにより、ツールの導入や活用のハードルが低く、多忙なビジネスパーソンにとって理想的な選択肢となっています。

## まとめ

リアルタイム会議文字起こしは、会議の効率化を目指す企業や個人にとって重要な技術です。正確で迅速な記録により、後処理の負担を軽減し、会議の透明性や生産性を向上させます。中でも**Soro.jp**のようなツールを活用すれば、さらに高い利便性と正確性を実感できるでしょう。ぜひ、次回の会議で活用してみてください。
他の言語と比較しながら勉強するPython


みんなもよく知っているであろう 東大の[Pythonプログラミング入門](https://github.com/UTokyo-IPP/utokyo-ipp.github.io)を使ってPythonの勉強をしている。
初めて触るプログラミング言語がPythonであれば驚かなかったかもしれないが、「え、Pythonだとそうなの？」というところが序盤にパラパラ出てくるので、以下に軽くまとめてみた。まだテキストは完読しておらず、1-2の途中くらい。

## 全般
+ 型宣言が無い(つけることもできる)
+ 物理行っぽい構成(ただし、丸括弧の中身を複数行書けることは確認済み)
+ else ifでもなくElseIfでもなくelsifでもなくelif:を使う
+ elif:のほかにも文法にコロンが登場する(全部把握してない)

## 演算子
整数の商だけ求める//演算子が独特。

```python
10//2    #5
10//2.0  #5.0 (これは実数)
7//1.5   #4.0 (商は合ってるが実数)
```
キャストの関係は後で整理したい。


べき乗の**演算子もちょっと珍しい。べき乗演算子はPerlにもあったけど、他では見かけず「MathライブラリのPower使ってくれ」というのが多い印象だった。

```python
2**2**3 #これは2**(2**3)となり、答えは256になる。(2**2)**3=64とはならない。
```

他と違って右結合なので、ちょっとわかりにくいのがあまり見かけない理由かもしれない。

## 型宣言しないときの変数の挙動
### 整数値の最大値が無い
整数値が無限に大きくなっていく。オーバーフローを気にしないで済むのは良いかもしれないと思った。ただ、おそらくビット演算とかには向かないんだろう。

## and演算子やor演算子の優先順位が低い

これはPerlと同じなのでわかりやすかった。Perlには&&とandの両方演算子があったのだが(優先順位が違う)、Pythonにはandだけが残ったらしい。
~~a > b && a > c とa > b and a > cの結果が違うと判っていても分かりにくいからしょうがない。~~

### グローバル変数とローカル変数が共存しない
他言語と異なるので間違えやすそうなところ。
```python
a = 10
def foo():
    return a  #結果は10
def bar():
    a = 3 #ここはローカル変数が新規に作られている
    return a  #結果は3

#bar()の実行後にaを参照しても、10のままになっている
```

知っている限りの他の言語[^1]では、こういった挙動はしない。他の言語から移植したときは罠になりそう。
…やっぱり変数宣言無いタイプは曖昧で苦手。

[^1]:CとC++とPerlとVBとPHPとJava
読書ログ - 30代からどう働くか

# 概要
- 2025年1冊目
- 本屋で手に取りすぐに買ってしまった。
- 考え・行動を変えさせられた本。非常におすすめ。

# 本のタイトル
ソフトウェア開発現場の「失敗」集めてみた。
[amazon link](https://www.amazon.co.jp/30%E4%BB%A3%E3%81%8B%E3%82%89%E3%80%81%E3%81%A9%E3%81%86%E5%83%8D%E3%81%8F%E3%81%8B%EF%BD%9E%E3%81%8A%E9%87%91%E3%80%81%E3%82%84%E3%82%8A%E3%81%8C%E3%81%84%E3%80%81%E8%87%AA%E7%94%B1%E3%83%BC%E3%83%BC%E4%BD%95%E3%82%82%E3%81%82%E3%81%8D%E3%82%89%E3%82%81%E3%81%AA%E3%81%84%E4%BA%BA%E7%94%9F%E6%88%A6%E7%95%A5-%E4%BC%8A%E5%BA%AD%E6%AD%A3%E5%BA%B7/dp/4479798161)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3973326/ee6d19f4-f19a-b1d7-2c51-aa163f787510.png)


# 著者
伊庭正康

# 読んだ日
- 2025/1/1-1

# 感想
## 印象に残った・学んだ部分 😊
### 強みの3つの要素
**強み = うまくできる × 活力が湧く × 成果が出ている**

1. **努力せずともなぜかできる**  
2. **やることで活力が湧く**（やること自体が好き）  
3. **実際に成果が出ている**（褒められたことがある）

---

### 強みの内容
- 49項目ある
- カテゴリは以下の5つ
- それぞれの力を10点満点で自己分析してみる（2025/1/1時点）
1. 志向の強み
1. 動機の強み
1. スタンスの強み
1. コミュニケーションの強み
1. 人間関係の強み

#### 志向の強み
1. 計画力:3
1. 問題解決力:7
1. アイデア力:4
1. 整理力:5
1. チェック力:7
1. 効率力:9👍
1. 楽観力:7
1. 熟考力:3
1. 順守力:4

#### 動機の強み
1. 逆境力:5
1. 成長欲求:7
1. 競争心:7
1. 成長サポート力:7
1. ハードワーク力:8👍
1. 状況対応力:9👍
1. 自信:5
1. 決断力:6
1. やり抜き力:3
1. 目標志向:4
1. 改善力:8

#### スタンスの強み
1. 不安克服力:6
1. 受容力:6
1. 奉仕力:9👍
1. 自我力:5
1. 冷静力:7
1. 感謝力:8👍
1. 道徳力:8👍
1. 約束遵守力:7
1. ミッション志向力:4
1. 追求力:3
1. 最高志向力:5
1. 継承力:4
1. 謙虚さ:9

#### コミュニケーションの強み
1. 文章表現力:5
1. 俯瞰力:4
1. 傾聴力:9👍
1. ユーモア力:6
1. フィードバック力:7
1. ストーリーテリング力:4
1. 説明力:6
1. 注目性:7

#### 人間関係の強み
1. 説得力:4
1. 人を成長させる力:3
1. 関係構築力:6
1. 思いやり:9👍
1. 公平性:5
1. 個性を尊重する力:4
1. 人をつなげる力:7
1. 打ち解ける力:7

### 強みマッピングからの気づき
- 努力せずともなぜかできる
    - 状況対応力
    - 傾聴力
    - 効率力
- やることで活力が湧く（やること自体が好き）
    - 奉仕力
    - 思いやり
    - 効率力
- 実際に成果が出ている（褒められたことがある）
    - 効率力

### マッピングから得られた自分の強み
効率力！

---

### 所属ではなく「ジョイン」する
- **プロのフリーランスの感覚**で働く

---

### ロールモデルの活用法
- ロールモデルをそのままコピーするのは得策ではない。  
  **自分の強みが消える可能性があるため**
- コピーよりもインスパイア（触発）を重視する。  

### ロールモデルの見つけ方
- さまざまな人と接する中で見えてくる。  
- ビジネス書やYouTubeからも探せる。  
- テーマごとに探すと見つけやすい
  - **例：**
    - 時間管理
    - マネジメント
    - 社内人脈
    - 趣味との両立

---

### 上司に希望を伝える
- 希望を伝える人はチャンスを得やすい。  
- 足りない部分を教えてもらえる

---

### 社内外問わず経営者が欲しがる人材
1. 実績を出している  
2. 周囲と良好な関係が築ける  
3. 成果から逃げない  
4. フォロワーシップがある  
   - 自分のことより組織の問題解決を優先して考える  
   - 自ら率先して問題解決にあたる  

---

### 飛行機の離陸と仕事の逆境
- 飛行機は逆風を生かして浮いている。  
- **仕事の逆境も同じ。**

---

### 飲み会での上司の悪口は逆にチャンス
- フォロワーシップには5種類がある：

### フォロワーシップの種類
1. **模範的フォロワー**  
   - 自ら提案し、建設的な意見を述べる。  
   - 最もキャリアを開きやすいタイプ
2. **孤立型フォロワー**  
   - 批判はするが行動しない。  
3. **順応型フォロワー**  
   - 批判を持たない。  
4. **消極型フォロワー**  
   - 遠慮しがちで発言を控える。  
5. **実務型フォロワー**  
   - 変革より現実的な対処を優先する。  
   - 組織の常識にとらわれる場合がある

---

### 問題の捉え方
- 人のせいにも自分のせいにもしない  
- 問題の在りどころを「行動」に置く

---

### インプットの重要性
- **情報や知識をインプットする習慣を持つことが必須**  
  - 「今、何をしておくべきなのか」を考えやすくなる。  
  - インプットがないと他者の取り組みや世の中の流れを知らないままになる。  
- インプットを習慣化すると、**「やってみたい」「やらねばならない」テーマ**が見つかりやすくなる


## 自分のアクション 🤔
### Must
- 強みの点数をマッピングする(1/1完了)
- 強みが何か特定する　→　効率力と特定(1/1完了)
- ロールモデルを見つける
    - 効率力：Kさん(1/1記載)
    - 人脈形成：
    - タイムマネジメント：
    - 趣味との両立：
    - 人間性（話し方・聞き方）：Oさん(1/1記載)

### Nice to have


# 総合評価 ⭐
（5点満点で評価）
★★★★★
メール認証 : Login / Plain

# はじめに
皆さんはメールサーバの構築を行ったことがありますか？また、Redmineなどのプロジェクト管理ツールの構築を行ったことがありますか？
上記の構築を行うと、メール配信の設定を行う必要があります。その際に、smtpサーバに対して認証を行う必要があります。この認証方式について今回は説明します。

# login / plainの違い
postfixの場合、`/etc/postfix/main.cf`にsmtpサーバに関する設定を行うファイルがあります。そこに以下の様な記述があります。
```
smtp_sasl_mechanism_filter = plain, login
```

この記述はsmtpに対する認証方式として`plain`にするか、`login`にするかを決定します。
それぞれ以下のような違いが存在します。

* plain : userid/passwordをbase64にエンコードしてsmtpサーバに送信
* login : userid/passwordをbase64にエンコードして、それぞれ別々にsmtpサーバに送信

これらはbase64にエンコードするだけで暗号化するわけではないです。

# 参考文献
[What SMTP Authentication Is and Why You Can’t Ignore It](https://mailtrap.io/blog/smtp-auth/)
【緊急公開】現役エンジニアが教える！本当は教えたくない最強のコーディング効率化テクニック10選

## 実は、この記事

https://qiita.com/muu3/items/ea1e616ffae5b34dfa18

という選手権で生成AIが考えたタイトルになります！
さぁ、生成AIの筋肉、ならぬ「バズマッスル」の真価を見せてもらいましょう:tada:

## はじめに
タイトルは生成AIが考えましたが、内容は開発レベル初級くらいの人間が書いたものになります。ですので、本記事は
**~~【緊急公開】~~ 現役エンジニアが教える！~~本当は教えたくない~~みんな知ってる~~最強の~~コーディング効率化テクニック10選**
となります！お許しくださいいいい:pray_tone1:


### 1. コードエディタのショートカットキーをフル活用しよう
VSCode（Mac）でよく使うショートカットキーを紹介します
- `Cmd + Shift + P` : コマンドパレットを開く
- `Cmd + P` : ファイルを開く
- `Option + Shift + Down` または `Option + Shift + Up` : 行をコピー
- `Option + Shift + F` : フォーマット
- `Ctrl + G` : 行に移動
- `Cmd + Z` : 元に戻す
- `Cmd + Shift + Z`: やり直し
- `Option + Cmd + Down` または `Option + Cmd + Up` : 複数行にカーソルを出す
- `Cmd + D` : 選択した単語にカーソルを出す
- `Cmd + J` : ターミナルの表示・非表示を切り替える


### 2. コードリンティングで正しく美しく仕上げよう
VSCodeの拡張機能から追加できます。後述するDev Containersと併用することで、開発メンバー間で拡張機能の共通化もできます。
- ESLint : JavaScriptのコードが正しいかをチェックするツール
- Prettier : フォーマッター


### 3. スニペットを活用しよう
VSCodeのスニペットを使えば、定型コードを瞬時に展開することができます。
こちらの記事がよくまとまっていますのでリンク貼らせていただきます:bow_tone1:

https://qiita.com/P-man_Brown/items/047aefd720ad7388e8d0


### 4. コンテナ化して開発環境を標準化しよう
VSCodeの拡張機能である[Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers)です。
こちらの記事がよくまとまっていますのでリンク貼らせていただきます:bow_tone2:

https://zenn.dev/secondselection/articles/how_to_devcontainer


### 5. タスクランナーで繰り返し作業を自動化しよう
Makefileは、ソフトウェア開発におけるタスクランナーとして使われる設定ファイルです。コマンドの実行手順を「ターゲット」と「ルール」の形式で定義し、自動化できます。

```makefile
build: @npm run webpack
```


### 6. Gitの達人になろう
ソースコードの管理といえばGitですよね！便利コマンドはこちらの記事にまとめました:tada:

https://qiita.com/muu3/items/c99ec4df17acf498aec1


### 7. CI/CDパイプラインでデプロイを自動化しよう
開発効率を向上させるテクニックとして、CI/CDパイプラインの構築は外せません。デプロイを自動化することで、ミスを減らしたりリリースまでの時間を大幅に短縮できます。
#### おすすめツール
- GitHub Actions
- Jenkins
- CircleCI


### 8. AIコーディングアシスタントを活用しよう
AI技術の進化により、コーディングアシスタントが開発者の強力な味方になってきています。コード補完やエラー検出、リファクタリング、さらにはドキュメント生成も支援してくれます。
#### 代表的なツール
- GitHub Copilot
- Amazon CodeWhisperer
- Gemini
- ChatGPT

#### 注意点
- 過信は禁物 : AIから提案されるコードが常に正しいとは限らないというか、想定通りの動作をしないことがわりとある
- セキュリティリスク : 非公開情報や機密コードをAIに入力しない！
- 自身のスキル向上も重要 : AIに頼りすぎると、基礎的なプログラミング能力が低下する可能性がある


### 9. 効率的に情報収集しよう
今の情報・手段が最適解とは限りません！新鮮な情報を定期的に摂取しましょう:yum:
こちらの記事がよくまとまっていますのでリンク貼らせていただきます:bow_tone3:

https://qiita.com/small_island/items/de0a568612aa94a58153


### 10. 心身ともに健康でいよう
最後にして一番大事なことはこれです！安定したパフォーマンスを出し続けるために無理せず、自分に優しい生活をしましょう:hugging:
- 睡眠 : 睡眠不足は脳・体・心すべてにデバフ:zzz:
- 食事 : 不足しがちなタンパク質・ビタミン・ミネラルを意識して摂取しよう:tomato:
- 娯楽 : 心が赴くままに、笑顔になれる楽しみをもとう:ramen:（犯罪以外）


## さいごに
タイトル詐称な内容でしたが、最後までお読みいただきありがとうございました:bow_tone1:
【JavaScript】オブジェクトの繰り返し処理

## `for...in`ループ

`for...in`ループを使用すると、オブジェクトのすべての列挙可能なプロパティを繰り返し処理できます。

```js
const obj = {
    name: 'Alice',
    age: 25,
    city: 'Tokyo'
};

for (const key in obj) {
    if (Object.hasOwn(obj, key)) {
        console.log(`${key}: ${obj[key]}`)
    }
}
```

- `for...in`ループは、オブジェクトの各キーを反復処理
- `Object.hasOwn()`メソッドを使用して、オブジェクト自身のプロパティのみを処理

## `Object.keys()`メソッド

`Object.keys()`メソッドを使用すると、オブジェクトのキーの配列を取得し、それを使って繰り返し処理できます。

```js
const obj = {
    name: 'Bob',
    age: 30,
    city: 'New York'
};

Object.keys(obj).forEach(key => {
    console.log(`${key}: ${obj[key]}`)
})
```

- `Object.keys(obj)`は、オブジェクトのキーを配列として返す
- `forEach`メソッドで各キーに対して処理を行う

## `Object.entries()`メソッド

`Object.entries()`メソッドを使用すると、オブジェクトのキーと値のペアを配列として取得し、それを使って繰り返し処理できます。

```javascript
const obj = {
    name: 'Charlie',
    age: 35,
    city: 'San Francisco'
};

Object.entries(obj).forEach(([key, value]) => {
    console.log(`${key}: ${value}`)
})
```

- `Object.entries(obj)`はオブジェクトのキーと値のペアを含む配列を返す
- 配列の分割代入を使用して、キーと値を簡単に取得できる

## `for...of`ループと`Object.entries()`

`for...of`ループを使用して、`Object.entries()`から得られた配列を繰り返し処理することもできます。

```javascript
const obj = {
    name: 'Diana',
    age: 28,
    city: 'London'
};

for (const [key, value] of Object.entries(obj)) {
    console.log(`${key}: ${value}`)
}
```

- `for...of`ループを使用することで、配列の各要素に対して簡潔に処理を行うことができる
Git rebase の使い方を、たくさんの実例で初心者にも分かりやすく解説してみた！

### 前書き
**`Git rebase`** って、使うのがちょっと怖いと思ったことありませんか？
Gitを使った開発の中で、rebaseコマンドは非常に強力ですが、「履歴が書き換えられる」「競合が増える」「チームメンバーに怒られた」など、怖い噂を聞いて敬遠している方も多いのではないでしょうか。

でも実は、`Git rebase`を正しく理解すれば、mergeよりも履歴を綺麗に整理できたり、効率的に開発を進められる場面がたくさんあります。
この記事では、`Git rebase`の基本から実践的な活用方法まで、初心者にもわかりやすく解説します。

また、`git merge`と比較して、`git rebase`を使用する上での注意点や、使いどころの判断基準についても触れます。
「怖いから使わない」ではなく、「安全に使いこなす」ための方法をこの記事でマスターしましょう！

### 基本概念：`git rebase` と `git merge` の違い
#### 1. **`git merge`**
- **目的**: ブランチを統合する。
- **特徴**: 履歴を変更せず、統合時に「マージコミット」が作成される。
- **結果**: 履歴が「分岐と統合」の形で残る。

#### 2. **`git rebase`**
- **目的**: 一つのブランチの変更を別のブランチの先頭に適用する。
- **特徴**: 履歴を書き換えるため、より「直線的」な履歴を作成できる。
- **結果**: 履歴が「一本の線」のように見える。

---

### 実例 1: チーム開発でのブランチの整理
#### シナリオ:
- あなたのチームでは、`feature-A` ブランチで新機能を開発中。
- しかし、その間に `main` ブランチが更新されてしまった。
- 今、自分の `feature-A` を `main` にマージする前に最新の状態に合わせたい。

#### 解決方法: `git rebase main`
```bash
# 1. mainブランチを最新に更新
git checkout main
git pull origin main

# 2. feature-Aに移動
git checkout feature-A

# 3. rebaseを実行
git rebase main
```

#### 効果:
- `feature-A` の変更が `main` の最新のコミットに適用されます。
- 履歴が「一本の線」になります。

#### 比較: `git merge` を使った場合
```bash
git checkout feature-A
git merge main
```
- マージコミットが追加され、履歴が「分岐と統合」の形で残ります。

**どちらを選ぶべき？**
- **`merge`**: コミット履歴を完全に残したい場合。
- **`rebase`**: 履歴を整理してクリーンに保ちたい場合。

---

### 実例 2: コミットの整理
#### シナリオ:
- あなたのブランチには、開発中に行った細かいコミットがたくさんある。
- 他の人に共有する前に、これらを1つの意味のあるコミットにまとめたい。

#### 解決方法: インタラクティブリベース
```bash
git checkout feature-A

# 過去3つのコミットを編集する
git rebase -i HEAD~3
```

エディタが開き、次のようなリストが表示されます：
```
pick abc123 First commit
pick def456 Second commit
pick ghi789 Third commit
```

`pick` を以下のように変更します：
```
pick abc123 First commit
squash def456 Second commit
squash ghi789 Third commit
```

結果、3つのコミットが1つにまとまります。

---

### 実例 3: フォークしたリポジトリを最新に保つ
#### シナリオ:
- オープンソースプロジェクトをフォークして、あなたのリポジトリで作業を進めている。
- オリジナルのリポジトリ（`upstream`）が更新されたので、それを取り込む必要がある。

#### 解決方法: `rebase`
```bash
# 1. upstreamリモートを追加
git remote add upstream https://github.com/original/repo.git

# 2. upstreamの変更を取得
git fetch upstream

# 3. 自分のmainをupstreamのmainに合わせる
git checkout main
git rebase upstream/main
```

#### 効果:
- オリジナルのリポジトリの変更を取り込む際に、クリーンな履歴を保てます。

---

### 実例 4: コンフリクトの解消
#### シナリオ:
- `git rebase` を実行中にコンフリクトが発生した。

#### 解決方法:
1. コンフリクトを解消します。
```bash
# ファイルを編集してコンフリクトを解消
git add conflict-file.txt
```
2. リベースを続行：
```bash
git rebase --continue
```

3. 必要に応じて作業を中断：
```bash
git rebase --abort
```

---

### 実例 5: チームに迷惑をかけないリベース
#### ポイント:
- リベースは履歴を書き換えるため、**共有されたブランチでリベースを行うと他の人に迷惑をかける**ことがあります。

#### ベストプラクティス:
- **`main`** や共有されているブランチではなく、自分のローカルブランチでのみリベースを使う。
- 既にプッシュした変更は、可能な限り `merge` を使う。

---

### まとめ
1. **`git merge` と `git rebase` の選択**
   - 履歴を残したい場合：`merge`
   - クリーンな履歴が欲しい場合：`rebase`

2. **`git rebase` の活用場面**
   - 履歴を整理したいとき。
   - 最新のブランチに変更を適用したいとき。
   - コミットをまとめたいとき。

3. **注意点**
   - リベースは履歴を書き換えるので慎重に使用する。
   - 共有ブランチではリベースしない。

開発現場では `rebase` と `merge` を適切に使い分け、クリーンな履歴と効率的なコラボレーションを実現しましょう！
Next.js App Router でクエリパラメーターをすべて取得する方法

# やりたいこと

Next.js App Router でクエリパラメーターを文字列形式ですべて取得したい
※ 使用している Next.js のバージョンは14系（App Router） です

## Server Component の場合

Server Component の場合、`page.tsx` の Props で `searchParams` を受け取ることができる

`searchParams` は Plain Object の形式なので `toString` で文字列に変換すると、ブラウザのアドレスバーにURLとして記載されているクエリパラメーターを文字列形式ですべて取得できる

### app / page.tsx

```tsx
import { ReadonlyURLSearchParams } from “next/navigation”

type Props = {
  params: { slug: string };
  searchParams: ReadonlyURLSearchParams
};

export default async function SCSample(props: Props) {
  const { params, searchParams } = props;

  // ?page=1 でアクセスすると { page: '1' } を取得できる
  console.log("searchParams", searchParams);

  const allQueryParameters = searchParams.toString();

  // URLSearchParams を使用することで page=1 の文字列を取得できる
  console.log("allQueryParameters", allQueryParameters);

  return <div>クエリパラメータ {allQueryParameters}</div>
}
```

## Client Component の場合

Client Component の場合、`next/navigation` から参照できる `useSearchParams` を使用することができる。従来は `useRouter` の `router.query` で取得していたが、App Router から `useSearchParams` を使用してクエリパラメータを取得するように仕様が変更した。`useSearchParams` の返却値を `toString` で文字列に変換することで、ブラウザのアドレスバーにURLとして記載されているクエリパラメーターを文字列形式ですべて取得することができる

```tsx
"use client"

import { useRouter, useSearchParams } from "next/navigation";

export const CCSample = () => {
  const searchParams = useSearchParams();

  const allQueryParameters = searchParams.toString();

  // ?page=1 でアクセスすると page=1 の文字列を取得できる
  console.log("allQueryParameters", allQueryParameters);

  return <div>クエリパラメータ {allQueryParameters}</div>
}
```
WindowsでPLaMo PrimeのAPIを使用 python openaiライブラリにて

PLaMo PrimeのAPIを使用したくてPythonでコードを作成していたのですが、少してこずったのでまとめておきます。

PLaMo PrimeのAPIの使用方法は以下のページに記載されています。

API 利用方法

https://docs.plamo.preferredai.jp/ja/getting-started

しかしこのページではLinuxでのコマンドの入力方法しか記載されていない。

``` Linux
export PLAMO_API_KEY="your_api_key"
export OPENAI_API_KEY=$PLAMO_API_KEY
```
上記はPLAMO_API_KEYの環境変数を作成し、APIキーの値を入れる。
またOPENAI_API_KEYの環境変数を作成し、PLAMO_API_KEYの環境変数の値を代入するというもの。
your_api_keyの欄に取得したAPIキーを入れる。

上記のコマンドはWindowsのPowerShellでも実行できる。

``` PowerShell
[System.Environment]::SetEnvironmentVariable("PLAMO_API_KEY", "your_api_key", [System.EnvironmentVariableTarget]::User)
[System.Environment]::SetEnvironmentVariable("OPENAI_API_KEY", $env:PLAMO_API_KEY, [System.EnvironmentVariableTarget]::User)
```

また正しく代入されているかは以下で確認できる。
上のコマンドを入れたら一度、PowerShellを閉じて確認する必要がある。
``` PowerShell
echo $env:PLAMO_API_KEY
echo $env:OPENAI_API_KEY
```

`もっと簡単な方法としてwindowsの検索欄から環境変数と検索して「環境変数を編集」を表示させる。
新規(N)を押して、変数名（OPENAI_API_KEY）と変数値（APIキー）を入れてOKを押すとういう方法もある。`

またopenaiライブラリーで使用するために以下のサンプルが提供されている。

``` python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://platform.preferredai.jp/api/completion/v1",
    # other params...,
)

completion = client.chat.completions.create(
    model="plamo-1.0-prime",
    messages=[
        {"role": "system", "content": "あなたは旅行アドバイザーです"},
        {"role": "user", "content": "金沢で朝から夕方まで1日のおすすめの観光ルートを教えて下さい"},
    ],
    stream=True,
)

for chunk in completion:
    if chunk.choices and chunk.choices[0].delta.content is not None:
        print(chunk.choices[0].delta.content, end="", flush=True)
```
```python
client = OpenAI(
    api_key="APIキー",
    base_url="https://platform.preferredai.jp/api/completion/v1",
    # other params...,
)
```
とすることでコードに直接APIキーを入れることができる。

このコードのclient.chat.completions.createの機能はopenaiライブラリのバージョンが1.*以上の系統でないと使用できない。

また以下の記事にrequestsを使用した方法が記述されています。

https://qiita.com/AzukiImo/items/20a58336985da680a5a5
ffmpeg で動画ファイルから 5秒ごとに画像を切り出すスクリプト

## 概要・目的

5秒ごとに1スライドがある動画ファイルから画像を切り出したかった。

生成AIでざっくりスクリプトを書いてもらって、一部手直しをしたら使えたので記事にまとめておきます。用途は限定的ですが動作確認済みです。

写真をスライドショー的な動画ファイルにして、これで展開とかも使えそう。

## 動作確認

* macOS 14.4
* ffmpeg

```
ffmpeg version 7.1 Copyright (c) 2000-2024 the FFmpeg developers
  built with Apple clang version 16.0.0 (clang-1600.0.26.4)
```

* bash

```
GNU bash, version 3.2.57(1)-release (arm64-apple-darwin23)
Copyright (C) 2007 Free Software Foundation, Inc.
```

## スクリプト

```bash
#!/bin/bash -xe

# 動画ファイル名
input_video="input.mp4"

# 出力画像のディレクトリ
output_dir="output_images"

# 切り出す間隔 (秒)
interval=5

# 出力画像の形式
format="jpg"

# 出力画像のファイル名フォーマット
filename_format="image_%04d.%s"

# 出力ディレクトリを作成 (存在しない場合)
mkdir -p "$output_dir"

# 動画の長さを取得
duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$input_video")
# 切り出し回数を計算
count=$(printf "%.0f" $(echo "$duration / $interval" | bc -l))

# 切り出し処理
for ((i=0; i<$count; i++)); do
  filename=$(printf "$filename_format" "$i" "$format")
  ffmpeg -ss "$((i * interval))" -i "$input_video" -frames:v 1 -vf scale=-1:720 "$output_dir/${filename}"
done
```

## 解説など

以下の内容も確認済みです。

### スクリプトの解説

1. **変数定義:**
   - `input_video`: 入力動画ファイル名
   - `output_dir`: 出力画像のディレクトリ
   - `interval`: 切り出す間隔 (秒)
   - `format`: 出力画像の形式 (jpg, pngなど)
   - `filename_format`: 出力画像のファイル名フォーマット (image_%04d.jpgのように連番で保存)
2. **出力ディレクトリ作成:** `mkdir -p`コマンドで出力ディレクトリを作成します。
3. **動画の長さ取得:** `ffprobe`コマンドで動画の長さを取得し、`duration`変数に格納します。`interval` で割って切り出し回数を計算します。
4. **切り出し処理:**
   - `for`ループで、`interval`秒ごとに動画から1フレームを切り出します。
   - ファイル名を `printf` で連番で生成します。
   - ffmpeg
     - `-ss`: 動画の開始位置を指定します。
     - `-frames:v 1`: 1フレームだけ出力します。
     - `-vf scale=-1:720`: 出力画像の高さを720pxにリサイズします。幅は自動調整されます。

### スクリプトの実行方法

1. 上記のスクリプトをテキストエディタで作成し、`.sh`拡張子で保存します (例: `extract_images.sh`)。
2. ターミナルでスクリプトのあるディレクトリに移動します。
3. 実行権限を与えます: `chmod +x extract_images.sh`
4. スクリプトを実行します: `./extract_images.sh`

### 注意点

- **動画の長さ:** 動画の長さが非常に長い場合は、処理時間がかかる可能性があります。
  - 約18分の動画(1920x1080)で200枚の切り出しでしたが1分程度だった。
- **出力画像のサイズ:** `-vf scale`オプションで出力画像のサイズを調整できます。
- **出力形式:** `format`変数を変更することで、出力画像の形式を変更できます。

## **参考:**

* [ffmpeg Documentation](https://ffmpeg.org/ffmpeg.html)

## おわりに

ffmpeg も bash での制御文も、一から書くととても時間がかかる。
生成AIに依頼することでそれっぽいものができた。
エラーをつぶすだけだったのでかなり時間短縮ができた。

## 手で修正した箇所

### for 部分

```bash
## 修正前
# 切り出し処理
for ((i=0; i<=`echo "$duration / $interval" | bc -l`; i++)); do

## 修正後
# 切り出し回数を計算
count=$(printf "%.0f" $(echo "$duration / $interval" | bc -l))
# 切り出し処理
for ((i=0; i<$count; i++)); do
```

修正前だと計算結果に小数点が出て for のシンタックスエラーになった。
事前に小数点を切り捨てるようにした。

### ファイル名

```bash
## 修正前
for ...
  ffmpeg -ss "$((i * interval))" -i "$input_video" -frames:v 1 "$output_dir/${filename_format}" -vf scale=-1:720
done

## 修正後
for ...
  filename=$(printf "$filename_format" "$i" "$format")
  ffmpeg -ss "$((i * interval))" -i "$input_video" -frames:v 1 -vf scale=-1:720 "$output_dir/${filename}"
done
```

ffmpeg の結果ファイル名を連番ファイル名にするべきところが `$filename_format` だった。

ついでに ffmpeg のオプションの scale の位置がまちがっていた。