OmniAICreator/Qiita-1.07M huggingface dataset:
Playwright – getByTestId と getByText をチェーンして利用する 

# コード例

以下のように書くと「指定の data-testid を持つ要素が、指定のテキストを持っている」という検証ができるようだ

```ts
await expect(page.getByTestId('some-id').getByText('some-text')).toBeVisible()
```

つまり複数のlocatorを組み合わせて使えるらしい

# 公式


>You can chain methods that create a locator, like [page.getByText()](https://playwright.dev/docs/api/class-page#page-get-by-text) or [locator.getByRole()](https://playwright.dev/docs/api/class-locator#locator-get-by-role), to narrow down the search to a particular part of the page.
>In this example we first create a locator called product by locating its role of listitem. We then filter by text. We can use the product locator again to get by role of button and click it and then use an assertion to make sure there is only one product with the text "Product 2".


翻訳

> page.getByText() や locator.getByRole() など、ロケーターを作成するメソッドを連鎖させて、ページの特定の部分に検索を絞り込むことができます。
>この例では、最初に listitem の役割を見つけて product というロケーターを作成します。次に、テキストでフィルタリングします。製品ロケーターを再度使用して、ボタンの役割を取得してクリックし、アサーションを使用して、テキスト「Product 2」を持つ製品が 1 つだけであることを確認します。

以下の例では一時変数を使ってるが、やっていることは変わらないはず


```ts
const product = page.getByRole('listitem').filter({ hasText: 'Product 2' });

await product.getByRole('button', { name: 'Add to cart' }).click();

await expect(product).toHaveCount(1);
```


https://playwright.dev/docs/locators#matching-inside-a-locator

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# プロフィール・経歴

https://github.com/YumaInaura/YumaInaura
npsp__ACCT_AccountMerge_TDTM.handleAccountMergeFixupsFuture でのエラー

[NPSP エラーに戻る](https://qiita.com/Keiji_otsubo/items/9765a3f1078b99d8223f)



# Message: "First error: Delete failed. First exception on row 0 with id 00K8c00000F9TAZEA3; first error: ENTITY_IS_DELETED, entity is deleted: []" Context: npsp__ACCT_AccountMerge_TDTM.handleAccountMergeFixupsFuture

+ [What is Error Type: Future method error](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000Jgloc)

:::note
This error is coming because it thinks that the record it is trying to delete has already been deleted

Records beginning 00K are Opportunity Contact Roles - so it thinks that the Opportunity Contact Role it is trying to delete has already been deleted

Does that give you any clue as to what is going on?

https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000BtvTzSAJ

このエラーは、削除しようとしているレコードがすでに削除されていると考えられるために発生します。

00K で始まるレコードは商談取引先責任者の役割です。そのため、削除しようとしている商談取引先担当者の役割はすでに削除されていると考えられます。

それは何が起こっているのかについて何か手がかりを与えますか？
:::

+ [Message: "First error: Delete failed. First exception on row 0 with id 00KVr000001zsQeMAI; first error: ENTITY_IS_DELETED, entity is deleted: []"Context: npsp__ACCT_AccountMerge_TDTM.handleAccountMergeFixupsFuture](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007bLcCd)
Windows10のgolangでオレオレ証明書を作ってみた

golangのオマケのプログラムでオレオレ証明書が作れるのですが、windows10上での作成法を検索しても見つからなかったのでメモを残しておきます

```
go run "C:\Program Files\Go\src\crypto\tls\generate_cert.go" --rsa-bits 2048 --host localhost
```

実行ファイル化する方が使いやすいそうですよ

以上です
他のコンピュータをリモートで操作したい(ssh, waypipe ssh)

リモートでPCを操作したい場合は、`ssh`コマンドを使用する。

```
$ ssh [ログインするユーザー名]@[ログイン先コンピュータのIPアドレス]
```

ログインするユーザー名が`user`、ログイン先コンピュータのIPアドレスが`192.168.33.14`の場合は、
```
$ ssh user@192.168.33.14
```

のように実行する。

ディスプレイサーバーを使うと、リモートPCのデスクトップ画面を転送することができる。
ディスプレイサーバーを使って、デスクトップ画面を転送するためには、`-Y`,`-C`オプションを指定すれば良い。
```
$ ssh -Y -C user@192.168.33.14
```

`ssh`で接続ができた後に、`nautilus`コマンドを実行すると、ウィンドウが開いてGUIで操作できるようになる。

```
$ ssh -Y -C user@192.168.33.14
$ nautilus
```

X転送の後継の「Wayland」に移行しており、Ubuntu21.04以降などの環境では動作しないアプリケーションがある。その場合は、`apt install waypipe`でwaypipeをインストールすればよい。
また、`waypipe`を利用してデスクトップの転送をする場合は、`ssh`の代わりに`waypipe ssh`を利用する。
一連の操作手順は、下記のように行う。
```
$ sudo apt install waypipe
$ waypipe ssh user@192.168.33.14
$ nautilus
```

Ubuntu21.10以前の環境だと、`apt`でwaypipeがインストールできないので、ソースコードから直接インストールすればよい。ホームディレクトリ`~`にソースコードをダウンロードする場合の実行例を記載した。
- https://gitlab.freedesktop.org/emersion/waypipe
```
$ sudo apt install meson python3 pkg-config \
    ninja-build build-essential \
    liblz4-dev libgbm-dev libdrm-dev libavcodec-dev \
    libva-dev libswscale-dev
$ git clone https://gitlab.freedesktop.org/emersion/waypipe.git
$ cd waypipe
$ mkdir ~/bin build-waypipe
$ meson --buildtype debugoptimized -Dprefix=$HOME build-waypipe
$ ninja -C build-waypipe install
```

この後、一旦ログアウトして、ログインし直すとwaypipeコマンドが使える状態となる。

### 付録
#### Linuxディストリビューションのバージョンを確認する方法
LinuxディストリビューションのOSやカーネルのバージョン情報は、`/etc/`下の`*-release`ファイルに記載されている。`*`の部分は、ディストリビューションにより異なる。例えば、Ubuntuだと`/etc/lsb-release`や`/etc/os-release`に記載されている。
筆者のWSL環境での実行例は下記のようになる。
```
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.2 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.2 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
```
Javaで「デフォルトエンコーディングを確認する」の動作を確認してみた

# 概要

Javaで「デフォルトエンコーディングを確認する」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/encoding/index1.html

# 実装

以下のファイルを作成しました。
```JSample1_1.java
class JSample1_1{
  public static void main(String[] args){
    System.out.println(System.getProperty("file.encoding"));
  }
}
```
```JSample1_2.java
class JSample1_2{
  public static void main(String[] args){
    System.out.println("こんにちは");
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample1_1.java 
$ java JSample1_1 
UTF-8
```
```
$ javac JSample1_2.java 
$ java JSample1_2
こんにちは
```

# まとめ

何かの役に立てばと。
ATtinyしりーずのピンアサインを推測する方法

## まえがき

みなさまこんにちは、特にブラインドのみなさまこんにちは。

フィジカルコンピューティングをやりたいかなり見えにくい方々、手に入れたいろんな基板たちのピン配置を調べるのには案外難儀しているのではないかと思います。そんな私も難儀しているわけでして、調べたものは極力
[自分のブログ](https://www.rd01.net/)
に書くようにはしています。とはいっても、自分が興味のあるものしか掲載しませんし、シリーズ全部のパーツを掲載するわけでもありません。

ということで、ATtinyシリーズはいろいろと面白いマイコンなのですが、おそらく一度もピン配置を掲載していません。

そこで、各種リソースを眺めながらピン配置を推定しようというのがこの記事の目的です。

## ATtinyシリーズのピン配置原則

この記事では、両側に足が生えているATtinyを扱います。おそらくDIPに変換したものを使おうとしていらっしゃるのだろうと思います。あるいはカスタム基板に搭載されているものでしょうか？私は、202, 1614, 3216の3つを所持しています。

どちらが1番ピンであるかどうかはわかっているものとします。これは触って判別ができません。

* 1番はかならずVCCです。電源ですね。
* 最後のピンはGNDです。1番の向かい側になるピンですね。

ぶっちゃけこの接続を間違えなければ簡単には壊れるものでもありません。間違えても壊れないこともあります。ただ、ものすごく発熱することがありますので、触るときには注意して！

ATtinyマイコンにはA, B, Cというピンのグループがあります。Cグループがないマイコンもありますが、一応3つあります。それぞれのグループは、最大8本のピンがあるようです。

これを覚えておきながら、次に進みましょう。

## PlatformIOのピン定義を眺めてみる

Arduinoにも同じファイルが入っているはずですが、場所が特定できませんのでPlatformIOで書きます。
### ATtyny XX2シリーズ
~/.platformio/packages/framework-arduino-megaavr-megatinycore/variants/txy2/pins_arduino.h
``` C
#define PIN_PA6   (0)
#define PIN_PA7   (1)
#define PIN_PA1   (2)
#define PIN_PA2   (3)
#define PIN_PA3   (4)
#define PIN_PA0   (5)
```

この定義の順番で２番ピンから順番にならんでいます。この定義は6個ありますから8ピンのマイコンだということになりますね。

### ATTiny XX4シリーズ

~/.platformio/packages/framework-arduino-megaavr-megatinycore/variants/txy4/pins_arduino.h
``` C
#define PIN_PA4          (0)
#define PIN_PA5          (1)
#define PIN_PA6          (2)
#define PIN_PA7          (3)
#define PIN_PB3          (4)
#define PIN_PB2          (5)
#define PIN_PB1          (6)
#define PIN_PB0          (7)
#define PIN_PA0         (11)
#define PIN_PA1          (8)
#define PIN_PA2          (9)
#define PIN_PA3         (10)
```

こちらは12個定義がありますから、14ピンですね。

### ATTiny XX6シリーズ

~/.platformio/packages/framework-arduino-megaavr-megatinycore/variants/txy6/pins_arduino.h
``` C
#define PIN_PA4         (0)
#define PIN_PA5         (1)
#define PIN_PA6         (2)
#define PIN_PA7         (3)
#define PIN_PB5         (4)
#define PIN_PB4         (5)
#define PIN_PB3         (6)
#define PIN_PB2         (7)
#define PIN_PB1         (8)
#define PIN_PB0         (9)
#define PIN_PC0        (10)
#define PIN_PC1        (11)
#define PIN_PC2        (12)
#define PIN_PC3        (13)
#define PIN_PA0        (17)
#define PIN_PA1        (14)
#define PIN_PA2        (15)
#define PIN_PA3        (16)
```

何ピンでしょうか？はい、20ピンですね。

## UPDIのピンはどこ？

このマイコンたちに書き込むためには電源とUPDIの3本を接続する必要があります。ではUPDIって？

答えはPA0です。上記の定義からPA0を探して、そのピン番号を推測して接続します。間違ってたら書き込めないだけです。VCCとGNDを間違えなければ壊れません。

## 最後に

ほぼ完全に、私と似たような見えにくい人たちに向けて、フィジカルコンピューティングのハードルをちょっとでも下げてみようかなと思って、私のメモから記事を書いてみました。これらのマイコンたちはブレッドボードで直接扱えないので、どうにかしてDIP変換したものを手に入れないといけないのですが、それでもピン配置が予測できると、一つハードルが下がります。

では、ハッピー・ハッキング！
Solidityで関数宣言する方法

solidityで関数宣言する際の書き方をまとめてみたので忘れてしまった方は参考にしてください。

# 書き方の例
## 通常の形
基本的にはJavascriptと同様の書き方をします。
```
function 関数名(引数) {

}
```
## プライベートorパブリック
コントラクトにデプロイする際は、悪意のある外部からの関数呼び出しを避けるため、基本的にはプライベートにしましょう。
```
function func(string hoge) private {

}
```
```
function func(string hoge) public {

}
```
## 戻り値あり
returnsの後に戻り値の型を書く。
```
function func(string hoge) private returns (string) {

}
```
## 通例+最終形
通例として、関数のパラメータやプライベート関数の名前には最初にアンダースコアを付けましょう。
```
function _func(string _str) private returns (string) {
    return _str;
}
```
atcoder_practice×online-judge-tools/oj  サンプルコードを一発でフォルダに配置するスクリプト

## 概要
mookjpさんのatcoder_practiceでテンプレート構築したあと、サンプルコードを手動で取り込むのが面倒だったので、online-judge-toolsで取得して配置するスクリプトを作成してみた。

## 私の実行環境

Windows11/Ubuntu 22.04.4 LTS(WSL)
atcoder_practiceのinit.shがちゃんと動く環境なら大丈夫なはず。

## 前提

当然以下２つの準備が必要(手順は割愛)

https://github.com/mookjp/atcoder_practice

https://github.com/online-judge-tools/oj


## 手順

①atcoder_practiceのinit.shと同じフォルダにget_testcase.shを配置。

<details><summary>get_testcase.sh</summary>

```bash:get_testcase.sh
#!/bin/bash -e

# ojコマンドで取得したものをatcoder_practiceに適合するように配置するshell

CONT_NM="abc351"
pattern="^[0-9]+$"
MOD_FOLDER="${CONT_NM}"

if [ $# -eq 3 ] && [[ $2 =~ $pattern ]] && [ -d $3 ]; then
  CONT_NM=$1$2
  MOD_FOLDER=$3
elif [ $# -eq 2 ] && [[ $2 =~ $pattern ]] && [ -d $1$2 ]; then
  CONT_NM=$1$2
  MOD_FOLDER="${CONT_NM}"
elif [ $# -eq 2 ] && [[ $2 =~ $pattern ]] && [ -d $2 ]; then
  CONT_NM=$1$2
  MOD_FOLDER=$2
elif [ $# -eq 1 ] && [[ $1 =~ $pattern ]] && [ -d abc$1 ]; then
  CONT_NM=abc$1
  MOD_FOLDER="${CONT_NM}"
elif [ $# -eq 1 ] && [[ $1 =~ $pattern ]] && [ -d $1 ]; then
  CONT_NM=abc$1
  MOD_FOLDER=$1
else
  echo "usage: get_testcase.sh {contest name} {contest number} {folder name}"
  echo "e.g. abc 351 abc351"
  echo "**run ./init.sh first**"
  exit 1
fi

BASEDIR=$(/bin/pwd)

for q in {a..f}; do
  url="https://atcoder.jp/contests/${CONT_NM}/tasks/${CONT_NM}_$q"
  PARENT_FOLDER="${BASEDIR}/${MOD_FOLDER}/$q/question"
  if [ ! -d ${PARENT_FOLDER} ]; then
    echo "run ./init.sh first"
    exit 1
  fi
  if [ -d "${BASEDIR}/test" ]; then rm -r "${BASEDIR}/test"; fi
  oj download "${url}" || exit 1
  if [ -d "${PARENT_FOLDER}/testfiles" ]; then rm -r ${PARENT_FOLDER}/testfiles; fi
  mv test ${PARENT_FOLDER}/testfiles/
  cd ${PARENT_FOLDER}/testfiles
  for i in {1..3}; do
    if [ -f ./sample-$i.in ]; then
       mkdir 00$i
       mv ./sample-$i.in ./00$i/stdin.txt
       mv ./sample-$i.out ./00$i/stdout.txt
    fi
  done
  cd "${BASEDIR}" || exit 1
done
```
</details>

②init.shを動かしてコンテスト用のフォルダを生成する。
③get_testcase.shを動かす

```shell
./init.sh github.com/jitaoepsilon/atcoder abc351
# 初回は実行権限の付与を忘れずに
sudo chmod +x get_testcase.sh
./get_testcase.sh abc 351 abc351
```

## 補足

引数は何パターンか想定している。

```shell
# 適当にフォルダ名を設定していても第３引数に指定していれば動く
./get_testcase.sh abc 351 ABC351
# フォルダ名がabc351 or 351のパターンの場合、第３引数は省略可
./get_testcase.sh abc 351
# abcも省略できるが、フォルダ名は２パターンのみ(abc351 or 351)
./get_testcase.sh 351
```

## 今後
以下サイト等を参考にいろいろ引数関係のところを修正したさある。少なくとも以下は対応したい
- urlを直で指定するオプション
  - 今のところ `[a-z]+[0-9]+` のパターンであれば大丈夫なはず
- フォルダ名を直で指定するオプション(第３引数はオプション化したい)

https://zenn.dev/takakiriy/articles/e65780261dd5e3
【ABC334】FortranでA,B,C問題

## 目次
  - [A - Christmas Present](#a---christmas-present)
  - [B - Christmas Trees](#b---christmas-trees)
  - [C - Socks 2](#c---socks-2)


## A - Christmas Present
### 問題
バットかグローブのうち、値段が高い方を出力します。

>**制約**
>1. B,G は 1 以上 1000 以下の相異なる整数


詳細はこちらです。

https://atcoder.jp/contests/abc334/tasks/abc334_a

### 解説
バットとグローブの値段を比較して、金額の大きい方を出力します。

### プログラム例
```Fortran
program abc333a
    !B:バットの値段
    !G:グローブの値段
    implicit none
    integer B, G

    !入力
    read (*, *) B, G

    !出力
    if (B > G) then
        write (*, *) "Bat"
    else
        write (*, *) "Glove"
    end if
end program abc333a
```



## B - Christmas Trees
### 問題
東西に無限に伸びる道路があり、座標が A である地点を基点にして M m おきにクリスマスツリーを立てます。
座標L,R (L≤R)の間にあるクリスマスツリーの本数を求めてください。

>**制約**
>1. $−10^{18}≤A≤10^{18}$
>2. $1≤M≤10^9$
>3. $−10^{18}≤L≤R≤10^{18}$
>4. 入力は全て整数

詳細はこちらです。

https://atcoder.jp/contests/abc334/tasks/abc334_b

### 解説
座標Aを原点にL,Rの位置を考えて間にあるツリーの数を数えます。
座標Aは$−10^{18}≤A≤10^{18}$であるため、L、Rの座標は座標Aの分だけオフセットします。

またL,Rの範囲は$−10^{18}≤L≤R≤10^{18}$であるため、値の正負の組み合わせは「正正」、「正負」、「負負」の３パターンあります。
３パターン分の計算を考えるのは大変なので、L、Rにはあらかじめ大きい数を足しておき、値の正負の組み合わせを「正正」のみにしておきます。

### プログラム例
```Fortran
program abc333b
    !L：高橋君の位置
    !R：青木君の位置
    !A：基点になる座標
    !M：ツリーを建てる間隔
    implicit none
    integer(16) A, M, L, R, X, ans

    !入力
    read (*, *) A, M, L, R

    !クリスマスツリーの本数計算
    L = L - A; R = R - A
    X = 10.0**18
    L = L + X*m; R = R + X*m
    ans = (R/M) - ((L - 1)/M)

    !結果出力
    write (*, *) ans
end program abc333b
```



## C - Socks 2
### 問題
 
N 組の靴下のうち、色 $A _1,A_2,…,A_K$の靴下を 1 枚ずつなくしました。
残った靴下を組み合わせて、新しく靴下の組みを作り直します。

異なる色からなる靴下の組に「奇妙さ」という指標を設けます。
奇妙さは$∣i−j∣ $で定義されます。

靴下の組み合わせを作り直す時、奇妙さの総和が最小でいくつになるか求めてください。
ただし、無くした靴下が奇数の場合はどの組にも含まれない靴下が 1 枚存在することに注意してください。

>**制約**
>1. $1≤K≤N≤2×10^5$
>2. $1≤A_1<A_2<⋯<A_K≤N$
>3. 入力は全て整数

詳細はこちらです。

https://atcoder.jp/contests/abc334/tasks/abc334_c


### 解説
なくしていない色の靴下はその色同士で組を作るのが最適です。

なくした色の靴下の組み合わせは、無くした靴下の数が偶数か奇数かによって異なります。

偶数の場合、奇妙さの総和が小さくなる様に隣同士の靴下$A_i、A_{i+1}$で組み合わせを作成し、奇妙さの総和を計算します。

奇数の場合は使わない靴下を1つ選ぶ必要があります。
使わない靴下を選んだ後は、偶数の場合と同様に隣同士の靴下$A_i、A_{i+1}$で組み合わせを作成し、奇妙さの総和を計算します。

ただし、使わない靴下を変える度に奇妙さの総和を計算し直すと**TLE**となります。
対策として使わない靴下を$A_1$から順番に選んでいき、変更した差分のみを計算することで計算量を削減します。


### プログラム例
```Fortran
program abc333c
    !N      ：靴下の組数
    !K      ：無くした靴下の数
    !A      ：無くした靴下の種類
    !min_Ans：奇妙さの最小値
    !Ans    ：奇妙さの計算
    implicit none
    integer N, K
    integer i, Ans, min_Ans
    integer, allocatable::A(:)

    !入力
    read (*, *) N, K
    allocate (A(K))
    read (*, *) A(:)
    Ans = 0

    !最小の奇妙さの計算
    if (mod(K, 2) == 0) then !無くした靴下が偶数個の場合
        do i = 1, K - 1, 2
            Ans = Ans + (A(i + 1) - A(i))
        end do
        min_Ans = Ans
    else !無くした靴下が奇数個の場合
        !1番目の靴下を使わない
        do i = 2, K - 1, 2
            Ans = Ans + (A(i + 1) - A(i))
        end do
        min_Ans = Ans
        !3~K番目の靴下を使わない
        do i = 3, K, 2
            Ans = Ans - (A(i) - A(i - 1))
            Ans = Ans + (A(i - 1) - A(i - 2))
            min_Ans = min(min_Ans, Ans)
        end do
    end if

    !結果の出力
    write (*, *) min_Ans
end program abc333c
```
《Claude》チームプラン・iOSアプリを発表

Claudeに関する2つのアップデートを発表されました。新しいチームプランとiOSアプリです。

---

こちらの記事もおすすめ

https://hamaruki.com/create-release-notes-extremely-quickly-using-claude-ai-and-sourcesage/

https://hamaruki.com/harina-receipt-analysis-discord-bot-app-using-claude-3-haiku/

## チームプランの特徴

* チームプランでは、メンバーの利用量を増やしユーザーや請求を管理するツールを備えたワークスペースを作成できます。業界を問わずチームが次世代のClaude 3モデルファミリーを活用するのに最適な方法です。このプランは、ユーザー1人あたり月額30ドルで利用できます。

* チームプランの主な特徴は以下の通りです。
  - **利用量の増加**: Proプランと比較して、ユーザーごとの利用量が大幅に増加。チームメイトがClaude3とのチャット回数を大幅に増やすことができます。
  - **Claude 3モデルファミリーへのアクセス**: Opus、Sonnet、Haikuを含むClaude 3モデルファミリー全体を提供。ビジネスニーズに合わせて最適なモデルを選択できます。
  - **200Kのコンテキストウィンドウ**: 長文書の処理、複雑なトピックの議論、複数ステップの会話の維持が可能になり、データからより深い洞察を得ることができます。
  - **管理ツールと請求管理**: ユーザーと請求を簡単に管理できる管理ツールを導入。オンボーディングの手間を減らせます。
  - **Proの全機能**: 優先アクセス、新機能の早期利用、利用量の増加など、Proのすべてのメリットがあります。

## iOSアプリの機能

* Claudeの新しいiOSアプリの主な特徴は以下の通りです。
  - **ウェブチャットとのシームレスな同期**: デバイス間でチャットの続きを簡単に行えます。 
  - **ビジョン機能**: ライブラリの写真を使用したり、新しい写真を撮ったり、ファイルをアップロードしたりして、リアルタイムの画像分析やモバイル中心の使用事例を外出先で利用できます。
  - **オープンアクセス**: Pro、Teamなど全プランのユーザーが無料でアプリをダウンロード可能。

アーリーテスターからは、Claudeアプリは移動中のアイデア出し、質問への素早い回答、実世界のシーンや画像の分析に優れていると報告されています。新しいiOSアプリにより、最先端のAIがいつでもポケットに。

AppStoreからダウンロードできます。まずは無料で体験を。

## 参考サイト

https://www.anthropic.com/news/team-plan-and-ios

https://www.anthropic.com/news/claude-3-family
Lambda 関数 URL で OAC で CloudFront 経由の実行のみを許可する

# 概要

https://aws.amazon.com/jp/about-aws/whats-new/2024/04/amazon-cloudfront-oac-lambda-function-url-origins/

# 抑えておくべき用語

## Lambda 関数 URL

API Gateway 無しに Lambda のメニューから機能を ON にするだけ HTTPS 公開ができる。

https://qiita.com/leomaro7/items/f2142431e10cd7cc470d

## OAC

指定された CloudFront ディストリビューションからのアクセスのみにする。

https://qiita.com/leomaro7/items/b9deda523f0c94a494ca

# やってみる

## Lambda 1

Lambda 関数は単純に Hello World を返すもののため省略します。

関数 URL には「**AWS_IAM**」を指定。
![スクリーンショット 2024-05-01 15.46.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/4ff8b6af-23e0-b2ce-abfb-6015a13e0966.png)

## CloudFront

Origin domain に「関数 URL」を指定。
![スクリーンショット 2024-05-01 15.51.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/6068e57d-f3cb-c5f7-8d3d-136556295174.png)

Origin access control を作成し指定。
![スクリーンショット 2024-05-01 15.57.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/bd634137-2fc4-73f3-f22f-c7e9f21f3b0b.png)

## Lambda 2

作成中に表示さされた CLI を実行して、リソースベースのポリシーステートメントを追加します。

```
aws lambda add-permission \
--statement-id "AllowCloudFrontServicePrincipal" \
--action "lambda:InvokeFunctionUrl" \
--principal "cloudfront.amazonaws.com" \
--source-arn "arn:aws:cloudfront::１２３４５６７８９０１２:distribution/XXXXXXXXXX" \
--region "ap-northeast-1" \
--function-name oac_lambda_function_url
```

## 動作確認

CloudFront ディストリビューションドメイン名でアクセスできることを確認

```
curl https://XXXXXXXXXXXX.cloudfront.net/                                   
{
    "version": "2.0",
    "routeKey": "$default",
    "rawPath": "/",
    "rawQueryString": "",
    "headers": {
        "x-amz-content-sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
        "cloudfront-is-android-viewer": "false",
        "x-amzn-tls-version": "TLSv1.2",
        "cloudfront-viewer-country": "JP",
        ///以下省略
```

Lamda 関数 URL でアクセス拒否されることを確認

```
curl https://XXXXXXXXXXXX.lambda-url.ap-northeast-1.on.aws/
{"Message":"Forbidden"}%            
```
Hello! World!を表示させたい。

# プロジェクトを作ったら。
前回、プロジェクトを作成したが、それはWebアプリケーションの土台となる部分。Djangoのプログラムの構造は、プロジェクトがあって、その中にいろんなアプリケーションを作って、そのそれぞれのアプリケーションの中に、そのためのプログラムを作っていく感じ。

![Django_kousei.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779281/fd6c795b-0d69-9939-6359-4e265612432b.png)

なので、なにかしらアプリケーションを作っていこう。
### アプリケーションを作る方法
ターミナルで、カレントディレクトリをdjango_appに移動させてから
```
python manage.py startapp アプリの名前
```
これで、アプリは完成。

## Hello!world!を表示させるだけのアプリを作る
先ほど作った、アプリの中にある、views.py開く。これは、画面に表示させるものを記述するためのもの。まさに、やりたいことそのまんま。これに下のやつを書いていく。
```
// django.httpというモジュールから、HttpResponseというクラスをimport
from django.http import HttpResponse
```
HttpResponceとは、Webアプリにアクセスしてきた側(いわゆるクライアント)に送り返す内容を管理するクラス。
```
def index(request):
   return HttpResponse("Hello! World!")
```
def index(request): とは、indexという名前の関数を作っている。引数にはrequest。この、requestというのは、Djangoビュー関数に渡されるHTTPリクエストオブジェクト。このオブジェクトは、クライアントからのHTTPリクエストに関する情報を含んでいて、例えば、GETやPOSTで送信されたデータ、クッキー、セッション、ユーザーエージェント情報などが含まれる。簡単に言うと、アクセスしてきた側の情報がたくさん入っている変数？だとぼくは認識。

Djangoのビュー関数では、通常、この request オブジェクトを受け取り、それに基づいて処理を行う。しかし、今回クライアントの情報なんて全く使ってないから、なくてもOK。ただ、入れといて損することないってことだと思う。

## urls.pyを変えよう。
views.pyだけかえても、アプリケーションは使えない。urls.pyに、「このURLにアクセスされたら、このファイルのこの関数を実行させてね。」っていうことを逐一書いていかなけらばならん。めんどくさいけど、たくさんのアプリが繋がってできたプロジェクトになると、必要不可欠。
なので、次のように書いていく。
```
from django.contrib import admin
from django.urls import path
import hello.views as hello //今回は、helloというアプリを作った。

urlpatterns = [
    path("admin/", admin.site.urls),
    path("hello/", hello.index),
]
```
import hello.views as hello とは、「hello」フォルダ内の、views.pyをhelloという名前で呼べるようにした。

### path関とは
```
path(アクセスするアドレス, 呼び出す処理)
```
第一引数に与えたアドレスにアクセスをしたら第二引数の処理を実行してくれという意味。
だから、
hello/にアクセス
↓
path("hello/", hello.index)
↓
hello.indexを実行
となる。

:::note info
urlpatterns は、DjangoのURL設定で使用される特別なリストです。Djangoはこのリストを使用して、クライアントのHTTPリクエストを適切なビューにルーティングします。通常、urlpatterns リストには、path() や re_path() などの関数を使用して、URLパスとそれに対応するビューを指定します
:::

## アクセスしてみる！
Djangoで作ったWebアプリにアクセスするためには？
まず、ターミナルで次のコマンドを実行して、ローカルサーバを立ち上げるんでしたよね。
```
python manage.py runserver
```
そしたら、この立ち上げたサーバ(localhostサーバ)にアクセスするため、次のアドレスをChromeでもなんでも検索してみる！ここで、今回は、作ったサーバのhelloにアクセスする！
```
http://localhost:8000/hello/
```
「Hello! World!」と表示できた!
reviewdogを使っているときにハマったときのメモ

### reviewdogを使っているときにハマったときのメモ

```yaml
name: ESLint

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

jobs:
  eslint:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    defaults:
      run:
        working-directory: my-vue-app
    steps:
      - uses: actions/checkout@v4
      - uses: reviewdog/action-eslint@v1
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          reporter: github-check
          eslint_flags: "src/"
```
公式にならって以上の通りに書いてました。
```bash
Run reviewdog/action-eslint@v1
Run $GITHUB_ACTION_PATH/script.sh
🐶 Installing reviewdog ... https://github.com/reviewdog/reviewdog
sh: 1: eslint: not found
 Running `npm install` to install eslint ...
sh: 1: eslint: not found
eslint version:
 Running eslint with reviewdog 🐶 ...
Error: Process completed with exit code 1.
```
なぜか落ちる
<pre>
.
├── .github
    └── workflow
         └── ESLint.yml
└── my-vue-app
     └── src
         └── package.json
         └── ...
</pre>
ディレクトリ構成は以上の通り

#### 原因
- 公式に二通りあり、プロジェクト直下じゃないと上記では動かない？
- src直下に辿り着いていない？

##### 修正
```diff_yaml
name: ESLint

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

jobs:
  eslint:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    defaults:
      run:
        working-directory: my-vue-app
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v3
        with:
          node-version: "20"
      - run: npm install
      - uses: reviewdog/action-eslint@v1
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          reporter: github-check
          eslint_flags: "src/"
+          workdir: my-vue-app 

```
注意してほしいのが、`defaluts`部にworking-directoryを指定してもreviewdogにworkdirを割り当てる必要があります。(自分の環境だけかも)

```bash
Run reviewdog/action-eslint@v1
Run $GITHUB_ACTION_PATH/script.sh
🐶 Installing reviewdog ... https://github.com/reviewdog/reviewdog
v8.57.0
eslint version:v8.57.0
 Running eslint with reviewdog 🐶 ...
  reviewdog: Reporting results for "eslint"
  reviewdog: No results found for "eslint". 0 results found outside diff.
```
**よきlintライフを**
Node.jsでexpressとejsを使用しウェブページを作成（参考程度

# 使用したパッケージ
### 1.express
インストールコマンド
    
npm
    
```
npm install express
```

yarn
    
```
yarn add express
```


### 2.ejs

インストールコマンド
npm
    
```
npm install ejs
```
    
yarn
    
```
yarn add ejs
```
# サイトのファイル構成
- publicフォルダー
    cssやimgなどを置くフォルダー
- views
    app.jsでアクセスがあったページのejsを置く場所
- app.js
    サイトへアクセスがあったページへ移動処理など


```
sample/
┣━ public/
┃　　　┣━ css/
┃　　　┗━ img/
┣━ views/
┃　　　┣━ top.ejs
┃　　　┗━ index.ejs
┣━ app.js
etc

```

    
# ページ表示の処理
app.js ファイルで行う

### expressを使用するためapp.jsの先頭で宣言
```javascript
//expressを使うためのコード
const express = require('express');
const app = express();
```
### cssやimgお置いてあるpublicフォルダーへアクセスするための処理
ejsファイル内でcssやimgフォルダーへアクセスするのに必要
```javascript
app.use(express.static('public');
```

### サイトへアクセスがあった時の処理
```javascript
// '/'にアクセスしたときの処理
app.get('/', (req, res) => {
    //top画面のejsファイルを開く
    res.render('top.ejs');
});
```

## ejsの記述
1.HTMLは特別変わらない

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>topページ</title>

     <!-- publicを起点としたパスを記述 -->
	<link rel="stylesheet" href="/css/style.css">
 
  </head>
  <body>
    <div>
    
        <!-- publicを起点としたパスを記述 -->
		<img src="/img/">

        <!-- /indexへ移動できる -->
        <a href="/index" >もどる</a>
  
    </div>
  </body>
</html>
```

2.javascriptが記述できる
- <% %>
    javascriptの処理を表示したくない場合に書く
    
- <%= %>
    javascriptの処理を表示したい場合に書く
```html
<body>
    <div>
        //表示されない
        <% const name = "名前"; %>
        //「名前」と表示される
        <p><%= namae %></p>
    </div>
  </body>
```
Ruby on Rails: Ransackを用いたモデル検索のエラー解決方法②

この記事では、Ruby on RailsでRansackを使った検索機能の設定方法について説明します。前回の記事では、Ransackの設定と関連するモデルへのホワイトリストの追加を行いました。今回は、フォームから送信されるパラメータに対する処理の方法と、検索結果を正しく絞り込むための対策に焦点を当てます。

## 前回の記事

https://qiita.com/KM9973/items/92ef1698202dc9a89681

## 背景

Railsアプリケーションで、`Reservation`モデルに対して、顧客単位で検索を行う必要がありました。しかし、Ransackの設定やビューからのパラメータ処理に問題が生じ、検索が正常に動作しないという課題がありました。

## エラー内容

フォームから検索を行うために、以下のように設定しました：

```ruby
<%= search_form_for @r, url: reservations_path, method: :get, local: true, class: 'custom-form-group d-flex' do |form| %>
  <div class="form-group d-flex align-items-end me-2">
    <div class="w-100">
      <label>顧客名検索:</label>
      <%= form.search_field :customer_name_cont, id: 'single-simple-search-name_cont', class: 'form-control me-2', placeholder: '顧客名検索' %>
    </div>
  </div>

  <%= form.submit '検索', class: 'btn btn-primary' %>
<% end %>
```

このフォームからの検索結果が正しく処理されないという問題がありました。具体的には、検索結果が全て表示されてしまう、またはフォームからのパラメータが無視されてしまうという問題です。

## 解決方法

1. **コントローラーでの`params[:q]`の利用:**

   変更前はparams[:r]を使用していたものをparams[:q]に変更する。
   こうすることでコントローラーでの検索処理に対し、フォームからのパラメータを正しく受け取れるようになる。

   ```ruby
   class ReservationsController < ApplicationController
     def index
       @r = Reservation.ransack(params[:q]) # フォームからのパラメータを`params[:q]`として受け取る
       @reservations = @r.result
     end
   end
   ```

   このように`params[:q]`を使うことで、フォームからのパラメータが正しく受け取られ、Ransackによる検索処理が正常に行われます。


## 設定のポイント

- **フォームとコントローラーの連携:** Ransackを用いる検索の場合、フォームから送信されるパラメータは`params[:q]`としてコントローラーに渡され、それに基づいて検索が行われます（インスタンス変数が@rになったからといって、パラメータがparams[:r]になることはないことに注意）
- **Ransackの設定:** `Reservation`モデルに対するカスタムransackerやホワイトリストなどの設定が、検索キーに対して適切に機能することを確認します。
Node.jsでmariaDBを使用してウェブサイトの作成（参考程度


# Node.jsとmariaDBを使用してウェブサイトを作成メモ

## 使用したパッケージ
|パッケージ名 |機能

1. express
    
1. ejs
    HTMLとjavaScriptの両方を記述できるejsファイル作成できる
1. mariadb
    MariaDBを使用するためのパッケージ

## expressとejsでサイトの記述の仕方

https://qiita.com/kaisei_siratama/items/81b2057e9d02373231d1

## mariadbを使用して操作の仕方

https://qiita.com/kaisei_siratama/items/f3b29b7e8fb9a5a4a791

## MariaDBUtilクラスで宣言し再利用しやすくしてみた
https://qiita.com/kaisei_siratama/items/e02640f09e468e1a0d86

## MariaDBをsequelizeで試験接続
https://qiita.com/kaisei_siratama/items/f9b0dda4cd8dade51499
GPTはLinux贔屓で思いやりが好き？

# はじめに
GPTに聞いてみました。「AIの視点で優位なサーバーOSはWindowsかLinuxか？」

# GPT曰く(無修正)
AI（人工知能）技術の進展において、適切なサーバーオペレーティングシステム（OS）を選択することは、開発と運用の効率性に直結します。一般的に、WindowsとLinuxが広く利用されていますが、AIの視点から見た場合、どちらのOSが優位に立つかは、特定の用途や必要とされる機能に強く依存します。

Linuxはそのオープンソースの性質と、カスタマイズの容易さから、AI研究開発者によって広く支持されています。多くのAI開発ツールやライブラリがLinux上で最初に作られ、最適化されている点も、Linuxを選ぶ大きな理由の一つです。一方、WindowsはGUIが優れており、特定のアプリケーションや商業目的での使用では便利な選択肢となることもあります。

これらの観点から、AI開発においてはLinuxを推奨する意見が多く見られます。Linuxは高度な計算処理が要求されるAIタスクに対する高いパフォーマンスと柔軟性を提供します。さらに、コストパフォーマンスに優れ、クラウド環境との相性も良いという特徴があります。

# では、どのLinuxがいいの？
GPTに聞いてみました。「AIの視点で2024年4月時点でのおすすめLinuxディストリビューションはどれか？」

# GPT応えて曰く(無修正)
2024年4月の時点でおすすめのLinuxディストリビューションを考察する場合、複数の要因を考慮する必要があります。利便性、コミュニティサポート、安定性、パフォーマンス、そしてAI開発における互換性などが重要な指標となります。

以上の点を総合考慮すると、UbuntuがAI開発において強く推奨されるディストリビューションの一つです。Ubuntuは広範囲に渡るデバイスとクラウド環境でのサポート、アップデートの容易さ、そして卓越したセキュリティ機能によって、多くの開発者から信頼を得ています。また、UbuntuはNVIDIAやGoogleのような大手AI技術企業からも支持されており、AI開発用のツールやライブラリが豊富に揃っています。これらの点から、Ubuntuは2024年4月の時点でも、AI開発を行ううえで最適な選択肢の一つと言えるでしょう。

まとめると、AI技術に特化したサーバーOSの選択においては、Linuxの利点が際立ち、中でもUbuntuが特に優れた選択肢であると言えます。このようなOSの選択は、AIプロジェクトの成功に間接的ながら重要な役割を果たすことになるでしょう。

# さいごに
GPTはLinux推し。それも、思いやりでできているUbuntu推し。
24.04 LTSがリリースされたばかりのUbuntu、使っていますか？

https://qiita.com/BeautifulShadow/items/4d4ab356f543a1eff640
初めてのDjangoプログラム

# プロジェクトを作ろう。
djangoの環境構築をしたフォルダでコマンドを実行したい。なので、カレントディレクトリを移動しよう。
```
cd 移動先のファイル 
```
移動した先に、「django_app」というプロジェクトのフォルダを作る。
```
django-admin startproject django_app
```
これで、djangoのプロジェクトを作れた！
## "django_app"フォルダの中身を見てみよう
django_appの中には、同じ名前のフォルダが一つあり、その中を見てみると、いろんなファイルが入っている。
```
## ファイルの構成
django_app/
    manage.py
    django_app/
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py
```

・\_\_init__.py
→Djangoプロジェクトを実行するときの初期化処理を行うスクリプトファイル。
・settings.py
→プロジェクトの設定情報を記述したファイル
・urls.py
→プロジェクトで使うURLを管理するファイル
・wsgi.py
→Webアプリケーションのメインプログラム

みたいな感じ。
manage.pyはこのプロジェクトで実行する様々な機能に関するプログラム。

正直、最初はよくわからなくても大丈夫！使っているうちに、「ああ、このファイルはこれを記述するためのファイルね。」ってちょっとずつわかってくる。

## いったんWebブラウザアクセスしてみよう
「まって、まだWebサーバ買ってないし、そこにアップロードもしてないよ。」と思いますが、DnangoにはWebサーバの機能も組み込まれている。なので、コマンドを実行するだけで、試験的にWebサーバを起動し、そこで動かせる。ターミナル開いて次を実行してみよ。
```
python manage.py runserver
```
### 実際にWebブラウザ開いてアクセス！
Webブラウザ(GoogleChrome, safari等)で以下のアドレスにアクセス。
```
http://localhost:8000/
```
うまくできると、「The install worked successfully! Congratulations!」ってほめてくれる。これができたってことは、Djangoプロジェクトが動いたってこと。

:::note info
http://localhost:8000/ は、Djangoプロジェクトがローカルサーバーで実行されるデフォルトの場所。ローカルホストは、コンピューター自体を指す。ネットワーク上で通信する際、コンピューターはIPアドレスで識別されるが、"localhost" という特別な名前は、自分自身を指すために使用される。つまり、 "localhost" にアクセスすると、自分自身を指定しているため、自分自身のコンピュータで立ち上げたサーバに接続することになる。したがって、Djangoが runserver コマンドを使用して起動されたとき、デフォルトでポート番号8000でローカルホスト上のサーバーが起動される。これにより、Djangoアプリケーションが http://localhost:8000/ でアクセス可能になる。ちなみに、ポート番号8000は、WebフレームワークのDjangoによく充てられるポートだから、これを指しているってっこと。
ってChatGPTが言ってた。
:::
ChakraUI FigPilotを使ってみた感想

ハッカソンでフロントエンドを担当することになり，試してみました．

# [ChakraUI FigPilot](https://figma.chakra-ui.com/)
ChakraUI FigPilotは，ChakraUIの公式で公開されているFigmaのUIキットを使ってFigma上のデザインからコードを自動的に生成するFigmaのプラグインです．
ChakraUIのUIキットは無料で使えますが，コード生成をするChakraUI FigPilotは有料(15ドル)です．

一部のコンポーネントでコード生成ができなかったので，ここにまとめておきます．

<details><summary>コード生成ができるコンポーネント</summary>

- Stack
- Box
- Text
- Alert
- Avatar
- Badge
- Beadcrumb
- Button
- Card
- CheckBox(CheckBoxのみ)
- Icons
- Image
- Input
- Kbd
- Menu
- Modal
- NumberInput
- PinInput
- Progress(Progressのみ)
- Select
- Skelton
- Slider
- Stat
- Tabs
- Tooltip
</details>

<details><summary>コード生成ができないコンポーネント</summary>

- CloseButton(stackになる)
- Radio(stackになる)
- Switch(stackになる)
- Table(StackとTextになる)
- Textarea(stackになる)
</details>

# 使ってみた感想
### 良かった点
- コード生成だけである程度形になったものができる
- ボタンのアイコン等をFigma上で設定できる

### 悪かった点
- コード生成したときに必要のないプロパティまで書かれる
- VStackとHStackを使い分けずに全てStackで書かれる
- 一部のコンポーネントがStackになってコード生成がうまくいかない

<br>
良かった点，悪かった点それぞれあるのですが，結構使いづらかったです．

特にコード生成が厄介で，生成したコードを修正する作業に時間を取られていました．簡単なデザインならChakraUI FigPilotを使った方が時間がかかると思います．実際，ハッカソンでは途中からChakraUI FigPilotを使わずに開発していました...

FAQに書かれているのですが，ページ単位ではなくデザイン単位でコード生成をすると良いみたいです．
【TypeScript】非nullアサーション演算子について

非nullアサーション演算子(`!`)を使用すると`null`または`undefined`でないことをTypeScriptに伝えることができます。

```ts
let sample: string | null = fetchSomeNullableString()
let test: string = sample! // 非nullアサーション演算子を使用
```

上記の例では、`sample`の型は`string | null`ですが、非nullアサーション演算子を使用することで、`string`型である`test`に`sample`を代入できています。
ABC060 ARC073 の問題を解いてみました

今回から記事の書き方を変更していく予定です。

## A問題
https://atcoder.jp/contests/abc060/tasks/abc060_a

言われているとおりに判定しましょう。

~~~C++
#include <bits/stdc++.h>
using namespace std;
//Created by karaju.

int main(void){
  string a, b, c;
  cin >> a >> b >> c;
  
  //しりとりになっているか判定する
  if(a.back() == b.front() && b.back() == c.front()){
    cout << "YES" << endl;
  }
  else{
    cout << "NO" << endl; 
  }
}
~~~

## B問題
https://atcoder.jp/contests/abc060/tasks/abc060_b

まず、$A$の倍数は、いくつ足しても$A$の倍数です。
つまり、問題文は$B$で割ると$C$あまる$A$の倍数は存在するか、という問題に言い換えられます。

そして、少し考察をしてみると、$A$の倍数を$B$で割ったあまりは$B$個ごとに周期的に繰り返されているということがわかります。
<details><summary>具体例</summary>

$A = 5, B = 3$ とすると、

$A$ に 1 をかけたとき、あまりは 2
2 をかけたとき、あまりは 1
3 をかけたとき、あまりは 0
4 をかけたとき、あまりは 2
5 をかけたとき、あまりは 1

</details>

なので、$An \ (1 \leq n \leq B) ≡ C \pmod B$ となるような$n$が存在するかを確かめればよいです。

~~~C++
#include <bits/stdc++.h>
using namespace std;
//Created by karaju.

int main(void){
  int a, b, c;
  cin >> a >> b >> c;
  
  for(int i = 1; i <= b; i++){
    
    if(i * a % b == c){ //条件を満たすのか判定する
      cout << "YES" << endl;
      return 0;
    }
  }
  cout << "NO" << endl;
}
~~~

## C問題
https://atcoder.jp/contests/abc060/tasks/arc073_a

この問題では、$i$人目と$i+1$人目との間のお湯が出る時間について考えます。
入力例2を見てみます。
~~~:入力例2
2 4
0 5
~~~
この場合、1人目と2人目の間では、4秒お湯が出ています。

入力例1を見てみます。
~~~:入力例1
2 4
0 3
~~~
この場合、1人目がスイッチを押した3秒後に2人目がスイッチを押しているので、3秒しかお湯が出ていません。

これらのことから、$i$人目と$i+1$人目の間には、$min(T, t_{i+1} - t_i)$秒間お湯が流れるということがわかります。

なので、$min(T, t_{i+1} - t_i)$ の値を足していけば、答えが求まります。
($N$人目は、必ず$T$秒お湯が流れます)

~~~C++
#include <bits/stdc++.h>
using namespace std;
//Created by karaju.

int main(void){
  int N, T;
  cin >> N >> T;
  int t[N], ans = 0;
  for(int i = 0; i < N; i++) cin >> t[i];
  //入力受け取り
  
  for(int i = 0; i < N - 1; i++){
    ans += min(T, t[i+1] - t[i]);
  }
  ans += T;
  
  cout << ans << endl;
}
~~~

## D問題
https://atcoder.jp/contests/abc060/tasks/arc073_b
[NestJs][WebSocket.io]Jwt認証の実装方法

# はじめに
本記事は表題の通り、NestJsでWebsocket.ioを使用する際、Jwt認証を行う方法について記載します。
実装方法については以下を参考にしてください。わかりやすかったです。

https://qiita.com/jumokuzai/items/39f9bc0213e00e2a4de8

# (推奨)handleConnectionで認証を行う
handleConnection内で認証を行います。
また、定期的にトークンの有効期限の確認も行います。

フロント側でauthにトークンを付与します。
```typescript:フロント側
    const socket = io('http://localhost:3001', {
      auth: {
        token: `Bearer ${accessToken.data.accessToken}`,
      },
    });
```


NestJs側でトークンを取得、configServiceを使用して検証を行います。
```typescript:NestJS側
  handleConnection(client: Socket) {
    const tokenVerificationInterval = setInterval(() => {
      try {
        const token = client.handshake.auth.token.startsWith('Bearer ') ? client.handshake.auth.token.slice(7) : client.handshake.auth.token;
        const secret = this.configService.get<string>('JWT_SECRET_KEY');
        const decoded = this.jwtService.verify(token, { secret });
      } catch (error) {
        // トークンが無効な場合、切断する
        console.log('トークンが無効または期限切れです。接続を切断します...');
        client.disconnect(true);
      }
    }, 60000); // 例: 60秒ごとにトークンの検証を行う

    client.on('disconnect', () => {
      clearInterval(tokenVerificationInterval);
    });
```

# (非推奨)guardを実装して関数ごとにアクセスを制限する
@UseGuardsを使用して関数単位でアクセスを制限する方法もありますが、
関数単位での制限は可能ですが、WebSocket接続自体を防ぐことはできません。
そのため非推奨です。

以下のような形で独自のguardを実装してください
```typescript
import { ExtractJwt, Strategy as BaseJwtStrategy } from 'passport-jwt';

import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PassportStrategy } from '@nestjs/passport';
import { JWTPayload, JWTStrategyPayload } from '../dto/jwt-payload';
import { Request } from 'express';

@Injectable()
export class JwtStrategy extends PassportStrategy(BaseJwtStrategy) {
  constructor(configService: ConfigService) {
    super({
      // Authorization bearerからトークンを読み込む関数を返す
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: configService.get<string>('JWT_SECRET_KEY'),
      passReqToCallback: true,
    });
  }
}
```

# 終わり
業務で実装した内容が多かったので、サンプルコードは大部分を割愛しています。
ご了承ください。

WebSocketの実装方法自体はすぐ見つかったのですが、
業務で使用するため認証が必要になり、苦労しました。

他にも問題がいくつかあり、より良い実装を模索中です。
任意のサイズのダミー画像を作成するCLIツールを作ろう

# はじめに
webサービス開発をしていると、「仮の画像を一旦入れておきたい」みたいなシーンありますよね。

例えばweb上では、[株式会社ソフテル](https://www.softel.co.jp/)様が[placehold.jp](https://placehold.jp/)というツールを提供されています。

https://placehold.jp/

似たようなことがローカル環境でもできたら開発が便利になるのではと思いました。

# 結論
作ったのでよかったら使ってみてください。
https://www.npmjs.com/package/placeholder-craft-cli

# 使い方
以下、[Node.js](https://nodejs.org/en/download)がインストールされていることを前提としています。
## インストール
```sh
npm install -g placeholder-craft-cli
```

## 画像を生成
```sh
phcraft --width 500 --height 500 --filename hoge.png
```
現時点で以下のオプションに対応しています。
```
  -w, --width      幅(必須)
  -h, --height     高さ(必須)
  -b, --bgColor    背景色(デフォルト: "grey")
  -t, --textColor  文字色(デフォルト: "white")
  -f, --filename   ファイル名(デフォルト: "placeholder.png")
```

# 実装の話
## 画像生成
[node-canvas](https://github.com/Automattic/node-canvas) という、webの[Canvas API](https://developer.mozilla.org/ja/docs/Web/API/Canvas_API)との互換を目指したNode.jsで使えるパッケージを利用しています。

https://github.com/Automattic/node-canvas

```typescript
import { createCanvas } from "canvas";

// 縦横を指定してキャンバスを生成
const canvas = createCanvas(width, height);
// 二次元の描画コンテキストを取得
const ctx = canvas.getContext("2d");
// 好きなように描画していく
ctx.fillStyle = bgColor;
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = textColor;
```

最後に、ファイル出力してあげればOKです。
```typescript
const buffer = canvas.toBuffer("image/png");
	fs.writeFileSync(filename, buffer);
```

## オプション引数
コマンドライン引数の受け取りを[yargs](https://github.com/yargs/yargs)を使って実現します。

https://github.com/yargs/yargs

```typescript
import yargs from "yargs";

const argv = yargs
	.option("width", {
		alias: "w",
		describe: "The width of the image",
		type: "number",
		demandOption: true,
	})
     // optionは複数定義可能
     .option("hoge", {
		// 略
	})
	.help() // --helpオプションに対応
	.parseSync() as PlaceholderImageOptions; // オブジェクトにパース

createPlaceholderImage(argv);
```

# コード
以下に全文が載っています。
https://github.com/macaroni10y/placeholder-craft-cli

# さいごに
何かご質問、ご指摘などありましたら是非お願いいたします。
MariaDBにCSVデータを一気にinsertする方法

### 開発環境
- Windows 10 Pro(64bit)
- 11.3.2-MariaDB

1.テーブルを事前に作成
```sql
CREATE TABLE product_master(
  product_code INT AUTO_INCREMENT PRIMARY KEY,
  product_name TEXT NOT NULL
)default charset=utf8mb4;
```


2.テーブルと同じ構造のCSVデータを用意。
```csvs:product_master.csv
product_code,product_name
1,カメラ
2,冷蔵庫
3,自転車
4,掃除機
5,テレビ
6,扇風機
7,ノートパソコン
8,LED電球
9,シャワーヘッド
10,時計
```

今回は、このproduct_master.csvを、Cドライブ直下にcsvディレクトリを作成し、その中に、保存します。


3.以下のSQL文を、Cドライブ直下にsqlディレクトリを作成し、その中に保存します。
```sql:csv_insert.sql

-- CSVデータがshift_jisで保存されていた場合の日本語の文字化け対策。
-- 文字化けしなければ、除外して良い。
set character_set_database=cp932;

load data local infile "C:\\csv\\product_master.csv"
into table product_master
columns terminated by ','
lines terminated by '\r\n'
(product_code, product_name);

```

4.MariaDBへアクセスし、product_masterテーブルのあるデータベースへ切り替え、以下のコマンドを実行
```sql
source c:\csv\csv_insert.sql;
```


### 参考リンク
- [【MySQL】LOAD DATA INFILE するときのファイルの文字コード](https://www.softel.co.jp/blogs/tech/archives/2293)
完全未経験（元消防士）からWEB系エンジニアへの道　

昨日および本日はProgateで、HTML,CSSの初級を引き続きやった。

今日の学習内容の整理　アウトプットを兼ねて　

・レイアウトの基礎である、ヘッダー⇨メイン⇨フッターを学習。
　div要素をグループ化するために使用
　「header」、「main」、「footer」というclass名を持った3つのdiv要素でレイアウトを分割

・エディタの補完機能⇨タグ名を入力し、「Tab」キーを押すと終了タグまで補完してくれる。

・リストのマークをなくす
li要素にlist-styleプロパティを用いてnoneを指定すると、リストの先頭のマークを消すことができる。基本的に先頭の黒点は必要ない。
黒点なくす機能は、気になっていたから学習できて嬉しかった。

・ヘッダーの中身を横並びにする
HTMLで記述した要素は基本的に縦に並んでいくので、横並びにするにはCSSが必要
floatプロパティを用いることで、指定した要素を横並びにすることができる
float: left;を指定すると要素が左から順に横に並ぶ。

・ヘッダーの余白の調整について
『padding』内側の余白
padding: 〇〇px;　上下左右全ての方向に余白が追加される。
省略形①
padding: ２０px 10px 10px 10px;　上　右　下　左
省略形②
padding：　20px 10px；　上下　左右
個別指定
padding-top   　　上
padding-right　　　　右
padding-bpttom　　下
padding-left　　　　　　左

　『margin』（外側の余白）
 paddingと基本的には使用方法は変わらない。
 

・入れ子のセレクタ
「.header-list」の後にスペースを空けてliと続けると、「header-list」の中の<li>要素にのみCSSを適用することができる。
これにより、ヘッダーの<li>要素とフッターの<li>要素に別々のCSSを適用することができる

・要素を左右に配置する
float: leftとfloat:rightを組み合わせることで、ロゴとリスト全体を左右に配置することができます。

・『span』要素
文中の一部にCSSを適用させたい場合は、<span>要素で囲む。
下の図では、＜span＞タグにCSSを指定することで、文字の色を一部変えていく。
例）おにぎりの具は＜span＞ツナマヨ＜span＞です
ツナマヨの部分をCSSで色指定するとツナマヨだけ色を変えられる。

・（お問い合わせフォームのレイアウト）input,textareaについて
input要素は１行のテキスト入力を受け取るための要素
textarea要素は複数行のテキスト入力を受け取るための要素
input要素は終了タグは不要！

・送信ボタンを作る
送信ボタンにもinput要素を使う
input要素にはtype属性を指定することができ、type属性にsubmitを指定すると送信ボタンになる
input type="submit"

・value属性
input type="submit" value="保存"
value属性に任意の値を指定することで、ボタンに表示されるテキストを変更することができる。

・複数のセレクタに同じCSSを指定する
複数のセレクタをコンマ（,）で区切ることで、それらに同じCSSを適用することができる。
input,textarea{
 boeder: 3px solid #ff0000
 }
 
HTML＆CSS初級編が終了した。
見本を見て、コードのイメージとかはつかめてきている。
苦手なのは、余白について　margin padding部分が一から自分だけでコード書くのは無理かな
なぜか、苦手　上下左右とか理解しきれていない
あとは、送信ボタンのところが苦手なイメージ　課題でもミスしていた。

「感想、まとめ」
明日は、HTML&CSSの中級編をメインでやっていこうと思う。
並行して、IT業界でのキャリアプラン、そもそもなぜITなのか、visionを言語化して、IT業界の職種などについてもインプット・アウトプットしていく。
他の完全未経験者と差別化していく
会社だよりの受験者が多いはずやからとにかく、学習とIT業界の働くイメージを明確化
マインドアップ作成
電池で駆動するNeoPixel制御ボードのサンプルプログラム①


# RP2040-ZEROを使ってNeoPixelを制御するサンプルプログラム①です。

- ### サンプルサンプルプログラム内容
　NeoPixelカラーLED（6x6）の点灯チェックプログラムです。　
　組み立て後チェックで使用。

- ### プログラム環境
　ArduinoIDE バージョン：2.2.1
　使用ライブラリAdafruit NeoPixel Library 1.12.0

- ### ハードウェアの主な仕様
　マイコン:PR2040-ZERO
　NeoPixel接続ピン　GPIO8
　乾電池2本でお外へ持ち出し可能。



- ### サンプルプログラム

```c++
//全LEDを徐々に明るくする
//色は６色

#include <Adafruit_NeoPixel.h>

#define LED_PIN    8
#define LED_COUNT  36

// Initialize NeoPixel strip object with LED_COUNT and LED_PIN
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  strip.setBrightness(64);  // 明るさ倍率設定 (RGB設定値 * 明るさ倍率、最大255)
}

void loop() {
  // Loop through the range of red values from 0 to 255
  for (int redValue = 0; redValue <= 96; redValue=redValue+8) {
    // Set the color of each LED in the strip
    for (int i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color(redValue, 0, 0));

    strip.show(); // Update the LED strip with the new colors
    delay(5);    // Delay for smoother transition (adjust as needed)
    }    
  }

    for (int greenValue = 0; greenValue <= 96; greenValue=greenValue+8) {
    // Set the color of each LED in the strip
    for (int i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color(0, greenValue, 0));

    strip.show(); // Update the LED strip with the new colors
    delay(5);    // Delay for smoother transition (adjust as needed)
    }    
  }

    for (int blueValue = 0; blueValue <= 96; blueValue=blueValue+8) {
    // Set the color of each LED in the strip
    for (int i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color(0, 0, blueValue));

    strip.show(); // Update the LED strip with the new colors
    delay(5);    // Delay for smoother transition (adjust as needed)
    }    
  }


    for (int rgValue = 0; rgValue <= 96; rgValue=rgValue+8) {
    // Set the color of each LED in the strip
    for (int i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color(rgValue, rgValue, 0));

    strip.show(); // Update the LED strip with the new colors
    delay(5);    // Delay for smoother transition (adjust as needed)
    }    
  }

    for (int gbValue = 0; gbValue <= 96; gbValue=gbValue+8) {
    // Set the color of each LED in the strip
    for (int i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color(0, gbValue, gbValue));

    strip.show(); // Update the LED strip with the new colors
    delay(5);    // Delay for smoother transition (adjust as needed)
    }    
  }

    for (int rbValue = 0; rbValue <= 96; rbValue=rbValue+8) {
    // Set the color of each LED in the strip
    for (int i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color(rbValue, 0, rbValue));

    strip.show(); // Update the LED strip with the new colors
    delay(5);    // Delay for smoother transition (adjust as needed)
    }    
  }

  
}
```
個人開発の規模を超えた個人開発に参画した話

## 概要

個人開発の規模を超えた個人開発に参画した話をまとめます。

## なにを作ったの！？

[DokuPro](https://dokupro.dev/)というサービス作りに参画しました！

**現在絶賛先行登録受付中です〜！！** メインサービスオープンと同時に通知メールが届くようになりますので良ければ先行登録お待ちしております！！

https://dokupro.dev/

簡単に言うと「プログラミングを教えて欲しい人」と「プログラミングを教えたい人」のマッチングサービスです。

サービス名の語源は「独学プログラミング」を短縮して「ドクプロ」って感じですね！

共同開発者の[Sado](https://qiita.com/derasado)さんと自分は、異業種から独学でプログラミングを学びなんとかエンジニアになることができました。

Sadoさんのサービス紹介記事はこちら↓

https://qiita.com/derasado/items/7c8c7a78dd844e1c4552

未経験時代の苦労話をする中で「よく考えたら、未経験エンジニアに特化したプログラミングを人から学べるサービスって無くない！？（スクールを除く）」という話になったのです。

話が盛り上がり、作ることになり、作り始めていくうちに「あれ！？これボリュームやばくね！？」となり、何名かの方々に参加いただきβ版（現在は[ウェイティングリスト](https://dokupro.dev/waiting-list)公開中）まで持ってくることができました。

**「未経験エンジニア」や「独学エンジニア」とかの言葉が出ていますが、「プログラミングを教えて欲しい人」は必ず未経験である必要は一切ありません！ 我々のサービスは未経験の方専用ではなく「未経験の方にも優しい、使いやすいサービス」をコンセプトにしています。**

## どこを担当したの？？

自分はバックエンドの開発の一部を担当しました。
立ち上げ初期のCIの作り込み、自動化チェック（Linter・静的解析・テストコード）の仕組みづくり、テストコード記載時のルール、アーキテクチャ（DDDの真似事）を決める部分なども担当しました。
外部APIの呼び出し部分なども骨組みを作ったりしました。（初期の仕組みづくり・ルールづくりが結構楽しいことがわかった。）
設定画面などのAPIも複数作成しました。

## サービスの軸

**「できるかぎり未経験エンジニアの方に優しくなるように作ろう」**

自分の独学でプログラミングを学んでいたときの心境はこんな感じでした。

- 専門用語が多いな、、、
- 基礎からもう分からん、、、
- SNSで知り合った一緒に独学で頑張ってた彼は素敵なポートフォリオを作ったらしい、、、
- 現職やりながら、習得するの大変だな、、、
- 勉強会ってなに！？もくもく会ってなに　！？！？怪しいセミナーじゃないかな、、、

そうなんです。独学でプログラミング学ぶのって大変だし、まっさらな状態からだとまず何をしたらいいか分からないんです。更に知らないことばっかりで心がしんどい。。
自分はたまたま今は無き未経験エンジニアのエージェントサービスのkiitokさんに出会えたからこそ本当に奇跡的にエンジニアになることができました。
更に参加させていただいているコミュニティが素敵な場所ばかりでしたのでなんとかエンジニアになることができました。

世の中には「本当はエンジニア適正がめっちゃあるのに挫折してしまった人」が多くいるのではないかと思ったのです。

そんな未経験エンジニアの方を一人でも多く救うため「学びたい人に少しでも使いやすい・優しいサービス」にすることを心がけました。
現在はβ版のためまだ基本的な部分しかありませんが、これからの機能追加・改修ではこの軸に沿ったものが増えてゆくと思います。

## 開発の軸

**「まだギリギリ若いって言われるうちに自分たちだけでなにか成し遂げたい」「開発を通じて自分たちのスキルアップをしたい」「自分たちの責任において開発をしたい」**

エンジニアになって4年くらい、まだまだ自分は会社でチームでは成果は出せても一人だとどうにも、、、という毎日が続いています。そんな中で近い境遇の仲間といっしょになにかを成し遂げたいという欲求がありました。
もちろん自分たちがサービスの運営となるわけで、責任ももちろん自分たちに直接降り掛かってきます。そんな中で得た経験は確実に後々の人生の宝になるんじゃないかと思っています。

アーキテクチャも自分たちで考えました。細かいルールもすべて自分たちで考えました。
これからのエンジニア人生で、特にプロジェクトの立ち上げ期の知見が豊富にたまりました。外部APIを使う、Webhookを使うなんてことも今までの開発ではあまりやって来ませんでした。本当に勉強になりました。

## 個人開発の規模を超えた話

β版でもかなり機能を削っては居るのですが、見積もりが甘く想定よりかなりボリュームが大きくなってしまいました！ｗ
最初は「参考にできる既存サービスも複数有るし、そんなに難しくないっしょ！！」って感じで始めたのですがこれが大誤算、、！（何ならバックエンドなんかちゃっちゃと片付けて、いい機会だしフロントエンドの方も触れてみよ〜！なんて思ってた。）

自分の希望的観測で「会社の仕事進めながら、同時並行で個人開発なんて全然できるっしょ！」という感覚がそもそもの間違いでした。自分がそんなに効率の良い働き方ができるわけもなく。そもそも気持ちの浮き沈みが激しい性格であることも忘れ。。。

Sadoさんにはかなり作業巻き取ってもらったと自負しています。この場を借りてお礼申し上げます。本当に助かりました。。

## まとめ

ポエムのように書き連ねてしまいましたが、まとめると

**「プログラミングを教えて欲しい人」と「プログラミングを教えたい人」のマッチングサービス作ってみましたよ〜〜！！良ければ皆さん使ってみてください〜〜！**

ということでした！！

https://dokupro.dev/
Ruby on Rails: Ransackを用いたモデル検索のエラー解決方法①

この記事では、Ruby on RailsでRansackを使ってモデルの検索を行う際に発生したエラーの解決方法について説明します。特に、関連するモデルの属性に対する検索のためのホワイトリストの設定や、カスタム検索の実装について触れます。

## 背景

Railsアプリケーションで、`Reservation`モデルの検索を行い、予約をした顧客単位で検索する必要がありました。しかし、Ransackの設定や関連するモデルへのアクセスに問題が発生し、検索フォームが正しく動作しないという課題が生じました。

## エラー内容

Reservation検索を実装するために、ビューで以下のようにフォームを設定していました：

```ruby
<%= search_form_for @r, url: reservations_path, method: :get, local: true, class: 'custom-form-group d-flex' do |form| %>
  <div class="form-group d-flex align-items-end me-2">
    <div class="w-100">
      <label>顧客名検索:</label>
      <%= form.search_field :customer_name_cont, id: 'single-simple-search-name_cont', class: 'form-control me-2', placeholder: '顧客名検索' %>
    </div>
  </div>
  <%= form.submit '検索', class: 'btn btn-primary' %>
<% end %>
```

しかし、これに対して以下のエラーが発生しました：

```
RuntimeError at /reservations
Ransack needs Customer attributes explicitly allowlisted as searchable.
```

このエラーは、Ransackが関連する`Customer`モデルの属性にアクセスできないために発生しています。

## 解決方法

1. **`Customer`モデルでの`ransackable_attributes`メソッドの追加:**

   この問題を解決するため、`Customer`モデルに対するホワイトリストメソッドを追加します：

   ```ruby
   class Customer < ApplicationRecord
     # その他のモデル設定...

     def self.ransackable_attributes(auth_object = nil)
       %w[city created_at description email id name postal_code prefecture street_address telephone updated_at]
     end
   end
   ```

   このメソッドで、`Customer`モデルの検索に必要な属性をホワイトリスト化し、Ransackが正常に検索できるようにします。

2. **`Reservation`モデルのカスタムransackerの追加:**

   次に、`Reservation`モデルで顧客単位での検索を行うためのカスタムransackerを追加します：

   ```ruby
   class Reservation < ApplicationRecord
     # その他の設定...

     ransacker :customer_name do |parent|
       # Reservationのcustomer_idを元に、関連するCustomer.nameで検索するための設定
       Arel::Nodes::InfixOperation.new('LIKE', parent.table[:customer_id], '%')
     end

     def self.ransackable_attributes(auth_object = nil)
       %w[company_id created_at customer_id date ...]
     end
   end
   ```

3. **ビューでの検索フォーム:**

   最後に、ビュー内で以下のように検索フォームを設定し、`customer_name_cont`などのフィールドで検索ができるようにします：

   ```ruby
   <%= search_form_for @r, url: reservations_path, method: :get, local: true, class: 'custom-form-group d-flex' do |form| %>
     <div class="form-group d-flex align-items-end me-2">
       <div class="w-100">
         <label>顧客名検索:</label>
         <%= form.search_field :customer_name_cont, id: 'single-simple-search-name_cont', class: 'form-control me-2', placeholder: '顧客名検索' %>
       </div>
     <% end %>
    ```

これらの修正により、Ransackで`Reservation`モデルの検索を顧客単位で行うことができるようになります。

## 次回の記事

https://qiita.com/KM9973/items/1ca3b28b3c1b71b8a9f7
LLM モデルの必要なファイルのみローカルに保存する方法

# Huggingface Hub リポジトリ内のすべてのファイルをダウンロードする
python の transformers パッケージを使って以下のコードを実行した場合、huggingface_hubからモデルのリポジトリ内にあるファイルをすべてダウンロードし始めます。

```python:
from transformers import AutoTokenizer, AutoModelForCausalLM

model_name = 'model_name'
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)
```

モデルのどのチェックポイントを使用するか迷っている人にとって、この手法は有用です。しかし、試験的にLLMを動かしたい人やストレージサイズが小さい人は、別のよりリソース消費量の少ない方法を望むかもしれません。

# 必要なファイルのみをダウンロードする
この方法は2段階の構成になっています。初めにモデルの重み以外の軽量なファイルのみをダウンロードします。次にモデルの必要な重みファイルのみをダウンロードします。必要なファイルのみをダウンロードするには huggingface_hub パッケージの `snapshot_download` を使用します。[Huggingface 公式サイト](https://huggingface.co/docs/huggingface_hub/v0.21.4/guides/download)に記載の通り、このモジュールを使用することで必要なファイルのみをダウンロードすることができます。

例えば、以下のように記載することでリポジトリ内の`.safetensors`以外のファイルをダウンロードできます。

```python:
from huggingface_hub import snapshot_download

repo_id="lysandre/arxiv-nlp" #huggingface hub上のリポジトリ名
local_dir="./llm"  # 保存先フォルダ名
snapshot_download(repo_id=repo_id, local_dir=local_dir, ignore_patterns=["*.safetensor"])
```

あとは、`.safetensors`を huggingface hug から直接ダウンロードすることで、不要なモデルの重みによるストレージの圧迫や、ダウンロード時間を短縮することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310198/e31b173a-9952-803c-998c-dc06473aa9a7.png)