OmniAICreator/Qiita-1.07M huggingface dataset:
Next.jsで使用される主要なキャッシュの構造

Next.jsは、アプリケーションの高速化とパフォーマンスの向上のために、様々な種類のキャッシュを使用しています。

# Next.jsで使用される主要なキャッシュの構造

### ページキャッシュ（Page Cache）
ページを自動的にキャッシュします。このキャッシュには、サーバー側でレンダリングされたページのHTMLや、クライアント側でレンダリングされたJavaScriptのバンドルなどが含まれます。ページキャッシュは、同じURLを持つリクエストがあった場合に、レスポンスします。


### ファイルシステムキャッシュ（File System Cache）
ページコンポーネントなどのJavaScriptモジュールを読み込むために、ファイルシステムを使用します。ファイルシステムキャッシュは、ファイルの変更を追跡して、必要に応じて再読み込みすることで、パフォーマンスを改善します。

### コンポーネントキャッシュ（Component Cache）
コンポーネントレベルでキャッシュを使用することができます。これにより、再利用可能なコンポーネントの再レンダリングが最小限に抑えられ、パフォーマンスが向上します。

### APIキャッシュ（API Cache）
APIエンドポイントに対してキャッシュを使用することができます。APIキャッシュは、リクエストとレスポンスをキャッシュし、同じリクエストがあった場合には、キャッシュからレスポンスを返すことができます。


# APIキャッシュの実装方法

APIキャッシュはデフォルトでは無効になっています。

APIキャッシュを有効にするには、`getServerSideProps`や`getStaticProps`のオプションである`revalidate`を設定する必要があります。revalidateは、秒単位で指定された有効期限を設定します。たとえば、`revalidate: 60`を設定すると、キャッシュされたレスポンスは60秒間有効です。

```
export async function getServerSideProps(context) {
  const { params } = context;
  const res = await fetch(`https://example.com/api/data/${params.id}`)
  const data = await res.json()

  return {
    props: { data },
    revalidate: 60 // 60秒間キャッシュされる
  }
}

```

### キャッシュのキーについて

APIキャッシュはリクエストのURL、HTTPメソッド、クエリパラメータ、ヘッダー、Cookieなどの情報に基づいて一意のキーが生成されます。そして、キーを使用してキャッシュが保存されます。
つまり、APIキャッシュが同じリクエストかどうかを判断するためには、contextだけでなく、リクエストのURLやヘッダーなどの情報も含めた全ての情報が一致する必要があります。
以下は、APIキャッシュを生成するための情報です。
- リクエストのURL
- HTTPメソッド（GET、POST、PUTなど）
- クエリパラメータ
- ヘッダー（User-Agent、Accept-Encoding、Accept-Languageなど）
- Cookie

Next.jsでは、これらの情報を使用してAPIキャッシュを生成し、同じリクエストが来た場合はキャッシュからレスポンスを返します。

### クエリパラメータが同一の場合に限定する場合

上記の通りUser-Agent等が異なると別キャッシュとして扱われてしまうので、クエリパラメータが同一の場合にのみキャッシュを有効にしたい場合などは`node-cache`などのライブラリを使用して独自にカスタムキャッシュの実装が必要になります。

# まとめ

Next.jsで使用される主要なキャッシュ構造と、APIキャッシュの実装方法について詳しく説明しました。
キャッシュを使用することで、アプリケーションの応答速度を向上させることができます。さらに、アプリケーションがより軽量になるため、ユーザーエクスペリエンスが改善されます。キャッシュを正しく実装することで、APIの呼び出し回数が減るため、ネットワークの帯域幅を節約することもできます。キャッシュは、アプリケーションのパフォーマンスを向上させるために非常に重要な役割を果たします。
Smary4でEUCを使う方法

# いやーいまどきEUCなんてというなかれ
結構現役で動いてるところまだあるんじゃないでしょうか。そして今どきSmartyなんていうなかれ、まだまだ動いてるでしょう。しらんけど。

# 結論
* smarty4でEUCを使いたいと、お急ぎの方はこれで
```php
\Smarty::$_CHARSET = 'EUC-JP';
$smarty = new \Smarty();
$smarty->setEscapeHtml(true);
```

# smarty3ではSMARTY_RESOURCE_CHAR_SETという定数があった
* ちなみにsmarty3では定数定義してあげればEUCで動きます
```php
define('SMARTY_RESOURCE_CHAR_SET', 'EUC-JP');
```

# smarty4ではこの定数なくなったので、どうしたらいいんだろうと途方に暮れる・・・
* ググってもあまりでません
  * だいたいきょうびEUCて
* しょうがないのでコードを読んでみることに・・・
* このへんぽい
```php
 164     /**
 165      * Flag denoting if Multibyte String functions are available
 166      */
 167     public static $_MBSTRING = SMARTY_MBSTRING;
 168
 169     /**
 170      * The character set to adhere to (e.g. "UTF-8")
 171      */
 172     public static $_CHARSET = SMARTY_MBSTRING ? 'UTF-8' : 'ISO-8859-1';
```

## public staticだから上書きできるな、グヘヘ
* と思っていたら、ドキュメントに書いてありました
  * https://smarty-php.github.io/smarty/4.x/programmers/charset/
* いつものドキュメントをちゃんと読みましょう的な

# これで労することなくEUCを表示できるぜベイベーと思っていたら・・・
* 表示できひんやんけ！
* 真っ白・・・
* 10秒考えました、、、、この現象なんだっけ、、、、euc扱ってるとこれ発生するんですよね
* DBからとってきた値が表示されない、まっしろ
* そうだ！

## htmlspecialcharsの文字コード指定だ
* これどこで設定しているかというとさっきの、$_CHARSETを引数にしているんですね
* ということはどっかで設定できるのかなとまたpublicメソッドを徘徊です・・・
* ありました、名前もズバリそのままsetEscapeHtml
  * こいつにtrueを渡してあげることで、htmlspecialcharsの文字コード設定されて無事表示されます

# smarty的にはUTF-8使えよと言ってる
* UTF-8前提でコードが変更されているので、致し方ないのではあるが
* escape設定をいれてあげないと動かないのはこれはわからないですよ・・・
* とにかく、動いてよかった
[Rails] ブックマーク機能の実装

# はじめに
ブックマークを実装するための忘備録です。

# 実行環境
- Rails 5.2.3
- Ruby 2.6.4

# 実装
## 1. アソシエーション
![bookmark.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118527/9aa1312a-57e4-0b89-6bcd-8a9b0cf84079.png)

中間テーブルとしてbookmarksテーブルを作成。


## 2. モデル

### 2.1 モデルの作成
```
$ rails g model Bookmark user:references board:references
```
マイグレーションファイルに追記をします。
```ruby: db/migrate
class CreateBookmarks < ActiveRecord::Migration[5.2]
  def change
    create_table :bookmarks do |t|
      t.references :user, foreign_key: true
      t.references :board, foreign_key: true

      t.timestamps
    end

    add_index :bookmarks, [:user_id, :board_id], unique: true
  end
end
```

重複を防ぐために、複合キーインデックスを使い、unique:trueとします。
データベースへ反映させます。
```
$ rails db:migrate
```

### 2.2 モデルの関連付け
```ruby: app/model/bookmark.rb
class Bookmark < ApplicationRecord
  belongs_to :user
  belongs_to :board

  validates :user_id, uniqueness: { scope: :board_id }
end
```
モデルのバリデーションでも重複を防ぐために、scopeを使ってuniquness制約をつくります。
```ruby: app/model/user.rb
class User < ApplicationRecord
  .
  .
  has_many :bookmarks, dependent: :destroy
  .
  .

end
```
```ruby: app/model/board.rb
class Board < ApplicationRecord
  .
  .
  has_many :bookmarks, dependent: :destroy

  def bookmarked_by?(user)
    bookmarks.where(user_id: user).exists?
  end
end
```
ブックマークが既にされているかのメソッドをモデルにbookmarked_by?(user)として定義します。

## 3. コントローラーの作成
```
$ rails g controller bookmarks
```

```ruby:app/controllers/bookmark_controller.rb
 class BookmarksController < ApplicationController
  def create
    board = Board.find(params[:board_id])
    bookmark = board.bookmarks.build(user_id: current_user.id)
    if bookmark.save
      redirect_to request.referer
    else
      redirect_to request.referer
    end
  end

  def destroy
    board = current_user.boards.find(params[:board_id])
    bookmark = board.bookmarks.find_by(user_id: current_user.id)
    if bookmark.present?
      bookmark.destroy
      redirect_to request.referer
    else
      redirect_to request.referer
    end
  end
end
```



## 3. ルーティングとビューの作成
```config/routes.rb
  resources :boards do
    resource :bookmarks, only: %i[create destroy]
  end
  
```

```app/views/board/index.html.erb
  <% if board.bookmarked_by?(current_user) %>
    <%= link_to "ブックマーク", board_bookmarks_path(board), method: :post %>
  <% else %>
    <%= link_to "ブックマークを外す", board_bookmarks_path(@board), method: :delete %>
  <% end %>
```





# 参考にさせていただいた記事
https://qiita.com/japwork/items/3ca48e7c5fa1053b910b

https://qiita.com/jaramon/items/248bcb4b56e9fed8fc90
【shell】ディレクトリ内フォルダ名をスラッシュ(/)なしで取得・利用する方法

:::note info
さらに追記
↓このワンライナーで解決できました...少し賢くなった٩( ᐛ )و
ls -l /dir/ | grep ^d | awk '{print $9}'
:::

:::note info
追記:
コメントにて素敵な書き方を教えて頂きましたので、そちらを参考にどうぞ٩( ᐛ )و
(詳細なコメントを下さった方、ありがとうございます!!!:sunny:)

以下、参考までに記事内容は残してありまーす ♪( ´▽｀)
:::

カレントディレクトリにあるフォルダ名を/無しでとりたい&リストにして使用したい時があった。
この時

```shell:uhuhu.sh
ls -d */
```
だと

```shell:uhuhu.sh.out
uuu/ iii/ ppp/
```
このように/がついてしまうので、このまま配列にして使うとちょっと使いにくい。
ということで下記のようにしやした٩( ᐛ )و↓

```shell:runrun.sh
dir_name=`ls -d */`
dirary=()
for dir in $dir_name; do
    dirary+=("$dir")
done

# ディレクトリ一覧
for i in ${dirary[@]}; do
    iii=`echo ${i} | tr -d /`
    echo ${iii}
done
```
そしたらこうなるよ-٩( ᐛ )و

```shell:runrun.sh.out
uuu iii ppp
```
拡張書記素クラスターのサイズの上限を設ける


## 概要
JavaScript で Intl.Segmenter が標準化され、拡張書記素クラスター単位で文字列を扱えるようになりました。拡張書記素クラスターを扱う上での課題はサイズの上限がないことです。そのため、従来の文字列メソッドとの使いわけやサイズの上限を超える拡張書記素クラスターの扱いについて方針が必要になります。

## 文字列メソッドの使いわけ

 * 部分文字列を取り出すときは拡張書記素クラスター単位
 * 文字数の上限はコードポイントもしくはバイト単位

上述の通り、拡張書記素クラスターの上限のサイズはないので、データベースに保存するときはコードポイントもしくはバイトのサイズをチェックする必要があります。

## 文字数が変わる処理への注意

 * 大文字小文字変換
 * ユニコード正規化
 * 不正なバイト列の置き換え

上述の処理では文字数が変わってしまう可能性があるので、文字数の上限チェックの際はこれらの処理も考慮する必要があります。

## ファクトリ関数の定義

Intl.Segmenter にはスタティックファクトリメソッドが存在しないので、自分でファクトリ関数を定義する必要があります。

```js
function createGraphemeSegment(str) {
    return (new Intl.Segmenter(
                navigator.language,
               {granularity: "grapheme"}))
        .segment(str);
}
```

## 拡張書記素クラスターのサイズの上限（ストリームセーフテキストフォーマット）

巨大な拡張書記素クラスターはアプリのクラッシュや画面を壊す手段になるので、Apple (MacOS や iOS) や C++ ライブラリの Boost.Text は拡張書記素クラスターのサイズの上限をコードポイント32個未満としています。この値はストリームセーフテキストフォーマットの仕様（UAX15-D3）に記載されています。

## サイズの上限を超える拡張書記素クラスターの扱い

後続の装飾記号（ノンスターター）を代替文字（U+FFFD）に置き換えたり、削除する方法が考えられます。原則論としては削除はセキュリティの問題になる可能性があるので、代替文字に置き換えることが望ましいです（例 at\x80rack -> attack）。

自前で文字列関数を定義する場合、文字数の数え方の仕様を決める必要があります。ストリームセーフテキストフォーマットの仕様には「数字の2、1万のウムラウト、ドットビロー、数字の3」の文字数は「10003」とするという例が記載されているので、これを仕様とすることができます。言い換えると、上限のサイズを超えた拡張書記素クラスターは構成するコードポイントの数で数えるということです。
Arch linuxにoperaのインストール。


ArchLinuxにOperaのインストールをします。

```
yay -S opera
```

そのままではtwitterやfacebookの動画が見れないので、
コーデックのインストールをします。

```
sudo pacman -S opera-ffmpeg-codecs
```

operaの日本語化は、実行時にオプション`--lang=ja`を付けるだけでOk
v-row v-col 子要素の高さを親要素に合わせて自動的に大きくする（レスポンシブ対応）

## 意外と苦戦するこういうレイアウト・・

左側はラベル領域で高さいっぱいの背景にする。
右側はデータによって高さが可変というパターン。
かつ、レスポンシブにも対応する。

![スクリーンショット 2023-03-29 16.00.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266846/208c83f9-0563-6abe-4bda-74cd0ec9521f.png)

## ソース

```vue
<template lang="pug">
v-container 
    v-row.align-stretch(align="center" no-gutters)
        v-col(v-for="i in 10" sm="6" cols="12" :key="i")
            v-row(no-gutters style="height:100%; border-bottom:1px solid #ccc")
                v-col.grey(sm="3")
                    .ma-2 label:{{ i }}
                v-col(sm="9")
                  .ma-2
                    div(v-if="i % 2 == 0")
                        v-textarea(outlined label = "textarea")
                    div(v-else)
                        v-text-field(outlined label = "textfield")
</template>
```

## ポイント
親のv-rowに.align-streachを当てて子供のv-rowにstyle="height:100%;する。
ポストモーテムはじめました

こんちは。
最近SREの領域にも足を踏み入れ始めた[とよしー](https://twitter.com/_toyo_sea_) です。

2月からSREの役割も担うことになりました。
とはいえ、SREってなにすればええんや...状態でした。

最初になにを取り組もうかと考えている時に、インシデントを目の当たりにしました。
そこで、ふと
・エンジニアにこの障害から学んだ教訓をもっと認知させたい
・エンジニアの言語でもわかるような再発防止策を共有したい
と思い、ポストモーテムを実施してみようと考えました。

というわけで、今回の記事はポストモーテムをどのように実施し、やってみてどうだったかをまとめた記事になります。

## ポストモーテムってなに？
そもそもポストモーテムってなんやねん？ですよね。
直訳すると「検死」という意味でもあり、もともとは司法機関が遺体を解剖するなどして死因を調べ、犯罪性の有無を明らかにする行為だったそうです。

システムも予期せぬ障害やインシデントが発生しますよね。（できれば発生してほしくないけど...）
主に障害の事後検証や根本原因分析を行い、それらをドキュメントにまとめる流れのことをポストモーテムといいます。

## ポストモーテムのテンプレート
弊社で行う際のポストモーテムのテンプレートは下記のような感じです。

```
## アイスブレイク
=> 少し緊張する内容の会議体なので、最初にアイスブレイクを行うのはおすすめです

## ポストモーテムとは
=> ポストモーテムに慣れていない人が多い場合は、説明や参考記事をのせています

## ルール
人に対する非難を行わないこと
=> 人を非難しても何もいいことは起きないので場のルールとして定めています

## 障害の概要
=> その名の通り障害の概要を端的に書きます

## 対応者
=> 障害復旧にあたった担当者を書きます

## タイムライン
=> 障害対応時になにをやったのか分刻みで記録したものを書きます

## 何がおこったか
=> 端的にこの障害でシステムに何が起こっていたのかを書きます

## 根本原因分析
=> 何が原因だったのかを深掘りしたものを書きます

## 解決方法
=> 障害をどのように解決したかを書きます

## インシデント分析
### どれくらいのユーザーに影響があったか
=> ○人 / 全ユーザー

### 障害発覚から終息までの時間（平均回復時間）
=> ○分○秒

## アクションアイテム
### 観点
・今回のような事象を防ぐ方法
・障害発生から回復するまでの時間を減らすにはどうしたら良いか

## ふりかえり
### よかったこと

### 改善したいこと
```


## やってみてよかったこと
エンジニアの言語でもアクションアイテムが出せるので、具体的かつすぐにできそうなアクションにつなげることができたことが良い点でした。
経験則ですがふわっとしたアクションアイテムだと決めて終了...という悲しいことになりかねないです。
極端な例ですが、
「みんなが仕組みを改善する意識をもつ」
とかは危険信号だと思っています。（意識ってなんやねん）

また別観点では、根本原因分析をする中で「こうすればよかったのかもしれない」というアイデアがたくさん出てきたことも良い点でした。
対話する中で気づき/学びを得ることがポストモーテムの良いところでもあるので、それを感じられてよかったです。

## やってみてわかったこと
障害からポストモーテム実施までの時間は早ければ早いほど良いことに気づきました。
ポストモーテムを1週間後に設定したことがあるのですが、障害の詳細の部分まで思い出せなかったり、思い出すのに時間を要するシーンがあったので、障害発生からいかに早くポストモーテムを開催するかが今後の課題です。


## 参考
[システム運用アンチパターン ―エンジニアがDevOpsで解決する組織・自動化・コミュニケーション](https://www.amazon.co.jp/%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E9%81%8B%E7%94%A8%E3%82%A2%E3%83%B3%E3%83%81%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3-%E2%80%95%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%8CDevOps%E3%81%A7%E8%A7%A3%E6%B1%BA%E3%81%99%E3%82%8B%E7%B5%84%E7%B9%94%E3%83%BB%E8%87%AA%E5%8B%95%E5%8C%96%E3%83%BB%E3%82%B3%E3%83%9F%E3%83%A5%E3%83%8B%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3-Jeffery-D-Smith/dp/4873119847)
metabaseのDBファイルを覗いてみる

# はじめに
metabaseとは、気軽に導入できるのが特徴のオープンソースのBIツール（データ可視化ツール）です。

https://www.metabase.com/

今回はmetabaseのDBファイルを覗いてみる機会があったので、その備忘録として記事を残しておきます。



# 背景
metabaseのDB調査が必要になった経緯はこんな感じです。

・metabaseはローカルPCで試験的に運用
・ある日metabaseにログインできなくなった
・LDAPサーバーに変更があり、認証ができなくなったと判明
・復旧しようにも管理アカウントのIDは不明
・SMTP設定がされていないため、リセットメールの送信も不可

なかなかな状況ですが、DBファイルを覗ければなんとか復旧できるかもしれません。
試しにやってみましょうとなりました。

# DBファイルの構造
DBファイルはmetabaseのルートフォルダの下に保存されています。

```
└metabase.db
　├ metabase.db.mv.db
　└ metabase.db.trace.db
```
metabaseのDBは、デフォルトではH2という形式が使われています。


# H2のコンソールを入手
H2のDBを開くためにはH2のコンソールを入手しましょう。
公式サイトからダウンロードができます。
実行には[JAVA](https://www.java.com/)のインストールが必要です。事前に用意しておいてください。

http://www.h2database.com/html/main.html

インストーラを使ってもいいですが、今回はZIPを使用することにしました。
DLして展開できたらbinフォルダにある「**h2-X.X.XXX.jar**」を起動するとコンソールが立ち上がります（Xの部分にはバージョン番号が入ります）

ここで要注意なのが、metabaseで使われているH2とコンソールのバージョンを合わせる必要があるということです。
うまくいかない場合は、H2公式サイトの「[Archive Downloads](http://www.h2database.com/html/download-archive.html)」から適合するバージョンを探してください。


# H2のDBに接続する
コンソールが立ち上がったら、DBを開くために各種の設定を入れていきます。
![H2コンソール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987979/49c00d6a-333a-c025-3a1a-9150c708b484.png)
JDBC URLには上記の構造で挙げたmetabase.dbフォルダのパスをfile:の形式で指定します。
**metabase.db.mv.dbファイルのパスではないので注意！**
ここでパス指定をミスると、新規作成扱いになり、シレッと空のテーブルが開かれてしまうので気をつけましょう。

ユーザ名・パスワードを入力して、「接続」を押して進みましょう。
ここでのユーザ名・パスワードはmetabase自体のものではなく、H2のDBに設定されているもので、
metabaseのデフォルト状態では空になっています。


# DBから必要な情報を得る・操作する
接続したらDBの各種テーブルが閲覧できます。
左のテーブル一覧から開きたいテーブルを選ぶとクエリが補間されるので「実行」します。
![H2操作.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987979/748547d7-c9cc-4fc5-7933-fc9e121a97f8.png)

今回のようなケースの場合、目的のデータは「**SETTING**」にあり、基本設定が保存されています。
ここからSMTPの設定やLDAPの設定を得ることができます。

また「**CORE_USER**」で登録されているユーザーの一覧を見ることができます。
どんなアカウントがあるかや設定されたメールアドレスを確認できます。
(パスワードはハッシュで保存されているので直接は見れません)

クエリに必要な情報を記述して実行し、復旧のための情報を書き換えたら、作業完了です。
2つのCSVファイルの指定したデータをグラフにする方法

# プログラムについて
2つのCSVファイルの指定したデータをグラフにして，1枚の図で表示するプログラムを作りました．
凡例はCSVファイルから取得するようにしています．

# 環境
- MacBook Air(M1, 2020)
- Python 3.8.8

# プログラム
```python:graph.py
import sys
import pandas as pd
import matplotlib.pyplot as plt

# コマンドライン引数からファイル名を取得する
if len(sys.argv) != 7:
    print("Usage: python graph.py file1.csv y_col1 y_col2 file2.csv y_col1 y_col2")
    sys.exit(1)

file = sys.argv[1]
y_col1 = sys.argv[2]
y_col2 = sys.argv[3]

file2 = sys.argv[4]
y_col21 = sys.argv[5]
y_col22 = sys.argv[6]

#CSVファイルを読み取る
df = pd.read_csv(file)
cols = df.columns.tolist()
x_col = cols[0]  # 1つ目の列をxとする
y_col_1 = cols[int(y_col1)]  # 初めに指定した列をy1とする
y_col_2 = cols[int(y_col2)]  # 次に指定した列をy2とする
x = df[x_col]
y_1 = df[y_col_1]
y_2 = df[y_col_2]

#CSVファイルを読み取る
df2 = pd.read_csv(file2)
cols2 = df2.columns.tolist()
x_col2 = cols2[0]  # 1つ目の列をxとする
y_col_21 = cols2[int(y_col21)]  # 初めに指定した列をy21とする
y_col_22 = cols2[int(y_col22)]  # 次に指定した列をy22とする
x2 = df2[x_col2]
y_21 = df2[y_col_21]
y_22 = df2[y_col_22]

# グラフを作成する
fig, ax1 = plt.subplots()
ax1.set_xlabel('time', color='black')
ax1.set_ylabel('[V]', color='black')

# データをプロットする
ax1.plot(x, y_1, color='red', label=y_col_1)
ax1.plot(x, y_2, color='blue', label=y_col_2)

# データをプロットする
ax1.plot(x2, y_21, color='green', label=y_col_21)
ax1.plot(x2, y_22, color='magenta', label=y_col_22)

# グラフの凡例を表示する
ax1.legend(loc='best')

# グラフの設定を調整する
fig.tight_layout()

# PNG形式で保存する
plt.savefig('graph.png')
```

# 実行結果
今回はテストとして，sin関数のデータ(test1.csv), cos関数のデータ(test2.csv)の合計2つのデータを表示するようにしています．


```:実行例
python3 graph.py test1.csv 1 2 test2.csv 5 6
```
作成された図は以下のようになっています．

![graph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2758310/812d4dd5-1f39-7160-72e4-f584a26a0d2d.png)
Cockroach DBをsingle-node clusterで動かすdocker-compose最小構成

```yaml:compose.yaml
version: "3.9"
services:
  db:
    image: cockroachdb/cockroach:latest
    environment:
      COCKROACH_DATABASE: app
    ports:
      - "26257:26257"
      - "8080:8080"
    command: start-single-node --insecure
    volumes:
      - "roach-single:/cockroach/cockroach-data"

volumes:
  roach-single:
```

psqlで繋ぐときは以下

```bash
$ psql "postgresql://root@127.0.0.1:26257/app?sslmode=disable"
```
【ServiceNow】Content Publishingでの機械翻訳②

前回（[リンク](https://qiita.com/kamitani_shiho/items/51cba2880ccf87a4f554 "Content Publishingでの機械翻訳①")）に引き続きContent Publishingでの機械翻訳についてお話します。

## 機械翻訳設定
機械翻訳を利用するにあたって必要な設定について説明いたします。
①プラグインのインストール
ServiceNowインスタンスでプラグインをインストールします。
エージェント画面で「プラグイン」画面を開き、下記のプラグインを検索・インストールします。
・Localization Framework (id: com.glide.localization_framework)
![プラグインインストール画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603803/5fb0e33c-1c17-657e-d650-40a13a52abd1.png)

②リクエスター / 承認グループ作成
機械翻訳を行うためには翻訳リクエスト・承認を行うユーザグループをあらかじめ作成しておく必要があります。
リクエスター、承認グループについてそれぞれ下記の通りロールを付与します。
・リクエスターグループ：localization_requester
・承認グループ：localization_fulfiller
※ロールについては下記ドキュメントに詳細記述されています。
　必要に応じてロール付与してください。
　Localization Framework Roles

③ローカリゼーション設定
下記の手順でローカリゼーション設定を行います。
１．フィルターメニューより「Localization Framework > Settings」を選択。
２．「新規」ボタンよりレコードを作成。
　　各項目については下記公式ドキュメントをご参照ください。
　　[Localization Framework の設定](https://docs.servicenow.com/ja-JP/bundle/tokyo-platform-administration/page/administer/localization-framework/concept/localization-settings.html "Localization Framework の設定")

・翻訳設定
    ![ダウンロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603803/0fac52b3-f717-303f-d40b-edd402480d60.png)
・ワークフロー設定
![ダウンロード (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603803/6ecc354c-50d3-dd2a-3fde-6647840e5f80.png)
・プロジェクト設定
![ダウンロード (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603803/47eb233a-e0b8-c90a-df3a-d2043d428c10.png)

次回、コンテンツパブリッシングでの機械翻訳手順を紹介します。
Livebookでprotocolを扱いたい場合

## 現象

Livebookでモジュールにprotocolを実装する場合、そのままでは以下警告が出て上手く動作しないことがある。

```text
warning: the XXXX protocol has already been consolidated, an implementation for Unzip.S3File has no effect. 
If you want to implement protocols after compilation or during tests, check the "Consolidation" section in the Protocol module documentation
```

## 対策

Mix.installに`consolidate_protocols: false`を追加する

```elixir
Mix.install(
  [
    deps
  ],
  consolidate_protocols: false
)
```

## 参考

https://hexdocs.pm/elixir/Protocol.html#module-consolidation

>Although doing so is not recommended as it may affect the performance of your code.
Rustでシングルトンする方法を考えてみた

てきとうに書いてみただけなのでもっといい書き方あるんかな?

pub nameになっちゃってるところは、[Getters](https://docs.rs/derive-getters/latest/derive_getters/)マクロを使えばGetterをはやせるので、外部からはgetter経由で読み取りオンリーで書き込みできなくすることはできるのでunsafeでも実質safe!!!

```rust
static mut hoge: Hoge = Hoge {
    name: None,
    loaded: false,
};

pub struct Hoge {
    pub name: Option<String>,
    loaded: bool,
}

pub fn get() -> &'static Hoge {
    unsafe {
        if hoge.loaded {
            return &hoge;
        }

        hoge.name = Some("reoring".to_owned());
        hoge.loaded = true;
        return &hoge;
    }
}
```
Visual Studio CodeでCopilotを使う

Copilot Labsは現在プロトタイプであることをご理解ください。
# この記事に書いていないこと
・GitHub Copilotがどんなものか
・Copilotの購入(サブスクライブ)方法

# 準備
・vscodeでgithubへのサインインをしておく

# 対象のプラグイン
- [GitHub Copilot](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot) -- いわゆるコードを提案してくれるやつ
- GitHub Copilot Labs (なぜかMarketplace には出てこない) -- 質問できるやつ

# 始め方
### Copilot
Copilotを購入済みでvscodeでサインインし、拡張を入れるだけで使えます。すごい楽！
この時点からコードを提案してくれます。

### Copilot Labs
拡張を入れて使おうとしたらサインアップしろと怒られた。
[GitHub Copilot Labs](https://githubnext.com/projects/copilot-labs/)にサインアップする必要があります。


# 感想
### Copilot 
Copilotの提案は特にneovimで使った時と大差ない。

### Copilot Labs
explain, language translation, brushes, test generationの4機能がある。
Copilot Labsは(2023/03/29時点で)vscodeのみ対応しているが、以下の様な使用感だった。
(go言語の簡単なプログラムを説明してもらいました。)

- explain -- 英語でのみ説明が可能。範囲選択したとこを説明してくれるが、わざわざ説明する必要のない事も言ってくる。makefileを説明させてみるととても酷かった。
- language translation -- 試しにgo -> pythonへ変換。普通に読めるコードを生成したが、実行エラーを吐き出した。
- brushes -- 一番使えそうなツール。コードを目的に沿って書き換えてくれる。が、余計なことをされたり構造を壊したりもするので何をしてくれるのか把握してからがいい。
- test generation -- `JavaScript`と`TypeScript`のみ対応。僕には嬉しくない。

# 今のCopilotで、できなそうなこと
- 既存プロジェクトの改修
- 意図の共有
- 足りないimport, include系を勝手に補完

# 参考
[Getting started with GitHub Copilot](https://docs.github.com/ja/copilot/getting-started-with-github-copilot?tool=vscode)
[Copilot Labs](https://githubnext.com/projects/copilot-labs/)
ExcelVBAスタンダード合格を振り返って

# はじめに
この記事では、私がExcelVBAスタンダード合格するまでに実施した勉強法を振り返ります。
主観的な話になるかとは思いますが、これからExcelVBAスタンダード取得に向けて勉強する人に少しでも助けになればと思います。
[前回のExcelVBAベーシック合格の記事はこちら](https://qiita.com/koki_hayashi/items/24a55f9ae180fe72b3e2)

### プロフィール
事前情報として私のプロフィールを載せます。
・社会人歴4年目。
・過去にVBA,SQLserver,SAPを利用し開発を2年ほど担当していた。
・学生時代は情報科に所属し、C,Java等のプログラミングやIT知識を学んでいた。
・現在はローコード開発を主軸としてDX推進をしている。

# 勉強時間及び内容
期間：2022/12/27～2023/01/21
時間：不定期(計30時間程)
内容：問題集(VBAエキスパート試験対策)
# 勉強方法
私が行っていた勉強方法を説明します。
### 問題集にて試験対策
[VBAエキスパート試験対策](https://www.exam-vba.com/)という有料のサービスを利用しました。約200問の問題が用意されており、問題が分野別に分かれていたり、解答履歴から間違えた数が多い問題をピックアップしたりできます。
- 振り返り
実際の試験で類似の問題が出題されることがあるので、利用するべきだと感じています。
この試験対策で出題される問題のサンプルコードの処理の流れをイミディエイトウィンドウやウォッチウィンドウで確認しつつ、コードの書き方を覚えることが良いかと思います。

# 試験
試験概要
ExcelVBAスタンダードHPより抜粋しました。
詳細は[VBAスタンダード試験概要](https://vbae.odyssey-com.co.jp/about/excel_standard.html)よりご覧ください。

問題数：40問前後
出題形式：選択肢形式、ドロップダウンリスト形式、クリック形式、ドラッグ＆ドロップ形式、穴埋め記述形式
試験時間：50分
合格基準：650～800点(1000点満点中)
　⇒問題の難易度によって上下します。私の受験時は700点が合格ラインでした。

# ポイント
VBAベーシックと比較して、穴埋め記述形式がより多く出題されます。
コードを理解していないと合格できないようになっているため、問題集を解くだけではなく実際にコードを書いて処理の流れを確認することが大事だと思います。
そもそものコードの処理がわからない場合は、[公式テキスト](https://www.amazon.co.jp/VBA%E3%82%A8%E3%82%AD%E3%82%B9%E3%83%91%E3%83%BC%E3%83%88%E5%85%AC%E5%BC%8F%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-Excel-VBA%E3%82%B9%E3%82%BF%E3%83%B3%E3%83%80%E3%83%BC%E3%83%89-%E7%94%B0%E4%B8%AD-%E4%BA%A8/dp/4908327122/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=2P7UC02BREP63&keywords=VBA%E3%82%A8%E3%82%AD%E3%82%B9%E3%83%91%E3%83%BC%E3%83%88%E5%85%AC%E5%BC%8F%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88&qid=1680058371&s=books&sprefix=vba%E3%82%A8%E3%82%AD%E3%82%B9%E3%83%91%E3%83%BC%E3%83%88%E5%85%AC%E5%BC%8F%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%2Cstripbooks%2C147&sr=1-1)で一度勉強してから問題集を利用した方が良いかと思います。

# おわりに
スタンダードは確実にベーシックより難しいので、必ず試験対策をしてから臨むことを強くお勧めします。
私は試験対策サービスを利用することで苦手分野を特定することができました。

これから受験する人は頑張ってください！
【SAP】CO（Controling）：管理会計モジュール

# CO（Controling）：管理会計とは
管理会計とは社内向けに費用・収益の分析をすることです。

## COモジュール全体図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/4b027a90-fa73-1962-7b96-347ea8190bf5.png)

## 役割
COのゴールは社内向けのレポートです。
社内向けに費用・収益を分析、レポーティングすることを目的とします。そのため、COモジュールでは社内全てのお金に関するありとあらゆる情報が集まります。

人件費・購買費・生産費・光熱費・・・・。最終的には〇〇費と呼べるお金に関する情報が全てCOに集まってくると言えます。

## 原価とは何か
<font color=red>総原価</font>　＝「<font color=red>製造原価</font>」＋「<font color=red>販売費及び一般管理費</font>」
### 「製造原価」とは
製品を作るのにどれだけコストがかかったかを計算します。

具体的にいうと、材料費・加工費・製造部門の人件費・製造機器の購入代（減価償却費）などが、これにあたります。

<font color=red>製造原価</font>　＝「<font color=red>直接費</font>」＋「<font color=red>間接費</font>」
■直接費とは
　どの製品に使ったコストなのか直接的に分かる費用のことです。
■間接費とは
　複数の製品にまたがって使用されるコストで、どの製品に使ったのか直接的にはわからない費用のことです。

|分類| 費用 | 説明 |
| :--- | :--- | :--- |
|直接費|直接経費|外注加工費など|
|直接費|直接労務費|製造部門の給料など|
|直接費|直接材料費|原材料、資材、部品など|
|間接費|間接経費|工場の減価償却費、電気代、水道代、雑費など|
|間接費|間接労務費|品質管理部門、物流部門の給料など|
|間接費|間接材料費|消耗品、品目管理しない梱包材など|

### 「販売費及び一般管理費」とは
営業のコストや間接部門のコストを計算します。

具体的にいうと、広告宣伝費・間接部門の人件費・オフィスの家賃・電話代などの通信料などが、これにあたります。

### 原価管理鳥瞰
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/cf4e11ea-bc4f-7423-f1db-d45942d4aaa3.png)


## COの主要３機能
①CO-OM：間接費管理
②CO-PC：製造原価管理
③CO-PA：収益性分析

### CO-OM：間接費管理
OMとは「Overhead Management」の略です。
#### 目的
１．間接費を集計すること
２．集計した間接費を関連する製造部門に配賦すること

##### 間接費
　製造をするための工場も、製造に直接は関わらない品質管理部門・構内物流部門の方の人件費も、文房具などの消耗品も、すべて生産活動をする上で必要なコストです。
##### 配賦
　上記の間接費コスト各関連部門に割り勘する
　例えば：該当商品製造するため、合計何十万円の印刷紙が利用して、この紙は管理部門も製造工場も品質管理も利用しました、各部門は何割を振りますか。

### 製造原価管理（CO-PC）
PCとは「Production Cost」の略です。

#### 目的
１．間接費の配賦
２．生産マスタ/製造実績の集計
３． １、２を元に標準原価計算・実際原価計算

##### 標準原価計算
標準原価計算は、生産マスタのBOM・作業手順マスタを使って、製品・半製品の原価を計算する機能です。
標準原価はマスタデータより、原価の見込みです。
例えば：
飲料水生産したい、コスト見込みは
砂糖：１０円
天然水：２０円
ペットボトル：１０円
人工費：１０円

飲料水標準原価：<font color=red>５０円</font>

##### 実際原価計算
実際原価計算は、標準原価（BOM・作業手順）に対して、実際に材料をいくら使ったか、実際にいくら作業時間がかかったか、という実際の生産活動・購買活動を元に、算出される原価のことです。

実際原価は生産活動する時、実際発生のコストです。

例えば：
飲料水生産する時
砂糖：<font color=red>５円</font>
天然水：<font color=red>３０円</font>
ペットボトル：<font color=red>８円</font>
人工費：<font color=red>１５円</font>

飲料水標準原価：<font color=red>５８円</font>
### 収益性分析（CO-PA）
PAとは「Profitability Analysis」の略です。

#### 目的
１．「間接費管理・製造原価管理から連携された原価情報」と「SD・FIから連携された収益情報」を合わせた分析

収益性分析のレポートでは、製品別・得意先別・販売組織別など、多次元で収益性の分析ができます。

## まとめ
１．間接費管理で、間接費の集計をし、各部門へ配賦
２．製造原価管理で、直接費と配賦された間接費を、製造実績を元に計上
３．収益性分析で、集まった原価情報やFI・SDから連携された収益情報を元に分析
Go言語における並列処理について

### はじめに
Go言語は、並列処理を容易に実装するための強力な機能であるゴルーチン(`goroutines`)とチャネル(`channels`)を提供しています。ゴルーチンは軽量なスレッドのようなもので、低いオーバーヘッドで大量の並列処理を実行できます。チャネルは、ゴルーチン間でデータの受け渡しを行うための同期メカニズムです。

#### ゴルーチンの軽量性
Go言語のゴルーチンは、軽量なスレッドのようなもので、低いオーバーヘッドで大量の並列処理を実行できます。他の言語のスレッドよりもリソース消費が少なく、数千や数万のゴルーチンを同時に実行することが可能です。

#### 簡潔な並列処理の構文:
Go言語は、`go`キーワードを使って簡単に並列処理を実装できます。これにより、関数やメソッドをゴルーチンとして実行でき、コードの可読性が向上します。他の言語では、スレッドの作成や管理に多くのコードが必要であることが多いですが、Go言語では簡潔に記述できます。

#### チャネルによる同期とデータの受け渡し:
Go言語では、チャネルを使用してゴルーチン間でデータの受け渡しを行い、同期をとることができます。これにより、複雑なロックや同期プリミティブを使わずに、直感的かつ安全な並列処理を実現できます。他の言語では、ロックや条件変数などを使って同期を行う必要がある場合が多く、コードが複雑になりがちです。

#### ガーベッジコレクション:
Go言語は、ガーベッジコレクションをサポートしており、メモリ管理が容易です。他の言語では、メモリ管理が手動で行われることが多く、並列処理の実装時にリソースリークやデータ競合が発生しやすいですが、Go言語では自動的にメモリ管理が行われるため、そのような問題が少なくなります。

#### 優れた標準ライブラリ:
Go言語は、並列処理やネットワーキングをサポートする優れた標準ライブラリを提供しています。これにより、開発者は追加のライブラリを探すことなく、効率的な並列処理を実装できます。

### サンプル説明
Go言語での並列処理のサンプルコードを記載。

```golang
package main

import (
	"fmt"
	"time"
)

// 時間のかかる処理を模した関数
func worker(id int, jobs <-chan int, results chan<- int) {
	for j := range jobs {
		fmt.Printf("Worker %d started job %d\n", id, j)
		time.Sleep(time.Second) // 1秒間スリープ
		fmt.Printf("Worker %d finished job %d\n", id, j)
		results <- j * 2
	}
}

func main() {
	// ジョブ用のチャネルと結果用のチャネルを作成
	jobs := make(chan int, 100)
	results := make(chan int, 100)

	// 3つのワーカーゴルーチンを起動
	for w := 1; w <= 3; w++ {
		go worker(w, jobs, results)
	}

	// ジョブを9つ追加
	for j := 1; j <= 9; j++ {
		jobs <- j
	}
	close(jobs)

	// 結果を9つ表示
	for a := 1; a <= 9; a++ {
		fmt.Printf("Result: %d\n", <-results)
	}
}
```
↓上記のコードを動かす(コードをコピーして貼り付けで動作確認出来ます。)↓

https://go-tour-jp.appspot.com/welcome/1

このコードでは、`worker`関数が、ゴルーチンで実行される処理を定義しています。この関数は、`jobs`チャネルからジョブを受け取り、処理を行った後に、`results`チャネルに結果を送信します。

`main`関数内では、まず`jobs`と`results`という2つのチャネルを作成しています。次に、3つのワーカーゴルーチンを起動して、それぞれのワーカーに`jobs`とr`esults`チャネルを渡しています。その後、`jobs`チャネルに9つのジョブを追加し、最後に`results`チャネルから結果を受け取り、表示しています。

このサンプルコードは、並列処理を実現しており、3つのワーカーゴルーチンが同時にジョブを処理し、結果を返す様子が確認できます。

https://zenn.dev/tatsurom/articles/go-routine-and-chanel

https://www.akariinc.com/ja/blog/golang/golang-3-parallel-goroutine

https://golangstart.com/parallel/
個人用apexのSOQL例文

ここで記述するのが自分がよく使う例文です。
//期限内最も適応開始日に近い行を選択する
```
 list<TaxRateMaster__c> tr = [select Id, Name, TaxRate__c,StartDate__c from TaxRateMaster__c where StartDate__c <=:qs[0].LastModifiedDate
                 order by StartDate__c desc limit 1];
```
Azure Administrator(AZ-104)：Azure でのストレージの実装と管理「URIパラメーターとSASパラメーター」

Microsoft Learnを用いたMicrosoft Azure Administrator(AZ-104)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始め、AZ-900取得後の資格としてAZ-104取得を目指している方の参考になれば幸いです。
※AZ-900の内容は本投稿では省略しております。再度復習したい方は下記をご参照ください。
[Azure Fundamentals(AZ-900)：試験合格に向けた学習内容のまとめ](https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8)

## 今回の学習内容
**◆「URIパラメーターとSASパラメーター」**
◇対応するMicrosoft Learn ラーニングパス
[AZ-104:Azure でのストレージの実装と管理](https://learn.microsoft.com/ja-jp/training/paths/az-104-manage-storage/)
◇対応するモジュール
[URI パラメーターと SAS パラメーターを識別する](https://learn.microsoft.com/ja-jp/training/modules/configure-storage-security/4-identify-uri-sas-parameters)

※前回の投稿は下記から確認できます。
[Azure Administrator(AZ-104)：Azure でのストレージの実装と管理「Shared Access Signature」](https://qiita.com/fsd-jume/items/c153f0a656db09c97d54)

## URIパラメーターとSASパラメーター
### URIの構成
・Azure StorageリソースのURIとSASトークンで構成
　-StorageリソースのURI：`https://...`
　-SASトークン：`?sv=...`など「?」以降

**◆SASトークン**
・リソースへのクライアントのアクセス方法を示す
・クライアント側で生成する文字列

**◆SASトークンの署名**
・Storageリソースへのアクセス承認に使用
・クエリパラメーターの一つであり、SASパラメーターで作成
・下記を使用してSASトークンに署名可能
　-ユーザ委任キー
　-ストレージアカウントキー(共有キー)

**◆SASトークン使用の流れ**
①SASを作成し、クライアントアプリに配布
※配布対象：ストレージアカウント内のリソースへのアクセスを必要とするアプリ
②クライアントアプリから、要求の一部としてSAS URIをAzure Storageに提供
③サービスがSASパラメーター/署名をチェック
④署名が有効：要求が承認
⑤署名が無効：要求はエラーコード403で拒否

### URIの定義とパラメーター
・例：下記のアクセス許可を付与するサービスSAS
　-BLOBに対する読み取り
　-BLOBに対する書き込み

```:URI
https://myaccount.blob.core.windows.net/sascontainer/sasblob.txt?sv=2019-02-02&st=2019-04-29T22%3A18%3A26Z&se=2019-04-30T02%3A23%3A26Z&sr=b&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https&sig=Z%2FRHIX5Xcg0Mq2rqI3OlWTjEg2tYkboXr1P9ZUXDtkk%3D
```

**・`https://myaccount.blob.core.windows.net/sascontainer/sasblob.txt`**
リソースURI
**・sv=2019-02-02**
Azure Storageのバージョン
**・st=2019-04-29T22%3A18%3A26Z**
開始時刻(省略ですぐに開始)
**・se=2019-04-30T02%3A23%3A26Z**
期限切れ日時
**・sr=b**
リソース(今回はBLOB)
**・sp=rw**
アクセス許可(今回はread/write)
**・sip=168.1.5.60-168.1.5.70**
許可されるIP範囲
**・spr=https**
許可されるプロトコル
**・sig=Z%2FRHIX5Xcg0Mq2rqI3OlWTjEg2tYkboXr1P9ZUXDtkk%3D**
署名

## 次の学習内容
**◆Azure Storageの暗号化**

https://qiita.com/fsd-jume/items/21f5da17db39d78481b1

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/6eda24728c9c03c36bc3
MacのpythonでGS1 Data Matrix を生成する方法

GS1 Data Matrix（データマトリックス）を生成するのに手こずったのでメモ。

データマトリックス（バーコード）は以下のような画像になります。
製品の識別や追跡、情報の管理などに使用されます。
![dmtx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1810463/db3dff54-d0ce-ae23-7f66-f4c0ee374590.png)

## 現在の環境
- 機種: M1 MacBook Pro
- OS: MacOS Ventura
- python: Python 3.10.4

## ライブラリのインストール
こちらのページの手順に沿って行いました。
https://pypi.org/project/pylibdmtx/


Homebrewでlibmtxをインストール。
```shell
> brew install libdmtx
```
インストールを確認します。
```shell
> find /opt/homebrew -name libdmtx\*

/opt/homebrew/Cellar/libdmtx/0.7.7/include/dmtx.h
/opt/homebrew/Cellar/libdmtx/0.7.7/lib/libdmtx.0.dylib
/opt/homebrew/Cellar/libdmtx/0.7.7/lib/pkgconfig/libdmtx.pc
/opt/homebrew/Cellar/libdmtx/0.7.7/lib/ (2 other files)
/opt/homebrew/Cellar/libdmtx/0.7.7/share/man/man3/libdmtx.3
```

pythonのlibdmtxラッパーをインストール。
```shell
> pip install pylibdmtx
```

pythonのインタラクティブシェルに入ります。
```
> python3
Python 3.10.4 (main, Jul  8 2022, 12:41:13) [Clang 13.1.6 (clang-1316.0.21.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
```

上記参考ページのExample usageを実行します。
デコードが先に書いてありますが、今回はエンコードだけできたらいいので、エンコードは飛ばします。
ただしデコードのインポート部分は必要になります。
１行ずつコピペして実行します。
```
>>> from pylibdmtx.pylibdmtx import decode
>>> from pylibdmtx.pylibdmtx import encode
>>> from PIL import Image
>>> encoded = encode('hello world'.encode('utf8'))
>>> img = Image.frombytes('RGB', (encoded.width, encoded.height), encoded.pixels)
>>> img.save('dmtx.png')
>>> print(decode(Image.open('dmtx.png')))
[Decoded(data=b'hello world', rect=Rect(left=9, top=10, width=80, height=79))]
```

と、すんなり動けば成功ですが、下記のエラーに悩まされました。
```
raise ImportError('Unable to find dmtx shared library')
```

色々検索してみたものの、改善されず。
試しに Intel MacBook Pro で試したらすんなり動くという謎……
その後も検索を続けて、たどり着いたページ。
https://github.com/dmtx/libdmtx/issues/31
ページの下の方にあるシンボリックリンクを貼るという方法で解決しました
```
sudo ln -s /opt/homebrew/lib/libdmtx.dylib /usr/local/lib/
```
以上、何かの参考になれば幸いです。
【Laravel】BreezeとJetstremの違い

Laravelの認証機能を実装するために使用するBreezeと
Jetstremの違いをまとめました。

# Jetstream

Laravel8から登場。
機能が充実しているが使いにくい。

Livewire版
Bladeファイルを扱う。

Inertia版
Vue.jsを扱う。

### 機能

・ログイン/登録
・メール認証
・2段階認証
・セッション管理
・プロフィール更新
・チーム管理機能
・APIサポート(Laravel Sanctum)

# Breeze

Jetstreamの簡易版。

### 機能

・ログイン/登録
・パスワードリセット
・メール認証などのオプション

※2段認証やチーム機能が入っていない
SymPy 1.11 documentation「Hongguang Fu’s Trigonometric Simplification 」を調べた。simplify,trigsimp,expand_trigも

sympy.simplify.fu.TR12(rv, first=True)だけです。

オリジナル

https://docs.sympy.org/latest/modules/simplify/fu.html#sympy.simplify.fu



# sympyで(TR12)
異なるs,tで計算後,subsしています。

sympy.simplify.fu.TR12(rv, first=True)

https://docs.sympy.org/latest/modules/simplify/fu.html#sympy.simplify.fu.TR12


```python
from sympy import *
from sympy.simplify.fu import TR12
s=Symbol('s',real=True,positive=True)
print("#",TR12(tan(t + t)))
print("#",TR12(tan(s + t)))
print("#",TR12(tan(s + t)).subs({s:t}))
# tan(2*t)
# (tan(s) + tan(t))/(-tan(s)*tan(t) + 1)
# 2*tan(t)/(1 - tan(t)**2)
```
①私の環境は,pycharmです。
②よく聞くのは、Jupyterです。
③web上で、上記のソースを「SymPy Live shell」に、コピー貼り付けでもできました。
黒背景の右上に、マウスを移動すると、コピーマークが発生します。
資源の無駄使い。ごめんなさい。

https://live.sympy.org/


# 参考

https://docs.sympy.org/latest/tutorials/intro-tutorial/simplification.html#trigonometric-simplification





# simplify,trigsimp,expand_trig

```python
from sympy import *
t=symbols("t",real=True)
f=(1/sin(t)+1/cos(t))**2
print("#",simplify(f))
print("#",trigsimp(f))
print("#",expand_trig(f))
# 8*(sin(2*t) + 1)/(1 - cos(4*t))
# (1/cos(t) + 1/sin(t))**2
# (1/cos(t) + 1/sin(t))**2
```
NUCLEO-G031K8ではHAL_GPIO_EXTI_Callback関数が使えない。

# HAL_GPIO_EXTI_Callback関数が動かない

主題の通り、NUCLEO-G031K8を使って外部割り込みを試みたが、HAL_GPIO_EXTI_Callback関数を呼び出してるのに全く割り込んでくれない。
```c:Core\Src\main.c
/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if (GPIO_Pin == GPIO_PIN_0)
	{
		HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET);
	}
	else
	{
		__NOP();
	}
}
/* USER CODE END 4 */
```

公式のチュートリアルそのままなのに、動いてくれない。

# そもそもHAL_GPIO_EXTI_Callback関数が存在しなかった。
試しに、HAL_GPIO_EXTI_Callback関数を検索したら全くヒットしない。
おかしいと思ってstm32g0xx_hal_gpio.cを覗いてみたらそもそもHAL_GPIO_EXTI_Callback関数が存在しなかった。
そりゃ動きません。
```c:Drivers\STM32G0xx_HAL_Driver\Src\stm32g0xx_hal_gpio.c
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  /* EXTI line interrupt detected */
  if (__HAL_GPIO_EXTI_GET_RISING_IT(GPIO_Pin) != 0x00u)
  {
    __HAL_GPIO_EXTI_CLEAR_RISING_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Rising_Callback(GPIO_Pin);
  }

  if (__HAL_GPIO_EXTI_GET_FALLING_IT(GPIO_Pin) != 0x00u)
  {
    __HAL_GPIO_EXTI_CLEAR_FALLING_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Falling_Callback(GPIO_Pin);
  }
}

/**
  * @brief  EXTI line detection callback.
  * @param  GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
  * @retval None
  */
__weak void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(GPIO_Pin);

  /* NOTE: This function should not be modified, when the callback is needed,
           the HAL_GPIO_EXTI_Rising_Callback could be implemented in the user file
   */
}

/**
  * @brief  EXTI line detection callback.
  * @param  GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
  * @retval None
  */
__weak void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(GPIO_Pin);

  /* NOTE: This function should not be modified, when the callback is needed,
           the HAL_GPIO_EXTI_Falling_Callback could be implemented in the user file
   */
}
```

# 解決
今回は立ち下がりで割り込んでほしかったので、HAL_GPIO_EXTI_Falling_Callback関数を使った。
```c:Core\Src\main.c
void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
{
	if (GPIO_Pin == GPIO_PIN_0)
	{
		HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET);
	}
	else
	{
		__NOP();
	}
}
/* USER CODE END 4 */
```

これで動いてくれた。良かった良かった。
ChatGPTは数字に強いのか？

## はじめに ##
文章で質問を行えるChatGPTですが文章によっては謎の回答や間違った回答をしてしまう事がわかりました．
では，数字の扱いはどうなのでしょうか．
今回はソートや数値のカウントを試してみました．

## 入出力文 ##
~~~ :ChatGPTの回答
質問：1,3.14,-2,0,1/2を昇順に並べて下さい
-2, 0, 0.5, 1, 3.14


質問：1,3.14,-2,0,1/2を降順に並べて下さい
3.14, 1, 0.5, 0, -2

質問：√２,0,1/9，πを降順に並べて下さい
π, √2, 1/9, 0

~~~

昇順，降順を把握しており，小数，分数，負の数，記号も判別できていますね．
並び順も正しいです．
しかし，分数は割り切れる数の場合小数に変換されるようになっているようです．
ソートに関しては問題なく動作していますね．

~~~　:ChatGPTの回答
質問：3,3,2,5,1,6,4,8,3,7,3,8,8,8,8,8,9を数値別に出現回数を表記してください

1: 1回
2: 1回
3: 4回
4: 1回
5: 1回
6: 1回
7: 1回
8: 6回
9: 1回

~~~

出現回数のカウントも問題なく行えます．
半角，全角は別の文字として扱われるので注意が必要です．

~~~　　:ChatGPTの回答
質問：3,3,2,5,11,6,4,8,3,7,3,8,8,8,8,8,9を
1以上9以下の値について数値別に数値小さい順に出現回数を表記してください．
出現回数が0回の場合は0回と表記してください

1: 0回
2: 1回
3: 4回
4: 1回
5: 1回
6: 1回
7: 1回
8: 7回
9: 1回

~~~

出力する値に条件を付け．はずれの値も入れてみましたが問題ないですね．
似たような表記でも1~9や1から9のような表記方法だと0や11を回答に含んでしまう場合もありました．
数値の扱いに関してはChatGPTの信頼性は高いのではないでしょうか．
HTTPのメソッドについておさらいしようとしたら、奥が深かった。って話。

## きっかけ
Twitter上で、全部GETでやりゃいいじゃん、的な言葉を見たので、
改めてちゃんと調べてみようと思った。

## HTTPのメソッド

1. GET
指定されたリソースの表現を**取得**するために使用される。
URIから中身を取得するだけで、変更することはない。

1. POST
新しいリソースを**作成**するために使用される。
通常、リソースを作成、更新、または削除するときに使用され、
サーバーが作成した新しいリソースののURIを取得する。

1. PUT
指定されたURIのリソースを**置き換える**ために使用される。
リクエストのボディにリソースの内容が含まれ、
指定されたURIでリソースが存在する場合は置き換え、
存在しない場合は、新しいリソースを作成する。

1. PATCH
指定されたURIのリソースを**部分的に更新**するために使用される。
リクエストのボディに更新の部分があり、
指定されたURIのリソースを部分的に更新する。

1. DELETE
指定されたURIのリソースを**削除**するために使用される。
URIのリソースを削除し、削除に成功した場合は
204 No Contentステータスコードを返す。

1. HEAD
GETメソッドと同じように動作するが、レスポンスボディを含まない。
指定されたURIのリソースが存在するかどうかを**確認**するために使用される。

1. OPTIONS
指定されたURIに対するHTTP**メソッドのリストを取得**するために使用さる。

※まだ他にもあるけど、今回は主要なやつだけ


## 調べていく中で思い出したこと
インターネットの歴史みたいな本か何かで、HTTPを設計したとき、
ブラウザ（開発当時はそういう概念はなかったが）からファイルの操作ができたらいいな、
という、
狙いがあったって話を思い出しました。

それがあって、プログラムでやってるような
ファイル操作(GET, POST, PUT, PATCH, DELETE)や
違うサーバー間でやり取りするための情報取得(HEAD, OPTIONS)なんて
メソッドが生まれたのかと思いました。

個人的なプロジェクトでAPI部を改良しているのですが、
記載データを修正するときに
　元データを修正 →　JSON化
　 → バッファサーバー（と呼んでる一時置き場）更新（※API返答コンテンツ）
という流れでやっているのを
HTTP経由でPATCHで置き換えるなんてこともできるのかな、
なんてことを考えました。

いままでPATCHやOPTIONSの存在に気づいてなかったんで、
なにか機会があったらいじってみようかと。


## 参考
[RFC 9110: HTTP Semantics](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods)
github上にpushしたcommitを取り消す方法の１例

## 手順

#### 1.手元のブランチから直前のcommitを消す

```
git reset --hard HEAD^
```


#### 2. リモートブランチを手元のcommit履歴に無理やり合わせる

```
git push --force
```

以上になります。

## 注意点
この記事はcommit履歴をきれいにすることを目的としたものになっており、実行すると対象のcommitした内容が完全に消えます。
汚くてもいいからcommit履歴を残したいという方は`revert`について記載のある別の記事をご参考ください。

もしよく考えず`git reset`して元に戻したい方は、[この記事](https://tech-blog.rakus.co.jp/entry/20210528/git)の`git reflog`の部分に従ってコマンドを打っていただければと思います。
[AWS Q&A 365][CloudFront]AWSのよくある問題の毎日5選 #18

# 1. Amazon CloudFrontとは何ですか？そして、どのように機能しますか？
回答：Amazon CloudFrontは、低遅延、高転送速度でグローバルの顧客にデータ、動画、アプリケーション、APIを安全に配信するコンテンツ配信ネットワーク（CDN）です。CloudFrontは、世界中のエッジロケーションでコンテンツをキャッシュし、ユーザーがコンテンツを要求するときには最も近いエッジロケーションから配信されるため、より高速で信頼性の高い配信が可能になります。

# 2. Amazon CloudFrontのユースケースは何ですか？
回答：Amazon CloudFrontのユースケースには、静的ウェブサイトコンテンツ配信の高速化、ビデオオンデマンドやライブストリーミングビデオの提供、システム処理中の特定のフィールドの暗号化、エッジでのカスタマイズ、Lambda@Edgeカスタマイゼーションを使用したプライベートコンテンツの提供などがあります。

# 3. Amazon CloudFrontを使用するにはどうすればよいですか？
回答：Amazon CloudFrontを使用するには、AWSアカウントにサインアップし、管理者ユーザーを作成し、AWS Command Line InterfaceまたはAWS Tools for Windows PowerShellを設定し、AWS SDKをダウンロードする必要があります。これらを行った後、CloudFrontディストリビューションを作成し、コンテンツをAmazon S3にアップロードし、CloudFrontを介してコンテンツにアクセスすることができます。

# 4. Amazon CloudFrontでファイルURLをカスタマイズするにはどうすればよいですか？
回答：Amazon CloudFrontでファイルURLをカスタマイズするには、独自のドメイン名（example.com）を使用したり、URLにスラッシュ（/）を追加したり、制限されたコンテンツに対して署名付きURLを作成したりすることができます。

# 5. Amazon CloudFrontでキャッシュと可用性を最適化するにはどうすればよいですか？
回答：Amazon CloudFrontでキャッシュと可用性を最適化するには、Origin Shieldを使用したり、クエリ文字列パラメーターに基づいてキャッシュしたり、CloudFrontがオブジェクトをキャッシュする時間を指定したりすることができます。また、エッジロケーションでキャッシュを使用することでキャッシュヒット率を向上させることもできます。
[AWS Q&A 365][CloudFront]Daily Five Common Questions #18

# 1. What is Amazon CloudFront and how does it work? 
Answer: Amazon CloudFront is a content delivery network (CDN) that securely delivers data, videos, applications, and APIs to customers globally with low latency, high transfer speeds, all within a developer-friendly environment. CloudFront works by caching content at edge locations around the world, so when a user requests content, it is delivered from the nearest edge location, providing faster and more reliable delivery. 

# 2. What are the use cases for Amazon CloudFront? 
Answer: The use cases for Amazon CloudFront include accelerating static website content delivery, serving video on demand or live streaming video, encrypting specific fields throughout system processing, customizing at the edge, and serving private content by using Lambda@Edge customizations. 

# 3. How can I get started with Amazon CloudFront? 
Answer: To get started with Amazon CloudFront, you need to sign up for an AWS account, create an administrative user, set up the AWS Command Line Interface or AWS Tools for Windows PowerShell, and download an AWS SDK. Once you have done that, you can create a CloudFront distribution, upload your content to Amazon S3, and access your content through CloudFront. 

# 4. How can I customize file URLs in Amazon CloudFront? 
Answer: To customize file URLs in Amazon CloudFront, you can use your own domain name (example.com), use a trailing slash (/) in URLs, or create signed URLs for restricted content. 

# 5. How can I optimize caching and availability in Amazon CloudFront? 
Answer: To optimize caching and availability in Amazon CloudFront, you can use Origin Shield, cache based on query string parameters, and specify how long CloudFront caches your objects. You can also improve your cache hit ratio by using caching with edge locations.
pythonのsubprocesの仕様が変

python3のsubprocess,コマンドラインの引数を分割して入力しないといけない。
そうでなければ,shell=Trueを使えと。どういう開発体制なのがしらないがなにかおかしい。

commandsモジュールもなくなったし右往左往している印象がある。使い方が異常に面倒なsubprocessなんとかならんかな。

pythonのos呼び出し関係がなかなかにまともにならなくてつらいな。
os.systemしか使う気にならん。
Azure Firewall ルール検証ツール

Azure Firewall を利用している際にどのルールで許可、拒否されているかを確認したい場合、診断ログが有効であればログから確認することができますが、まだ発生していないトラフィックがどうなるかなど、特定の送信元、宛先を元にトラフィックをテストするような機能は現状ありません。

https://learn.microsoft.com/ja-jp/azure/azure-monitor/reference/tables/azfwnetworkrule

そこで Azure Firewall のチェックツールを Powershell で作成してみました。Windows 10,11 であれば動作することを確認済みです。作業時のヒントとしてご利用いただければ幸いです。
IP アドレス、サービスタグの判定については https://www.syuheiuda.com/?p=4158 の "Check-AzureIpAddress.ps1" 内のロジックを参考に作成しております。

## 利用シナリオ
- Azure Firewall にルールを追加する前に事前に許可、拒否を確認したい
- トラブルシューティングの一環で影響する可能性があるルールを一覧で出力したい
- SYN/ACK が拒否されるパターンに該当していないか確認したい

## 利用方法
以下の "Check-AzureFirewall-Rules-FWPolicy.ps1" ファイルを Powershell で実行します。親ポリシーは現状考慮できておりません。※ Classic を利用している場合、xx-Classic.ps1 を利用

https://github.com/ms-ishiyam/AzureFirewall-Tools

### コマンド構文

~~~
.\Check-AzureFirewall-Rules-FWPolicy.ps1 `
 -protocol TCP `
 -SourceIpAddress 192.168.0.4 `
 -DestinationIpAddress 10.200.0.4 `
 -DestinationPort 80 `
 -FW_ARMTemplateFilePath "C:\work\tools\FWpolicy.json" `
 -IPG_ARMTemplateFilePath "C:\work\tools\IPgroup.json" `
 -ServiceTagFilePath "C:\work\tools\ServiceTags_Public_20230320.json"
~~~

### パラメーター
|Prameter|Mandatory|Allowed value|Additional Info|
|:---|:---|:---|:---|
|$Protocol|true|TCP/UDP/ICMP||
|$SourceIpAddress|true|IPv4 Address||
|$DestinationIpAddress|false|IPv4 Address|DestinationIpAddress または DestinationFQDN は必須です|
|$DestinationFQDN|false|FQDN|Not wildcard|
|$DestinationPort|true|Port Number||
|$FW_ARMTemplateFilePath|true|File Path|Firewall Policy or Firewall ARM Template|
|$IPG_ARMTemplateFilePath|false|File Path|IP Group ARM Template. ファイルは一つである必要があります。また、グループ名もユニークである必要があります。指定がない場合、IP Group が含まれるルールの精査はしません。|
|$ServiceTagFilePath|false|File Path|もし、サービスタグファイルがない場合、インターネットから取得します。指定した宛先が Private IP (IANA Range) である場合、サービスタグの精査は行いません。|

### 有効なルール
|DNAT|NetworkRule|ApplicationRule|
|:---|:---|:---|
|NotSupported|Supported (IP/IPGroup/ServiceTag/FQDN)|Supported (FQDN のみ)|

### 実行結果例
以下の拒否、許可の該当するすべてのルールを出力し、最もプライオリティが高い Action を元にトラフィックの Allow/Deny を表示します。

宛先が IP アドレスの場合：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/206b925b-74a5-7f0b-d000-526e5240e125.png)

宛先が FQDN の場合 (NetworkRule, ApplicationRule 両方を評価)：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/94c155f5-6e79-b731-949b-5c59957a143b.png)


もし、以下の様に **"Traffic : Deny (Return packet [SYN/ACK] is denied.)"** と表示されたら SYN/ACK パケットが拒否される可能性があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/64c26a40-b2d4-5330-75a1-125181d4f449.png)

https://learn.microsoft.com/ja-jp/azure/firewall/rule-processing#three-way-handshake-behavior

:::note warn
VNet-A から VNet-B への許可規則を作成しても、VNet-B から VNet-A への新たに開始される接続が許可されるわけではありません。

そのため、VNet-B から VNet-A への明示的な拒否規則を作成する必要はありません。 この拒否規則を作成すると、VNet-A から VNet-B への最初の許可規則の 3 方向ハンドシェイクを中断することになります。
:::
【ドラゴンボール風解説】EC2 リザーブドインスタンスについて

# はじめに
この記事はAWSの説明は今ひとつよくわからないのでドラゴンボールに例えて説明してほしい。
というAWS初学者向けの記事です。
※投稿記事作成にはchatGPTを使用しております

# EC2 リザーブドインスタンス
「なんだかんだでオラ、AWSのクラウドコンピューティングサービスにはお世話になっているんだぜ。その中でも、EC2という仮想サーバーの利用料金を安くする方法があるんだ！それが、**リザーブドインスタンスだ**！

リザーブドインスタンスは、サーバーをレンタルするってことだ！長期的にサーバーを借りる場合には、リザーブドインスタンスを使えば、利用料金を安くすることができるんだ！まさに、あいつらサイヤ人が、**長期間の戦いの**ために身に付ける技みたいなもんだぞ！

しかも、リザーブドインスタンスを使うと、バトル時に使うパワーをより効率的に使えるようになるんだ！例えば、**毎日同じ時間帯にサーバーを使用する場合**には、リザーブドインスタンスを使うと、パワーの消費量を減らせるぞ！

しかし、リザーブドインスタンスは、長期契約のため、**バトル中に柔軟に戦略を変更することはできない**場合もある。だから、リザーブドインスタンスを使う場合には、事前に計画を練っておく必要があるんだ！

それにしても、AWSの技術はすごいな！界王神界の高度な技術を思い出すぞ！」
Tabler Iconsのアイコンを動的に使用する

## はじめに
[Mantine](https://mantine.dev/)のサイト内では基本的に各種アイコンに[Tabler Icons](https://tabler-icons.io/)が利用されており、コンポーネントの利用例にもTabler Iconsが使用されています。（[これ](https://mantine.dev/core/theme-icon/)とか）  
Tabler Iconsのアイコンを動的に利用したい場面があったのですが、公式ドキュメントを見ても任意のアイコンを利用するケースでのコードしか載っておらず、日本語でその方法を掲載している記事が見つからなかったため、記録として残しておきます。

## 実装
例えば下記のようなデータがあったとします。
```jsx
const categories = [
  {
    name: '食事',
    icon: 'IconFish',
  },
  {
    name: '書籍',
    icon: 'IconBook',
  },
  {
    name: '病院',
    icon: 'IconBuildingHospital',
  },
]
```

`icon`の値には、通常アイコンを利用する際、importに記述する値を入れています。

![スクリーンショット 2023-03-23 22.06.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359978/00824972-e8e1-b439-7fbb-7085c578cbe4.png)

ひとまず横並びに表示させようとします。
```jsx
import { Flex, ThemeIcon } from '@mantine/core'
import * as icons from '@tabler/icons'

const categories = [
  {
    name: '食事',
    icon: 'IconFish',
  },
  {
    name: '書籍',
    icon: 'IconBook',
  },
  {
    name: '病院',
    icon: 'IconBuildingHospital',
  },
] as const

function Demo() {
  return (
    <Flex gap="xs">
      {categories.map((category, i) => (
        <ThemeIcon key={i}>
          {ここにアイコン表示させたい}
        </ThemeIcon>
      ))}
    </Flex>
  )
}

export default Demo
```

`{ここにアイコン表示させたい}`の箇所にアイコンを表示させるために、`JSX.Element`を返す関数を作成します。

```jsx
import * as icons from '@tabler/icons'

...省略

type Props = {
  icon: keyof typeof icons
}

const TablerIcons = (props: Props) => {
  const { icon } = props
  const Icon = icons[icon]

  return <Icon />
}
  
...省略

<ThemeIcon key={i}>
  <TablerIcons icon={category.icon} />
</ThemeIcon>
```

無事、動的にアイコンを表示できることができました🎉

![スクリーンショット 2023-03-23 22.22.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359978/7d46bd5f-69e3-2b4f-69c7-bb5e8e24f238.png)

### 最終コード
```jsx
import { Flex, ThemeIcon } from '@mantine/core'
import * as icons from '@tabler/icons'

const categories = [
  {
    name: '食事',
    icon: 'IconFish',
  },
  {
    name: '書籍',
    icon: 'IconBook',
  },
  {
    name: '病院',
    icon: 'IconBuildingHospital',
  },
] as const


type Props = {
  icon: keyof typeof icons
}

function Demo() {
  const TablerIcons = (props: Props) => {
    const { icon } = props
    const Icon = icons[icon]

    return <Icon />
  }

  return (
    <Flex gap="xs">
      {categories.map((category, i) => (
        <ThemeIcon key={i}>
          <TablerIcons icon={category.icon} />
        </ThemeIcon>
      ))}
    </Flex>
  )
}

export default Demo
```

## 参考
[Dynamic Tabler Icons import for react](https://gist.github.com/aleyrizvi/036b05e948307c28affdb4e16045f2dc)

## 最後に
### GoQSystemでは一緒に働いてくれる仲間を募集中です！
ご興味がある方は以下リンクよりご確認ください。

https://goqsystem.recruit.site/?qiita=e10721b4172e2fea9a8f
Powershellでのecho、Write-Host、Write-Outputの違い

**Powershell**で下記の3つのコマンドの出力結果の違いを検証しました。

```Powershell
############################################
#   echo、Write-Host、Write-Outputの違い    ###
#  新規作成  2023/3/29                    ###
############################################


Write-Host "***** echo コマンドの出力結果"
echo $PSVersionTable

Write-Host "***** Write-Host コマンドの出力結果"
Write-Host $PSVersionTable


Write-Host "***** Write-Out コマンドにパイプでFormat-Listの出力結果"
Write-Output $PSVersionTable | Format-List

```

出力結果です
echo コマンドの結果
```
Name                           Value                                                                                                 
----                           -----                                                                                                 
PSVersion                      5.1.19041.2673                                                                                        
PSEdition                      Desktop                                                                                               
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                                                               
BuildVersion                   10.0.19041.2673                                                                                       
CLRVersion                     4.0.30319.42000                                                                                       
WSManStackVersion              3.0                                                                                                   
PSRemotingProtocolVersion      2.3                                                                                                   
SerializationVersion           1.1.0.1              
```

Write-Hostでの出力結果

```
***** Write-Host コマンドの出力結果
System.Collections.DictionaryEntry System.Collections.DictionaryEntry System.Collections.DictionaryEntry System.Collections.Dictionary
Entry System.Collections.DictionaryEntry System.Collections.DictionaryEntry System.Collections.DictionaryEntry System.Collections.Dict
ionaryEntry
```

Write-OutputにパイプでFormat-Listを付けたときの結果

```
Name  : PSVersion
Value : 5.1.19041.2673

Name  : PSEdition
Value : Desktop

Name  : PSCompatibleVersions
Value : {1.0, 2.0, 3.0, 4.0...}

Name  : BuildVersion
Value : 10.0.19041.2673

Name  : CLRVersion
Value : 4.0.30319.42000

Name  : WSManStackVersion
Value : 3.0

Name  : PSRemotingProtocolVersion
Value : 2.3

Name  : SerializationVersion
Value : 1.1.0.1
```

以上のように違いが出ます。