OmniAICreator/Qiita-1.07M huggingface dataset:
【備忘録】Jetson AGX Xavier（JetPack 5.1.3）にてIPアドレスを固定する方法

# ゴール
JetPack 5.1.3がインストールされたJetson AGX のIPアドレスを固定する

# 手順
JetPackではGUIによりIPアドレスを固定できます。バージョンによりGUIが異なるので注意が必要です。

1. [settings]を起動する
1. [network]をクリックする
1. Wireの歯車をクリックする
    ![Screenshot from 2024-08-09 21-56-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35883/d38a7d38-3948-5aa1-d621-a36e73f18fc3.png)
1. [IPv4]_[IPv4 Method]にてマニュアルを選択する
1. Address, Netmask, Gateway を入力する
**NetmaskはCIDR表記でもなく、2進数表記でもなく、10進数表記のため注意が必要です**
![Screenshot from 2024-08-09 21-56-52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35883/b4daaddd-38ad-f404-e25d-df35e81bafb8.png)

# おわりに
Jetson AGXのIPアドレスを固定することで、リモートアクセスやネットワーク管理が容易になり、開発環境の安定性が向上します。JetPackのGUIを利用することで、初心者でも比較的簡単に設定ができる反面、Netmaskの表記方法など細かな部分に注意が必要です。今後もJetson AGXを使ったプロジェクトが増えるにつれて、こうしたネットワーク設定の知識が役立つ場面が多くなるでしょう。今回の手順を参考に、ぜひ自分の環境でも試してみてください。
GradleとDockerを活用したSpring BootアプリケーションのMySQL連携

## プロジェクトの準備
まず、Spring Bootプロジェクトを用意します。以下は、基本的なプロジェクト構成の例

```css
/project-root
│
├── build.gradle
├── settings.gradle
├── Dockerfile
├── docker-compose.yml
└── src
    └── main
        └── java
            └── com
                └── example
                    └── todoapp
                        └── TodoappApplication.java
```
## GradleでJARファイルを作成
build.gradleファイルが設定されていることを確認し、以下のコマンドを使用してプロジェクトをビルドし、JARファイルを生成します。

```bash
./gradlew clean build
```
このコマンドを実行すると、プロジェクトのルートディレクトリにあるbuild/libsフォルダ内に、Spring BootアプリケーションのJARファイルが生成されます。

例: build/libs/todoapp-0.0.1-SNAPSHOT.jar

## Dockerfileの作成
プロジェクトのルートディレクトリにDockerfileを作成し、以下の内容を記述します。
```Dockerfile  
# ベースイメージとしてOpenJDKを使用
FROM openjdk:17-jdk-alpine
# 作業ディレクトリを作成
WORKDIR /app
# アプリケーションのJARファイルをコンテナにコピー
COPY build/libs/todoapp-0.0.1-SNAPSHOT.jar /app/app.jar
# アプリケーションを起動
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
```
このDockerfileは、JARファイルを含むDockerイメージを作成し、コンテナ内でSpring Bootアプリケーションを実行します。

## docker-compose.ymlの作成
次に、docker-compose.ymlを作成し、Spring BootアプリケーションとMySQLを連携させる設定を行います。
`[] = 各自設定`
```yaml
version: "3.8"

services:
  mysql:
    image: mysql:8.0
    container_name: mysql-container
    environment:
      MYSQL_ROOT_PASSWORD: []
      MYSQL_DATABASE: []
      MYSQL_ROOT_HOST: "%"
    ports:
      - "3307:3306"
    volumes:
      - mysql_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u[]", "-p[]"]
      interval: 10s
      timeout: 5s
      retries: 5

  spring-app:
    build: .
    container_name: spring-app-container
    ports:
      - "8081:8080"
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/logindemo?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
      SPRING_DATASOURCE_USERNAME: []
      SPRING_DATASOURCE_PASSWORD: []
    depends_on:
      mysql:
        condition: service_healthy

volumes:
  mysql_data:
  ```
このdocker-compose.ymlは、MySQLコンテナとSpring Bootアプリケーションコンテナを連携させて起動します。

## Dockerイメージのビルドとコンテナの起動
プロジェクトのルートディレクトリで以下のコマンドを実行し、Dockerイメージをビルドし、コンテナを起動します。

```bash
docker-compose up --build
```
### このコマンドで以下の操作が行われます：

Dockerfileを基に、Spring BootアプリケーションのDockerイメージがビルドされます。
MySQLとSpringアプリケーションのコンテナが起動され、連携します。
Springアプリケーションはポート8081で動作し、MySQLと接続されます。
typstでanswer box の簡易版を作る

先行研究
https://zenn.dev/1step621/articles/df285be712d9d5

途中までやって放置していたら，同じような機能を実装されている方がいました．

こちらは簡易版として，ここに供養します．以下をコピペすると機能が使えるようになります．

```
#let copy_array(height, rows) = {
if type(height) != array {
  let heights = ()
  for i in range(rows){
    heights.push(height)
  }
  return heights
}
else {return height }
}

#let ansbox(..args, type: "default", daimon: "1", shomon: "(1)", height:1.5cm,content:(), hide-content:false, shomon_width:2em, daimon_width:2em, box_width:1fr, shomon_start:1, inset: 4pt) = {
let list = args.pos()
let rows = list.len()
let heights = copy_array(height, rows)
let box_widths = copy_array(box_width, rows)
//ansbox_num.step()
let row_list = ()
let cur_sho = shomon_start
let total = 0
for i in range(rows) {
  let cells = ()
  let col_cel = ()
  let algn = ()
  for j in range(list.at(i)){
    algn.push(center+horizon)
    algn.push(left)
    col_cel.push(shomon_width)
    col_cel.push(box_widths.at(i))
    cells.push([#numbering(shomon, cur_sho)])
    cells.push([#if content != () {if hide-content == true{hide[#content.at(total+j)]}else{content.at(total+j)} }])
    cur_sho = cur_sho + 1
  }
  row_list.push(table(inset:inset,stroke: (x,y) => {if calc.odd(x) {(left:(dash:"dotted"), right:1pt, y:1pt) } else {(x:1pt, y:1pt)}}, columns:col_cel,..cells,rows:heights.at(i), align:algn))
  total = total + list.at(i)

}
let colls 
show figure: it => {

if daimon != none{
grid(columns:(daimon_width, 1fr),   
grid.cell(rowspan: rows,
stroke: 1pt,
align:center+horizon,
[#numbering(daimon,..it.counter.at(it.location()))],
),   ..row_list
)
} else {
grid(columns:(1fr),   
  ..row_list
)
} 

}
figure([1],kind:"answerbox",supplement: none)
}
```

## 使い方の例

```
#ansbox(1,4,3)
//基本的に，数字を入れていくと，各行にいくつのボックスを作るかを指定できます．


#ansbox(4,2,3, daimon:"1", shomon:"(a)", height:(1cm,2cm,3cm))
//高さを行ごとに指定できます


#ansbox(1,2,3, 
content:([1],[2],[3],[4],[5],[$ (sum d^3)/(sum d^3)$]),
height:(2cm,auto,auto)
)

//contentでボックスの中に書き込めます．contentはarray方式で，すべての小問の中身の列を作る必要があります

#ansbox(1,2,3, 
content:([1],[2],[3],[4],[5],[$
(sum d^3)/(sum d^3)
$]),
height:auto,
hide-content:true
)

//contentを隠すこともできます

#ansbox(3,2, 
inset:0pt, 
daimon:none, 
shomon:"問1.", 
shomon_width:4em, 
shomon_start:7, 
content:([],[],[],[],ansbox(2,2,daimon:none)), 
box_width:(2cm,1fr,auto), 
height:(1cm,auto,auto)
)
//contentの中にansboxを書き込むことで，入れ子にもできます．heightはauto, insetは0ptにしておくと，きれいになります（多分）．


```
コンパイルすると以下のようになります.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3787163/7d64a321-9752-8bd9-7d89-59990be4425e.png)
nRFConnectSDKを基盤としたSesameの暗号通信 #3 開発ツールの準備

![nRF5-SDK](https://www.jetbrains.com/clion/img/clion_ide_overview.png)


# 目的
開発ツールの準備

# 技術
- [Visual Studio Code]
- [Clion]
- [Iterm]
- [Xcode]
- SEGGER Embeded Studio: *使いにくい*

# 雑談
もしここまで読んで、まだコードを書き始めていない私に対して「何を無駄話しているんだ」と感じているなら、それはごもっともです。すみません。でも、実はCANDY HOUSEの入職訓練はこれ以上に厳しいものでした。私は新人に環境を再インストールさせ、何度もコードを書き直させます。開発中にショートカットキーの設定ができなかったり、使い方がわからなかったりすると、開発を中止させ、正しく設定できるまで指導します。本当に申し訳ないです。

# 心配


# 用語
 
- [Visual Studio Code]
- [Clion]
- [Iterm]
- [Xcode]

# 困惑



# 関連記事

- [nRFConnectSDKを基盤としたSesameの暗号通信](https://qiita.com/tse123321/items/c0fa105cd5b9f14c2a0c)
【個人開発/学生】ポートフォリオの描画内容を管理するヘッドレスCMSを作成しました。

# はじめに
**Next.js** + **NestJS** + **Cloudflare R2** + **Neon** + **Koyeb** でポートフォリオの描画内容を管理するヘッドレスCMSを作成しました。

## リポジトリ
https://github.com/warabimochi1126/portfolio-headless-cms-frontend

https://github.com/warabimochi1126/portfolio-headless-cms-backend

## 作成した動機
・新しいバージョンの**NestJS**と**TypeORM**を学びたかった。
・**インターンシップ**の業務内容に似たアプリケーションを開発したかった。
の２点です。

## デモ画像
・選択画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/8eb00392-fb7c-9f8a-ece1-68ba4acb5442.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/80275d92-89a8-5619-ee47-ea54599c90a9.png)

・既存のカードを一つ選択した画面 **(update側)**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/90d98734-702c-1f25-54b3-72de5f2d004b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/4118996c-7ecc-24bb-e73c-284674a19f11.png)

・新しい作品を登録するカードを選択した画面 **(create側)**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/d2aae078-732f-aa10-e20c-f920aa61e5ea.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/0bc9c57d-9409-00bf-2b83-f73f77ace44e.png)

・左上に存在する`redeploy`ボタンは、**SSGで描画しているポートフォリオサイト**をデプロイし直して、DBに存在している最新データを反映します。

## 技術構成図
![portfolio-cms-tech-flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/50be98be-fb9c-a141-da1a-8f13fda5af53.png)

## 改善点
データがどのように循環するか考えずに実装を始めてしまったため、やらなくて良いようなデータ変換をしてしまったように感じました。
このため、readされるデータ構造が決まっている場合は、そのデータ構造のままテーブルを作ってしまうのが良いと思いました。
また、入力値をBFFでテーブルに沿うように型を変えるのが綺麗に循環しそうだなと思いました。

# さいごに
KoyebでもDBが使えるっぽかったので、neonを使わずにデプロイ・DBどちらもKoyebを使えば良かったな～と思いました。
PySide6で実装するUI

今回はPySide6を用いて，ボタンを配置していきます．HTMLのようなブロック構造を採用しつつ，数値による指定を行わなくても簡単にブロックを配置することができます．


## 記述例
まず，記述例から見ていきます．解説は後で行います，
```python
from PySide6.QtWidgets import QApplication, QHBoxLayout, QVBoxLayout, QPushButton, QWidget

app = QApplication([])

window = QWidget()
main_layout = QVBoxLayout()

# サブレイアウトを作成
sub_layout = QHBoxLayout()
button1 = QPushButton('Button 1')
button2 = QPushButton('Button 2')
sub_layout.addWidget(button1)
sub_layout.addWidget(button2)

# サブレイアウトをメインレイアウトに追加
main_layout.addLayout(sub_layout)

# 別のボタンをメインレイアウトに追加
button3 = QPushButton('Button 3')
main_layout.addWidget(button3)

window.setLayout(main_layout)
window.show()

app.exec()

```

## 実行結果
図1のように分割されたボタンが出現します．
![PySideの表示例2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457930/21152207-d54f-cf7d-005d-642fee954049.png)
図1　ボタンの表示例

## 解説
図2のような構成になっています．
![PySideの表示例イメージ図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457930/da11e674-bfc8-aebb-e847-ef0c17c4a716.png)


図2　エリアの分割図


**垂直に分割**した後に，一つ目のブロックだけ，**水平に分割**しています．

## QVBoxLayoutとQHBoxLayout
分割方法の決め方には下記の2種類があります．
**QVBoxLayout**はvertical（垂直）に要素の数分，分割するクラスです．

![box1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457930/6aa196c7-485f-90d6-4db8-efe6dda612eb.png)

図3　QVBoxLayout：vertical（垂直）な分割の例

一方，**QHBoxLayout**は，horizontal（水平）に要素の数分，分割するクラスです．
例を図4に示します．

![box2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457930/d802e6ae-9eca-65c5-fa61-29c9745af14e.png)

図4　QHBoxLayout：horizontal（水平）な分割の例

## addwidgetとaddlayout
### addWidget
addWidget メソッドは、レイアウトにウィジェット（例えば、ボタンやテキストボックスなどのUI要素）を追加するために使用されます。このメソッドを使うと、レイアウト内の特定の位置にウィジェットを配置できます。


### addLayout
addLayout メソッドは、レイアウトの中にさらに別のレイアウトを追加するために使用されます。これは、ネストされたレイアウトを構築する際に便利です。たとえば、垂直レイアウトの中に水平レイアウトを配置して、複雑なUIレイアウトを作成する場合などに使用します。

イメージ図としては図5のようになります．

![PySideの表示例イメージ図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457930/db4dae2e-0b36-749c-e53e-85277b4f85ee.png)

図5　addwidgetとaddlayoutによる層の種類
nRFConnectSDKを基盤としたSesameの暗号通信 #2 開発環境の確認

![nRF5-SDK](https://www.nordicsemi.com/-/media/Images/Products/SDKs/nRF5-SDK.png?h=421&iar=0&mw=350&w=300&hash=EEC514EB72DAAA8F194444F96BA4BF3E)

![nRFConnectSDK_new](https://www.nordicsemi.com/-/media/Images/Products/SDKs/nRFConnectSDK_new.png?h=350&iar=0&mw=350&w=350&hash=74B0FED7269C642A50A3F5AC07E03F2E)

# 目的
ノートパソコンの開発環境の確認

# 技術
- mac pro:*私はMacしか持っていません*
- nRF Connect SDK:*最新の開発環境*
- nrf5-sdk:*最も安定した開発環境*
- nRF Connect for Desktop:*公式で提供されている、コンピュータにインストールするアプリケーション*


# 雑談
nrf52840には、公式に2つの開発環境が提供されています。最初はnrf5-SDKだけで、Sesameの開発を始めたときも、このSDKしかありませんでした。その後、nRF Connect SDKが登場したとき、心がざわつきました。「もしJermingに知られたら、全部書き直しを求められるかもしれない」と不安になったのです。いくつかのサンプルを試してみたところ、nRF Connect SDKはまだ安定していないと感じたので、最新のnRF Connect SDKには更新しませんでした。

その結果、後に半導体不足が起こり、Nordicの製品が全面的に品薄になってしまいました。どちらを選んでも正解にはならない状況になってしまいました。

# 心配
ここで最初の難題を指摘しておきます。開発環境の選択はどうすれば良いのかということです。公式の環境が既に断片化しており、非常に苦しい選択を迫られています。


# 用語
 
- [nrf5-sdk](https://www.nordicsemi.com/Products/Development-software/nRF5-SDK)
- [nRF Connect SDK](https://www.nordicsemi.com/Products/Development-software/nRF-Connect-SDK)
- [nRF Connect for Desktop](https://www.nordicsemi.com/Products/Development-tools/nRF-Connect-for-Desktop)

# 推薦


# 困惑
誰が私の書いている記事を読んでいるのか分かりませんが、申し訳ありません。すみません、私は書きながら何度も修正する習慣があります。もしあなた方が選ぶとしたら、どの開発環境を選びますか？


# 関連記事

- [nRFConnectSDKを基盤としたSesameの暗号通信](https://qiita.com/tse123321/items/c0fa105cd5b9f14c2a0c)
tf.data.Datasetをunzip（メソッドzipの逆操作）する方法

## 結論

例えば、

```python
import tensorflow as tf

a = tf.data.Dataset.range(0, 5)
b = tf.data.Dataset.range(5, 10)

ds = tf.data.Dataset.zip((a, b))

print(ds.element_spec)
```
```:出力
(TensorSpec(shape=(), dtype=tf.int64, name=None), TensorSpec(shape=(), dtype=tf.int64, name=None))
```

このようにzipされたDatasetに対して、zipの逆操作をしたい場合、

```python
c = ds.map(lambda x, y: x)
d = ds.map(lambda x, y: y)

print(c.element_spec)
print(d.element_spec)
```
```:出力
TensorSpec(shape=(), dtype=tf.int64, name=None)
TensorSpec(shape=(), dtype=tf.int64, name=None)
```

このように、片方の要素を取り出すLambda式をmapすれば取り出すことができます。

## 環境

Python: 3.10.8
TensorFlow: 2.12.0

## 背景

TensorFlow公式の時系列予測チュートリアルの「[ tf.data.Dataset を作成する](https://www.tensorflow.org/tutorials/structured_data/time_series?hl=ja#4_tfdatadataset_%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)」の節について、

```python
def make_dataset(self, data):
  data = np.array(data, dtype=np.float32)
  ds = tf.keras.utils.timeseries_dataset_from_array(
      data=data,
      targets=None,
      sequence_length=self.total_window_size,
      sequence_stride=1,
      shuffle=True,
      batch_size=32,)

  ds = ds.map(self.split_window)

  return ds

WindowGenerator.make_dataset = make_dataset
```

`ds.map(self.split_window)`で返ってくるDatasetをunzipしたくなったのが発端です。

このチュートリアルを参考にしながら独自のモデルを作成しているのですが、もう一つ別で用意したDatasetを入力に加えたく、一度unzipしてからzipし直すに至りました。

## p.s.

「もっとスマートにunzipする方法がある。」
「そもそもそんな手順踏まなくてもkerasのInput層にデータを流せる。」
等々、もっと賢い方法がある場合はご教示いただけるとありがたいです。
Doker python 開発環境設定

cdで目的のpyファイルのある場所に移動
以下でdoker起動　
仮想フォルダと本体のhomeフォルダにマウント
cdで仮想のhomeに移動
sudo docker container run --user=$(id -u $USER):$(id -g $USER) --env="DISPLAY" --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" --interactive --tty --mount "type=bind,source=$(pwd),target=/home" py-ubuntu:commit bash
【Jest×Testing Library】queryByTextとgetByTextの違いでハマった件

# はじめに
Jest、Testing Libraryを使用したテストでハマりました。

# 問題
画面上に値が存在しないことの確認をするためにテストを実行時、以下のソースの箇所でエラーが発生。

```diff_tsx:App.test.tsx（中略）
    // 事前検証
    await waitFor(() => {
      // 登録する記録が画面上に表示されていないこと
+      expect(screen.getByText("追加の勉強")).not.toBeInTheDocument();
+      expect(screen.getByText("4時間")).not.toBeInTheDocument();
+      expect(screen.getByText("2024/01/04 00:00")).not.toBeInTheDocument();
      // 合計時間
      expect(screen.getByTestId("sum-time").innerHTML).toEqual("6時間");
    });
```

```console:エラーメッセージ
Unable to find an element with the text: 追加の勉強. This could be because the text is broken up by multiple elements.
In this case, you can provide a function for your text matcher to make your matcher more flexible.
```

エラーメッセージでは、「追加の勉強」という要素が画面上に存在しません的なエラーが表示されています。
存在しないも何もそれが正しいんだよと思いながらハマりました。

# 解決方法
要素の取り方がおかしかった。
getByTextではなくqueryByTextを使うとのこと↓。

```diff_tsx:App.test.tsx（中略）
    // 事前検証
    await waitFor(() => {
      // 登録する記録が画面上に表示されていないこと
+      expect(screen.queryByText("追加の勉強")).not.toBeInTheDocument();
+      expect(screen.queryByText("4時間")).not.toBeInTheDocument();
+      expect(screen.queryByText("2024/01/04 00:00")).not.toBeInTheDocument();
      // 合計時間
      expect(screen.getByTestId("sum-time").innerHTML).toEqual("6時間");
    });
```

# おわりに
copilotにgetByTextとqueryByTeｘｔの違いを聞いたら以下の通りとのこと。
これは知らないと分かりませんね…

:::note info 
2つのメソッドの違い
- queryByText:
要素が見つからない場合、nullを返します。
要素が存在しないことを確認するために使用されます。
エラーをスローしないため、要素が存在しないことをテストするのに適しています。
- getByText:
要素が見つからない場合、エラーをスローします。
要素が存在することを確認するために使用されます。
要素が確実に存在することを前提としたテストに適しています。
:::

## JISOUのメンバー募集中🔥
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？
気になる方はぜひHPからライン登録お願いします！👇

https://projisou.jp/
30秒で読めるTensorflowのgpuインストール方法

# 記事のターゲット層
ネットに散乱するインストール手順を試して失敗した人向け（CUDA、cudnnのインストールを行った）

# 要は
https://www.tensorflow.org/install/pip

英語版のインストール手順見たほうがいい（日本語版は色々古くて大変）
最強のKubernetes入門

## Kubernetesを極めたいあなたへ
クラウドネイティブアプリケーションの開発とデプロイメントにおいて、Kubernetes（クバネティス）は非常に重要な役割を果たしています。

この記事では、Kubernetesの基礎を学ぶためのトレーニングコースについて詳しくご紹介します。このコースは、初心者から中級者を対象としており、Kubernetesの基本概念から実際のデプロイメントまでをカバーしています。

### 第1章: Kubernetesとは？

Kubernetesは、Googleによって開発されたオープンソースのコンテナオーケストレーションプラットフォームです。コンテナ化されたアプリケーションのデプロイ、スケーリング、管理を自動化するためのツールセットを提供します。Kubernetesは、マイクロサービスアーキテクチャを採用する企業や、クラウド環境でのアプリケーション管理を効率化したい開発者にとって不可欠な技術です。

### 第2章: Kubernetesの基本概念

#### ポッド（Pod）

ポッドは、Kubernetesの最小デプロイメント単位であり、1つ以上のコンテナを含むことができます。ポッド内のコンテナは、同じネットワーク名前空間を共有し、互いに通信が可能です。

#### ノード（Node）

ノードは、Kubernetesクラスター内のワーカーマシンであり、ポッドを実行するためのリソースを提供します。ノードは、物理マシンまたは仮想マシンのいずれかです。

#### クラスター（Cluster）

クラスターは、Kubernetesの基本的なアーキテクチャ単位であり、複数のノードで構成されます。クラスターは、アプリケーションの高可用性とスケーラビリティを実現するための基盤です。

### 第3章: Kubernetesのインストール

Kubernetesのインストールは、いくつかの方法で行うことができます。ここでは、最も一般的な方法の一つである「Minikube」を使用したローカル環境へのインストール手順を紹介します。

```bash
# Minikubeのインストール
brew install minikube

# Minikubeクラスターの開始
minikube start

# クラスターのステータス確認
minikube status
```

### 第4章: Kubernetesの基本操作

#### デプロイメントの作成

Kubernetesでアプリケーションをデプロイする際には、デプロイメントリソースを作成します。以下は、Nginxをデプロイするための基本的なYAMLファイルの例です。

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
```

このファイルを使用してデプロイメントを作成するには、以下のコマンドを実行します。

```bash
kubectl apply -f nginx-deployment.yaml
```

#### サービスの作成

デプロイされたアプリケーションを外部からアクセス可能にするためには、サービスを作成します。以下は、Nginxデプロイメント用のサービスの例です。

```yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: nginx
```

このサービスを作成するには、以下のコマンドを実行します。

```bash
kubectl apply -f nginx-service.yaml
```

### 第5章: Kubernetesのスケーリングと更新

Kubernetesを使用すると、アプリケーションのスケーリングや更新が容易に行えます。以下は、デプロイメントのレプリカ数を変更する例です。

```bash
kubectl scale deployment nginx-deployment --replicas=5
```

また、コンテナイメージを更新する際には、以下のコマンドを使用します。

```bash
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
```

### 第6章: Kubernetesの学習を進めるために

Kubernetesの基本を理解した後は、より高度なトピックに進むことをお勧めします。

たとえば、Helmを使用したパッケージ管理、Kustomizeを用いた設定のカスタマイズ、RBAC（Role-Based Access Control）によるアクセス制御などがあります。

これらのトピックは、Kubernetesをより効果的に活用するために重要です。

### 結論

Kubernetesは、現代のソフトウェア開発において不可欠なツールです。

この入門トレーニングコースを通じて、Kubernetesの基本をしっかりと学び、実際のプロジェクトで活用できるスキルを身につけましょう。

今後のキャリアにおいても、大いに役立つことでしょう。
Python f文字列の機能：デバッグ出力が格段に楽になる小技を紹介

## はじめに
Pythonのf文字列（フォーマット済み文字列リテラル）は、文字列内に変数や式を簡単に埋め込むことができる便利な機能です。しかし、多くの開発者が見落としがちな、デバッグに非常に役立つ隠れた機能があります。この記事では、f文字列を使ってデバッグ出力を劇的に改善する方法を紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/503e9d6e-4fde-b095-386d-1d0d79fa1b82.png)

## f文字列の基本

まずは、f文字列の基本的な使い方を簡単におさらいしましょう。

```python
name = "Alice"
age = 30
print(f"{name} is {age} years old.")
# 出力: Alice is 30 years old.
```

## デバッグ出力のための秘密の武器：'='演算子

f文字列には、'='演算子という隠れた機能があります。これを使うと、変数名とその値を同時に出力できます。

```python
x = 10
y = 20
print(f"{x=}, {y=}")
# 出力: x=10, y=20
```

この方法を使えば、どの変数がどの値を持っているかを一目で確認できます。

## 複雑な式にも対応

'='演算子は単純な変数だけでなく、複雑な式にも使えます。

```python
numbers = [1, 2, 3, 4, 5]
print(f"{len(numbers)=}, {sum(numbers)=}, {max(numbers)=}")
# 出力: len(numbers)=5, sum(numbers)=15, max(numbers)=5
```

## フォーマット指定子との組み合わせ

さらに、フォーマット指定子と組み合わせることで、出力をカスタマイズできます。

```python
pi = 3.14159
print(f"{pi=:.2f}")
# 出力: pi=3.14
```

## まとめ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/bf4e6add-7d34-d042-0e29-f8f450409ec7.png)

f文字列の'='演算子を使うことで、デバッグ出力が格段に読みやすくなります。変数名と値を同時に出力できるため、コードの動作を追跡しやすくなり、デバッグ時間を大幅に短縮できます。

この小技を活用して、より効率的なデバッグを行いましょう！

## 補足：Python バージョンの注意点

この機能はPython 3.8以降で使用可能です。それ以前のバージョンを使用している場合は、アップグレードを検討するか、従来の方法（例：`print(f"x: {x}")"`）を使用してください。

## 参考情報

1. [PEP 498 – Literal String Interpolation](https://peps.python.org/pep-0498/)
   - f文字列の公式仕様です。f文字列の詳細な動作や制限について知りたい場合に参照してください。

2. [Python公式ドキュメント - フォーマット済み文字列リテラル](https://docs.python.org/ja/3/reference/lexical_analysis.html#f-strings)
   - f文字列の文法や使用例が詳しく解説されています。

3. [Real Python - Python 3's f-Strings: An Improved String Formatting Syntax](https://realpython.com/python-f-strings/)
   - f文字列の詳細な使用方法や、他の文字列フォーマット方法との比較が載っています。

4. [Python Tips - F-strings](https://book.pythontips.com/en/latest/fstrings.html)
   - f文字列の様々な使用例やベストプラクティスが紹介されています。

これらの資料を参考にすることで、f文字列についてより深く理解し、効果的に活用することができます。

https://qiita.com/Tadataka_Takahashi/items/1f667e11f80423e2dda1
deviseとsorceryについて深ぼってみる

## はじめに
deviseとsorceryという認証機能に関わるものについて前回あたりで調べたことをまとめてみましたが。今回はもう少し深ぼってまとめてみたいと思います。

## 一般的とされるdeviseだが…
### 1. deviseはRailsエンジンを用いており、動作を定義してしまう。つまり、ライブラリとしての独立性に乏しいのでsorceryがいいこともある

**Railsエンジン**とは、Railsアプリケーションの一部として動作するモジュール（再利用可能なコードの塊）です。Railsエンジンを使用することで、機能や部分を独立して作成し、Railsアプリケーションに組み込むことができます。`devise`はこのRailsエンジンを利用しており、認証機能の動作を多くの既存のRails機能に組み込んでいます。

このため、`devise`はRailsの内部で多くの機能や動作を定義しており、これがライブラリとしての**独立性**を低くしています。
<br>

つまり、`devise`を使うと、認証機能がRailsの他の部分と強く結びつき、カスタマイズや他のライブラリとの互換性が難しくなることがあります。


### 2.deviseはコントローラーのオーバーライドやソースコードを読んで一部メソッドをオーバーライドするなど依存が激しいのでsorceryｇｓいいことがある。

- **コントローラーのオーバーライド**とは、`devise`が提供するデフォルトのコントローラーやアクションをカスタマイズするために、自分自身でコントローラーを作成して`devise`のコントローラーの動作を変更することです。
- **一部メソッドをオーバーライドする**とは、`devise`が提供する既存のメソッド（例えば、ログイン処理など）をカスタマイズするために、同じ名前のメソッドを自分で定義し直すことです。
- **オーバーライド**とは、既存のクラスやモジュールの機能を上書きして、自分の目的に合わせてカスタマイズすることを指します。

つまり、`devise`の内部実装に依存するため、カスタマイズが難しくなり、`devise`のバージョンアップや他のライブラリとの互換性に問題が生じる可能性があります。


### 3. sorceryも1モデルでしか使えない？！

**1モデル**とは、`sorcery`が基本的に1つのモデル（例えば、`User`モデル）に対してのみ認証機能を提供することを意味します。つまり、`sorcery`を使って複数のモデルに対して認証機能を設定するのが難しいという制約があります。例えば、`User`と`Admin`のような複数のモデルに対して認証機能を設定したい場合、`sorcery`では少し手間がかかります。

このような理由から、`sorcery`はシンプルで使いやすいですが、複雑な認証要件には不向きかもしれません。


## さいごに
deviseとsorceryどちらを利用するか非常に悩ましい。シンプルなミニアプリとかならsorceryでいいのかもしれません。他におすすめの認証機能等があれば教えていただきたいです。
自作という手もあるのか…。
Preferred ElementsのPLaMo βを試す

Preferred Elementsがフルスクラッチで開発した大規模言語モデル「PLaMo β版」を試しました。

# PLaMo
- 1000億パラメータのマルチモーダル基盤モデル「PLaMo-100B」。
- 合計2兆トークンの日本語と英語のテキストデータを事前学習し、既存のLLMモデルを使わずフルスクラッチで開発しています。日本語性能を評価するいくつかのベンチマークでGPT4よりも高い数値を出しています。
- 記事執筆時点ではトライアル版で秋から商用版も発売予定とのことです。


# WEB上での対話
トップ画面はこんな感じです。「Try Demo」をおすとPLaMoと対話できるデモページに遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698823/245679f4-1d7c-ddcd-7bd9-434e39935afa.png)


対話画面のUIはこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698823/ca2051b3-94a6-9882-7e41-c084a24f81ed.png)

右上に”Configure Parameters”というボタンを押すとTempertureやTop Pなどパラメータを調整することができます。他の対話型LLMでは見られなかったので個人的に驚きでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698823/07e7681f-1c8c-2e19-31e4-84c64269bd65.png)

質問してみます。日本語のモデルなので日本のお盆について聞いてみると丁寧に説明してくれました。間違いもなさそうです(多分)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698823/78791cb6-be5e-f348-3b49-f3b7356f809c.png)

最近，諸説あるらしい鎌倉幕府についても聞いてみると現時点で有力とされている内容を出力してくれました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698823/90fdc522-f91d-97e5-a26e-56251a5c454b.png)

レスポンスの速度はGPT4と同程度くらいといった感じでした。

# APIへのリクエスト
PLaMo β API は、langchain-openai やopenai ライブラリとおおよその互換性があります。Colabで試してみましたがlangchain-openaiでリクエストを送ることができました。APIへのキーはデモ画面から入手することができます。以下にサンプルコードを記載します。



``` python
import os
from openai import OpenAI

os.environ['API_HOST'] = "https://platform.preferredai.jp"

client = OpenAI(
    api_key = API_KEY, # 取得したapiキーを設定
    base_url=f"{os.environ['API_HOST']}/api/completion/v1",
)

completion = client.chat.completions.create(
    model="plamo-beta",
    messages=[
        {"role": "system", "content": "あなたは旅行アドバイザーです"},
        {"role": "user", "content": "東京で訪れるべき観光スポットを教えてください"},
    ],
    stream=True,
)

for chunk in completion:
    if chunk.choices[0].delta.content is not None:
        print(chunk.choices[0].delta.content, end="", flush=True)
```
以下のような結果が返ってきました。
```
もちろんです！東京にはたくさんの観光スポットがありますが、特に人気のある場所をいくつかご紹介します。

1.浅草寺:東京最古の寺院で、美しい建築物と周辺の仲見世通りでのショッピングや食べ歩きが楽しめます。

2.明治神宮:緑豊かな広大な神社で、都会の喧騒を忘れさせてくれます。有名な清正の井戸も必見です。

3.東京スカイツリー:東京の街を一望できるタワーで、併設されたソラマチではショッピングやグルメが楽しめます。

4.上野恩寵公園:桜の名所として有名な公園で、動物園、美術館、博物館などの文化施設が充実しています。

5.お台場:ショッピング、グルメ、エンターテインメントが楽しめるエリアで、ガンダム像やチームラボのデジタルアートミュージアムが人気です。

6.皇居:かつての江戸城で、現在は美しい庭園や歴史的建造物が見学できます。

7.新宿御苑:都会のオアシスと呼ばれる公園で、四季折々の美しい自然を楽しむことができます。

8.渋谷スカイ展望デッキ:渋谷スクランブルスクエアの屋上にある展望デッキで、東京の街を一望できます。

これらのスポットは、東京の多様な魅力を体験するのに最適です。訪れる際には、営業時間や入場制限などの最新情報を確認してください。東京での滞在を楽しんでくださいね！
```
requestによってアクセスする方法については以下の記事をご参照ください。

https://qiita.com/AzukiImo/items/20a58336985da680a5a5

# まとめ
PLaMoのトライアルを触ってみました。無料トライアルは秋までとのことなので気になる方は今のうちに触ってみるとよいと思います。以下のリンクから申込ができます。

https://www.preferred.jp/ja/news/pr20240807/

# 参考リンク
https://tech.preferred.jp/ja/blog/plamo-100b/
dockerでmysql環境構築

dockerでmysqlの設定をする。

https://qiita.com/taniann/items/ed9ec892d91e5af962c6

https://qiita.com/tseno/items/1b20f8961166b22d613d

便利なまとめがあるので、読みながら設定。

```yaml:docker-compose.yml
version: '3'

services:
  db:
    image: mysql:8.0.37
    container_name: mysql_prologue
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${ROOT_PASS}
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASS}
      TZ: ${TZ}
    ports:
        - ${DB_PORT}:3306
    volumes:
        - db-store:/var/lib/mysql
        - ./conf/my.cnf:/etc/mysql/conf.d/my.cnf
volumes:
  db-store:
```

```my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_bin

[client]
default-character-set=utf8mb4
```

```.env
ROOT_PASS=ルートのパスワード
DB_NAME=prologue
DB_USER=user
DB_PASS=実際使うユーザのパスワード
DB_PORT=3306
TZ=Asia/Tokyo
```
営業職におけるウェイトとバイアスを理解する：学びの途中での試行錯誤をシェア

### 1. **はじめに**

最近、機械学習やデータ分析を学び始めました。その中で、よく出てくる「ウェイト（重み）」と「バイアス（偏差）」という言葉に初めはかなり戸惑いました。これらの概念を理解するのに時間がかかったので、同じように悩んでいる人たちの助けになればと思い、営業職の例を使って、私が学んだことをこの記事にまとめてみました。

### 2. **ウェイトとバイアスって何？**

#### 2.1 ウェイトの理解
まず、ウェイトとは「このデータが結果にどれだけ影響を与えるか」を示すものです。営業職で考えると、例えばアポイント数が契約数にどれだけ影響を与えるかという感じです。簡単に言えば、アポイントを増やせば契約数も増えるだろうと考えたとき、その影響度がウェイトです。

#### 2.2 バイアスの理解
バイアスは「何もしなくても得られる基準値」として説明されることが多いです。これも営業職で考えてみると、仮にアポイントがゼロだったとしても、以前の顧客からの再契約などで多少の契約は見込めるかもしれません。このような場合の「ゼロからでも得られる契約数」がバイアスにあたります。

### 3. **営業職の具体例で考えてみる**

#### 3.1 アポイントと契約の関係をモデル化
営業職では、アポイント数と契約数の関係を分析することが重要です。例えば以下のようなデータがあったとします：

| 営業担当者 | アポイント数 (X) | 契約数 (Y) |
|--------------|-------------------|------------|
| A            | 10                | 3          |
| B            | 20                | 5          |
| C            | 30                | 7          |

このデータを使って、契約数（Y）がアポイント数（X）によってどれだけ影響を受けるかを見てみましょう。

#### 3.2 Pythonでの実装

次に、Pythonを使ってこの関係をモデル化します。以下のコードを実行すると、ウェイトとバイアスが自動的に計算されます。

```python
import numpy as np
from sklearn.linear_model import LinearRegression

# データのセットアップ
X = np.array([[10], [20], [30]])
Y = np.array([3, 5, 7])

# 線形回帰モデルの作成とフィッティング
model = LinearRegression().fit(X, Y)

# ウェイトとバイアスの取得
weight = model.coef_
bias = model.intercept_

# モデルの結果を表示
print(f"ウェイト: {weight}")
print(f"バイアス: {bias}")
```

実際にこのコードを動かすと、以下の結果が得られます：

```
ウェイト: [0.2]
バイアス: 1.0
```

#### 3.3 結果を解釈してみよう
- **ウェイト**: ウェイトが0.2ということは、アポイント数を1つ増やすごとに契約数が0.2増えることを意味します。つまり、アポイント数が多ければ多いほど、契約も増える可能性が高くなります。
- **バイアス**: バイアスが1.0なので、アポイントがゼロでも1件は契約が見込めるということです。これは、例えば過去の顧客からの再契約や、既存の関係性に基づいた契約がある場合を示しています。

### 4. **まとめ**

このように、営業職の例を使ってウェイトとバイアスの意味を考えてみると、少し理解が進みました。初めて学ぶときは、これらの概念が非常に抽象的で分かりにくいと感じましたが、具体例を用いて考えることで、現実のビジネスにどのように応用できるのかがわかるようになりました。私と同じように学んでいる方々が、このプロセスを通じてウェイトとバイアスを理解できるようになれば嬉しいです。
【Angular】Excelのダウンロード機能を実装！

Angularって情報少ないよなっていつも思う泉（[@izumin_0401](https://twitter.com/izumin_0401)）です。

# ブログ記事はこちら

https://traveler0401.com/angular-excel-download

# AngularでExcelをダウンロードしたい
早速ですが、AngularでExcelのダウンロード機能を実装してみましたよん。

# Excelのダウンロード機能を実装する手順

## 「xlsx」のインストール
```terminal
$ npm install xlsx
```

## ソースコード
```typescript
import * as XLSX from 'xlsx';

.
.
.

download() {
  const header = [
    "ウンコ",
    "ウンコ数"
  ];

  const data = [
    [
      "大きいウンコ",
      1
    ],
    [
      "小さいウンコ",
      2
    ]
  ];

  // ヘッダを先頭に追加
  data.unshift(header);

  // aoa_to_sheetはデータが配列の配列の場合に使う
  const workSheet: XLSX.WorkSheet = XLSX.utils.aoa_to_sheet(data);
  const workBook: XLSX.WorkBook = XLSX.utils.book_new();
  
  XLSX.utils.book_append_sheet(workBook, workSheet, 'sheet1');
  XLSX.writeFile(workBook, 'unko.xlsx');
}
```
上記のコードでExcelファイルをダウンロードできます。

意外と簡単だった。

# まとめ
なんでExcelをダウンロードしたいのかって？

...大人の事情だよ！！

# 最後に
暇つぶしに[Twitter](https://twitter.com/izumin_0401)と[ブログ](https://traveler0401.com/)もやってるので見てね。
SUNMI V2 PRO の STARPAY モデルで GMS を有効にする

:::note alert
この記事は、SUNMI V2 PRO の STARPAY モデルを Android 検証機として利用するための方法です。STARPAY 社のサービスをご利用の方は、この記事の手法は利用しないでください。
:::

業務用スマホ SUNMI V2 PRO はサービス提供会社向けにカスタムされたモデルが複数存在します。その中で STARPAY 社向けの端末は入手性の高いモデルの１つです。私も STARPAY モデルを所有しています、2台ほど。

|所有するSTARPAYモデル|ロゴの表示方法が異なる|
|:-:|:-:|
|<img width="" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24345/32e43380-ce92-4264-2c9e-7e867a4fc0fa.jpeg">|<img width="" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24345/5f959571-4de1-7969-3e66-08dc806d0fd1.jpeg">|

なぜ2台持っているのかというと、GMS が有効にできる端末とできない端末があるからです。この画像において、左のロゴがシールの端末はGMS無効、右のロゴが印刷された端末はGMS有効です。それぞれのスペックは次のとおりです。

| モデル | SUNMI OS | firmware | storage | memory | NFC | GMS |
| :-- | :-- | :-- | :-- |:-- | :-- | :-- |
| STARPAY（左） | 1.2.2 | 162 | 8 GB | 1 GB | なし |無効 |
| STARPAY（右） | 2.7.15 | 205 | 8 GB | 1 GB | なし | 有効 |
| 正規販売店 | 3.6.23 | 754 | 16 GB | 2 GB | あり |有効 |
| foodpanda | 1.0.33 | 138 | 8 GB | 1 GB | なし |有効 |

比較として、正規販売店で購入したモデル、かつてフードデリバリーサービスを展開していた foodpanda モデルを添付します。なお、すべてのモデルは Android 7.1.2 です。

## GMS を有効にする

もし、お持ちの端末が SUNMI OS 1.2.2 のモデルであれば、GMS を有効にする方法は今のところありません。一方で SUNMI OS 2.7.15 であれば、次の手順で GMS を有効にできます。

### 開発者向けオプションとアクティベート

端末を初期化して、利用言語とタイムロケールを設定します。その後、Wi-Fiを設定する画面に遷移しますが、そのまま体験モードを選びます。

:::note info
このタイミングで Wi-Fi を設定しても大丈夫かもしれません。ただ、アクティブになった際に、制御プログラムが何か影響するかもしれない？と思い、私はここで Wi-Fi を設定しませんでした。
:::

設定の端末情報からビルド番号を連打して、開発者向けオプションを有効にします。その後、開発者向けオプションでUSBデバッグを ON にします。この状態で adb が利用できるパソコンに接続して、adb コマンドを実行しても `unauthorized` になり操作はできません。

```shell
% adb devices
List of devices attached
端末のシリアル番号	unauthorized
```

ここで Wi-Fi に接続して端末をアクティベートします。その状態でパソコンに接続すると `Debugging success` がホーム画面に表示されます。

|　`Debugging success` が表示される|
|:-:|
|<img width="400" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24345/b30feff8-7289-0802-5390-eb185473bdd0.png">|

この状態になれば、adb コマンドが利用できるようになります。

```shell
% adb devices
List of devices attached
端末のシリアル番号	device
```

### GMSを恒久的に有効にする

adbコマンドが利用できるようになれば、あとは簡単です。次のコマンドを使って、無効になっている GMS を有効にします。

```shell
% adb shell pm enable com.google.android.gms
% adb shell pm enable com.android.vending
```

|　有効になって表示された Play ストアのアプリ|
|:-:|
|<img width="400" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24345/f8e8a309-0be4-1304-18b0-d8654313197d.png">|


ただし、このコマンドは一時的な効果なので、GMS を無効化しているプロセスを無効にします。

```shell
% adb shell pm disable-user --user 0 com.sunmi.baseservice
```

これで晴れて立派な Android 端末になりました。

## まとめ

私が持っているロゴが印刷された端末は GMS が有効になりました。ただし、注意点として、ロゴが印刷なら GMS が有効、ロゴがシールなら GMS が無効とは限りません。

SNS を見ていると、シールの端末でも GMS が有効になった端末も観測されます。その逆のパターンも見ました。また、シールが剥がされた第三の見た目の端末もあります。外観だけで GMS が使えるかの判定は難しいです。もしショップやフリマサイトで見かけたら、出品者に聞いたり、SUNMI OS のバージョンを確認するとよいです。
SORACOMLagoonを使ってみての感想

現在SORACOMラグーンを使用して、IoTのデータをクラウド上で確認できるようにしているが
今回できることとできないことが分かったので、まとめていく。

## できること
・SORACOMHarvestに上げたデータを四則演算して、パネル表示する



## できないこと
・正時事にデータを纏めて表示する。
・今のデータと一つ前のデータをdiffする。
　（例えば今の値が1005で一つ前のデータが1000の場合、差分は5などの表示ができない）


今も開発中なので随時更新していきます。
実はできるよ！！
って分かる方はアドバイスお願いします！
【#1】Git入門 「Gitがきっと好きになる。エンジニアの第一歩踏み出そう！ 」

この記事は私の所属しているプロジェクト団体の初学者向けに書いた文章です。
# Hello!
こんにちは！普段は真面目な私ですが、今回はみなさんにGitを楽しく学んでいただきたいと思い、カジュアルな 感じで記事を書きました。
# はじめに
この記事では、「Git」について聞いたことはあるけれど、詳しく知らない方向けに説明します。主に以下の3点についてお話しします：

- なぜエンジニアはGitを使うのか
    - Gitを使うとどんなメリットがあるのか
- バージョン管理の恩恵
- GitとGitHubの違い

# なぜエンジニアはGitを使うのか
エンジニアがGitを使う主な理由は、バージョン管理ツールとして優れているからです。
ん？バージョン管理？
バージョン管理って何でしょうか？

## プログラムコードは流動的
プログラムは常に変化しています。昨日書いたコードが、今日は全く違うものになっていることもあります。そんなとき、「あの時の状態に戻りたい...」と思うことがよくあります。
例えば、こんな状況を想像してみてください
```:僕の経験談
あなた：新機能を追加しよう！（プログラムを100行書く。それも複数のファイルで）
コード：エラーだらけで動かない
あなた：ぎゃああ゛ー！昨日の状態に戻したい！
```
バージョン管理ソフトを使っていないと、この「昨日の状態」に戻るのが難しいんです。でも、Gitのようなバージョン管理ソフトを使えば、簡単に過去の状態に戻れるんです！

:::note info
用語：バージョン管理
ファイルの変更履歴や変更内容などを記録し、管理すること。
ファイルを編集している間、ずっとメモを取ってくれている秘書みたいなものです。
:::

## バージョン管理の恩恵
実際にソフトウェア開発の現場を想定してどのようなときに`バージョン管理`の恩恵を受けられるのか考えてみましょう。

### なぜ`バージョン管理`が必要なの？
実際の開発現場で、バージョン管理はどんな場面で役立つのでしょうか？
1. 変更履歴の確認
「先週の金曜日に追加した機能、どんなだったっけ？」と思ったとき、簡単に確認できます。

2. 失敗してもやり直せる
新機能を追加してバグだらけになっても、すぐに前の正常な状態に戻せます。

3. 複数人での作業が楽になる
AさんとBさんが同じファイルを編集しても、変更を簡単に統合できます。


4. 実験的な機能を安全に試せる
「ブランチ」という機能を使えば、メインのコードを壊さずに新しいアイデアを試せます。



:::note info
用語：ブランチ
メインの開発ラインから分岐した、独立した開発ラインのこと。
実験的な機能を安全に開発できます。
:::
# GitHubとGitの違いはなんやねん！
ここで `Git`についておさらいしておきます
`Git`はバージョン管理ソフトの一つで、変更履歴を管理するツールです。

`GitHub`はその`Git`を使うためのウェブサービスです。Gitで管理しているプロジェクトをネット上においてほかの人と一緒に共有できるようにするサービス。つまり、バージョン管理をみんなで見られるようにした掲示板サイトみたいなものです。

主な違い
- `Git`はツールで`GitHub`はインターネット上のサービスでブラウザから使います。
- `Git`は個人で利用して一人で黙々とコードを書いていても便利で、`GitHub`は他の人とコードを共有したり、一緒に開発したりするときに便利
- `Git`は無料。`GitHub`は一部有料（学生なら無料になることもある）

GitとGitHubは、セットで使うと最強です。Gitでコードを管理して、GitHubで世界中の開発者と共有する。そうやって、みんなで協力して素晴らしいものを作っていくんです。

# さいごに
`Git`を使うと、複数人でのプロジェクト開発がスムーズになります。初めての方にとっては勉強するのが難しいと思うかもしれません。
学習コストは確かに大きいですが、少しずつ勉強してマスターしていきましょう！

次の記事では
1. Gitの基本コマンドを勉強
を行います。乞うご期待👍
自己代入の省略した書き方

# 自己代入の省略した書き方

::: note info
自己代入とは 🌱
自分自身に代入すること
例えば、中身が3である`x`に2を足して`x`を5とする↓

 x = 3
 x = x + 2
 
:::

 ### 省略形

 ```x10.java
//  基本形       省略形
 x = x + 10;    x += 10;
 x = x - 10;    x -= 10;
 x = x * 10;    x *= 10;
 x = x / 10;    x /= 10;
 x = x % 10;    x %= 10;
 ```

 値が1の場合のみさらに省略が可能

 ```x1.java
 //  基本形       省略形       さらに省略形
 x = x + 1;     x += 1;         x++;
 x = x - 1;     x -= 1;         x--;
```

# さいごに
省略形はたまに記述するので、ちゃんと覚えておこうと思いメモしました！
アートなLineアプリの作り方

## アートなアプリとは
ものづくりの考え方として、アート思考とデザイン思考という考え方があります。
ここでは、アート思考によるソフトウェア開発についてご説明します。

## アート思考とデザイン思考

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212141/fac676a3-7291-5e86-6866-9490c3e3f401.png)

ここに、その2つを対比させていますが、デザイン思考では***ユーザーの問題解決*** から発想するのに対して、アート思考では***作り手の自己表現***から発想される所が大きく違います。

これらは真っ向から対立するようですが、ヒットするプロダクトではこの双方の要素が欠かせないものです。例えばiPhoneを見れば、それぞれの要素が見えてくると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212141/19b83b48-3626-aa57-41fe-7898c7d509ba.png)

左は、当時もっとも普及していたスマートフォンのBlackberry、右がiPhone 3Gです。どちらもヒットした商品です。
iPhoneでは、思い切ってボタンやスイッチを省略し、あらゆる操作をタッチパネルで行うという設計は、スティーブジョブズのこだわり無くしては出てこなかったと思います。

## 自分の感性で企画する
LineBOTとして、数字を入れるとその数字を説明してくれる、というチャットボットを企画しました。視点としては、
- おおよそ役に立たない
- ちょっと楽しい

という視点です。

なぜ数字、という所は、たまたまNumbersAPIというものを見つけたからですが、それが目に留まったのは自分が数字が好きだから、だと分析しています。

以下、使った感じです。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212141/ddf6fbd6-b656-2a97-6779-34e788f53ed4.png width=50%>

数字を入れると、その数字がどんな数字かを説明してくれます。
同じ数字を入れても、違う説明が出てくることもあります。

アプリは公開しています。文末にQRコードを公開しておきますが、月間1000回までしか対話できないので、もしかしたら反応が無いかも知れません。悪しからず。

## 実装について

実装に使用したツールは以下の通りです。
- Line
- make
- Numbers api
- DeepL

makeはノーコードツールで、全体のロジックを組んでいます。Lineからのメッセージはこのmakeのモジュールで受信し、必要な処理を行って、Lineのメッセージを返す処理を行っています。

ロジックは以下の図になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212141/488c6477-e89a-bbc8-c126-50ccecd6db06.png)

左から右に処理は流れていきます。

Lineで受け取ったメッセージは、Routerで判定されます。正規表現にマッチした場合は、次のNumbers apiの処理に入ります。マッチしなかった場合は、斜め上のルートに入って、エラーメッセージを返します。
正規表現は、数字だけが含まれているかという判定をします。

数字の場合は、HTTPのGETで、"http://numbersapi.com/数字" というリクエストを投げます。その戻り値が、その数字の説明になるのですが、この段階では英語です。

DeepLモジュールを使って、Numbers apiの戻り値を翻訳し、Lineに返して、プログラムは終了します。

## Line Messaging API
蛇足になるかもしれませんが、Lineとどのようにインターフェースを取るのかを説明します。キーワードは
- チャネルアクセストークン
- Webhook

手順は以下の通りです
- 自分のLineアカウントを使って、Line Developersのサイトにログインします。
- プロバイダーを作成し、開きます。
- 新規チャネルを作成し、開きます。

この作成したチャネルが、メッセージをやり取りする、Messaging APIのインターフェースになっています。

チャネル基本設定に、アイコンや説明など、必要な設定を行います。

Messaging API設定のタブを開いて、一番下のチャネルアクセストークンを発行します。
このトークンを、make側のConnectionの設定で使用します。

QRコードの下あたりに、Webhook設定というのがあります。ここに、makeのWebhookの設定で生成されたURLを設定します。

この設定で、Lineのメッセージが入った時に、make側のURLを呼び出すことで、プログラムが開始されます。これをWebhookと言います。

その後、makeがLineのチャネルとデータをやり取りするためのセキュリティが必要ですが、その設定がチャネルアクセストークンです。

慣れると簡単にできますが、あまり情報が無いので最初は戸惑うのではないかと思い、念のため説明しておきました。

## 各モジュールの設定について
- RouterとHTTP間のフィルタ

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212141/54f24560-e591-a9a6-bac2-167b4be8f006.png width=50%>

- HTTP (Numbers API)

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212141/1e10a7f9-397d-ca8e-afa5-0bdc29c4fe69.png width=50%>

- DeepL

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212141/59ec5c0f-495d-069b-b395-70b6320b2e22.png width=50%>

## アートなポイント
このアプリはアート思考が強いものだと考えています。

- 独自の視点や感覚
	数学が好き – 独自性
- 結果より過程を楽しむ
	プログラムの美しさ
- 複数の答えを受け入れる
	答えは毎回変わる
- 感性や直感を重視
	役に立つか立たないかは二の次

これからもアート思考でアプリ開発を楽しんでやっていきたいと思います。

## Numbers Line BOT
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212141/1f550864-d6ed-da72-a751-e292e0c8397c.png)

以上
【あるようで意外となかった】Macで音声ファイルを使ってVTubeStudioのキャラクターに口パクしてもらう方法

みなさん、こんにちは！
Cor.Inc.のAIアンバサダー、宇宙野クラウディアっちゃ！

今回は下の記事の補足記事として、VB-CABLEをMacで使ってVTubeStudioのキャラに口パクしてもらう方法を解説するよ！

https://qiita.com/Cloudia_Cor_Inc/private/aec8cdf2aa4e18e25e1b

早速やっていこー！

![dcf770fa4f40b5ce9df7e8763a69abee.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3826031/8467eb07-a0c4-6f9a-fe14-5fd82b2b7b7c.png)


## 参考記事はこちら！📖

今回はちょっとした違いを説明するだけだから、参考にした記事をここに書いておくよ！

https://note.com/sirodon_256/n/ncf791dd0b1c0

VB-CABLEのダウンロード、インストールまでは一緒！
VTubeStuioのリッピング設定も変わらんからそっちをみてね！

でも、音のモニタリング設定だけ全く違ったから、今回はそこを説明していくよ！

## Audio MIDI設定で出力をカスタムしよう！🎹

Macで入出力を調整するなら、プリインストールされている**Audio MIDI設定**をまず立ち上げる必要があるっちゃ！
![スクリーンショット 2024-08-09 17.56.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3826031/3a892eab-beaf-eaa2-14ff-b4613cfce698.png)
*アプリケーションから「audio」で検索すると早いんよ！*

アプリを開いたら、左下の+ボタンを押して、「複数出力デバイスを作成」を選択して新しいオーディオ装置を作る！
そしたらいま選択できるオーディオ装置が出てくるけん、VB-Cableと出力したい装置を選んだら閉じちゃってOK!

![スクリーンショット 2024-08-09 17.59.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3826031/eb74a912-2569-333a-1083-f98643934ca4.png)
*こんなふうに選択できるんよ！*

例えば、デバイス自体から音を出しながらVTubeStudioのキャラに口パクしてもらいたいなら「MacBook　Airのスピーカー」をVB-Cableと併せて選択してればいいし、ZoomAudioDeviceを選択するとZoomの時も簡単に音声出力ができると！

今回はLT発表をするため「SBS-XB20」っちコンパクトスピーカーを選択しとるよ！

ここまできたらあとは簡単！

システム設定からサウンドを選択して、「出力と入力」の部分で「複数出力装置」を選択するだけでその設定に変えれるっちゃん！
![スクリーンショット 2024-08-09 18.10.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3826031/d9678aa0-9fea-03e3-7124-4044ac7fbdca.png)
*通常に戻したいときは「内蔵」もしくは「Bluetooth」を選べばOKよ*

## 複数出力装置を使う時の注意 👀

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3826031/51e141d8-541b-92e4-62fa-d93478365247.png)
複数出力装置でデバイスのスピーカーを設定してても、Bluetoothに繋いでも自動的には切り替わらんのよ！
音漏れしてとっても恥ずかしい・・・
っち思いをしないためにも、設定が本当に正しいかどうかちゃんとチェックしてから使ってね！

## 終わりに

今回はちょっとしたTips記事を書いてみたっちゃ！
どうだったかな？役に立ったら嬉しいな！
取り上げてほしいTipsとかもあったら気軽にコメントしてみてねー！

んじゃまたねー！
![bye0710.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3826031/3fdec071-9509-c5b7-f9b4-43ac1407e9b0.png)
Swaks でファイルを添付する方法【v20240103.0】

## 結論

- `--attachment @filename` のようにファイル名の前に`@`を加える。

- 以前のバージョンでは`@`は必要ないですが、v20240103.0 から`@`が必要になりました。

## 経緯

ファイルを添付して送る際に`@`を抜いた状態で送信したところ、ファイル名のみBase64にて暗号化される現象に悩まされました。

#### ファイル添付メール送信テスト（失敗例）
```
$ swaks -t you@example.com --from me@example.com -au me@example.com --attach swakstest.txt --server 192.0.2.1 --body body.txt --header "Subject: Mailtest"

(省略)

 -> ------=_MIME_BOUNDARY_000_168599
 -> Content-Type: application/octet-stream
 -> Content-Disposition: attachment
 -> Content-Transfer-Encoding: BASE64
 -> 
 -> c3dha3N0ZXN0LnR4dA==　　　# ファイル名「swakstest.txt」がBase64に暗号化
 -> 
 -> ------=_MIME_BOUNDARY_000_168599--
```

#### ファイル添付メール送信テスト（成功例）
```
$ swaks -t you@example.com --from me@example.com -au me@example.com --attach @swakstest.txt --server 192.0.2.1 --body body.txt --header "Subject: Mailtest"

(省略)

 -> ------=_MIME_BOUNDARY_000_175923
 -> Content-Type: application/octet-stream; name="swakstest.txt"
 -> Content-Description: swakstest.txt
 -> Content-Disposition: attachment; filename="swakstest.txt"
 -> Content-Transfer-Encoding: BASE64
 -> 
 -> 44GT44KM44Gvc3dha3Pjga7jg4bjgrnjg4jjgafjgZnjgIIK # ファイルの中身がBase64に暗号化されました！
 -> 
 -> ------=_MIME_BOUNDARY_000_175923--
```

## 参考

- Swaks Versions: https://jetmore.org/john/code/swaks/versions.html
例えばこんなコピーのできないメッセージダイアログがあるじゃないですか - snipping tool の text actions 機能の紹介

# 例えば
例えばこんなコピーのできないメッセージダイアログがあるじゃないですか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32143/727046a3-948d-e4a2-cbd1-059e25763bdc.png)

`Win`+`Shift`+`S` で `Snipping Tool` して 範囲をスクショするじゃないですか。 
そこから Snipping 標準の 編集ツールを開いて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32143/f5231442-3990-9561-3a11-e536931f359c.png)

上部メニューの `テキスト アクション` を実行してみると……!
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32143/6387a9d1-4fdf-0c3c-6f99-432127fbb457.png)

ほい。 コピーできる！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32143/1e0f821c-fb54-a28d-0291-53a5d6c9d047.png)


> There is a new version of the Unity Editor available
for download.
> 
> Currently installed version is 2022.1.18f1
> (8a091f9adba4)
> New version is 6000.0.10f1 (413673acabac)
> 
> A new version of Unity is available. Please update to the latest
> released version at your convenience. Release notes available on the
> download site. Click the "Download Installer" button.

精度は悪くないのではないでしょうか……？

# 環境
エディション: Windows 11 Pro
バージョン: 23H2
os ビルド: 22631.3958

# 参考

https://pc.watch.impress.co.jp/docs/news/1531889.html

https://atmarkit.itmedia.co.jp/ait/articles/2406/14/news034.html
json 形式で表示される cloudwatch event log のチートシート


AWS Cloudwatch で json 形式のログを吐き出している方が多いと思いますが、その検索方法について~~毎度ドキュメント読むのが面倒なので~~まとめておきます。

## 使える構文

文字で検索

```
{ $.message.path = "/hoge" }
```

数値で検索

```
{ $.message.statusCode = 500 }
```

ワイルドカードを使用して検索

```
{ $.message.statusCode = "*" }
```

`and` `or` を用いた検索
() を使用して優先順位をつけることもできます

```
{ $.message.statusCode = "*" && $.message.statusCode = "*" }
{ $.message.statusCode = "*" || $.message.statusCode = "*" }
{ $.message = "hoge" || $.message = "fuga" && $.message.statusCode = 400 }
```
Unixタイムスタンプ(m秒込み)のSparkのタイムスタンプ型への変換

意外にハマったのでメモ。

**やりたいこと**

> m秒を含むUnixタイムスタンプをSparkで読み込んで、Sparkのtimestamp型に変換したい

簡単だろうと思ったら一筋縄では行きませんでした。そもそも、Unixタイムスタンプにm秒ありとなしがあることも知りませんでした。

こちらが参考になりました。

https://lara-bell.com/2017/12/trap-of-unix-timestamp/

- m秒なし: 10桁
- m秒あり: 13桁

m秒なしなら[`from_unixtime`](https://spark.apache.org/docs/3.1.3/api/python/reference/api/pyspark.sql.functions.from_unixtime.html)を呼び出すだけです。しかし、説明にあるように対応しているのは秒までです。なので、以下のようにして変換するのですが、当然m秒は落ちてしまいます。

```py
df = df.withColumn(
    "spark_timestamp", F.from_unixtime(df.unix_timestamp / 1000).cast("timestamp")
)  # unix timestamp から spark timestamp へ (m秒が丸められている)
```

色々探していたら、こちらを見つけました。

https://stackoverflow.com/questions/61246054/convert-unix-timestamp-into-ms-timestamp-in-pyspark

> デフォルトの`to_timestamp`, `from_unixtime`, `unix_timestamp`関数はm秒を返しません。
>
> しかし、ワークアラウンドとしてm秒のタイムスタンプを得るために、`from_unixtime`と`concat`関数を使います。

なんと。試します。

```py
import pyspark.sql.functions as F

df = spark.createDataFrame([
    {'unix_timestamp': 1723191602124},
    {'unix_timestamp': 1723192950521}
])
display(df)
```
![Screenshot 2024-08-09 at 17.57.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/6a359892-f4dd-965e-9319-24ba35b6f25e.png)

はじめに上述の手法を試します。

```py
df = df.withColumn(
    "spark_timestamp", F.from_unixtime(df.unix_timestamp / 1000).cast("timestamp")
)  # unix timestamp から spark timestamp へ (m秒が丸められている)
display(df)
```

秒までしか入っていません。
![Screenshot 2024-08-09 at 17.58.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/0bbe55bc-43cb-01b1-d8f5-33b734a58cba.png)

ワークアラウンドを試します。わかりにくいですが、以下の流れです

1. 秒までのタイムスタンプを日付表現に変換
1. m秒を表現する文字列を抽出
1. `concat_ws`を用いて`.`を区切り文字として上の二つを文字列結合
1. `yyyy-MM-dd HH:mm:ss.SSS` 形式の文字列から Spark timestamp に変換

```py
df = df.withColumn(
    "spark_timestamp_w_milli",
    F.concat_ws(  # (3) 秒までの文字列とm秒の文字列をカンマ区切りで結合 
        ".",
        F.from_unixtime(
            F.substring(F.col("unix_timestamp"), 0, 10), "yyyy-MM-dd HH:mm:ss"
        ),  # (1) タイムスタンプの最初の10文字からyyyy-MM-dd HH:mm:ssに変換
        F.substring(F.col("unix_timestamp"), 11, 3),  # (2) m秒を表現する11文字目から3文字を取得
    ).cast("timestamp") # (4) yyyy-MM-dd HH:mm:ss.SSS 形式の文字列から spark timestamp に変換
)  

display(df)
```

できました！
![Screenshot 2024-08-09 at 18.02.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/8fdd6da3-2563-459e-3d71-11e02bf8923e.png)

### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
NetlifyでPDFや画像をnoindexに設定する方法


## はじめに

こんにちは。HRBrainでオウンドメディア・ランディングページの開発を担当している渡邉です。

先日、Netlifyでホスティングしている特定のPDFファイルを検索エンジンのインデックスから除外したい、という依頼を受けました。

通常、HTMLファイルであれば、以下のようにmetaタグを設置することで簡単にnoindexに設定できます。

```html
<meta name="robots" content="noindex">
```

しかし、PDFファイルにはmetaタグを設置することができません。

そこでこの記事では、Netlifyで特定のページやリソース（PDF、動画、画像など）をmetaタグを使わずにnoindexに設定する方法を紹介します。

## レスポンスヘッダーのX-Robots-Tagでnoindexを設定する

結論から言うと、X-Robots-Tagというカスタムヘッダーを指定することで、この問題を解決できます。

```
X-Robots-Tag: noindex
```

X-Robots-Tagは、HTTPレスポンスヘッダーに設定することで、検索エンジンに対するインデックス指示を行うためのものです。

これを使うことで、metaタグによるnoindex設定と同様に、ページやリソースを検索エンジンのインデックスから除外することができます。

実は、この方法はGoogleの公式ドキュメントでも紹介されています。

https://developers.google.com/search/docs/crawling-indexing/block-indexing?hl=ja

<br>

ちなみに、Netlifyのdeploy-preview環境が検索エンジンにインデックスされないのは、deploy-preview環境に対して`x-robots-tag: noindex`がデフォルトで設定されているためです。

![netlify_deploy_preview_noindex.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681000/b1e15b1a-e777-4bbb-2a20-215c3a0f9fd5.png)

## netlify.tomlでの設定方法
Netlifyで特定のディレクトリやファイルにX-Robots-Tagを設定するには、netlify.tomlファイルを使用します。

### 手順1: netlify.tomlファイルの作成
プロジェクトのルートディレクトリにnetlify.tomlという名前のファイルを作成します。

### 手順2: HTTPレスポンスヘッダーの設定
netlify.tomlにカスタムヘッダーを設定するためのセクションを追加します。

以下のように記述することで、特定のディレクトリやファイルに`X-Robots-Tag: noindex`を指定できます。

```toml:netlify.toml
[[headers]]
  path = "/hoge/*"
  [headers.values]
    X-Robots-Tag = "noindex"

[[headers]]
  path = "/fuga/sensitive-file.pdf"
  [headers.values]
    X-Robots-Tag = "noindex"
```

上記の設定では、`/hoge/`ディレクトリ内のすべてのファイルと、`/fuga/sensitive-file.pdf`という特定のファイルにnoindexが適用されます。

### 手順3: デプロイ
設定が完了したら、netlify.tomlを保存してNetlifyにデプロイします。

指定したリソースにアクセスすると、ヘッダー情報に`X-Robots-Tag: noindex`が適用されていることが分かります。

これにより、検索エンジンのインデックスから除外されます。

![netlify_pdf_noindex.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681000/151f1ebd-72fd-9d22-fd28-c36abbd2b818.png)

もし、すでにページやファイルがGoogleにインデックスされている場合は、Google Search ConsoleからURLの削除を行なってください。

https://support.google.com/webmasters/answer/9689846?hl=ja

## まとめ

X-Robots-Tagというカスタムヘッダーを設定することで、Netlifyにホスティングした特定のページやリソースをnoindexに設定することが可能です。

検索エンジンに対して特定のコンテンツをインデックスしないように指示でき、SEO対策やコンテンツ管理で役に立ちます。

実装する際の参考にしてください。

## PR

HRBrainではフロントエンドエンジニア（コミュニケーションデザイン）の採用も行なっているのでぜひ！

https://hrmos.co/pages/hrbrain/jobs/2110310

https://www.hrbrain.co.jp/recruit