OmniAICreator/Qiita-1.07M huggingface dataset:
【疑問】BM25でもTFIDF同様にコサイン類似度に基づいてランキングしてよいのか

# 概要
情報検索タスクにおける、TFIDFやBM25のコサイン類似度と関連性スコア（定義後述）について考えていたらよくわからなくなったのでとりあえず疑問点を整理しました。

- ネットの情報を軽く眺めた範囲では、情報検索タスクにおいて、TFIDFではコサイン類似度、BM25では関連性スコアを用いていることが多い。
- BM25でもコサイン類似度を用いたらだめなのか。

# 関連性スコア
関連性スコアというのは正式な名前ではないかもしれませんが、ここでは以下のように定義します。
- ある文章（クエリ）からみた別の文章（文書）の関連性スコアとは、クエリにおける単語の出現回数を、文書におけるその単語の重要度で重み付けして足し合わせた値である。

単語の重みはいわゆるTFIDFやBM25とよばれるものです。これらは、クエリの長さの影響は受けませんが、文書の長さの影響はうけるため、クエリと文書の役割を入れ替えると異なる関連性スコアとなります。つまり対称ではありません。

BM25（BM25Okapi）の関連性スコアの計算式を以下に示します。Qがクエリ、Dが文書です。

```math
\text{score}(D, Q) = \sum_{i=1}^{n} \text{IDF}(q_i) \cdot \frac{f(q_i, D) \cdot (k_1 + 1)}{f(q_i, D) + k_1 \cdot \left( 1 - b + b \cdot \frac{|D|}{\text{avgdl}} \right)}
```


# コサイン類似度
ある文章を、その文章における単語の重要度で重み付けした疎なベクトルに変換し、ベクトル同士のコサイン類似度を求めることで、文章同士が似ているかどうかを見積もることができます。コサイン類似度なので、対象性があります。TFIDFやBM25は単語の重要度に相当する概念のため、これで重みづけた文章ベクトルを作ることができます。

# TFIDFによる情報検索
TFIDFを用いた情報検索では、クエリと文書のコサイン類似度に基づきランキングすることが多いです（e.g. langchainのTFIDFRetriever）。
[スタンフォード大学の講義資料](https://web.stanford.edu/class/cs276/19handouts/lecture6-tfidf-1per.pdf)では関連性スコア（p23）が一瞬紹介されますが、そのあとは情報検索ではコサイン類似度を使うことが紹介されています（p26-）。

# BM25による情報検索
一方で、BM25では、クエリから見た文書の関連性スコアでランキングすることが多いです（e.g. rank_bm25）。TFIDF同様にコサイン類似度で計算してもよさそうですが、あまりそういう情報は出てきません。
[Wikipedia](https://ja.wikipedia.org/wiki/Okapi_BM25)では関連性スコアのみが紹介されています。
[スタンフォード大学の講義資料](https://web.stanford.edu/class/cs276/handouts/lecture12-bm25etc.pdf)でも関連性スコア（p28）が紹介されていますが、コサイン類似度は登場しません（見落としでなければ）。

追記：
BM25でベクトルの類似度を計算しているっぽい事例を見つけました。
- [ノンプログラミングでBERT,Word2Vec,tf-idf,BM25を試す](https://note.com/matrixflow/n/n682867ab1baa)

# 関連性スコアの課題

非対称であるために、文章の類似度の指標としては使いにくい気がします。
ひょっとしたら情報検索タスクだけであれば、非対称でも問題ないのかもしれません。例えば、文章Aをクエリとして文章Bがヒットするのは嬉しいが逆は嬉しくないということはあるかもしれません。しかし関連性スコアの計算式は必ずしもそのような効果を生むために非対称になっているわけでもなさそうなので、やはり微妙な印象はあります。

また関連性スコアそのものの課題というわけではありませんが、TFIDFとBM25は似たような概念なのに、情報検索におけるランキングのもとになる指標の計算方法が関連性スコアとコサイン類似度で異なるというのも、なんだか収まりが悪いです。

# おわりに
できたらBM25でもコサイン類似度でランキングしたいです。ネットに情報がでていないだけで、既存の検索システムは実はBM25のコサイン類似度を用いているのかもしれませんがどうなんでしょうか。気になります。
【Next.js】Server ActionsでブラウザにCookieをセットする方法

## Cookieをクライアントにセットするための関数を作成

クライアントでCookieをセットするための関数を以下の手順で作成します。

まず[`set-cookie-parser`](https://github.com/nfriedly/set-cookie-parser)をインストールします。

```terminal:ターミナル
npm install --save set-cookie-parser
```

次に`proxy-server-cookies.ts`を作成します。
Server Actionsでの`Set-Cookie`ヘッダーの値を`cookies().set`でセットしなおしています。

```ts:proxy-server-cookies.ts
import 'server-only'
import { cookies } from 'next/headers'
import setCookieParser from 'set-cookie-parser'

export function proxyServerCookies(headers: Headers) {
  const setCookie = headers.get('set-cookie')

  if (setCookie !== null) {
    const splitCookieHeaders = setCookieParser.splitCookiesString(setCookie)
    const cookieObjects = setCookieParser.parse(splitCookieHeaders)

    cookieObjects.forEach((cookieObject) => {
      const { name, value, sameSite, ...rest } = cookieObject
      cookies().set(name, value, {
        sameSite: sameSite === 'strict' ? 'strict' : 'lax',
        ...rest,
      })
    })
  }
}
```

## 上記の関数を使用してCookieをセットする

以下のように作成した関数を使用します。

```ts
'use server'

import { cookies } from 'next/headers'
import { proxyServerCookies } from './proxy-server-cookies'

export async function sample() {
  try {
    const res = await fetch(
      "http://example.com/sample",
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Cookie: cookies().toString(),
        },
        body: JSON.stringify({
          // ...
        }),
      }
    )

    // ...
  
    proxyServerCookies(res.headers)

    // ...
  } catch (err) {
    // ...
  }
}

```

## 参考

https://stackoverflow.com/a/77446172
[Security] プロキシ

# プロキシサーバ
|||
|:--|:--|
|フォワードプロキシ|Webブラウザの代理として、Webサーバにリクエストを送信する<br>クライアント-フォワードプロキシ-インターネット|
|リバースプロキシ|Webサーバの代理として、Webブラウザに応答する<br>インターネット-リバースプロキシ-Webサーバ|

# 参考リンク
- [リバースプロキシ（Reverse Proxy）とプロキシの違いは？](https://jitera.com/ja/insights/43726)
- [令和元秋35](https://www.ap-siken.com/kakomon/01_aki/q35.html)
Windowsで絶対開いていないフォルダなのに「別のプログラムがこのフォルダーまたはファイルを開いているので、操作を完了できません。」と言われてフォルダを移動/削除できないときの対処

# この記事のまとめ
- NASからマウントしたフォルダ内のフォルダを移動しようとしたとき「別のプログラムがこのフォルダーまたはファイルを開いているので、操作を完了できません。」と怒られる
- どうやらThumbs.dbというサムネイルのデータベースの再構成が悪さをしている
- 設定からThumbs.dbの再構成を停止することで解決する

# はじめに
Windowsでフォルダを移動しようとしたとき、絶対に自分では開いていないのに「別のプログラムがこのフォルダーまたはファイルを開いているので、操作を完了できません。」と怒られて移動できない現象に遭遇しました。
複数のフォルダ（数十フォルダ）で同様の現象が起きていて困ってしまい......。
そんなときの対処の備忘録です。


# 考えられる原因
意図的にフォルダを開いていないとしても、内部的なプログラムがフォルダやファイルを開いている可能性は考えられます。よく考えられるのは、セキュリティソフト等ですね。
このようなバックグラウンドで動作しているプログラムを調べるために、リソースモニターを利用して調査することができます。フォルダを使っているプロセスを特定できたら、プロセスを終了してフォルダを移動してあげましょう。

参考リンク：
https://qiita.com/ponponpoko/items/55afecd0281f371d00a4

私のケースでは、explorer.exeが開いていたり開いていなかったりするくらいで、これといった一貫性がなく、さらに困りました。
また、この作業を数十のフォルダに対して行うのはとても骨が折れる......。
そんな中目についたのが、explorer.exeが開いていた`Thumbs.db`というファイルでした。

# 原因はThumbs.dbの更新
私の今回の場合の原因は、Thumbs.dbというファイルがexplorer.exeによって開かれていることでした。
Thumbs.dbはWindowsのエクスプローラ上でファイルのサムネイルを保存するデータベースです。
なんらかの要因でこの生成が不完全になっていると、フォルダを選択した場合にexplorer.exeによるサムネイル生成の処理が走ってしまい、「プログラムによって開かれている」という扱いになってしまうようでした。
リソースモニターで調べた場合にexplorer.exeが開いていたり開いていなかったりしたのは、調べている間にサムネイル生成が終わっている場合・終わっていない場合があり、それにより表示されたりされなかったりしたのだろうと考えられます。


# 対処
対処法としてよく知られているのは、「適当な画像を該当フォルダに一旦保存して`Thumbs.db`を再生成する」というもののようでした。たしかにこの方法で`Thumbs.db`を再生成することにより、フォルダを移動することができました。
また、自分が個人的にうまくいくと思った方法は、フォルダを開いて表示形式をアイコン（大）にすることでサムネイルを強制的に表示させ、`Thumbs.db`を再構成させる方法です。

しかし、私のケースでは数十件のフォルダの移動を試みていたこともあり、上記方法では時間がかかり過ぎてしまいます。

## Thumbs.dbを更新させないようにする
このような場合の解決ですが、Windowsの設定でサムネイルを表示しない設定にすることで、`Thumbs.db`の更新を行わないようにできるようです。
方法は下記の通りです。
### コントロールパネルを開く
お好きな方法でコントロールパネルを開いてください。Windows+Rの検索画面から、controlと入力して開くのが早いと思います。
![スクリーンショット (47).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661623/37b13a65-8b96-30e9-1b54-c193e25e0731.png)


### システムとセキュリティを開く
![スクリーンショット (48).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661623/845c5ecf-5dbc-1eb5-f2a8-6fca80ade9d8.png)

### システムを開く
![スクリーンショット (49).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661623/b79823b2-17ca-ebd2-8ac9-e7cbb5f195d5.png)

### システムの詳細設定を開く
![スクリーンショット (50).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661623/f765f5a7-5b0f-8bde-050e-46df8033271f.png)


### パフォーマンス「設定」を開く
![スクリーンショット (51).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661623/73b83369-4179-6ced-aa1f-6e5e377e8b08.png)


### 設定の「アイコンの代わりに縮小版を表示する」のチェックを外す
![スクリーンショット (52).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661623/15e29451-b828-033d-0cdc-6fd672ae237a.png)

このチェックを外してあげることで、既存のThumbs.dbの更新も行われなくなるようで、エラーなく移動/削除できるようになりました！

# おわりに
今回は、開いていないフォルダが開いていると言われた場合の対処を紹介しました。
必ずしもこれが原因ではありませんが、もし同じ症状で困っている方がいらっしゃいましたら、お役に立てば幸いです！
今回の件では、NAS上のフォルダをマウントして操作しようとした際に問題が発生したので、もしかしたら関係があるかもしれません。

もし同じエラーで困ったら、Thumbs.dbを疑ってみましょう！
【ChatGPT】 VBAでコマンド文生成マクロを実装

vbaで下記を実装したい
①セルの値をもとにコマンド文を生成する
②①で生成したコマンド文をテキストファイルに出力（ダイアログで保存先指定）

```
Sub SaveCommandToFile()
    Dim cellValue As String
    Dim commandText As String
    Dim filePath As String
    Dim fileNum As Integer
    Dim dialog As FileDialog
    
    ' A1セルの値を取得
    cellValue = ThisWorkbook.Sheets(1).Range("A1").Value
    
    ' コマンド文の生成
    commandText = "echo " & cellValue & " > output.txt"
    
    ' 保存先を選択するダイアログを表示
    Set dialog = Application.FileDialog(msoFileDialogSaveAs)
    
    With dialog
        .Title = "保存先を指定してください"
        .FilterIndex = 2
        .DefaultExt = "txt"
        .InitialFileName = "default_command.txt" ' デフォルトのファイル名を設定
        
        ' ダイアログが開かれ、ユーザーが保存先を指定した場合
        If .Show = -1 Then
            filePath = .SelectedItems(1)
            
            ' テキストファイルにコマンド文を出力
            fileNum = FreeFile
            Open filePath For Output As fileNum
            Print #fileNum, commandText
            Close fileNum
            
            MsgBox "コマンド文を保存しました: " & filePath
        Else
            MsgBox "保存がキャンセルされました"
        End If
    End With
End Sub
Puppeteerで16384pxを超える巨大なスクリーンショットを撮影する方法

## 巨大なスクリーンショットの撮影に失敗する問題を解決した
Puppeteerでは縦横いずれかが16384pxを超えるスクリーンショットを撮影できない。
これはChromiumの仕様によるものだ。
高さのあるサイトのスクリーンショットを撮ろうとすると画像の左のように、上部が繰り返されてしまう。
[GitHubにイシューとして報告されており](https://github.com/puppeteer/puppeteer/issues/359)、問題が部分的に放置されたままcloseとなっていた。
そこで画像の右のように、下までちゃんとスクリーンショットが撮影できるようなコードを作成した。


![369992439-7b7e717f-14d2-4c94-969a-f3b637123429.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984288/2465d661-81e7-b2c9-8ddc-7bc6f5a03c30.png)

## 解決策
次に示すコードにある`takeFullPageScreenshot`関数を呼び出し、`page.screenshot`の代わりに使う。
```typescript
// Before
  const defaultScreenshot = await page.screenshot({
    fullPage: true,
  });

// After
  const screenshot = await takeFullPageScreenshot(page); // here!
```

takeFullPageScreenshotはこちら。

https://gist.github.com/matsuyama-k1/34188bfe4483e46b87e2c4a4716b54c3

軽く説明すると、細かく画像を分割してスクリーンショットを撮影し、最後に結合することで、16384pxのリミットを超えないようにしている。

## 使用例
```typescript
import fs from "fs";
import puppeteer from "puppeteer";

import takeFullPageScreenshot from "./index";

const url =
  "https://nextjs.org/docs/app/building-your-application/routing/route-handlers";
const width = 1500;
const deviceScaleFactor = 2;

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  await page.goto(url, { waitUntil: "load" });

  await page.setViewport({
    width: width,
    height: 500,
    deviceScaleFactor,
  });

  await new Promise((resolve) => setTimeout(resolve, 500));

  const screenshot = await takeFullPageScreenshot(page); // here!

  browser.close();
  fs.writeFileSync("./results/screenshot.png", screenshot);
})();
```

## 残りの問題
sharpというjavascriptの画像編集ライブラリを用いている。sharpに画像サイズのハードリミットが設定されているようで、これを超えると失敗する。
そうそう超えることはないだろうが、`deviceScaleFactor`を大きくするとリミットを超えて失敗することある。
基本情報技術者に向けて　Part.5

## サブネットマスク
事業部ごとにネットワークを分けるときに用いられる分割したネットワークのこと

## CIDR（Classless Inter-Domain Routing）
ネットワークを分割したり、ホストのアドレス数を増やして不空数のネットワークを集約するなど柔軟な構成ができる表記法

## IPv6(Internet Protocol Version 6)
IPV4の後継
IPv4では32ビットの数値によってIPアドレスを割りあてて、約43億個用意できる
IPv6では128ビットの数値によってIPアドレスを割り当てることで約340澗個となる

## DHCO(Dynamic Configuration Protocol)
ネットワークの設定作業を自動化することができるプロトコル

## NAT
グローバルIPアドレスとプライベートIPアドレスとを一対一で結び付けて、相互に変換を行う
同時にインターネット接続できるのは、グローバルIPアドレスの個数分だけとなる

## IPマスカレード(NAPT)
グローバルIPアドレスに複数のプライベートIPアドレスを結びつけて、一対複数の返還を行う
IPアドレスの返還時にポート番号も併せて書き換えるようにすることで、１つのグローバルIPアドレスでも複数のコンピュータが同時にインターネット接続をすることができる

## ドメイン名とDNS
IPアドレスに対して、文字で別名をつけたものがドメイン
ドメイン名とIPアドレスを関連付けして管理しているのがDNS（Domain Name System）
[IP Adress] IPアドレスクラス

# IPアドレスクラス
|クラス|先頭アドレス|ホストアドレス|
|:--|:--|:--|
|A|0|24|
|B|10|16|
|C|110|8|
|D|1110|0(マルチキャストアドレス)|



# 参考リンク
- [平成28秋33](https://www.ap-siken.com/kakomon/28_aki/q33.html)
CH32V003をいじり始めていきなり罠にハマった件

WCH-LinkEを使おうと思ってドライバをインストールしたのに
「不明なデバイス」になってしまった。
壊れたかと思ったけど何とかなった(っぽい) という記事です。

まず購入してすぐのときは正しく認識されていたと思います。
複合デバイス(composite device)になっていて、
シリアル(COM)ポートのドライバは勝手にインストールされて、
WCH-LinkEのドライバがあたっていない状態でした。 

MounRiverのインストールドライブの中に適合するぽいドライバがあったので
それをインストールしました。
それで通信してみようと思ったところMounRiverがWCH-LinkEを認識していないようなエラーが。
で、WCH-LinkEを抜き差ししたりしていたところ、「不明なデバイス」になっていることに気付きました。 


壊れたかと思ったのですが、VID_4348&PID_55E0というハードウェアIDは見えている状態。
ということは、何か突然別のデバイスとして認識されるようになってしまったという謎の状況…。 

Redditで似たような現象に苦しむ人を発見。
"WCH Link Utility"というツールを使えば治るっぽい。

https://www.reddit.com/r/embedded/comments/1bnil0t/pissed_about_wch_linke_not_working/?rdt=37343


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469946/bd4e93a0-9faf-620c-32e7-515560379b8d.png)

やってみた。
確かに、WCH-LinkEだったのがWCH-LinkRVになったけど認識されるようにはなりました。
この状態で使えることを確認できました。一安心ではあるけど、何なんでしょうこれ…。

ちなみにハードウェアIDはVID_1A86&PID_8010になってました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469946/a312ab72-6c2c-5492-b22a-8cae2ced3219.png)
投稿 95 README 2024/10/03

本日の勉強時間　3H

GitHubのREADMEは、リポジトリの概要や使い方、プロジェクトに関する重要な情報を説明するためのファイルです。通常、`README.md`という名前でMarkdown形式で書かれ、リポジトリのトップページに表示されます。READMEには以下のような情報が含まれます。

- プロジェクトの目的や概要
- セットアップ方法
- 使用方法
- 必要な依存関係やインストール手順
- 貢献ガイドラインやライセンス情報

READMEは、他の開発者やユーザーにプロジェクトを理解してもらうための重要なドキュメントです。
KDE Plasma (Wayland) でミドルクリックでのペーストを無効化

Wayland環境にで、ミドルクリックによるペーストを無効化するのに苦戦したので共有

# 環境
- Arch Linux
- KDE Plasma 6.1.5 (Wayland)

# 解決策

### ネイティブWaylandアプリケーションの場合

1. KDEのシステム設定を開く
2. 「ワークスペース」→「全般的な挙動」を選択
3. 「中クリック: 選択したテキストを貼り付ける」のチェックを外す
4. システムを再起動

### Xwaylandアプリケーションの場合
（例: Discordなど）

1\. [XMousePasteBlock](https://github.com/milaq/XMousePasteBlock)をインストール

```bash
$ yay -S XMousePasteBlock
```
xmousepasteblockの方だとビルドに失敗したので、
xmousepasteblock-gitを選んだほうがいいかもしれない。

2\. systemdにサービスを登録する

`/etc/systemd/system`に`mousepasteblock.service`を作成

```ini:mousepasteblock.service
[Unit]
Description=Userspace tool to disable middle mouse button paste in Xorg.

[Service]
ExecStart=/usr/bin/xmousepasteblock

[Install]
WantedBy=multi-user.target
```

3\. システムを再起動

### Firefoxの場合
`about:config`で`middlemouse.paste`を`false`に設定。

# おまけ
ミドルクリックでスクロールできるようにする方法。

### Firefoxの場合
Firefoxの設定を開き「スクロール」で検索し、
「自動スクロール機能を使用する」を有効化。

### Electronソフトウェアの場合
起動する際の引数に``--enable-blink-features=MiddleClickAutoscroll``を追加する。
Zabbix 4.0 連続して発生する同一メッセージ通報を集約する

# 設定方法

対象ファイル：`var/log/messages`
対象メッセージ：`continue`
対象アイテム：`logrt[/var/log/^messages$,continue,,,skip,,,]`

```bash:trigger
{server001:logrt[/var/log/^messages$,continue,,,skip,,,].regexp(.*)}=1
and
{server001:logrt[/var/log/^messages$,continue,,,skip,,,].nodata(120)}=0
```

設定 | 内容
--- | ---
正常イベントの生成 | 条件式
障害イベント生成モード | 単一
正常時のイベントクローズ | すべての障害

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/7c92def5-5183-b39f-10e1-f23c2c7e0fe6.png)






# 解説
triggerについて、`.regexp(.*)}=1`と`.nodata(120)}=0`をAND条件で結合しています。

`.regexp(.*)}=1`について、`regexp(.*)`自体は「何らかの文字列が存在する場合は1、そうでない場合は0」となるため、`=1`を評価する場合は「何らかの文字列が存在する場合」に式全体でTRUEになります。

`.nodata(120)}=0`について、`.nodata(120)`自体は「120秒内にデータがなければ1、あれば0」となるため、`=0`を評価する場合は「120秒内にデータがある場合」に式全体でTRUEになります。

そのため、同一メッセージが指定時間内に連続して発砲された場合、以下のようになります。

メッセージ出力 | 評価① | 評価② | 結果(論理和) | トリガー
--- | --- | --- | --- | ---
発生前 | 該当文字列を検知していない(FALSE) | 120秒内にデータがない(FALSE) | FALSE | 正常
初報 | 該当文字列を検知した(TRUE) | 120秒内にデータがある(TRUE) | TRUE | 発報
続報(120秒以内) | 該当文字列を検知した(TRUE) | 120秒内にデータがある(TRUE) | TRUE | 継続
終報(120秒以内) | 該当文字列を検知した(TRUE) | 120秒内にデータがある(TRUE) | TRUE | 継続
収束(120秒後) | 該当文字列を検知した(TRUE) | 120秒内にデータがない(FALSE) | FALSE | 復旧



# 確認

### 単発発報

```text:/var/log/message
Oct  3 22:40:41 cent76-zc4 root[1714]: test_message_continue
```

■初報
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/ecffc374-d305-a0a7-5aac-ac9a40359e60.png)

■終報
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/fb2e505c-14e8-c6a6-1d1d-19ce7dec17d5.png)
→メッセージ発生から2分後に収束(”継続時間”を参照)


### 連続発報

```text:/var/log/message
Oct  3 22:47:01 cent76-zc4 systemd: Started Session 29 of user root.
Oct  3 22:47:01 cent76-zc4 root[1720]: test_message_continue
Oct  3 22:48:01 cent76-zc4 systemd: Started Session 30 of user root.
Oct  3 22:48:01 cent76-zc4 root[1723]: test_message_continue
Oct  3 22:49:01 cent76-zc4 systemd: Started Session 31 of user root.
Oct  3 22:49:01 cent76-zc4 root[1726]: test_message_continue
Oct  3 22:50:01 cent76-zc4 systemd: Started Session 32 of user root.
Oct  3 22:50:01 cent76-zc4 root[1731]: test_message_continue
```
※crontabにて1分おきに連打

■初報
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/e0e130d7-b2b3-538f-849c-f6d117bfe660.png)


■中間報
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/4aff0e06-7da4-ee59-08a4-82c80cac6aca.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/3d290d79-e550-4e8c-5051-44f1f9376d05.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/162769d3-3c54-88c2-8345-a7ebb17dd9d5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/215cd848-d81e-35be-6154-22d091eadf9b.png)


■終報
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/f3442004-a140-70f0-07f6-64d15bab1e8f.png)
→最後のメッセージ発生(22:50)から2分後(22:52)に収束(”継続時間”を参照)


# 参考
https://www.zabbix.com/documentation/4.0/en/manual/appendix/triggers/functions
【はじプロ】オイラー法

# はじめに
Switch向けに「ナビつき！ つくってわかる はじめてゲームプログラミング」（任天堂）という面白いソフトがある。はじプロと略されることもある。
ブロックをつなげるようにして簡単にゲームを作ることが出来るソフトだ。
購入して随分立つのだが、チュートリアルを中途半端に進めたまま放置していたので、オイラー法くらい作ってみるか、ということで作ってみた。

# オイラー法
オイラー法とは、微分方程式の初歩的な数値解法だ。今回解くのは、
$$
\frac{df}{dx} = -f
$$
である。解析解は簡単に求まるが、数値的に解いてみる。
単純に離散化してやると、
$$
\frac{f(x+\Delta x) - f(x)}{\Delta x} = -f(x)
$$
と書ける。これから、
$$
f(x+\Delta x) = f(x) - f(x)\Delta x
$$
となる。漸化式で書くと、
$$
f_{k+1} = f_k - f_k\Delta x
$$
と書ける。これをどんどん計算してやればよい。
精度はよくないので、注意。

# C++による実装
はじプロは残念ながら小数点以下2桁しか精度がないので、$\Delta x=0.01$とする。
正解の目安が欲しいので、
```cpp
#include <iostream>

int main()
{
	double f = 10;
	double dx = 0.01;

	for (int i = 0; i < 20; i++)
	{
		std::cout << f << std::endl;
		f = f - f * dx;
	}
	return 0;
}
```
実行すると、
```
10
9.9
9.801
9.70299
9.60596
9.5099
9.4148
9.32065
9.22745
9.13517
```
のような感じ。

# はじプロでの実装
ボタンを押す度に計算を進めることにした。ボタンを押しっぱなしにするとものすごい勢いで計算が進んでしまうので、タイマーを使って遅延させて、ゆっくり計算することにする。
値の保持に手間取ったのだが、カウンターを使えばいい。カウンターに初期値を設定して、ボタンを押す度にカウンターの値$\times \Delta x$を引けばいい。
下のような感じになる。
![2024100221475200_s.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/8e9f0991-be0d-541d-a260-4b86a76e98b9.jpeg)

実行すると次のような感じ。

<iframe width="560" height="315" src="https://www.youtube.com/embed/Nl8leiMIKcs?si=Uov-c0T5MO2-dz1Q" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

# 終わりに
楽しかった。
【備忘録】Vimeoの埋込動画をダウンロードする方法

## 結論

:::note alert
著作権で保護されたデータを不正に利用しないでください
:::

```
yt-dlp "Vimeoのリンク" --referer "埋込先のリンク" --cookies-from-browser firefox
```

ブラウザは[FireFox](https://www.mozilla.org/firefox/download/thanks/)を用いる。[^1]

[^1]: ChromeではCookieを取得することができない

### Vimeoのリンク

埋込元であるVimeoのリンクを探してくる。HTMLの要素を辿るか、FireFoxであれば`フレームを新しいタブで開く`から取得できる。

### 埋込先のリンク

Vimeoが埋め込まれている、元のサイトのリンクを取得する。

## 参考

https://github.com/yt-dlp/yt-dlp/issues/6382
Qiita Hackathon 2024で学んだプレゼン重視のハッカソン戦略

# はじめに
初めまして！チームflierの「やな」です！
2日間に渡って開催されるオンラインハッカソンQiita Hackathon2024の予選に参加し、見事予選突破しました！
今回は、予選突破の鍵となった2つのポイントをご紹介します！
1. プレゼン重視の考え方
1. アイデア出しのやり方

# プレゼン重視の考え方
今回のハッカソンには約80チームが参加し、各チーム3分という短い時間でプレゼンを行いました。そのため、私たちは印象に残るプレゼンを最優先しました。
私たちのアプローチ：
1. アイデア出し
2. プレゼンの大枠準備
3. 開発
4. プレゼンの改善
このやり方で、プレゼンの内容とデモを先に決めてから開発に取り組みました。

私たちがデモで必要な機能は二つです。
・Zoom内にbotを登場させる。
・botに話をさせる

早速取り掛かります。開発を始めて4時間、Zoom APIと格闘して全く成果の出ない時間が続きました。
休憩も取らず開発夢中で、苦戦しつつもできないとは言いたくありませんでした。

しかしメンバーからの「プロトタイプに注力しよう」という一言。この助言で、私達は一気に方向転換しました。
・Zoom APIの使用を断念
・Agoraを使用し、ビデオ会議システムも一緒に開発
この方向転換が功を奏しました。限られた時間内で会議システムの開発に成功し、プレゼンの練習時間も確保できました。結果、本番のプレゼンでは制限時間内に内容をしっかり伝えられました。

最初に決めたことに捉われず、状況に応じて柔軟に変えていく重要性を学びました。プレゼン重視の姿勢で、完璧を求め過ぎないことがハッカソン成功の鍵だったと思います。

# アイデア出しは紙とペンで
大きな模造紙とペンと付箋を使ってアイデア出しに挑みました。以下、アイデア出しの流れです。
1. テーマに関するものを個人がとにかくたくさん書き出す
1. 近いものを寄せつつ、話し合いながらアイデアあれば追加していく
1. 課題になりそうなものを複数ピックアップ
1. 話し合いながら最終絞り込み

今回のテーマは「オープン」という抽象度の高いものでした。
最初は戸惑いながらも、「オープン」に関するものを書き出してみると沢山でてきて白熱した議論になりました。
個人で考える時間を作ったこと、あえてアナログな道具を使ったことでリラックスしてアイデア出しに集中できたと思います。

アイデア達🐧
![アイデアだし.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575975/6699fa80-bea9-359f-38fc-6f3e47162915.jpeg)


# 最後に
今回ハッカソンを通してアイデアを実現してプロダクトを作る難しさを体感しました。
上記の他にも、今回のイベントがあって初めてZoomAPIやAgoraに触ったり、事前準備として色々なiPhoneの機能を使えるよう勉強するなど技術的にも学ぶことが多かったです。
ここまで読んで頂きありがとうございました！

こちらに発表資料を置いてますのでぜひ見てください！
[![thumbnail](https://files.speakerdeck.com/presentations/73ce7c581bab45b5acb4b4b5627eb0d3/slide_0.jpg?31830639)](https://speakerdeck.com/dyson_web/huasutopenginbot-at-qiita-hackathon-2024-yu-xuan)

今回のハッカソンをダイジェストで動画にまとめているのでこちらもぜひ！
<iframe width="560" height="315" src="https://www.youtube.com/embed/7g5ttxkrCiU?si=UP64tlwFmb8vVY-M" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
AWS SAPの勉強方法

## はじめに
AWS SAPの資格の勉強方法をまとめました！(まとめたというほどでもないですが、、、)
ちなみに筆者はawsの実務経験が一年ほどある程度です。

## やってること
- 無料WEB問題集
- udemy
- 現場で触る

## 無料WEB問題集
受験申し込みをする前に、まずこれをやってみることをお勧めします！
100問まで無料で解けるので、自分の現状を把握しやすいです。(ちなみに合格ラインは75%ぐらいです)
これを解いて、全然解けないって感じた方は、SAAの方から始めるのもありだと思います。

https://aws-exam.net/sap/

## Udemy
ほぼメインはこれです！
模擬問題が410問収録されています。
ある程度知識がある方はインプットの学習を飛ばしちゃって、いきなり問題演習を積むことが一番近道だと思います。そこで解けなかった問題を復習していくのが良そうです。
実際のテストで同じ問題が出ることも結構あるみたいです。

https://www.udemy.com/course/sap-c02aws-2024/

※Udemyは結構な頻度でセールしているのでそのタイミングで買うことをお勧めします！
(普段の値段が学生からするとヤクザみたい値段なので気を付けてください(笑))

## 現場で触る
まあ、当たり前ですが、やっぱ現場で触るとそのサービスに対して、かなり詳しくなれるので最強です！！！(とはいえ、なかなか現場でどのサービスを扱うかはなかなかコントロールできるものではないですよね、、、)

## 勉強していて感じたこと
- 現場では聞いたこともないサービスも結構出てくるので、一から勉強が必要なサービスも結構ある。
    - 出てくるサービスを元から全部知ってる方は、逆に資格取る意味がない気がします笑。。。
- SAAに比べて、問題文が長く、内容も複雑なので、問題演習は必須。
    - 言い回しがいつものawsの公式ドキュメント並にわかりづらいです笑

##
また、受験した後の所感も書きたいと思ってます！
最後まで読んで下さり、ありがとうございます。
install gphys on RockyLinux 8.8

# TL;DR

* install gphys（電脳地球ライブラリ）
* use gcc & gfortran
* use DCL-7.5.1（電脳地球ライブラリ）
* rocky linux 8.8

# url

https://www.gfd-dennou.org/library/ruby/products/gphys/

# prepare

## install DCL-7.5.1

https://qiita.com/it__ssei/items/fcc54a39183aa15e8c4e

## install ruby

```
ruby -v
# ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [x86_64-linux]
```

https://qiita.com/it__ssei/items/343c133c76af3a6d9fe3

## install rake-compiler

require for gem build

```
gem install rake-compiler
```

https://qiita.com/ongaeshi/items/39ef9d7c4e6db6d1f461

# gphys

## get

```
git clone http://dennou-k.gfd-dennou.org/arch/ruby/products/gphys/git_repos/gphys.git
```

https://ruby.gfd-dennou.org/products/gphys/develop/git_repo_howto.htm

## rake build

```
cd gphys

touch ChangeLog
rake build --trace
```

## install

```
cd pkg
gem install gphys-1.5.7.alpha.gem
```
【SwiftUI】inspectorで半画面モーダルを表示する



## まえがき
この記事はSwift独学者による備忘録です。
万が一誤った記載がある場合は、コメントでご指摘いただけると幸いですm(_ _)m

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

## Swiftにおける画面遷移について
Swiftの画面遷移には代表的なものが２つあり、そのうちの1つがモーダル遷移(表示)と呼ばれる遷移方法です。
モーダル遷移では基本的に下から画面がスワイプアップで表示されます。

いくつか方法はあるのですが、この記事ではinspectorのモディファイアを使用した半画面のモーダル表示例を簡単にまとめます。

sheetで表示する全画面モーダルについては[こちらの記事](https://qiita.com/komkom2/items/da710d5c7e4c8917f5f2)に概要をまとめています。

もう一つはプッシュ遷移と呼ばれるNavigationLinkを用いた遷移方法で、画面が右から左に切り替わります。
プッシュ遷移については[こちらの記事](https://qiita.com/komkom2/items/0bf992f6dc20e2408a1c)に簡単に概要をまとめています。

## コード例

```Swift:ContentView.swift
import SwiftUI

struct ContentView: View {
    @State private var isPresented = false
    
    var body: some View {
        ZStack {
            isPresented ? Color(red: 0.4, green: 0.4, blue: 0.4, opacity: 0.6) : Color.white
            VStack {
                Text("メイン画面です")
                    .font(.title)
                    .fontWeight(.bold)
                Button("モーダルを表示") {
                    isPresented = true
                }
                .padding()
                .background(Color.orange)
                .foregroundColor(.white)
                .cornerRadius(10)
            }
            .inspector(isPresented: $isPresented) {
                InspectorView(dismissAction: {
                    isPresented = false
                })
            }
        }
    }
}

struct InspectorView: View {
    var dismissAction: () -> Void
    
    var body: some View {
        VStack {
            Text("モーダル画面です")
                .font(.title)
                .fontWeight(.bold)
            Button("モーダルを閉じる") {
                dismissAction()
            }
            .padding()
            .background(Color.gray)
            .foregroundColor(.white)
            .cornerRadius(10)
        }
    }
}
```

画面表示は以下のようになります。

※グレーアウトさせている背景をタップしてもモーダルは閉じません。
タップで閉じることができるコードがあるのか、また時間があるときに調べてみようと思います！
| メイン画面 | モーダル画面 |
| ---- | ---- |
| <img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3805527/c8f1d814-5e44-be0c-ed52-fcb0a70f1d0f.png"> |<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3805527/5290fa28-6d85-783e-ce9d-50a25c3882cf.png"> |

## あとがき
簡単にinspectorで半画面モーダルを表示する例をまとめました。
今後も捕捉事項があれば随時更新していきます。
AzureでのToDoMVCフルスタックアプリ開発手順

Azure Static WebApps、Azure Functions、Node.js、Vue.js、Azure SQL、GitHub Actionsを用いて、ToDoMVCフルスタックアプリを開発する手順を紹介します。

## 概要

このアプリケーションは、フロントエンドにVue.jsを使用し、バックエンドにはAzure FunctionsとNode.js、データベースにはAzure SQLを使用しています。また、GitHub Actionsを使用して自動デプロイを実現します。

### 使用する技術
- **Azure Static WebApps**: WebアプリとAPIを一つにまとめて、GitHub CI/CDパイプラインで自動デプロイ
- **Vue.js**: フロントエンドクライアント
- **Azure Functions**: サーバーレスなバックエンドインフラ
- **Node.js**: バックエンドのロジック
- **Azure SQL**: ToDoデータの保存用データベース
- **GitHub Actions**: フルスタックWebサイトの自動デプロイ

## 手順

### 1. リポジトリのクローン
まず、GitHubリポジトリをクローンします。

```bash
git clone https://github.com/azure-samples/azure-sql-db-todo-mvc.git
cd azure-sql-db-todo-mvc
```

### 2. データベースのセットアップ
Azure SQLまたはローカルのSQLサーバーを使って、データベースをセットアップします。以下のコマンドでAzure SQLデータベースを作成できます。

```bash
az sql db create -g <resource-group> -s <server-name> -n todo_app --service-objective S0
```

次に、`/database/create.sql` スクリプトを実行して、データベース内に必要なテーブルやストアドプロシージャを作成します。

### 3. フロントエンドのセットアップ
`/client` フォルダに移動し、Vue.jsクライアントのセットアップを行います。

```bash
cd client
npm install
```

### 4. APIのセットアップ
`/api` フォルダに移動し、Azure Functionをセットアップします。

```bash
cd ../api
npm install
```

`.env.template` ファイルを元に、`.env` ファイルを作成し、Azure SQLへの接続情報を記入します。

```env
SQL_SERVER=<your-sql-server>
SQL_DATABASE=<your-database-name>
SQL_USER=<your-sql-username>
SQL_PASSWORD=<your-sql-password>
```

### 5. ローカル環境での実行
ローカル環境でAzure Static WebApps CLIを使用して、アプリを実行します。

```bash
npm install -g @azure/static-web-apps-cli
swa start --api ./api
```

ブラウザで `http://localhost:4280` にアクセスして、アプリケーションが正しく動作しているか確認します。

### 6. Azureへのデプロイ
GitHub Actionsを使用してAzureにデプロイします。最初に、リポジトリをフォークします。

1. GitHubリポジトリをフォークします。
2. GitHubトークンを取得します。
3. `azure-deploy.sh` スクリプトを実行します。

```bash
./azure-deploy.sh
```

スクリプトを実行すると、初回は `.env` ファイルが作成されるので、必要な情報を記入して再度実行します。

```bash
./azure-deploy.sh
```

デプロイが完了したら、Azureポータルにアクセスし、Azure Static Web Appの設定でデータベース接続文字列を追加します。

### 7. アプリの確認
Azureポータルでデプロイされたアプリケーションを確認し、正しく動作しているかを確認します。

## 終わりに
このガイドでは、AzureのStatic WebApps、Functions、SQLを使用して、ToDoMVCフルスタックアプリをセットアップおよびデプロイする手順を説明しました。サーバーレスアーキテクチャを活用することで、効率的なアプリケーション開発が可能です。

詳細な情報は、公式のドキュメントも参照してください。

- [Azure Static Web Apps](https://learn.microsoft.com/azure/static-web-apps/)
- [Azure Functions](https://learn.microsoft.com/azure/azure-functions/)
- [Azure SQL](https://learn.microsoft.com/azure/azure-sql/)
(Node.js) morganモジュールを理解する

# はじめに
node.jsのコードの中でmorganモジュールを使用する機会があったので、どのようなモジュールであるのか簡単にまとめたいと思います。

# morganモジュールとは
Node.jsアプリケーションで使用されるHTTPリクエスト（レスポンスではなく！）のロギングミドルウェアです。ExpressなどのWebフレームワークと組み合わせて使うことが一般的で、アプリケーションに送られてくるリクエスト情報（メソッド、ステータスコード、URL、レスポンスタイム（厳密にはリクエストに対するサーバーの応答時間を指すがこの情報も含む事ができる）など）を簡単にログとして記録することができます。

## 主な特徴
・HTTPリクエストのログ
サーバーに送られるすべてのHTTPリクエストをログに残します。リクエストの情報を記録することで、アプリケーションの動作確認やデバッグに役立ちます。

・プリセットのログフォーマット 
Morganは、combined、common、dev、short、tinyといったプリセットフォーマットが用意されており、すぐに使用できます。

・カスタムフォーマット
必要に応じて、カスタムログフォーマットを設定することも可能です。

# 使用方法
基本的には、
```
morgan(format, options)
```
という形で記載します。

### format
リクエストのログフォーマットを簡単に設定できるPredefined Formats（事前定義されたフォーマット）が用意されています。tiny、 devなどです。それぞれの特徴は、以下です。

tiny: 最もシンプルなフォーマット
HTTPメソッド、URL、HTTPステータスコード、レスポンスサイズ、レスポンスタイム
例：![スクリーンショット 2024-10-02 13.56.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3684675/4e8a6914-1e6d-f1b5-5fa5-94eeedb3c667.png)


dev: 開発中に使うためのフォーマットで、カラーリングされたシンプルなログ出力
HTTPメソッド、URL、HTTPステータスコード、レスポンスタイム、レスポンスサイズ
例：![スクリーンショット 2024-10-02 13.58.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3684675/97eb6402-7448-ccde-60a5-7c9857d07d95.png)


### options
オプションではstreamというものがあり、ログにストリームをアウトプットします。出力先はデフォルトでは、process.stdoutです。今回のサンプルコードの書き方がストリームとして本当に正しいのかは分かりませんが、動きはしました。

# サンプルコード
```javascript:morgan.js
const express = require('express');
const morgan = require('morgan');
const app = express();

const loggerStream = {
  write: message => console.log(`From loggerStream: ${message}`),
};

app.use(morgan('tiny', { stream: loggerStream }));

app.get('/', (req, res) => {
  res.status(200).send('Hello from the server side!');
});

app.listen(3000, () => {
  console.log(`App running on port 3000...`);
});
```

## コードの解説
```javascript
const loggerStream = {
  write: message => console.log(`From loggerStream: ${message}`),
};
```
writeメソッドを定義し、morganが生成するログを受け取って、カスタムメッセージを加えつつconsole.logで出力します。messageは、morganから渡されるログメッセージを表示します。

```javascript
app.use(morgan('tiny', { stream: loggerStream }));
```
morganのログ出力先を標準出力ではなく、カスタムで定義したloggerStreamに変更します。

```javascript
app.get('/', (req, res) => {
  res.status(200).send('Hello from the server side!');
});
```
GETリクエストが/（ルートパス）に送られたときに実行される関数を定義しています。クライアントにステータスコード200で「Hello from the server side!」というメッセージをレスポンスとして送ります。この記述はmorganモジュールとは関係ありません。


```javascript
app.listen(3000, () => {
  console.log(`App running on port 3000...`);
});
```
サーバーをポート3000で起動し、アクセス可能な状態にします。ポート3000がサーバーの接続口です。コールバック関数でサーバーが起動したことを示すメッセージ「App running on port 3000…」がコンソールに出力されます。

# 実行結果

![スクリーンショット 2024-10-02 14.24.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3684675/843196c8-3ee1-56d3-0f30-5752c14832a2.png)

node morgan.jsを実行した際に、「App running on port 3000...」が出力されます。
その後、「http\://127.0.0.1:3000/」にアクセス（リクエストを送る）した際に、「From loggerStream: GET / 200 27 - 2.455 ms」が表示されます。

# まとめ
node.jsのmorganモジュールの使用方法についてまとめました。

# Reference

https://www.npmjs.com/package/morgan

https://qiita.com/k96mz/items/668bee0c6d751a444b5c
SSH-Agentってなんだ？（初心者向け）

# この記事の内容
毎回SSHコマンドを打つのがめんどくさいなと思い、楽になる方法がないかと調べているとあったので紹介します。

`ssh-agent` と `ssh-add` は、SSH（Secure Shell）を使用する際に認証キーを管理・利用するためのツールです。これらを活用することで、SSH接続時に毎回パスフレーズを入力する手間を省くことができます！

## `ssh-agent` と `ssh-add` の概要

### `ssh-agent`

- **役割**: `ssh-agent` はSSH認証エージェントで、SSHキー（秘密鍵）のパスフレーズを一度入力するだけで、その後のSSH接続で再度パスフレーズを入力する必要がなくなります。これにより、複数のSSH接続を行う際の利便性が向上します。
- **使用方法**: `ssh-agent` を起動すると、エージェントがバックグラウンドで動作し、環境変数（例: `SSH_AUTH_SOCK`）を設定します。これにより、SSHクライアントがエージェントにアクセスできるようになります。

### `ssh-add`

- **役割**: `ssh-add` は、SSHエージェントにSSH秘密鍵を追加するためのコマンドです。エージェントが秘密鍵を管理し、SSH接続時に自動的に認証を行います。
- **主な機能**:
  - **キーの追加**: `ssh-add /path/to/private_key` で指定した秘密鍵をエージェントに追加します。
  - **パスフレーズの入力**: 秘密鍵がパスフレーズで保護されている場合、追加時にパスフレーズの入力が求められます。
  - **キーの一覧表示**: `ssh-add -l` でエージェントに追加されている鍵の一覧を表示します。
  - **キーの削除**: `ssh-add -d /path/to/private_key` で特定の鍵を削除、`ssh-add -D` で全ての鍵を削除できます。

## SSHエージェントの起動とSSH接続の実行方法

### エージェントの起動方法

1. **現在のシェルでエージェントを起動する**:

   ```bash
   eval "$(ssh-agent -s)"
   ```

   このコマンドを実行すると、SSHエージェントがバックグラウンドで起動し、必要な環境変数が現在のシェルに設定されます。

2. **新しいシェルでエージェントを起動する方法**:

   ```bash
   ssh-agent bash
   ```

   これにより、新しい `bash` シェルが `ssh-agent` とともに起動します。このシェル内でのみエージェントが有効になります。

### 秘密鍵のエージェントへの追加

```bash
ssh-add ~/.ssh/id_rsa
```

ここで、`~/.ssh/id_rsa` は秘密鍵のパスです。パスフレーズが設定されている場合、この段階で入力を求められます。

### SSH接続の実行

エージェントに鍵を追加した後、通常通りSSHコマンドを使用して接続できます。

```bash
ssh ユーザー名@リモートホスト
```

パスフレーズの再入力なしで接続が可能です。SSHクライアントは自動的にエージェントを介して認証を行います。

## 具体例

```bash
# 1. SSHエージェントを現在のシェルで起動
eval "$(ssh-agent -s)"

# 2. 秘密鍵をエージェントに追加
ssh-add ~/.ssh/id_rsa

# 3. SSH接続を実行
ssh user@remote_host
```

## まとめ

- **`ssh-agent`** は、秘密鍵のパスフレーズ入力を一度で済ませるためのエージェントです。
- **`ssh-add`** は、秘密鍵をエージェントに追加・管理するためのコマンドです。
- **SSH接続手順**:
  1. `ssh-agent` を起動する。
  2. `ssh-add` で秘密鍵をエージェントに追加する。
  3. 通常のSSHコマンドで接続する。

これらの手順を実行することで、SSH接続時の認証がスムーズになり、作業効率が向上します。
【Servicenow】Washington DCリリース「カタログアイテムの入力内容を下書きとして保存する」

# はじめに
みなさんこんにちは、三井情報株式会社です。
Washington DCバージョンにて追加された、カタログアイテムの新機能「カタログアイテムの入力内容を下書きとして保存する」を紹介します。

# 概要
ServiceNowではカタログアイテムを用いて申請の仕組みを作成することができ、フローと合わせることで申請の承認を行うこともできます。Washington DCバージョンではカタログアイテムの新機能として、申請画面で入力した内容を下書きとして保存することができるようになりました。

# 事前準備
カタログアイテムを1つ用意し、用意したカタログアイテム内の「Portal Settings＞Hide 'Save as Draft'」のチェックが外れていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599899/48f87f6a-0b5f-a929-ca61-945ae064ce47.png)


# 下書きの保存
ポータルを開いてカタログアイテムの申請画面を開き、フォームを埋めます。
フォームに記入したら「Save as Draft」を押下して下書きを保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599899/41ae06eb-ceca-cc3d-4b0e-20afdd8e5093.png)


一度下書きを保存した後は「Update Draft」を押下することで上書き保存できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599899/e6a1ec76-5d8c-6431-af21-6f78bc894f4e.png)


書いた下書きは、Requestsページの「My Requests＞Drafts」から確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599899/c1283b77-0733-c5ad-cb24-eeb978a4e64e.png)

名称は「カタログアイテム名 draft」となっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599899/f2ecee24-2db0-8684-ad58-35b12633303a.png)


押下することで、下書きがフォームに入った状態のカタログアイテム画面上に画面遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599899/c3522c2d-e2a1-3799-47a2-c05c700405b0.png)


# 「Save as Draft」を非表示にした場合
カタログアイテム側の設定で「Save as Draft」のチェックを入れて保存した場合、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599899/d690dfc2-49fe-adf9-6606-fb79705938e6.png)

申請画面から「Save as Draft」ボタンが非表示となるため、新規で下書きを作成することはできませんが、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599899/c1bbd917-b12b-ac51-0dea-cd8ceca1ae35.png)

既に保存している下書きは、Requestsページの「My Requests＞Drafts」から確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599899/aa8ef399-cabf-9e7c-ea01-9781079d1051.png)


# 下書きの保存先
下書きは「sc_cart_item」テーブルに保存されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599899/806417d0-db15-5b6d-fece-511726bafdf4.png)

このテーブルでは「snc_internal」ロールがあればCreate,Read,Writeが可能です。
Deleteについては「catalog_admin」ロールがあれば可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599899/84468801-3e99-2a35-fc9c-889792204574.png)


# おわりに
今回は「カタログアイテムの入力内容を下書きとして保存する」についてご紹介しました。
最後まで読んでいただき、ありがとうございました。
SOLID原則メモ

SOLID原則
・単一責任の原則
・オープンクローズドの原則
・リスコフの置換原則
・インターフェイス分離の原則
・依存関係逆転の原則

## 単一責任の原則

#### どんな原則
クラスを変更する理由はひとつであるべきという原則。
あれもこれも一つのクラスに詰め込んではいけない。
ひとつのクラスが責任を持ちすぎると、何か変更した時に思わぬ不具合を生む。
責任を持たせ過ぎてしまった場合は、関数を別のクラスに移動して凝集度を高めるようにする。
##### 参考にしたい
https://qiita.com/MinoDriven/items/76307b1b066467cbfd6a

## オープンクローズドの原則

#### どんな原則
拡張に対しては開いていて、修正に対しては閉じていなければいけないという原則。
新たな機能を追加するとき、既存のコードを変更せずに拡張できるようにするべき。
既存のコード変更が必要になると多くのことを考慮しなければならず、工数増加や不具合につながる。
単一責任になるようクラスを適切に分割し、依存の向きをコントロールすることで上位レベルのコンポーネントが下位レベルの変更影響を受けないようにするのがポイント。

## リスコフの置換原則

#### どんな原則
親クラスのインスタンスを使う代わりに、その子クラスのインスタンスを使っても、プログラムの動作が変わらないようにすべきという原則。
子クラスの都合で親クラスを変更するようなことがあってはならない。

## インターフェイス分離の原則

#### どんな原則
インターフェイスを分離し、必要なモジュールだけに依存するようにするべきという原則。
クライアントは自分が使わないメソッドにまで依存するべきではない。
インターフェイスを小さく設計することで、依存を減らし、コードの保守性や再利用性を高めることができる。

## 依存関係逆転の原則

#### どんな原則
具体的な実装ではなく、抽象に依存すべきという原則。
具象ではなく安定した抽象インターフェイスを参照させることで、新しい機能を追加するときも既存のコードに修正を加えるときも上位レベルには影響を与えずに済む。
Next.jsのアプリをPrismaを使ってMySQLと連携させる方法

![MextJsトップ画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1169664/c622a66e-cbd5-b24c-7bc6-d7d741e1477e.png)

今回は、タイトルにあるようにNext.jsとMySQL(またはMariaDB)とを連携させる方法について備忘録チックに紹介します。

SQLiteの記事はよく見かけますが、MySQLに関する情報はあまりないので、参考になったらうれしいです。

# Prismaのインストール

プロジェクトの配下まで移動して、下記のコマンドを入力する。

```
npm install prisma --save-dev
```

# MySQLのプロバイダーをインストール

プロジェクトの配下まで移動して、下記のコマンドを入力する。

```
npx prisma init --datasource-provider mysql
```

# envファイルを更新する。

envファイルを開いて、下記の通り修正する。
```
DATABASE_URL="mysql://(ユーザー名):(パスワード)@localhost:3306/(データベース名)"
```

こんな感じ↓
```
(例)
DATABASE_URL="mysql://root:password1234@localhost:3306/nextapp"

```

以上です。

では良いプログラミングライフを！！
Android TVでproxymanを使う

ハマったのでメモとして残しておきます

ProxymanのAndroid用手順では使えませんでした
（Proxyman Version 5.9.0）
使えない理由としては、
実機は証明書をインストールするGUIが用意されていません
エミュレータはarm64で用意されているOSがproduction buildでrootがとれません
（とれないので、証明書が置けない）

### 手順
1. Proxymanのpemを出力する
Proxymanの以下設定から出力できます
`Certificate -> Export -> Root Certificate as PEM...`
1. pemをAndroid TVのプロジェクト配下におく
`app/src/debug/res/raw`
このpemは個人の環境によるので、gitにcommitしない方が良いです
1. networkSecurityConfigを作る
    ```xml:app/src/debug/res/xml/network_security_config.xml
    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config>
        <debug-overrides>
            <trust-anchors>
                <certificates src="system" />
                <certificates src="@raw/${拡張子を除いたpemのファイル名}" />
                <certificates src="user" />
            </trust-anchors>
        </debug-overrides>
    </network-security-config>
    ```
1. AndroidManifestにnetworkSecurityConfig設定を追加する
    ```xml:app/src/debug/AndroidManifest.xml
    <application
        android:networkSecurityConfig="@xml/network_security_config">
    </application>
    ```
1. エミュレータの場合
Proxymanの以下設定から、No.2のスクリプトを実行する
`Certificate -> Install Certificate on Android -> Emulators...`
（エミュレータは対象の1つだけにして、実機はdisconnectしておいた方がいいです）
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441643/bf072c7a-4a2f-6ffd-bd5f-e2697c372e8f.png)
1. 実機の場合
Proxymanの以下設定から、No.2のプロキシ設定をする
`Certificate -> Install Certificate on Android -> Physical Devices...`
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441643/f00e9080-5d38-d4c6-272c-7a6c519ddad0.png)
CUDA,pytorchは動くのに command 'nvcc' not found

# 状況
環境はUbuntu20.04 + VSCode + CUDA12.1
説明が長いので一言でまとめると、cudaはある、pytorchの実行もできる、けどnvcc -Vが認識してない

途中でubuntuとvscodeでnvccのバージョンが違う状態に陥った。

```bash
pip install flash-attn --no-build-isolation
```

を実行したときに、subprocess errorでnvcc command has not foundとなり、vscodeのbash上ではnvcc -Vを実行しても反応しなかった。

# 解決方法

環境変数の設定として

```bash
export PATH=/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
```

を実行するとVSCodeのbash上でnvcc -Vに反応。

```bash
(env) tell@tell:~/devenv/Creativity$ nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2019 NVIDIA Corporation
Built on Sun_Jul_28_19:07:16_PDT_2019
Cuda compilation tools, release 10.1, V10.1.243

```

となり本来入っているはずのcudaのバージョン(今回は12.1)と異なるものが表示された。

VSCodeのbash上でバージョンを指定した上で以下を実行しても反応がない…

```bash
export PATH=/usr/local/cuda-12.1/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-12.1/lib64:$LD_LIBRARY_PATH
```

そこでUbuntuのterminal上で環境変数として

```bash
tell@tell:~$ export PATH=/usr/local/cuda-12.1/bin:$PATH
tell@tell:~$ export LD_LIBRARY_PATH=/usr/local/cuda-12.1/lib64:$LD_LIBRARY_PATH

```

を実行するとubuntuのターミナル上では

```bash
tell@tell:~$ nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2023 NVIDIA Corporation
Built on Tue_Feb__7_19:32:13_PST_2023
Cuda compilation tools, release 12.1, V12.1.66
Build cuda_12.1.r12.1/compiler.32415258_0

```

となりnvccを無事認識。

しかし、vscodeのbashでは release 10.0のままになった。

つまり、Ubuntuのterminal ⇒12.1 vscodeのbash⇒10.0という状況が発生

# VSCodeのterminalとUbuntuのbashでnvcc -Vが異なるときの解決方法

VSCODEの設定ファイルsetting.jsonにCUDA12.1を常に使用するように環境変数を追加

1. VsCodeでコマンドパレットを開く(Ctrl + Shift + P)
2. Preferences: Open User Settings(JSON)と入力してsetting.jsonを開く
3. 以下のように環境変数を設定する
    
    ```json
    {
      "terminal.integrated.env.linux": {
        "PATH": "/usr/local/cuda-12.1/bin:${env:PATH}",
        "LD_LIBRARY_PATH": "/usr/local/cuda-12.1/lib64:${env:LD_LIBRARY_PATH}"
      }
    }
    ```
    
    もともとなにか書き込まれている場合はこちら(私がそうだった）
    
    ```json
    {
      "explorer.confirmDelete": false,
      "explorer.confirmDragAndDrop": false,
      "terminal.integrated.profiles.linux": {
        "bash": {
          "path": "/bin/bash",
          "args": [],
          "env": {
            "PATH": "/usr/local/cuda-12.1/bin:${env:PATH}",
            "LD_LIBRARY_PATH": "/usr/local/cuda-12.1/lib64:${env:LD_LIBRARY_PATH}"
          }
        }
      }
    }
    
    ```
    
    これでVSCodeでもnvcc -Vが認識する
    
    ```bash
    (env) tell@tell:~/devenv/Creativity$ nvcc -V
    nvcc: NVIDIA (R) Cuda compiler driver
    Copyright (c) 2005-2023 NVIDIA Corporation
    Built on Tue_Feb__7_19:32:13_PST_2023
    Cuda compilation tools, release 12.1, V12.1.66
    Build cuda_12.1.r12.1/compiler.32415258_0
    ```
    

以上！
Databricks のデータをGoogle Spreadsheet に入れてみた。

こんにちは、データエンジニアのMarkです。今日は、たまたま発見した素晴らしいツールについてお話しします。

事の始まり：Spreadhseet職人vs.ビッグデータの戦い
皆さんは、こんな経験ありませんか？

最新のデータをDatabricksで処理 ✅
「Spreadsheetで見たい！」というユーザーからの熱烈なリクエスト 🔥
手作業でデータを渡す日々 😫

そう、これが私の日常でした。「自動化の時代にこんなことしてていいのか？」という疑問と戦いながら...
なんかいい解決策がないか？とググる日々を過ごしてました。ファイルに書き出し、それをSpreadsheet に貼り付ける、、そういう手法しか見つからなかった。そんな中、Googleワークスペースマーケットプレイスで出会いを果たしました。その名も「Bricksheet」ほんと最近リリースされたようです。

SpreadsheetからDatabricks Warehouseに直接アクセス、データをダイレクトにインポートできるツール、まさに求めていたものでした！ちょっと操作ステップをまとめてみました。

1.アドオンをインストール
https://workspace.google.com/marketplace/app/bricksheet/979793077657
2.Spreadsheetに「Bricksheet」メニューが出現
3.Databricksの設定を入力（Host、Warehouse ID、Auth Token）
4.参照したいカタログ、スキーマ、テーブルを選択
5.「インポート」ボタンをポチッ

そして...SpreadsheetにDatabricksのデータが！✨

ドロップダウンで簡単にCatalog, Schemaの選択が直感的でUIがシンプルで使いやすい。
Auth Tokenを利用しているため、権限に基づいたアクセス。
処理されて更新がかかったテーブルを常にインポートすることが可能。

Bricksheetのおかげで、楽になりそうです。

![Screenshot 2024-10-03 at 20.25.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3901270/c20519fe-501a-ff4d-4d96-c624b7956710.png)
Javascript応用文法

今回はJavascriptの中でも応用的な文法を記事にしたいと思います。

1. 関数式とアロー関数
JavaScriptでは、関数という特定の動作をまとめたものを作れます。通常の関数のほかに、「関数式」や「アロー関数」という書き方があります。

普通の関数：
```javascript
function sayHello(name) {
  return "Hello, " + name;
}
console.log(sayHello("Alice"));  // "Hello, Alice"
```
関数式：
関数を変数に代入する形で作ることができます。普通の関数と同じように使えますが、関数の書き方が少し違います。
```javascript
let sayHello = function(name) {
  return "Hello, " + name;
};
console.log(sayHello("Bob"));  // "Hello, Bob"
```

アロー関数：
アロー関数は、もっと短く書ける方法です。
```javascript
let sayHello = (name) => "Hello, " + name;
console.log(sayHello("Charlie"));  // "Hello, Charlie"
```
アロー関数は、コードをすっきりさせるために使います！

3. 非同期処理とPromise
非同期処理とは、すぐに終わらない作業（例：サーバーからデータを取得するなど）を待っている間に他のことをやっておくための仕組みです。Promise（プロミス）というものを使って、非同期の作業が終わったかどうかを確認できます。
```javascript
let promise = new Promise((resolve, reject) => {
  let success = true;
  if (success) {
    resolve("成功しました！");
  } else {
    reject("失敗しました");
  }
});

promise.then((message) => {
  console.log(message);  // "成功しました！"
}).catch((error) => {
  console.log(error);  // もしエラーがあったらここが実行される
});
```
ここでは、「成功」か「失敗」かが分かるまで他の作業を続けながら、成功したらメッセージを表示するというコードです。thenは成功したときの処理、catchは失敗したときの処理です。

4. モジュール
JavaScriptでは、モジュールという機能を使って、コードを別のファイルに分けて整理できます。これにより、コードが大きくなっても、読みやすくなります。

モジュールの例：
```javascript
// module.js ファイル
export const name = "Alice";
export function greet() {
  console.log("Hello, " + name);
}

// main.js ファイル
import { name, greet } from './module.js';

console.log(name);  // "Alice"
greet();  // "Hello, Alice"
```
module.jsというファイルで変数や関数を定義し、それを別のファイル（main.js）で使うことができます。コードを分割することで、管理が簡単になります！

5. スプレッド構文と分割代入
スプレッド構文は、配列やオブジェクトの中身を簡単に取り出して、別の場所に使うための便利な書き方です。
スプレッド構文の例：
```javascript
let arr1 = [1, 2, 3];
let arr2 = [...arr1, 4, 5];  // arr1の要素をそのまま使い、新しい配列を作る
console.log(arr2);  // [1, 2, 3, 4, 5]
```
また、分割代入を使うと、オブジェクトや配列から値を簡単に取り出せます。

分割代入の例：
```javascript
let person = { name: "Alice", age: 25 };
let { name, age } = person;  // personのnameとageをそれぞれの変数に代入
console.log(name);  // "Alice"
console.log(age);   // 25
```
6. 高階関数
高階関数は、他の関数を引数に取ったり、戻り値として返すことができる関数です。少し難しそうに聞こえますが、実際によく使うものです。たとえば、mapという配列のメソッドが高階関数です。

高階関数の例：
```javascript
let numbers = [1, 2, 3, 4, 5];
let doubled = numbers.map(num => num * 2);  // 配列のすべての要素を2倍にする
console.log(doubled);  // [2, 4, 6, 8, 10]
```
mapは、配列の各要素に対して関数を実行して新しい配列を作ります。この場合、num => num * 2という関数を使って、全ての数字を2倍にしています。

まとめ
これでJavaScriptの応用文法について説明しました。もう一度おさらいしましょう：

関数式とアロー関数：関数をもっと簡単に書ける。
非同期処理とPromise：すぐに終わらない作業を待っている間に他の作業をする方法。
モジュール：コードを別ファイルに分けて整理できる。
スプレッド構文と分割代入：配列やオブジェクトの中身を簡単に扱う。
高階関数：他の関数を引数として扱える関数。
マルチプロセスの gRPC サーバを Cloud Run にデプロイしてモニタリングするための参考資料

# gRPC ハンズオン

まずはこのあたりを一通り実施して雰囲気を掴みます。

公式チュートリアル: 

https://grpc.io/docs/languages/python/basics/

クイックスタート（helloworld サンプル）:

https://grpc.io/docs/languages/python/quickstart/

helloworld サンプル:

https://github.com/grpc/grpc/tree/master/examples/python/helloworld


# Protocol Buffer Compiler (protoc)

protoc をコマンドラインで実行する際には、カレントディレクトリ、.proto ファイル、モジュールの生成先の位置関係に気をつけてパラメータを指定する必要があります。特に `-I` パラメータの特殊な指定方法 (e.g. `-Igrpc/example/custom/path=../../protos`) についてはコマンドのヘルプ (`-h`) にも載っていないので、下記ページの **Generating gRPC interfaces with custom package path** セクションにある貴重な例を参考にしてください。

Python 用 protoc の使い方の説明:

https://grpc.io/docs/languages/python/basics/#generating-client-and-server-code


# サーバのマルチプロセス対応

gRPC サーバは ThreadPoolExecutor を使ってマルチスレッドで起動することになっていますが、これを単純に ProcessPoolExecutor に置き換えることではマルチプロセス対応ができません。  
まずサブプロセスを必要な数だけ fork してから、通常の ThreadPoolExecutor を使って gRPC サーバを起動する方法がよいとされています。

Multiprocessing のサンプル:

https://github.com/grpc/grpc/tree/master/examples/python/multiprocessing


# コマンドラインでリクエストを送る (grpcurl)

grpcurl は gRPC サーバに直接リクエストを送信できるコマンドラインツールで、開発時に便利です。

https://github.com/fullstorydev/grpcurl

grpcurl からリクエストを送る際に .proto ファイルを指定しなくていいように、gRPC サーバで server reflection という機能を有効にしておくのがおすすめです。

Server reflection 機能を有効にするサンプル:

https://github.com/grpc/grpc/blob/master/examples/python/helloworld/greeter_server_with_reflection.py


# Cloud Run 上で動作させる

デプロイ時に HTTP/2 を有効にすることや、クライアント・エッジロードバランサ・サーバのインスタンス間の関係に注意する必要があります。

https://cloud.google.com/run/docs/triggering/grpc?hl=ja


# OpenTelemetry 対応（モニタリング）

https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/grpc/grpc.html

トレースコンテキストは、ヘッダの `traceparent` に格納することが推奨されています。gRPC では HTTP/2 ヘッダのことを metadata と呼んでいます。

https://cloud.google.com/trace/docs/trace-context?hl=ja#grpc-requests

カスタム metadata を使用するサンプル:

https://github.com/grpc/grpc/tree/master/examples/python/metadata


# gRPC Keepalive について

別記事にしました。

https://qiita.com/k-akiyama/items/c0d5112be0e4858a3b22
【アプリ紹介】Arc Browserを要点だけ解説


:::note warn
この記事はnoteで4ヶ月前に投稿したものです． アカウント整理に伴ってこちらに移動しました． 情報が古い可能性がありますが，ご了承ください．
:::

![nd5780a235e5a_dc58b5de8928365eb898d6b5468d241a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655545/421d3721-5c15-c16d-f04d-1b41f6a35e8a.png)

今回は近年話題のArc Browserを，要点に絞って解説します！

## 概要

Arc Browserは近年話題になっている新しいブラウザです．新しい設計思想と非常にオシャレな見た目を持つだけでなく，ChromeやFirefoxの代わりとして十分に使えるだけの完成度を誇ります．

https://arc.net/

## 設計思想

Arc Browserの最大の特徴はその設計思想にあると個人的には思っています．突き詰めれば似たようなことは他のブラウザでも出来ますが，シンプルかつ筋の通った設計思想のおかげで他のブラウザでは実現できない快適な使い心地を実現しています．

その設計思想はズバリ"OS"であること．近年ではWeb上で非常に多くのアプリケーションを使えるようになったおかげで，ブラウザ経由でアプリを開くことが多くなりました．それ故，ブラウザを"Webアプリを使うためのOS"として定義し，それに特化させた機能を実装しよう！となったのがArcの出発点となっています．

## 特徴:3段階に分かれたブラウザ

Arcは，WebのOSであるという思想のもと，普段私達が使用しているタブを3段階のレイヤーに分割しています．

1. お気に入りタブ (全てのスペースで共通)
1. ピン留めタブ (スペースごとに存在)
1. 通常のタブ (スペースごとに存在)

まず，Arcは"スペース"という単位で作業環境が分割されています．これにより，別々のタスクでタブが混在することが無くなります．

![nd5780a235e5a_picture_pc_3638f5295a89fc8ee8892a94fe2c3df3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655545/2220d0c4-2844-4026-45c5-fe03d2a90955.gif)

①"お気に入り"タブは，全てのスペースで共通して存在するタブで，Chromeにおけるブックマークに近い存在です．しかし，ブックマークよりもWebアプリケーションを常駐させる場所として意味合いが強く，MacOSにおけるDock，Windowsにおけるタスクバーのほうが考え方が近いかもしれません．

②"ピン留め"タブは，各スペースごとに存在するブックマークだと考えると良いでしょう．ここに登録したタブは自動的に消滅することはありません．

③通常のタブは名前の通り普段の検索等に持ちいられる通常のタブですが，一定時間(デフォルトは12時間)で自動的に削除されるという特徴があります．

![nd5780a235e5a_1710162575939-LgFug3SZQp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655545/f3e65c25-4cb7-47b5-0ada-c222e9da57b6.png)

なぜこのようなタブの種類分けがされているのかと言えば，私達が普段使用するタブは**アプリケーション**と**よく参照するページ**，**情報収集/検索のためのタブ**に大別出来るためであり，それら性質の違うタブが同一レイヤー混在してる従来のブラウザとは一線を画す使い心地を実現しています．非常に理にかなった設計であると言えます．

実際のところ，自動的にタブが削除される機能は拒否感を覚える方もいるかもしれませんが慣れてしまえばとてもラクであり，特に困ったことになったことはありません．(もちろん履歴は残りますしね．ただ僕は削除までの時間を24時間に延長してあります．)

## 総評

総評としては，自信を持って他人にオススメできる完成度かと思います．利点と欠点は以下の通りです．

- 利点：設計思想が洗練されており使いやすい．何よりもかっこいい．
- 欠点：Chromeでない．(通常想定されているブラウザではない．)

利点としては，ChromeやFirefox，Safari以外でここまでしっかりしたブラウザはあまり無く，その上独自性がしっかりしていることでしょう．特にITエンジニアの皆様ならこの魅力をよくわかってくれると思います．

欠点はChromeではないこと笑．実際，僕もこの前確定申告を行いましたが，Web上の書類作成ツールを使用するときにサポート外のブラウザだと怒られました．これまで使用してきて，それ以外に目立った不具合はありませんでしたが，通常想定されるブラウザではないので思わぬところで使えないことがあるかもしれません．逆に言えば欠点はそれくらいです．

## おわりに
今回はArc Browserを紹介しました．(本当に今更ですが…)今後も新しいアプリやプロダクトを紹介していきたいと思いますので，よろしくお願いいたします．

## 余談
Arc Browserと同様，"OS"であるとの信念を持ち，比較的同時期に出現したブラウザとして**SigmaOS**というものがありました．

https://sigmaos.com/

機能面でもArcに非常に似ており，こちらはこちらでデザインがカッコいいのですが，1年ほど前にインストールしたときは若干動作が重かったんですよね…今はどうなっているんでしょうか？