OmniAICreator/Qiita-1.07M huggingface dataset:
「誰かがアダプティブ カードに応答した場合」が二重に実行されてしまう

# 概要
Power Automate のフローが特定の状況で二重に実行されてしまう挙動です。 
具体的には、**「誰かがアダプティブ カードに応答した場合」** *(When someone responds to an adaptive card)* をトリガーにしたフローの場合に、所有者を`自分`と`自分を含むセキュリティグループ(Teamsのグループなど)`にした場合に、 **1回のAction.Submitでフローが2回トリガーされます**。

:::note info
「When someone responds to an adaptive card」を使ったフローのサンプルとして、こちらを使って検証していきます。
[Power Autoate でタケノコニョッキをするフロー(@ksgiksg)
](https://qiita.com/ksgiksg/items/c3e626e54d084edeea9e)
:::


# 具体的な症例
## 所有者が自分自身のみ の場合
まずは通常の挙動です。
**所有者が自分自身のみ**の場合は、アダプティブカードのボタンを押しても1度だけトリガーされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/60b0f81c-72c3-7adb-9b4b-a73ff28bfe11.png)

このフローはトリガーされて実行されるたびに新しい投稿が追加されるフローですが、想定した挙動の通り、ボタンを押すたびに新しい投稿が1つ増えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/3e34823c-e0a1-2e74-1c35-e94f9c515994.png)

## 所有者にほかのユーザーを追加した場合
自分以外のユーザーを所有者に追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/4eb3d595-0266-3b9c-2202-b754ffebd610.png)

この場合も1回だけトリガーされました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/c4ec9762-aa2d-c453-d1cd-bb05e33c1f1e.png)


## 所有者に自分が所属していないグループを追加した場合
次にグループを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/c1d7cf5f-8a19-f0c2-f9fe-e4fe05deb2eb.png)

このグループには、自分(おいしみ)は所属していません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/cde17b87-406b-baa4-5e9a-01de1321c8a3.png)

この場合も1回だけトリガーされました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/9e65d0b6-cf9e-dffc-0340-91cdc3c73355.png)

## 所有者に自分が所属してるグループを追加した場合
次は自分の所属するグループを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/ffef1d38-4c6b-5e4b-b797-860fb7b099ec.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/03b3302f-0712-4251-bb6e-9c35bcbaf7ce.png)

このとき、アダプティブカードのボタンを1度押しただけで、2回のトリガーされてしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/8554f329-987d-7ab2-85b3-3133df051043.png)

ちなみに、この2つの実行を見分けて、片方を破棄することができればよかったのですが、トリガーの出力にはどちらか一方を破棄するのに分別できるプロパティは見つかりませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/9554a74b-ef6b-1e74-96e8-b780ddd05b39.png)

個人的に、チームで管理したいフローはTeamsのグループアドレスで共有することが多いので、この問題には少し困っています・・・。

# その他の既知の問題や制限
直接関連しませんが、このトリガーの既知の問題と制限をまとめておきます。
- 既定の環境でのみ機能
- ゲスト ユーザーには許可されません
- Adaptive Cardを送ったユーザーがオーナーのフローのみトリガー可能

https://learn.microsoft.com/ja-jp/connectors/teams/#%E3%83%88%E3%83%AA%E3%82%AC%E3%83%BC%E3%81%AE%E6%97%A2%E7%9F%A5%E3%81%AE%E5%95%8F%E9%A1%8C%E3%81%A8%E5%88%B6%E9%99%90

https://mofumofupower.hatenablog.com/entry/teams_adaptive_trigger
ROS2でキーボードを押すとトピックをPublishするPythonコード

# 経緯
キーボード押したときに気軽に何かTopic出したくなりました。
他に方法あると思いますので見つけたら追記します。

# コード

```py

import rclpy
from rclpy.node import Node
from geometry_msgs.msg import PoseStamped


class WaypointsPubTest(Node): 
    def __init__(self):
        super().__init__('waypoints_pub_test') 
        self.pose_pub = self.create_publisher(PoseStamped,'goal_pose',10)
        timer_period = 0.01
        self.timer = self.create_timer(timer_period, self.timer_callback)
            
    def timer_callback(self): 
        key = input("f:publish topic <<")
        print("key=", key)
           
        if key == 'f':
            goal_pose = PoseStamped()
            goal_pose.header.frame_id = 'map'
            goal_pose.header.stamp = rospy.get_time()
            goal_pose.pose.position.x = -3.0
            goal_pose.pose.position.y = 0.0
            goal_pose.pose.position.z = 0.0
            goal_pose.pose.orientation.x = 0.0
            goal_pose.pose.orientation.y = 0.0
            goal_pose.pose.orientation.z = 0.0
            goal_pose.pose.orientation.w = 1.0
            
            print("Pressed f")
            self.pose_pub.publish(goal_pose)

def main(args=None):
    rclpy.init(args=args)
    waypoints_pub_test = WaypointsPubTest()
    rclpy.spin(waypoints_pub_test)
    rclpy.shutdown()

if __name__ == '__main__':
    main()

```

# その他
パッケージとして作ってもいいかもしれません。
$ ros2 pkg create --build-type ament_python --node-name waypoints_pub_test waypoints_pub_test_node

実行
ros2 run waypoints_pub_test waypoints_pub_test_node

# 参考
https://demura.net/robot/ros2/20748.html
【私的】3dsMaxの操作方法メモ！

メモです、気が向いたら更新します(と言った記事がたくさん、一向に更新していないのは内緒！)
(画面は3dsMax2021、Mayaは2023です)(間違ってたらごめんね(ㅎ.ㅎ )

Mayaみたいな操作にする方法↓
https://www.cg-method.com/3dx-max-maya-like-settings/

<br>
<br>
<br>
<br>
<br>
<br>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843707/2077e507-3124-8bcf-98d8-0bd496d66c6a.png)
いろいろ出てくる、Boxだったりティーカップ
(最近ブラックコーヒー飲めるようになりました、これで大人(by高2)
<br>
<br>
<br>
赤がタイムラインバー
紫がXYZ
緑が再生とかのやつ
水色がオートキー(動かしたら自動でキーうつやつ)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843707/2444def7-d541-a509-878c-e7c5d288ba20.png)

<br>
<br>

#### 範囲選択の切り替え方法
Control+Fで範囲選択切り替え
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843707/6f585473-2181-468e-9a33-d756d70b30f9.png)

https://gyazo.com/b36a6ae7c65aee188e32424a18c13395

<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>

#### 視点(カメラ)の切り替え方法

上はズーム、視点のリセット
下は視点の移動関連(Wとか右クリックとかしたら解除できる)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843707/302cf951-bc82-1027-7551-58cc8aed22dd.png)


実際にやってみたらわかるよ!!

<br>
<br>
<br>
<br>
<br>
<br>

#### 5度ずつ回転
回転するときにチェックを入れると5度ずつ回転できる
(右クリック→Angleで何度かを調節できる)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843707/5f937bfb-2507-adc5-cf06-6cd82983dc29.png)


<br>
<br>
<br>

#### 画面の分割方法

この矢印みたいなのを押すとでてくるよ
わかりやすい→ https://area.autodesk.jp/movie/start-at-max/02.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843707/dd1b0ecc-d87e-97a2-d99c-172a8822996e.png)


<br>
<br>
<br>
<br>
<br>
<br>


#### Bipedくんをヒョロガリから変える方法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843707/0556272e-0c5b-e7c1-3b37-204833cc23df.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843707/31e60457-19ba-39aa-d581-416d323394ef.png)



<br>
<br>
<br>
<br>
<br>
<br>

#### BIpedのアニメーションを読み込む方法

キーフレームを全て削除
↓
Bipedのリグのどこでもいいんで一部を選択
↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843707/31ae24b0-4441-fa33-48ea-d1392a08e592.png)

あとはBipファイルを読み込む

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843707/4f840301-a39d-7edd-f573-e003190ac867.png)

<br>
<br>
<br>
<br>

#### シェーディングの設定

ボタンカチカチしたらシェーディング変わるよ
(例えば、Flat Colorは影がない、Default Shadingはデフォルトに戻る)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843707/16a56c39-5d36-13ba-7257-4debf7f937a3.png)


<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>

気が向いたら更新しまｓ(以下略)
Ubuntu Server 22.04にBraveをインストールする

## Brave Browserのインストール方法

Braveのインストールは、aptコマンドで行います。

```
sudo apt-get -y install curl
sudo curl -fsSLo /usr/share/keyrings/brave-browser-archive-keyring.gpg https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] https://brave-browser-apt-release.s3.brave.com/ stable main"|sudo tee /etc/apt/sources.list.d/brave-browser-release.list

sudo apt update

sudo apt-get -y install brave-browser
```

これでインストール完了です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85495/1c5b9049-a32d-3d7c-ae9c-b159e15a1e20.png)


### 参考
https://brave.com/linux/
re: Excelでもmermaidしたい

エクセルにMermaidを書き込んでオートシェイプにするやつを作り直した。

![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145884/bf967ae8-a08a-eacb-5391-0ee8464178eb.png)

## 説明
* [githubReleaseよりダウンロード](https://github.com/WaToI/re_xlMdDna/releases)
* zipを解凍してxllを開くとエクセル起動
* mermaid文を入力
* 数式に=mermmaid(mermaid文の範囲)入力
* ブラウザが開く
* Enter-Keyを押すとエクセルに挿入される
> 作成したsvgとemfが **%userprofile%\Documents\xlMdDna** に自動保存されるのでたまに手動掃除が必要


> 注意) 
xllと同根のMicrosoft.Web.WebView2.Core.dllが同一ディレクトリに必要。dllはxllの中に埋め込んでいるのだが、これだけ埋め込むと読みだせなくなる。
![CaptureD.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145884/2d9164d7-291b-679e-ea01-07ff576dfb2d.png)

## 動作環境
* .Net48で動作
* Excel2016（SVG対応バージョン）を推奨
* Excel2016 (SVG非対応バージョン）もしくは2016以前のものは
関数にオプション=mermmaid(range, emfUse:1)
> svgが使えないものはemfに変換して挿入する
SVG対応バージョンでもemfにしないと表記が崩れるものがある。
また、classDiagramはどちらでも表記が崩れるため現状使えない。

![howto01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145884/5b25af0c-97d3-82c9-6ab8-88b86b90c791.png)


> SVG対応しているエクセルなら標準機能でSVG貼り付ければと思うかもしれないが、SVGの文字表記textタグを使わずにspan等で文字をかかれるとテキストとして認識されず変換されないようだ。また、背景色などの装飾が正しく認識されず真っ黒になったりする。ExcelがSVG対応したと聞いてウキウキしながら試してガッカリした人は使ってみてほしい。


ソースは[github](https://github.com/WaToI/re_xlMdDna)
また、Excel-DNAというライブラリを使っているのだが、
たまにウイルス認定されてアンチウイルスに攻撃されるが慌てず冷静に対処してほしい。VSTOより使いやすいのでウイルスに利用されてその対処にExcel-DNAを使用したAddinがすべてウイルス認定されることがあるようだ。

> 説明書くのがつらい。
AIに代弁してもらう方法を模索せねば。
7年前とやってることが変わってない（　＾ω＾）・・・
【SwiftUI】自前で用意した画像の色を変更する

# はじめに
自前で用意した画像の色を変更します。

# 素材
こちらの魚を使います！

https://nureyon.com/bonito-1?pattern=3

黒色で保存します

# 実装
```diff_swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        Image("fish")
            .resizable()
+           .renderingMode(.template)
            .aspectRatio(contentMode: .fit)
            .frame(width: 200)
+           .foregroundStyle(Color.red)
    }
}
```

魚が赤くなりました！！！
![simulator_screenshot_836BD1DA-819B-432B-8BCB-CC6C80CE147B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/b421aab7-a34f-b103-5e3b-0f892b164a36.png)


# おわり
簡単にSFSymbolsが作れるようになって欲しいです。
[Python] 影の薄いfrozensetを救いたい

# はじめに
皆さんは, Pythonの「frozenset」を知っていますか？
恐らく普段Pythonを使っていてもほとんど目にする機会のない、あるいは全く見たこともないと答える方も多いでしょう。importせずに使えるにも関わらず、そのくらい影が薄いのがfrozensetなのです。

実際に、GoogleとQiitaで「Python frozenset」で検索し、組み込み型のコンテナデータ型とのヒット数を比べてみると、次のような結果になりました。(2023/6/25)

| データ型 |Google|Qiita|
|:-:|--:|--:|
|list |1,240,000,000|27,114|
|tuple |27,200,000|2546|
|dict |24,700,000|7898 |
|set |1,050,000,000 |22,218 |      
|**frozenset**|**271,000**|**93**|

そんなfrozensetを何とかして救ってあげようというのが当記事の目標です。

# frozensetの機能と使われない理由
本格的に救う前に（？）まずはfrozensetとは何かについて紹介します。

Pythonの組み込み型には、集合、すなわち被り・順序のないデータのまとまりを示すための型が存在します。「set」と「frozenset」です。この2つは、特定の要素の追加、削除、存在判定が高速なのが特徴です。
その中でも、リストに比べ「存在判定が高速に行える」のは大きな長所で、Qiitaでは過去にこのような記事で取り上げられて話題を呼びました。

[Pythonで"in list"から"in set"に変えただけで爆速になった件とその理由](https://qiita.com/kitadakyou/items/6f877edd263f097e78f4)
(@kitadakyou氏)

では、「set」と「frozenset」の違いは何でしょうか。それは、ミュータブル (変更可能) か、イミュータブル (変更不可能) か、という点です。setでは要素の追加、削除を高速に行えますが、frozensetでは不可能です。つまり、frozensetはsetの機能を限定したものといえます。

とはいえ、「イミュータブル = ミュータブルの劣化版」というわけではなく、例えば同じコンテナデータ型でイミュータブルであるtupleは、listの機能を限定したものですが、意図せぬ要素の書換を防げる、動作が軽いなどの点から多く使われています。

しかし、frozensetはどうでしょう。setでは、集合型の強みの1つである要素の追加、削除が高速に行えましたが、frozensetではできません。これではただ不便なだけです。
また、要素の存在判定も、setとfrozensetで大きな処理速度の差はありません。
そもそも、setが限られた場面でしか使用されないことや、listと異なり添え字アクセスではないことから、listとは違い誤って書き換えられることも少ないです。

つまり、メインの機能において**frozensetはsetの完全劣化版**ということです。劣化版なら、Qiitaで93件しかヒットしなかったのも納得です。

そんなfrozensetに、setと差別化できるポイントなどあるのでしょうか。

# frozensetの使い道(setとの差別化)
この記事を書くにあたり「変更不可能」以外の便利そうな使い道をGoogleに聞きましたが、答えが1件も返ってこなかったので自分で考えました。

重要な差別化ポイント、それは、辞書のキーとして使うことです。
イミュータブルな要素の強みの1つとして、辞書のキーとして使えることが挙げられます。Pythonの辞書はハッシュテーブルが用いられているため、変更不可能な要素でないと使えないようになっています。~~frozensetを辞書のキーとして使う機会があるかは置いておいて~~、setとの差別化の1つといえます。

…
**他の差別化できる点が1つも思い浮かびませんでした！(謝罪)**

# おわりに
**結論:どうあがいても救えない**

もし他のfrozensetの便利な使い道をご存知であれば、ぜひコメント欄で教えてください。
ここまで読んで下さりありがとうございました。
【Git】コンソール上にgitkコマンドで表示されるようなヒストリーを表示する

# 1. はじめに

突然だが、 gitk コマンドを実行したことはあるだろうか？  
あのコマンドはこれまでどんな作業をしてきたのかを、お手軽かつ俯瞰的に把握するのに便利なのだ。  
ただ、別ウィンドウが立ち上がってしまい、そのウィンドウを閉じないと次のコマンドが実行できないようになっているのはいただけないという気持ちもある。  
そこで、コンソール上に gitk で表示されるツリーが表示されるような Alias を組んでみた。  
するとどうだろう、 GUI から Git コマンドを実行するつもりのない自分にとって、コンソールにあのヒストリーが出力されるというのはとても快適だったのだ。  
同じような感受性を持った人が一人くらいはいるだろうと思ったので、この度は作った Alias をこの場を借りて紹介してみたいと思う。  

# 2. 動作環境

- Git がインストールされ、 PATH が通っていること  
  (gitk は Git の標準コマンドのはずなので、 OS は関係ないはず。)

# 3. 手順

## 3.1. ユーザーディレクトリ直下に .bashrc ファイルを配置する。(.bashrc なんて知らないよって人限定)

「もう配置済みだよ」って人はここはスキップして構わない。  
そんなもの知らないよって人のために一言だけ説明すると、 bash を使うための設定ファイルのようなものだ。  
.bashrc で Alias やよく使う処理群をまとめた関数なんかを書いておくと、作業が驚くほど捗る。  
初めて知った人も、知ってたけど面倒くさがっていた人も、これを機に重い腰を上げてみてくれ。  
(Linux 環境であればデフォルトで配置されている可能性も大いにあるが…)

.bashrc の配置先はユーザーディレクトリの直下でなければならない。  
万が一違うディレクトリに配置してしまうと、どんなに作りこんだ設定も有効にならないから注意してほしい。  

## 3.2. コンソール上にgitkで表示されるようなツリーを表示するコマンドを .bashrc に追記する

ここまで来たらやることは簡単だ。  
.bashrc のどこでもいいので、以下の Alias を追記すれば下準備は完了だ。  
Alias 名はなんでもいいが、自分は consol gitk を短縮して cgitk という名前で登録している。  
真似してもらっても構わないし、小一時間悩むのもまた一興だろう。  

```bash
alias cgitk='git log --all --color --graph --pretty=format:"%x09%C(yellow dim)%h%Creset %C(green dim)%cd%Creset %C(cyan dim)%an%Creset %s %C(red)%d%Creset" --date=format:"%Y/%m/%d %H:%M:%S"'
```

上のまま使ってももちろん問題ないのだが、気になる人がいれば配色や出力フォーマットをカスタマイズするのも楽しい時間となるだろう。  
一例として、 %C(yellow dim) や %C(green dim) など、`%C(...)` で囲まれた箇所で色を指定している。  
詳細は以下の公式ページを確認してもらえればと思うが、わかりやすく見栄えが変わるので、一番気軽に楽しめるカスタマイズといえるかもしれない。  
https://git-scm.com/docs/pretty-formats  

## 3.3. 実行してみる

Alias が登録できたところで早速実行してみよう。  
まず初めに、 Git Bash を立ち上げなおすか、 `source ~/.bashrc` を実行して .bashrc を読み込んでもらおう。  
そのあとは `cgitk` と打ち込んで Enter キーを押すだけだ。  

汚いコミットログは見なかったことにしてもらうとして、以下のような出力になる。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2540930/f7b0e5dd-4c7a-6b7d-f337-8c25b5a7c9ce.png)

# おわりに

最後まで読んでいただきありがとう。  
個人的に気に入っているカスタマイズなので、この場を借りて紹介させてもらった。  
読者の一人にでもこのカスタマイズを気に入ってもらえたのであれば嬉しい限りだ。  
それではまたどこかでお会いしよう。
LinuxでMacのopenコマンドを使ってみる

MACのようにLinuxでopenコマンドを使うための工夫。（aliasを活用する）
```
alias open='explorer.exe'
```

WSLとか使ってると、`open .`でWSLのエクスプローラーを開けるので地味に便利。

余談ですが、WindowsのStart、Macのopenに相当するLinuxのコマンドに、`xdg-open`というものがあるそうです。
gem, bundler, gemfileとは？

## はじめに
Ruby 学習で出てきた <b>gem, bundler, gemfile</b> についてメモ程度に載せておきます。

## 目次
1. [RubyGems とは？](#rubygems-とは)
2. [bundler とは？](#bundler-とは)
3. [gem とは？](#gem-とは)
4. [gem コマンドとは？](#gem-コマンドとは)
5. [gemfile とは？](#gemfile-とは)
6. [gemfile.lock とは？](#gemfilelock-とは)
6. [参考文献](#参考文献)

## RubyGems とは？
- Ruby 用の<b>パッケージ管理システム</b>
- gem <b>パッケージのインストール・アンインストール</b>等の操作に使用

※ 最近は <b>bundler</b> というパッケージ管理システムを使うことの方が多いようです。

## bundler とは？
- <b>gem の一種</b>
- 以下のような <b>gem の依存関係を解決しながら、パッケージの一括インストールが可能</b>
  - 「gem A'」を利用するには「gem A」のインストールが必須
  - 特定のバージョン以上の gem に依存している

## gem とは？
- 読み方は<b>ジェム</b>
- RubyGems が管理する <b>Ruby のパッケージ(あるいはライブラリ)</b>
  - ```パッケージ``` ： 開発におけるコーディングのお助け機能をひとまとめにしたもの
- ユーザー登録機能や認証機能等、<b>複雑な機能を簡単に実装可能</b>
- <b>RubyGems = gem</b> とも呼ぶ

## gem コマンドとは？
- <b>gem のインストール・アンインストール</b>等の操作に使用
- <a href="https://rubygems.org/gems">RubyGems.org</a> 等に各種コマンドの記載あり

以下、インストール・アンインストールのコマンドです。

<b>インストール</b> ： 上記で紹介したパッケージ管理ツール```bundler```をインストール
```ruby
gem install bundler
```
インストールされているかどうかは```bundler -v```で確認できます。
<br>

<b>アンインストール</b>
```ruby
gem uninstall bundler
```
インストールされている gem のリストは```gem list```で確認できます。

## gemfile とは？
- Rails アプリで必要な<b> gem の一覧が記述されているファイル</b>
- <b>gem のバージョン管理</b>を行うもの
- エラーの原因となる<b> gem のバージョン違い</b>が起こらないようにしてくれる

## gemfile.lock とは？
- <b>gemfile に記載された gem のバージョンや依存関係の解決結果</b>が記録されたファイル
- <b>bundler での gem インストール</b>の際に記録されていく
- bundler が自動更新するため、<b>手動では触れないファイル</b>

## 参考文献
<a href="https://pikawaka.com/ruby/how-gem-works">【Ruby】 gemの仕組みを図解形式で学ぼう</a>
<a href="https://pikawaka.com/rails/bundler">【Rails】 結局bundlerって何？bundlerの仕組みを図解形式で徹底解説</a>
【AWS】ECS on Fargateにおけるセキュリティグループの更新方法

最近、ECS on Fargateのセキュリティグループの更新に思いの外手こずりました。今回は私が調査した更新手順について共有したいと思います。

# ECSにおけるセキュリティグループの設定方法
ECSでは、セキュリティグループをタスク定義レベルではなく、ネットワークインターフェース(ENI)またはECSサービスレベルで設定する必要があります。ECS on EC2ではEC2インスタンスやAuto Scalingグループの設定でセキュリティグループを指定しますが、ECS on Fargateでは、ECSサービスのnetworkConfigurationパラメータで指定します。

# ECSサービスのネットワーク設定のアップデート
ECSサービスのネットワーク設定を更新するには、AWS CLIを使用します。具体的には、以下のコマンドを実行することで新しいセキュリティグループIDを指定します。

```bash
$ aws ecs update-service --cluster your-cluster-name --service your-service-name --network-configuration "awsvpcConfiguration={subnets=[subnet-1,subnet-2],securityGroups=[sg-1,sg-2],assignPublicIp=ENABLED}"
```

このコマンドでは、ECSクラスタ名、サービス名、サブネットID、セキュリティグループIDをそれぞれ適切に置き換える必要があります。また、assignPublicIp の値を ENABLED または DISABLED に設定することで、公開IPアドレスの割り当てを制御できます。

# ECSサービスのタスク更新
次に、タスクまたはサービスを更新し、新しいセキュリティグループ設定で新しいタスクを起動します。これは、タスクが起動する際にネットワーク設定が決定され、タスクが終了するまでその設定は変更できないためです。

サービスの設定を更新すると、新しいタスクが起動し、既存のタスクが停止します。その際、以下のコマンドを使用します。

```bash
$ aws ecs update-service --cluster your-cluster-name --service your-service-name --force-new-deployment
```

このコマンドを実行すると、サービスは新しいタスクを起動し、既存のタスクを停止します。このとき、新しいタスクが起動される際に、先ほど更新したネットワーク設定が適用されます。

ダウンタイムを発生させずに新しいタスクを更新するためには、minimumHealthyPercentを100%に設定します。これにより、ECSは新しいタスクが正常に起動し、ヘルスチェックを通過するまで既存のタスクを停止しません。

# ※ 既存セキュリティグループの確認方法
最後に、既存のセキュリティグループを確認する方法について説明します。AWS CLIを使用してECSサービスの詳細を取得することで、既存のネットワーク設定を確認できます。以下のコマンドを使用します。

```bash
$ aws ecs describe-services --cluster your-cluster-name --services your-service-name
```

ここでも、ECSクラスタ名とサービス名をそれぞれ適切に置き換える必要があります。
【Android】アプリ内にバナー広告を表示【Kotlin】

# はじめに
今回はアプリ内に表示するバナー広告の表示方法を記事に残します。
　参考資料はこちら↓

https://developers.google.com/admob/android/banner?hl=ja

# 実践
```layout.xml
    <com.google.android.gms.ads.AdView
        android:id="@+id/banner"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:adSize="BANNER"
        app:adUnitId="ca-app-pub-3940256099942544/6300978111"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />
```




```MainActivity.kt
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val banner = findViewById<AdView>(R.id.banner)
        banner.loadAd(AdRequest.Builder().build())
    }
```

これでアプリ内にバナー広告を表示できるようになります。





# 注意が２つ
１つ目は
公式にあるこのままの実装だと起動時にアプリがクラッシュしてしまうため以下の二つでクラッシュの対応をしてから　出ないとアプリが開けません。

https://developers.google.com/admob/android/quick-start?hl=ja#import_the_mobile_ads_sdk

https://qiita.com/masaibar/items/848362349442026063e2

２つ目は　**AdRequest**のimport時に複数あるので選択を誤るといつまで経ってもエラーが解消できないので気をつけましょう。






# その他参考

https://developers.google.com/admob/android/test-ads?hl=ja%C2%A5

https://akira-watson.com/android/kotlin/admob-sdk.html#4
dartsass-rails が Raspberry Pi 3 で動くようになった

dartsass-rails は Dart Sass のバイナリ実行ファイルを提供してくれる gem で、これのおかげで [Node.js なしでも Dart Sass が使える](https://techracho.bpsinc.jp/hachi8833/2022_03_02/116014)。

https://github.com/rails/dartsass-rails

ところがこの gem の v0.4.1 以前ではサポートしているプラットフォームが少なく、 私の持っている Raspberry Pi 3 では動作しなかった。
プラットフォームの判定は [このファイル](https://github.com/rails/dartsass-rails/blob/eeb2705c711ade07b978f55bc2cd3acc30e2e963/exe/dartsass) で行われていた。

```ruby
exe_path =
  case platform_string
  when /aarch64-linux/ then File.join(__dir__, "aarch64-linux/sass")
  when /arm(64)?-darwin/ then File.join(__dir__, "arm64-darwin/sass")
  when /darwin/ then File.join(__dir__, "darwin/sass")
  when /linux/ then File.join(__dir__, "linux/sass")
  when /mswin|mingw|cygwin/ then File.join(__dir__, "mingw32/sass.bat")
  else
    STDERR.puts(<<~ERRMSG)
      ERROR: dartsass-rails does not support the #{platform_string} platform
    ERRMSG
    exit 1
  end
```

この `platform_string` が、 Raspberry Pi 3 だと `armv7l-linux-eabihf` なので、 `/linux/` にマッチしていた。このとき使用される `linux/sass` がどのプラットフォーム用のバイナリだったか覚えていないのだが(64 bit 用だった記憶)、 Raspebrry Pi 3 では動作しなかった。

そのため、自分で [テキトーにパッチをあてて](https://github.com/mishina2228/dartsass-rails/commit/3951caf8fff83dd7fd11990b1ed65649adea0805) 使っていたのだが、先日の [v0.5.0 のリリース](https://github.com/rails/dartsass-rails/releases/tag/v0.5.0) で sass-embedded という gem を利用するように変更された。

https://github.com/rails/dartsass-rails/pull/42

https://github.com/ntkme/sass-embedded-host-ruby

これによって、各プラットフォームに対応した Dart Sass のバイナリ実行ファイルがインストールされるようになった。上記のPRのコメントにある通り、サポートしているプラットフォームの数が多い。

- arm64-darwin
- x86_64-darwin
- aarch64-linux-android
- arm-linux-androideabi
- x86-linux-android
- x86_64-linux-android
- aarch64-linux-gnu
- arm-linux-gnueabihf
- x86-linux-gnu
- x86_64-linux-gnu
- aarch64-linux-musl
- arm-linux-musleabihf
- x86-linux-musl
- x86_64-linux-musl
- x64-mingw-ucrt
- x64-mingw32
- x86-mingw32

ラズパイで dartsass-rails をアップデートしたところ、対応する sass-embedded がインストールされた。

```
Fetching sass-embedded 1.63.6 (arm-linux-gnueabihf)
Installing sass-embedded 1.63.6 (arm-linux-gnueabihf)
Fetching dartsass-rails 0.5.0 (was 0.4.1)
Installing dartsass-rails 0.5.0 (was 0.4.1)
```

Raspberry Pi 3 で Dart Sass が動いた！ :tada:

```
$ bundle exec dartsass --version
1.63.6
```
Android画面固定を設定する方法

開発する時にAndroid画面固定したい時があると思いますが、一度設定したら頻繁に使用するものではないので、見返せば設定できるように残しておこうと思います。


自分は開発していて、Manifestに設定することがほとんどだったので、Manifestに設定する方法です。

```AndroidManifest.xml
<!--縦固定-->
android:screenOrientation="portrait"
<!--横固定-->
android:screenOrientation="landscape"
```


以上です。
アップロードする画像にバリデーションを追加する

https://qiita.com/AttAtD/items/6b9502c0fa75531ee400
https://qiita.com/AttAtD/items/c2077d3bd3d0f1be3268
https://qiita.com/AttAtD/items/5bad43034dbb66c33e15
の続き

アップロードする画像にバリデーションを追加する。

サーバー側、クライアント側の両方でバリデーションを追加する。

## クライアント側

ファイルをアップロードする際のアクションにファイルの容量とファイル名のチェックを追加する

```
  readImage(e) {
    let input = this.inputTarget;
    let output = this.outputTarget;

    if (input.files) {
      let files = Array.from(input.files);

      //追加ここから
      let errors = []
      files = files.filter((f) => {
        if(f.size > 5 * 1024 * 1024) {
          errors.push(`5Mバイト以上のファイルはアップロードできません(${f.size} byte)`);
          return false;
        } else {
          return true;
        }
      });

      const stored = Array.from(data.files);
      files = files.filter((file) => {
        const index = stored.findIndex((f) => f.name == file.name);
        if (index != -1) {
          errors.push(`同じ名前のファイルはアップロードできません(${file.name} byte)`);
          return false;
        } else {
          return true;
        }
      });
      if(errors.length > 0) {
        alert(errors.join("\n"));
      }
      //追加ここまで

      files.forEach((f) => data.items.add(f));
      for (let i = 0; i < files.length; i++) {
        this.readOne(files[i], i, output);
      }
      input.files = data.files;
    }
  }
```

## サーバー側

validation用にgemを追加する

https://github.com/igorkasyanchuk/active_storage_validations

- Gemfile

```
gem 'active_storage_validations'
```

- posts_controller.rb

```

class Post < ApplicationRecord
...

    validates :photos,
            content_type: { in: proc { |a| a.supported_content_types } }, # コンテンツの種類をチェックする
            size: { less_than: 5.megabytes }, # 5Mバイト未満のファイルだけ許容
    def supported_content_types
        %w[image/jpg image/jpeg image/png]
    end
...
end

```
CDNってなんぞや

名称、内容、目的をざっと忘備録

### 一言で言うと
__CDN = サクサクさせるやつ__

- キャッシュサーバーを使ってサクサクネットにアクセスできる仕組み
- Cho(ちょー)Dekiru(できる)Net( ネット)
- 分散されたキャッシュサーバー群によるネットワーク

### 名称
ContentsDeliveryNetwork：コンテンツデリバリーネットワーク

### 内容
> Web上コンテンツを迅速にエンドユーザーに届けるための仕組み
> 各地に配置されたキャッシュサーバーにWebサイトのコンテンツを一次的に保存（キャッシュ）。
キャッシュサーバーからコンテンツを配信すること。
Webサーバーやネットワークの状態、物理的な距離にかかわらず、安定したコンテンツ配信を実現する。
>
> __CDNを使わない場合とどう違うか__
> 通常のWebサイト
> →コンテンツを配信するためのWebサーバーの処理能力やインターネットに接続されているネットワークの帯域幅などが制約される
> <img src ="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2867756/9ea8a895-613d-6b8d-c6d4-c2ce3aaf25c7.png" width="50%">
> <img src ="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2867756/003677c9-33ee-c665-2e7d-3be116544d7f.png" width="50%">
> わかりやすい解説・画像：[by J-Stream様](https://www.stream.co.jp/blog/blogpost-41362/)


### 目的　/CDNのメリット
CDNがあるメリット
- 可用性の向上
- 配信の高速化／表示速度の高速化
- コスト削減
- DoS/DDos攻撃対策
- サーバー負荷軽減

<font color="gray">
※DoS攻撃についてサクッと↓</font>

https://qiita.com/dameNingen_ganbaru/items/5ab673f3c02f98ef7ce5



### 感想
なぜ自分はCDNについて調べていたのか忘れた


### 参考文献
・Jstream、[CDNとは？　～ノンエンジニア向けにわかりやすく解説～](CDNとは？　～ノンエンジニア向けにわかりやすく解説～)
[ServiceNow] 空のアプリケーションの作成

# 概要
ServiceNowで空のアプリケーションを作成する。

※バージョン: Utah

# アプリケーションとは
ServiceNowはアプリケーションという単位でテーブル定義やスクリプトなどの各種設定を管理することができる。
作成したアプリケーションはGitと連携することで、バージョン管理や、他インスタンスへの共有も容易に行うことができる。

# 作成方法
System Application > Studio を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920664/2e352468-0f5d-890a-b0bf-fd3a2870010e.png)

別タブでStudio画面が開く。

「Select Application」画面で「Create Application」を選択する。
新規アプリケーションはここから作成する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920664/61d01095-ad72-040f-433d-ff1676880f4b.png)

「Let's get started」を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920664/b725bfd1-ccfd-9e58-1e27-8627ff8e257b.png)


アプリケーションの基本情報を入力し、「Create」を選択する。

* Name: アプリケーションの名前
* Description: アプリケーションの概要（自由記入）
* Advanced settings: アプリケーションの種類
* Scope: （上記で「Scoped」を選択した場合）アプリケーションの識別子

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920664/f1043e5f-eb38-8197-3bfa-cc7902c7dc65.png)
※ 識別子の「x_1022674」の箇所は、各インスタンスで固有の値となっている。

以降、ガイドに従ってロールやテーブルなど、アプリケーションに基本的に必要になる設定を行えるようになっているが、空の状態でアプリケーションを作成する場合は「Continue in Studio(Advanced)」を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920664/1188dd79-1cff-f3c3-728d-51570a8d6ad1.png)

「Select Application」画面に戻ってくるので、先ほど設定した名前のアプリケーションが存在することを確認する。
アプリケーションを選択すると、アプリケーションの開発を行うことができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920664/fa3780a4-daad-0348-0618-79d2817b49b7.png)

これで空のアプリケーションの作成が完了。
Node.jsでJavaScript を実行する

## はじめに
Node.js で JavaScript を実行します。  
Node.js はオープンソースの JavaScript 実行環境です。

## 環境
Ubuntu 22.04.2 LTS  
Node.js 18.16.1 LTS

## 手順の流れ
1. [curl のインストール](#1-curl-のインストール)
2. [Node.js のインストール](#2-nodejs-のインストール)
3. [バージョン確認](#3-バージョン確認)
4. [js ファイルの作成](#4-js-ファイルの作成)
5. [js ファイルの実行](#5-js-ファイルの実行)

## 手順

### 1. curl のインストール
Node.js のインストールに使用するため、curl をインストールします。  

```shell_session
# 一般ユーザー権限
$ sudo apt update
$ sudo apt-get install -y curl

# root権限
$ apt update
$ apt-get install -y curl
```

### 2. Node.js のインストール
NodeSource が 提供する PRA を使用して Node.js をインストールします。  
PRA は Personal Package Archive の略で Ubuntu の非公式リポジトリです。  
Ubuntu の公式リポジトリからは新しいバージョンの Node.js がインストールできないため、 NodeSource の PRA を使用します。  

https://github.com/nodesource/distributions#user-content-using-ubuntu-4

```shell_session
# 一般ユーザー権限
$ curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - &&\
sudo apt-get install -y nodejs

# root権限
$ curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - &&\
apt-get install -y nodejs
```

:::note alert  
dpkg: error processing archive と出力される場合
https://github.com/nodesource/distributions/issues/1157#issuecomment-1131212089

以下コマンドを実行後、再インストールします。

```shell_session
# 一般ユーザー権限
$ sudo dpkg --remove --force-remove-reinstreq libnode-dev
$ sudo dpkg --remove --force-remove-reinstreq libnode72:amd64

# root 権限
$ dpkg --remove --force-remove-reinstreq libnode-dev
$ dpkg --remove --force-remove-reinstreq libnode72:amd64
```
:::

### 3. バージョン確認
```shell_session
$ node -v
v18.16.1
```

### 4. js ファイルの作成
任意のディレクトリに hello.js というソースファイルを作成します。  
```shell_session
# js ファイルの作成
$ cat << EOF > hello.js
console.log("Hello World!");
EOF
```

### 5. js ファイルの実行
hello.js を実行します。
```shell_session
$ node hello.js
Hello World!
```

## 参考
https://nodejs.org/ja/about

https://github.com/nodejs/node

https://github.com/nodesource/distributions
TofセンサVL6180xをAPI叩いてnucleo-f303k8で使う

## 概要
STMマイコンを使ってみよう、ということでnucleo-f303k8でLチカ、HelloWorldをしたのだが、もともと練習の目標だった測距センサの評価がしたいね！ということで始まった。

CubeIDEの使いかた、APIとかセンサのデータシート読みで苦労したが、デキる人たちに助けてもらいI2Cを用いて何とか動かせた、という話。


## 使ったもの
https://www.st.com/en/evaluation-tools/nucleo-f303k8.html
https://www.pololu.com/product/2489


## 前段階
とりあえずHALでI2Cを動かしてみる。ArduinoのWireライブラリ様に慣れ切っていたためデータシート読んでレジスタ叩いて～というのに苦労した。
- I2Cの仕組みを知る(いいデータシートはそこから説明してくれてる)
- 書き込みと読み取りを「指定したレジスタ」に対して行うので、その表部分だけでもデータシートで読めば動く
ということを知る。

以下参考になったリンク
https://qiita.com/sttn/items/567c9f49b88ff275b51a
https://yukblog.net/stm32cubeide-printf-uart/
https://forum.digikey.com/t/stm32cube-hal-i2c/22664



## APIを使う
web系のサービスが強くなってそっちのイメージが強いAPIだけども、STMicroとかが用意してるセンサ類とかのAPIもある。
今回APIってライブラリみたいに入れたら簡単に使えて便利なんでしょ～と思っていたが、素人なのでかなり理解するまでに時間がかかった。
つまずいた点は以下
- CubeIDEが慣れない
- API使う上で一部自作しないといけない
- 回路のトラブル

まず、https://www.st.com/en/imaging-and-photonics-solutions/vl6180x.html　からAPI一式をダウンロード(登録が必要)をして、内包されているdocsの中のhtmlからデータシートを閲覧。
一通りの.hと.cをそれぞれCoreのIncとSrcに入れる。

そこで用意された関数が使えないことに気づく。
データシートを読んだ結果、VL6180x_I2CWriteとVL6180x_I2CReadを自作しないといけないこと、自分の思ってたデータ型が今回用意されてる構造体とあってなかったことに気づく。

## コード
https://github.com/daidai100/Tests/tree/main/vl6180xTesting/vl6180xTesting
にまんま挙げてある。
-.hをIncに.cをSrcにいれる
-.main.cに以下の文を足す
```main.c
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;

/* USER CODE BEGIN 0 */
int  VL6180x_I2CWrite(VL6180xDev_t dev, uint8_t  *buff, uint8_t len){
	HAL_I2C_Master_Transmit(&hi2c1, dev, buff, len , 1000);
	return 0;
}

int VL6180x_I2CRead(VL6180xDev_t dev, uint8_t *buff, uint8_t len){
	HAL_I2C_Master_Receive(&hi2c1, dev, buff, len, 1000);
	return 0;
}
/* USER CODE END 0 */
```

用意された関数を使いたいときはさらに初期化とデバイスの指定をしないといけない。(今回は単デバイスなのでシンプルだけど複数の時は用意された宣言方法に注意。)
```main.c
  VL6180xDev_t myDev = 0x52;
  VL6180x_RangeData_t Range;

  VL6180x_InitData(myDev);
```
これでやっと以下のようにAPIで用意されてて使いたかった関数が使えた！
```main.c
  VL6180x_RangePollMeasurement(myDev, &Range);
	  if (Range.errorStatus == 0 ){
		  printf("%d mm\r\n", Range.range_mm); // your code display range in mm
	  }else{
		  printf("Failed to get distance\r\n"); // your code display error code
	  }
```
連続モードとかいろいろとモードでまた微妙に使いかたが違うみたい。

## 問題点 
- 回路の問題で複数センサが同時に複数使えない→回路設計見直せば行けそう
- CubeIDE慣れない→PlatformIOとかをSTM仕様にしてやろうかな

## 今後
あまりプログラミングに耐性がない(一から作ろうとするとエラーの解決とかで大体挫折する)ので多少遠回りとか冗長でも外部リソースを使いたい！と思っているのでAPI使えるようになってきたのは大きな一歩だと思うことにした。

あとやっぱりプログラミングでエラーが出るとそこからの復帰が人より不得意であることを自覚したので人を使うなりAIとかツールを使うなり対策したい。

ArduinoIDEを使って書き込めばもっと簡単であった模様。

次はWeb系のAPIとか触ってみたいなーと思う今日この頃。
多少ごちゃってて重くてもAPI取説がしっかりしてるから動くのありがたい。
とにかく動くのが偉い。ということで。
今後作るものに活かしたい。
Qiitaメモ

Qiita記事のサムネイル画像を更新する方法
↓以下の記事を参照。

https://qiita.com/ume-san/items/ec8c771d21305f6ebef9?1

サムネイル更新テスト

https://qiita.com/MackyJP/items/fba09ca48866bf0a59d8?1
Macの自然言語処理環境の構築

自然言語処理の分析手順を備忘録として残しておく。

#### 環境構築手順
1. miniforge3をインストール後、仮想環境を構築する。
    ```
    conda create -n nlp python==3.10
    conda activate nlp
    conda installnumpy pandas matplotlib...
    ```
2. HomebrewでMeCabをインストールする
    ```
    # Homebrewのインストールがまだの場合
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
    # 下記も入れていなければ入れる
    brew install curl xz
    # MeCabと標準IPA辞書のインストール
    brew install mecab mecab-ipadic
    ```
    下記で動作確認を行える。
    ```
    mecab
    今日は暑いが、明日はさらに暑くなりそうだ。
    今日    名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
    は      助詞,係助詞,*,*,*,*,は,ハ,ワ
    暑い    形容詞,自立,*,*,形容詞・アウオ段,基本形,暑い,アツイ,アツイ
    が      助詞,接続助詞,*,*,*,*,が,ガ,ガ
    、      記号,読点,*,*,*,*,、,、,、
    明日    名詞,副詞可能,*,*,*,*,明日,アシタ,アシタ
    は      助詞,係助詞,*,*,*,*,は,ハ,ワ
    さらに  副詞,助詞類接続,*,*,*,*,さらに,サラニ,サラニ
    暑く    形容詞,自立,*,*,形容詞・アウオ段,連用テ接続,暑い,アツク,アツク
    なり    動詞,自立,*,*,五段・ラ行,連用形,なる,ナリ,ナリ
    そう    名詞,接尾,助動詞語幹,*,*,*,そう,ソウ,ソー
    だ      助動詞,*,*,*,特殊・ダ,基本形,だ,ダ,ダ
    。      記号,句点,*,*,*,*,。,。,。
    EOS
    ctrl + C で終了
    ```
3. [オリジナルのページ](https://github.com/neologd/mecab-ipadic-neologd/blob/master/README.ja.md)にしたがって、より高性能な mecab-ipadic-NEologd 辞書をインストールする。
    ```
    git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
    cd mecab-ipadic-neologd
    # 全部入りの辞書を構築するには -a オプションを下記に付与
    # 標準は512MB程度のメモリが必要で、全入りは2GB以上必要
    ./bin/install-mecab-ipadic-neologd -n
    ```
    動作確認は下記のように辞書のパスを指定して行う。
    ```
    mecab -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd
    ```
    標準辞書に設定する場合はmecabrcを書き換える。
    ```
    sudo nano [mecabrcのパス]
    # 上記で辞書の設定ファイルを開いた後、下記箇所を修正する。
    dicdir=[標準指定したい辞書のパス]
    ```
4. mecab-python3のインストールによりpythonからMeCabを使えるようになる。
    ```
    pip install mecab-python3
    ```

#### 参考
- [Python で自然言語処理をしてみよう - MeCab 編](https://rinsaka.com/python/nltk/01-prepare.html)
- [GitHub: mecab-ipadic-NEologd : Neologism dictionary for MeCab](https://github.com/neologd/mecab-ipadic-neologd/blob/master/README.ja.md)
- [MeCab: Yet Another Part-of-Speech and Morphological Analyzer](http://taku910.github.io/mecab/#install-unix)
Splunk: GUI画面の言語設定を切り替える


###### 実施環境： Splunk Free 8.2.2

### やりたいこと

 Splunk の GUI 画面について、言語設定が想定と異なる場合がまれにあります。
例えば、日本語で表示したかったのに英語で表示されてしまっている場合を考えます。

![WS000259.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/65fad0ee-df31-81f3-b2da-929a5ee2c47d.jpeg "英語")

この場合、言語設定を日本語に切り替えるにはどうすればよいでしょうか。
なお、 OS 自体の言語設定は英語と日本語両方が選択できる状態であるとします。

### 方法

答えは単純で、接続する URL を変更すればよいです。

例えば先ほどの画面は、以下のような URL になっています。

`http://***.***.***.***:***/en-US/app/launcher/home`

この URL 中の `en-US` を `ja-JP` に変更すれば、日本語で表示されます。

`http://***.***.***.***:***/ja-JP/app/launcher/home`

![WS000258.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/bff31a2b-21d5-74ce-8d67-698c8ae62adf.jpeg "日本語")

なお、ログイン状態だとうまく切り替わらない場合がありますので、すでに Splunk に接続している場合は一度 Splunk の画面をすべて閉じてから URL を変更して接続しなおす必要があります。
【作業メモ】Docker Desktop for Windowsでコンテナを立てる

コンテナ立ててアプリを動かすってどんな感じなのか試したかった。
基本下記の記事に沿って作業。自分のコンテナの知識があまりにも無さすぎてコンテナ構築で引っかかった。引っかかったところをメモ。超短い。

### アプリ構築からコンテナを立てるにあたって参考にさせていただいたサイト
https://qiita.com/yota_dev/items/ab8dea7f71c8a130d5bf

## 1. ローカルで開発
コンテナってどんな感じ？っていうのを見たいのでアプリ自体は特に指定無いんだけど、
上記サイトがPythonでREST API構築方法の紹介だったので参考にさせていただいた。

## 2. Docker Desktop for Windowsを入れる

Windows環境なのでfor Windows。
下記サイトからDocker Hubに飛んでインストーラ入手→インストール

https://docs.docker.jp/docker-for-windows/install.html

インストールしたバージョンは24.0.2, build cb74dfc

## 3. コンテナを立ててローカルで開発したアプリをコピーする

Dockerイメージを作るためのDockerfileをあらかじめ作っておく。
docker build コマンドでDockerfileを実行する。Dockerfile内のCOPYコマンドでローカルのコードをコンテナにコピーする。

COPYコマンドのパスは相対パスで書かないといけないのと、Dockerfileは自分が置かれている階層以下しか認識してくれないのに気付かず詰まった。

公式のドキュメントはちゃんと読まないといかんなと思いました。

https://docs.docker.jp/engine/reference/builder.html#copy

## おわりに

コンテナ立ててアプリ実行するイメージが（なんとなくだけど）ついた。
今度はパブリッククラウドでコンテナ立てて何かしら動かしてみたい。
DoS攻撃・DDoS攻撃ってなんぞや

名称、内容、目的をざっと忘備録。
### 一言で言うと
DoS攻撃＝アクセス妨害のサーバー攻撃。DDoSは進化版。

### 名称
・DoS攻撃【Denial of Service Attack】：サービス拒否攻撃
・DDoS攻撃【Distributed Denial of Serrvice Attack】：分散型サービス拒否攻撃

### 内容
__DoS攻撃__
故意的にサーバに大量のデータを送りつけることでサーバをパンクさせるサイバー攻撃。
<font color= "gray">
※依然厄介なサイバー攻撃であるが、事前に同IPからのアクセス回数を制限するという対策を講じることで防ぐことは可能になっているらしい。
</font>

><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2867756/3f7e81f6-9025-4aa5-cb04-d92526b0c66c.png" width="60%">
>
>画像参照：[攻撃遮断くん](https://www.shadan-kun.com/waf_websecurity/dos_ddos_attack/)

__DDoS攻撃__
・・・攻撃者は、マルウェアなどで不正に乗っ取った複数のコンピュータのIPを活用してDoS攻撃。
<font color="gray">
※不特定多数IPからの攻撃のため、防ぐのが難しいらしい、
</font>
><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2867756/248b2848-b51a-532f-3ade-a946282a0461.png" width="60%">
>
>画像参照：[攻撃遮断くん](https://www.shadan-kun.com/waf_websecurity/dos_ddos_attack/)

### 目的
・単純な嫌がらせ
・妨害行動
・脅迫行動
・他のサイバー攻撃との併用

### 感想
終始サイ○パスの唐之杜さんがやりそうなやつだなと想像して理解して納得した。
><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2867756/173b4268-6959-ddba-2f0d-226f2cb2ad27.png" width="80%">
>
>参照：[PSHYCHO-PASS公式HP](https://psycho-pass.com/fi/character/chara07.php)

### 参考文献
・攻撃遮断君、[DDoS攻撃とは？DoS攻撃の進化版](https://www.shadan-kun.com/waf_websecurity/dos_ddos_attack/)
・サイコパス製作委員会、[character](https://psycho-pass.com/fi/character/chara07.php)
Qiitaで使用可能・Backlogで使用不可能なMarkdown記法一覧

## 本記事について
### 本記事の対象者
* Backlogの課題の記述、Qiitaの記事の記述をMarkdown記法で書いている方

### はじめに
プロジェクト管理でBacklogを使っており、課題の内容をMarkdown記法で書いているという方も多いかと思います。
Qiitaで使えるMarkdown記法を確認している中で、Qiitaで使用可能なもののBacklogで使用不可能なMarkdown記法があったので備忘録としてまとめておきます。
これ以外にもたくさんあると思いますが、まずは筆者がQiitaで使っていて便利と感じているものだけまとめます。

### 参考記事
*  [公式] [Qiitaで使えるMarkdown記法](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)
*  [公式] [Backlogで使えるMarkdown記法](https://support-ja.backlog.com/hc/ja/articles/360036145833-%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E6%95%B4%E5%BD%A2%E3%81%AE%E3%83%AB%E3%83%BC%E3%83%AB-Markdown-%E8%A8%98%E6%B3%95-)

## Qiitaで使えるけどBacklogで使えないMarkdown記法一覧
### コードブロックへのタイトル挿入

Qiitaの場合、コードブロックを始める際の拡張子のバッククォート（ `` ` `` ）、チルダ（`~`）の横にコードブロックのタイトルを記述できます。
Backlogはこれには非対応のようです。（通常のタイトルなしのコードブロック記述はもちろん可能です。）

**Qiita例** 
~~~ md:Qiitaはコードブロックにタイトルを書ける
```拡張子:コードブロックのタイトル
hoge
foo
```
~~~

### 補足説明用のnote
Qiitaの場合、以下のように書くことで強調用の補足説明を表現できます。
あまり使用機会はないかもしれませんが、こちらもBacklogでは非対応のようです。

```: :::note　:::を使った強調表現
:::note info
info
:::

:::note warn
warn
:::

:::note alert
alert
:::
```
:::note info
info
:::

:::note warn
warn
:::

:::note alert
alert
:::
VSCode 本体と Integrated Terminal のキーバインドが被ってしまう場合の対処法

# 要旨

- VSCode の Integrated Terminal を利用している場合、デフォルトでは特定のキーバインド (ex:`Ctrl + P`) が Integrated Terminal ではなく VSCode 本体に優先的に作用してしまう。
- 設定 (`Integrated: Commands To Skip Shell`) により、当該キーバインドを Integrated Terminal に作用させることができる。

# 環境

- Visual Studio Code 1.79.2

# 本題

## VSCode の Integrated Terminal

VSCode を利用してプログラミングをする際、自分は Integrated Terminal を多用します。別 Window に立ち上げたターミナルにフォーカスを移す手間が省けたり、何かと便利です。
ただ、不満点もあったりします。自分はターミナルを Emacs キーバインドで利用しているのですが、通常のターミナルアプリでは「前回入力したコマンドを再度呼び出す」場合は `Ctrl + P` で実行できます。
しかし、VSCode の Integrated Terminal では、VSCode 本体に `Ctrl + P` がデフォルトで割り当てられており、Integrated Terminal 上で実行しても VSCode 本体にキーバインドが吸われてしまいます。。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23455/f33f3eda-1cac-2ad5-01ce-02eb9a7ba1bc.png "VSCode の Integrated Terminal")


## `Ctrl + P` を Integrated Terminal に取り戻す！

いつから存在する機能なのかは存じ上げませんが、ちゃんと Integrated Terminal に優先的にキーバインドを割り当てられる設定がありました。

### 設定項目

VSCode の設定画面で [機能] → [ターミナル] → [Integrated: Commands To Skip Shell]

### 設定方法

VSCode の設定画面上では、Integrated Terminal に優先させるコマンド (キーバインド) をリスト形式で入力する方式になっています。今回のケースでは、`Ctrl + P` が VSCode では `workbench.action.quickOpen` というアクションに紐づいているので、このコマンドを VSCode 本体ではなく Integrated Terminal に優先的に送るようにリストに入力します。

注意点として、Integrated Terminal に優先させるコマンドを入力する際、**当該コマンドの最初に `-` を付ける必要があります。**
今回の場合は、`-workbench.action.quickOpen` と入力します。

![設定画面上での設定箇所](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23455/c4ad8896-9d89-f8f1-a642-9e55e30dd5b0.png "VSCode 設定画面上での設定箇所")

これで Integrated Terminal 上で `Ctrl + P` を入力しても、従来のターミナルアプリ上と同じ挙動になってくれます。


# 参考資料

- [公式ドキュメント: Keybinding and the shell](https://code.visualstudio.com/docs/terminal/advanced#_keybinding-and-the-shell)
Google Colabでseaborn-analyzerのpairplotが描けなくなったのは。。。

![IMG_1123.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1275001/df37115e-7e02-dff2-3ac8-95f2b6be3021.jpeg)



## はじめに
Google Colabは、主要なライブラリがプリインストールされています。
いちいちインストールしたり、アップデートする必要がありませんのでありがたいのですが、別のライブラリを利用している動作させているライブラリの場合、利用しているライブラリのVer.に依存する場合があります。

要は、**Google Colabにプリインストールされているライブラリのアップデートによって動作しなくなるライブラリがあるということです。**

この影響で、seaborn-analyzerのpairplotが動作しなくなり、かなり苦労しましたので、備忘のため記事に残しておきます。


　
## 対処方法

scikit-learn と　seaborn の Ver.up が影響しているように思います。
筆者の環境では、以下の対処でpairplotを描くことができました。


```Python:scikit-learn ver指定してインストール
!pip install scikit-learn==1.0.2
```

```Python:seaborn ver指定してインストール
!pip install dtreeviz==0.11.2
```

```Python:seaborn-analyzer ver指定してインストール
!pip install seaborn-analyzer==0.2.13
```

筆者の環境では、上記の順序でインストールしないといけなかったように思います。
他のVer.でも通るかもしれません。あくまでもご参考まで。
Next.jsでTypeScriptを使うときmp3ファイルが読み込めなかった件

# 概要
Next.jsでタイマー的なアプリを作っているとき、Next.js上でmp3ファイルを扱うのに苦労しました。
ChatGPT様でも解決しなかったためちょっと共有したら助かる人もいるかな？と思い、共有することにします。


# 前提
```
Next.js ：
・バージョン13.4.7
やりたいこと：
・Use-Soundでmp3音源を再生したい
困ったこと：
・Next.jsがmp3ファイルをModuleとして読み込んでくれない
・型定義やfile-loaderの設定をするとそもそもアプリが起動しなくなる
```


# 対策
## 型定義をする。
プロジェクト直下に型定義ファイルを置いてください。
私の場合は`sound.d.ts`を作成しました。
内容は以下です。
```
// sounds.d.ts
declare module "*.mp3";

```

これにより、ビルド時のエラーは解消されます。
しかし、実行した際にはmp3ファイルが見つからないとエラーになります。


## url-loaderを設定する。
プロジェクト直下に`next.config.js`を作成し、url-loaderの設定を行います。
内容は以下です。
```
/**
 * @type {import('next').NextConfig}
 **/
const nextConfig = {
  webpack(config, options) {
    config.module.rules.push({
      test: /\.mp3$/,
      use: {
        loader: "url-loader",
        options: {
          limit: 8192,
        },
      },
    });
    return config;
  },
};

module.exports = nextConfig;

```


next.configやbabelなどがまだTypeScriptに対応していないため、
`.js`を使用します。
ChatGPTや検索した情報だと、Next.jsでJavaScriptを使用している場合の対策しか見つからず、
解決には至りませんでした。



# おわり
webpackの設定周りの問題らしいんですが、深堀はやめときました。
ちょっとわかってきたと思ったらまたわからないところが出てきて奥が深いです。
【MySQL】権限を確認／付与するコマンド

使用する機会があったのでメモです。

## ユーザーを確認
```
mysql> select user(), current_user();
+----------------+----------------+
| user()         | current_user() |
+----------------+----------------+
| root@localhost | root@localhost |
+----------------+----------------+
1 row in set (0.00 sec)
```

※SELECT USER()は接続に使用されているユーザー名とホスト名を返し、SELECT CURRENT_USER()は現在のセッションのユーザー名とホスト名を返す。

## 権限の確認
```
mysql> SHOW GRANTS FOR 'root'@'localhost';
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Grants for root@localhost                                                                                                                                                             |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| GRANT SELECT, RELOAD, SHUTDOWN, PROCESS, SHOW DATABASES, SUPER, LOCK TABLES, REPLICATION SLAVE, REPLICATION CLIENT, CREATE USER, EVENT ON *.* TO `root`@`localhost` WITH GRANT OPTION |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
```

## 権限を与える方法

データベース全体への権限を付与
```
GRANT 権限種類 ON データベース名.* TO 'ユーザー名'@'ホスト名';
```
特定のテーブルへの権限を付与
```
GRANT 権限種類 ON データベース名.テーブル名 TO 'ユーザー名'@'ホスト名';
```
全てのデータベースへの権限を付与
```
GRANT 権限種類 ON *.* TO 'ユーザー名'@'ホスト名';
```

例：'root'@'localhost'に全てのデータベースへの全ての権限を付与する場合
```
mysql> GRANT ALL ON *.* TO 'root'@'localhost';
```
アプリの企画

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/ac43421e-af18-b522-9a15-bbc3baf1334a.png)
１：ペルソナ
ペルソナとはマーケティングの用語で、「サービスを使用するユーザー」のことです。
似た言葉に「ターゲット」などがありますが、ペルソナはそれらよりも詳細に「サービスを使用するユーザー」を決めます。

年齢層や、職業。性別や、現在の境遇などまで決めることで、よりリアルに使用者の目線でサービスを考案できます。

２：アプリのペルソナを確認
「ペルソナを定義」
名前は、Aさんにします。

下記の順番でペルソナを決めていきましょう。

性別と年齢
職業
趣味
まず、性別と年齢層を決めます。

写真を共有するアプリケーションを考えているので、「性別は女性」に設定します。
一眼レフなどをカメラを購入する人が多いため、「年齢は20代」とします。

次に職業を決めます。
職業は、残業のあまりない会社で、ジャンルは設定しないようにします。
終業後の時間や、休日の時間を有効活用したいと考えています。

次に趣味を決めます。
　趣味は、綺麗な写真などをSNSなどで集めたり投稿することです。
SNSを数種類と、ネットサーフィンで探したりすることもあるので、1つにまとめて管理できたら便利なのに・・・と思っています。
友人同士でお気に入りの写真をシェアして、コメントし合えたら面白そうだなといつも考えています。
以上で、3つの項目を深く考えます。

今回ペルソナから読み取った課題は、下記の通りです。
①好きな写真がSNSやサービスごとに複数存在し、管理しにくいという課題
②写真をChromeなどの「お気に入り」や「ブックマーク」では、友人とシェアしにくいという課題
③友人のお気に入りの写真をみたりコメントしたいが、そのようなサービスがないという課題

　Aさんは、純粋に写真を共有し楽しみたいだけですが、そこには多くの課題がありました。

３：ユーザーストーリー
ユーザーストーリーとは、「ペルソナの課題に対して、どのような機能で解決していくのか」を明確にしたものです。

　たとえば、ペルソナの課題が「人気の映画情報をストックしたいけど、パンフレットなどを貯めておくと場所も取るし管理ができない」という課題だった場合、「人気の映画の一覧を表示する」という機能がユーザーストーリーになります。

「課題を改めて見直します。」

①好きな写真がSNSやサービスごとに存在し、管理しにくいという課題
②写真をChromeなどの「お気に入り」や「ブックマーク」では、友人とシェアしにくいという課題
③友人のお気に入りの写真をみたりコメントしたいが、そのようなサービスがないという課題

　次に、課題を解決できる機能を考えます。今回は、すでにSNSなどへアップされている画像のリンクを使用し、写真を共有できるアプリケーションを作成します。
インターネット上で写真を共有し、それに対してユーザーがアカウントを持ち、コメントができるアプリケーションにすれば解決できます。
また、共有された写真はいつでも検索できるようにしておけば写真の管理ができます。

下記のように必要な機能をまとめます。

①写真の共有機能がある。（削除や編集機能もつける）
②ユーザーの管理機能がある
③共有された写真に対して、コメントをつけられる。
④共有された写真を検索できる
Hugging Face Optimumでrinna GPTモデルをONNXに変換する

ONNXランタイムは、モバイルやエッジを含むクロスプラットフォームの推論エンジンです。ONNXモデルに変換することで、モデルを様々な環境で動かすことができます。

huggingface/optimumを利用することで、Transformersのモデルを簡単にONNXに変換できます。

https://github.com/huggingface/optimum

本稿はだいたい[Hugging Faceの公式ドキュメント](https://huggingface.co/docs/optimum/exporters/onnx/usage_guides/export_a_model)に書いてあることです。

## 環境
- Python 3.10.12
- optimum 1.8.8

今回はGoogle Colabを利用しました。予め`!pip install optimum[exporters]`でインストールしておきます。

## 変換
rinna社の提供する日本語GPTモデルである[rinna/japanese\-gpt2\-xsmall](https://huggingface.co/rinna/japanese-gpt2-xsmall)をONNXに変換してみましょう。下記のコマンドで、`my_onnx_gpt/`というディレクトリに変換されたモデルが出力されます。

```
!optimum-cli export onnx --model rinna/japanese-gpt2-xsmall my_onnx_gpt/
```

以上です。お疲れ様でした。

念のため確認してみましょう。

```
!ls my_onnx_gpt/
```

```:出力
config.json		   decoder_with_past_model.onnx  spiece.model
decoder_model_merged.onnx  generation_config.json	 tokenizer_config.json
decoder_model.onnx	   special_tokens_map.json	 tokenizer.json
```

どうやら`.onnx`に変換されているらしいことが分かります。

## 実行
optimumを利用してONNXモデルを実行するには、普通のTransformersを利用して実行するときとあまり変わりません。[Hugging Faceの公式ドキュメント](https://huggingface.co/docs/optimum/main/en/onnxruntime/package_reference/modeling_ort)から、適切なモデルクラスを選択して差し替えてください。今回であれば`ORTModelForCausalLM`です。

```python
from transformers import AutoTokenizer, pipeline
from optimum.onnxruntime import ORTModelForCausalLM

MODEL_NAME = "my_onnx_gpt"

tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
model = ORTModelForCausalLM.from_pretrained(MODEL_NAME)

onnx_gen = pipeline("text-generation", model=model, tokenizer=tokenizer)

gen = onnx_gen("昔々あるところに")
print(gen)
```

```:出力※毎回変化します
[{'generated_text': '昔々あるところに突然現れた - Cの C と言えば、C のキャプチャーを撮影したのが本当らしい。 そのカメラは「 500」という名称で、「'}]
```
エンジニアとしてのキャリアを可視化して俯瞰すると...

![CareeaMap2023.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916960/5ce33f04-d30e-d5a8-19a4-b87201cc5807.png)

# 目次
[1.概要](#1-概要)
[2.対象読者](#2-対象読者)
[3.本テーマの対象外とすること](#3-本テーマの対象外とすること)
[4.キャリアの定義を再認識する](#4-キャリアの定義を再認識する)
[5.エンジニアの定義を再認識する](#5-エンジニアの定義を再認識する)
[6.エンジニア人生の現在地とキャリアパス](#6-エンジニア人生の現在地とキャリアパス)
[7.今後の活動方針](#7-今後の活動方針)

# 1. 概要
30代で未経験からエンジニアへ転身してから、5年が経とうとしており、
これまでの振り返りと今後のキャリア形成の指針を大まかに見直してみました。(Qiitaへの初投稿）

# 2. 対象読者
IT系エンジニアのキャリア見直しを図るため、情報収集をされている方

# 3. 本テーマの対象外とすること
A）エンジニアならびに他の役割で目指す自我同一性（identity）の抽象化・具象化
B）「A」に関連する中核となる価値観の抽象化・具象化
C）「A」の実現に関わる、マインド・知識・技術要素等の具象化

# 4. キャリアの定義を再認識する
キャリア＝職業経験　とします。

# 5. エンジニアの定義を再認識する
本テーマでの「エンジニア」とは、システムの企画からリリース・保守、運用の複数、またはいずれかに従事する技術職とします。

# 6. エンジニア人生の現在地とキャリアパス
筆者のこれまでと現在、今後を大まかに説明します。

#### これまで
新卒 ⇒ メーカー系エンジニア ⇒ 法人営業※ ⇒ エンジニア採用 ⇒ システム監査 ⇒ エンジニア（現在）※からIT業界

#### 現在
本業・副業ともに、クラウド基盤に関する技術支援に従事。
（本業の在籍企業の許可を得て副業をしています。）

#### 今後
今後数年は、次の3点を中心に更に経験・スキルを積み上げて行く方針です。

観点
　1.DevOps基盤の上下流一連（DevOps Engineer）
　2.バックエンドの上下流一連（Backend Engineer）
　3.SRE領域の上下流一連（Site Reliability Engineer）
![CareeaMap2023.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916960/482275a9-93be-1427-6ae5-47708bf983f3.png)
　また、中長期視座の方針等は、定期的に見直していくことを想定していますが、
　現時点では、以下を中長期視座の方針と考えています。

中長期視座のキャリア形成方針
　一つの職業・職種に執着するよりも、組織やプロジェクト毎に図のように複数の立ち位置へ柔軟にスイッチしながら、アイデンティティを軸に上向きのスパイラル上に伸び続け、関わる組織・サービス発展への貢献を前提にエンジニアとしてのキャリアを形成する。

# 7. 今後の活動方針

今回の記事作成を通じて、次の２点を今後の活動方針とすることにしました。

・個人開発として、Webアプリケーションの企画段階からMVP方式で開発を行う。
・当面、Qiitaへの投稿記事は、個人開発の技術に関するテーマを扱う。

最後まで読んでくださりありがとうございました。
djangoで複数のアプリに共通して使用するmixinクラスの配置について

# 結論
ユーティリティディレクトリをプロジェクト内に作成し、その中にmixinクラスを作成するという方法があるそうです。作成後は`settings.py`の`INSTALLED_APPS`にユーティリティディレクトリを追加しておきます。

# はじめに
djangoで、mixinクラスを複数のアプリで共通して使用したいなという場面がありました。どういう方法が良いのか、最終的に落ち着いた方法を備忘録として投稿します。

# ChatGPTに聞いた
自身だけでは答えが出ないので、ChatGPTに聞いてみました。
> djangoで複数のアプリに共通して使用するmixinクラスはプロジェクトのどこに配置すれば良いですか？


> Djangoで複数のアプリで共通して使用するmixinクラスを配置する場所にはいくつかの選択肢があります。以下にいくつかの一般的な配置方法を紹介します。
> 1. プロジェクトのルートディレクトリに配置する: mixinクラスをプロジェクトのルートディレクトリに配置することができます。通常、ルートディレクトリにはプロジェクトの設定ファイル（settings.pyなど）がありますが、そこにmixinクラスを配置することもできます。
> 1. ユーティリティディレクトリに配置する: プロジェクト内に専用のユーティリティディレクトリ（例：utils）を作成し、その中にmixinクラスを配置する方法もあります。ユーティリティディレクトリは、プロジェクト全体で共有されるユーティリティ関数やクラスなどを格納する場所として利用されます。
> 1. 共通アプリを作成する: 共通の機能やユーティリティを提供するための独立したアプリケーションを作成する方法もあります。このアプリケーションにmixinクラスを配置し、他のアプリから参照することができます。この方法は、複数のアプリで共有される機能を明示的に分離するために使用されます。
> これらの選択肢の中で、最も一般的な配置方法は、プロジェクトのルートディレクトリまたは専用のユーティリティディレクトリにmixinクラスを配置することです。ただし、プロジェクトの構造や要件に応じて最適な配置方法を選択してください。また、mixinクラスを使用するアプリケーションやビューで適切にインポートして利用できるようにする必要があります。

3つの例のうち、2の方法を採用することにします。

# 実行

1. プロジェクトのフォルダの中に`utils`フォルダを作成します。
1. `utils`フォルダの中に`mixins.py`を作成し、任意の`mixin`クラスをファイル内に実装します。
    ```mixins.py
    from django.contrib.auth.mixins import LoginRequiredMixin
    
    # LoginRequiredMixinを継承したMixinの場合
    class CustomLoginRequiredMixin(LoginRequiredMixin):
        # Mixinクラスを実装する
        pass
    ```
1. `settings.py`ファイルの`INSTALLED_APPS`に`utils`を追加します。
    ```settings.py
    INSTALLED_APPS = [
	    …
        'utils'
    ]
    ```

1. 実際にmixinクラスを使用するファイルではutilsに作成したmixinクラスをimportすればOKです。
    ```.py
    from utils.mixins import CustomLoginRequiredMixin
    ```

以上です。