OmniAICreator/Qiita-1.07M huggingface dataset:
log:クロージャについて

```py
s = 'Takeshi'
def ask(x):
    def saying():
        return 'Im'+x
    return saying

#呼び出し
name = ask(s)
name()
```
つたないコードですが、学習したクロージャについて載せます。

関数の中に関数があります。

処理の流れ

1. askを呼び出し引数sを与え、name変数にいれる
1. askは呼び出されたとき同時にsaying関数を呼び出している。それがname変数に入っている。
1. saying関数は、askの仮引数xにある値を覚えている。つまりsを覚えている。
1. 最後にname()で動かすとsaying関数の処理'Im+xが戻り値としてでてくる
(xには'Takeshi'が入っているので'ImTakeshi'とでてくる)

このように外の関数に与えられた値を覚えていることをクロージャという。

以上がクロージャについて私が理解している内容になります。
え、Q#って終わるんですか？、、、

えー、緊急で記事を書いています。

ふと、Q#とPythonの実行方法にはまったので、ドキュメントを読もうと[Q# と Python を使用した開発 - Azure Quantum](https://learn.microsoft.com/ja-jp/azure/quantum/user-guide/)に行ったら、記事の内容が以下のようになっていることを確認。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243161/74902052-0af0-09c5-f6d5-b862e6e87c2a.png)

お判りいただけますか、2024年6月30日をもって``クラシックQDK``のサポートが切れるみたいです。。。



# ```Modern QDK```って何ですか？

もう眠いから[変更内容](https://learn.microsoft.com/ja-jp/azure/quantum/whats-new-modern-qdk)だけはって寝ます。。

あと[Modern QDK](https://learn.microsoft.com/ja-jp/azure/quantum/how-to-migrate-to-modern)についてはここかな
Visual Studio使ってないからどーでもいいやーー明日インストールしてみよーー

ショーもない記事書いてもうしわｋ
LLaVa





https://github.com/haotian-liu/LLaVA

パッケージのインストール
conda create -n llava python=3.10 -y
conda activate llava
pip install --upgrade pip  # enable PEP 660 support
pip install -e .

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60530/2516c7d2-b1b6-accb-1c49-e3192c195b37.png)




https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=powershell#enable-long-paths-in-windows-10-version-1607-and-later 


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60530/b11c3b1d-f37a-d2b5-17f9-919fcf94d4a1.png)


Type 'help' to get help.

   A new PowerShell stable release is available: v7.4.0
   Upgrade now, or check out the release page at:
     https://aka.ms/PowerShell-Release?tag=v7.4.0

PS C:\Windows\System32> New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" `
>> -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force

LongPathsEnabled : 1
PSPath           : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem
PSParentPath     : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
PSChildName      : FileSystem
PSDrive          : HKLM
PSProvider       : Microsoft.PowerShell.Core\Registry


PS C:\Windows\System32>
PS C:\Windows\System32>
AIの驚異的な進化：過去から未来へ

# わたし
いいね。では、実際にブログを作ってみて。Markdown形式でお願いします。ダウンロードリンクも作って。

# ChatGPT
了解しました。Markdown形式でブログを作成します。以下はその内容です。

# AIの驚異的な進化：過去から未来へ

### 1. AIのブームがすごい
AI技術は、私たちの日常生活に革命をもたらしています。スマートフォンのデジタルアシスタントから自動運転車、医療診断まで、AIはあらゆる場面で活躍しています。この章では、AIがどのように私たちの生活を変えているかを探ります。

#### AIの現在
デジタルアシスタント: SiriやAlexaなど、音声認識と言語処理を駆使して日常のタスクを支援。
自動運転車: Waymoなどの企業が提供する自動運転車は、交通の未来を変えつつあります。
医療画像分析: AIは医師を支援し、より正確な診断を可能にしています。


### 2. AIの歴史を振り返ってみよう
AIの歴史は、1950年代の学術研究から始まります。この章では、AIの発展に寄与した科学者たちとその業績を振り返ります。

#### AIの黎明期
1950年代: アラン・チューリングやジョン・マッカーシーなどがAI研究の基礎を築きます。
AIの進化
1960年代 - 現代: 1960年代のAIの冬から、1990年代の機械学習の発展、21世紀のディープラーニングまで、AIは目覚ましい進化を遂げてきました。

### 3. わずか数十年の進化の感想
AIの進化の速さには驚かされます。わずか数十年で、AIは科学フィクションから現実のものへと変わりました。

#### 未来への展望
AIの可能性: AIは今後も人類の想像力を超える可能性を秘めています。
責任ある使用: AIの発展は、責任ある使用が求められます。

#### 結論
AIの進化は、人類の創造性と科学的成果の象徴です。これからもAIは私たちの生活を豊かにし、新たな課題に挑戦する力を与えてくれるでしょう。
.iniファイルに定義されていたリストを扱うときにエラー

# 何が起きたか？
.iniから読み込んだリストの形をした文字列を`list()`で変換したら期待外れな値が返ってきた。

# 解決方法
`ast.literal_eval()`を使う。

# 目次
1. [問題の.iniファイル](#問題の.iniファイル)
1. [そのまま出力](#そのまま出力)
1. [間違ったやり方](#間違ったやり方)
1. [正しいやり方](#正しいやり方)
1. [ちなみに辞書も](#ちなみに辞書も)
1. [eval()の脆弱性](#eval()の脆弱性)


<a id="#"問題の.iniファイル"></a>
# 問題の.iniファイル

```ini:test.ini
[test]
target_l=[10,20,30]
```

<a id="#そのまま出力"></a>
# そのまま出力
```python
>>> import configparser

>>> config = configparser.ConfigParser()
>>> config.read('test.ini')

>>> target_l = config['test']['target_l']
>>> print(target_l)
'[10,20,30]' #文字列

```
文字列じゃなくてリストにしたい...


<a id="#間違ったやり方"></a>
# 間違ったやり方
```python
>>> import configparser

>>> config = configparser.ConfigParser()
>>> config.read('test.ini')

>>> target_l = list(config['test']['target_l'])
>>> print(target_l)
['[', '1', '0', ',', '2', '0', ',', '3', '0', ']'] #中身が一文字ずつ文字列に(汗)

```

<a id="#正しいやり方"></a>
# 正しいやり方
```python
>>> import configparser
>>> import ast

>>> config = configparser.ConfigParser()
>>> config.read('test.ini')

>>> target_l = ast.literal_eval(config['test']['target_l'])
>>> print(target_l)
[10,20,30] 

```


<a id="ちなみに辞書も"></a>
# ちなみに辞書も
```ini:test.ini
[test]
target_d={'a':'1', 'b':'2', 'c':'3'}
```
```python
>>> import configparser
>>> import ast

>>> config = configparser.ConfigParser()
>>> config.read('test.ini')

>>> target_d = ast.literal_eval(config['test']['target_d'])
>>> print(target_d)
{'a':'1', 'b':'2', 'c':'3'}
```

<a id="eval()の脆弱性"></a>
# ast.literal_eval()とeval()
今回の例では組み込み関数の`eval()`用いても同様な結果を得ることが可能です。
しかし`eval()`の主な用途は文字列をコマンドとして評価して実行することであるため、使用する際は注意が必要です。
```python 
eval("os.remove(test.py)")
```
一方、`literal_eval()`の場合は文字通りリテラルな文字列を対象とするため、別途定義された変数などを参照するとエラーを返してくれます。
【obniz】『推しらせたすかる（アクリルスタンド×からくり時計）』CFやってます！

**前回の記事で「クラウドファンディングやります！」と宣言しましたが…始まっています！
期間は、2024/1/11～1/24です…短期決戦！**

プロダクトの紹介動画を作成しましたので、よろしければご覧ください！
（無駄に荘厳なオープニング）

https://twitter.com/xe_ay51938/status/1746503364798718213

我ながら「誰得？」と思いますが…「私得」です！

obniz好きのあなた、アクスタ好きのあなたに共感してほしい…アクスタの輝きの向こうに、推しの面影を見てる…（？）

「ちょっと面白いかも」と思っていただけたら、応援いただけると大変励みになります！
**『推しらせたすかる』『#推しらせたすかる』、よろしくお願いします！**

https://camp-fire.jp/projects/view/731102
Kotlin+JUnit4でもProperty Based Testingがしたいんじゃ！！！

# この記事3行まとめ

1. androidでPBTをしたい！！
2. kotestは依存がでかすぎるんじゃ！！
3. いいライブラリみつからないねぇ・・・・

# PBT(Property Based Testing)とは

PBTとは自動テストの手法の一つでシステムのあるべき挙動を満たす条件（Property）を定義し、その条件を満たすであろう入力をランダムに自動生成し実行することで想定していない挙動をしないかどうか検証する手法です。
従来のテスト手法ではテストケースを事前に手動で作成する必要があり、テストケースを網羅的に作成することは大変です。
PBTではテストケースを自動生成するため、テストケースの作成にかかる工数と時間を削減することができます。また、ランダムな入力を生成するため、想定していない入力によるバグを検出しやすくなります。

## メリット

- テストケースの作成にかかる工数と時間を削減できる
- 想定していない入力によるバグを検出しやすくなる

## デメリット

- プロパティの定義が難しい
  - テスト対象のシステムのあるべき挙動を満たす条件（プロパティ）を定義する必要がある
  - プロパティを適切に定義できなければ、想定していない入力によるバグを検出できない可能性がある
- テストの実行時間が長くなることがある
  - ランダムな入力を生成するため、テストの実行時間が長くなることがある
- 想定外の入力によるバグを検出できないことがある
  - プロパティを満たす入力を生成するため、想定外の入力によるバグを検出できない可能性がある

# android = Kotlin + JUnit4

## 要件

1. JUnit4でうごくこと
   1. androidのテストをJUnit5で動かすのはあれこれ設定がめんどい
   2. composeやDaggerのテストなどはJUnit4向けに実装されている
2. KotlinフレンドリーなAPIであること
   1. androidの第一言語はKotlinなので
3. なるべくPrimitiveなテストをかけること
   1. Testingライブラリへの依存がでかいとTestingライブラリのバグがあった際が大変
4. (Optional) Robolectric環境下でも動くこと

## エントリー

### 1. Kotest

https://kotest.io/

https://github.com/kotest/kotest

#### ここがいい！

Kotlin + PropetyBasedTestといえばこれ
乱数生成器がいろいろ用意されていてよい
assertionもいろいろ用意されていてよい
android用のextensionもいくつか用意されていてよい
KMPでも動かせる！最高！

#### ここがいまいち！

JUnit4 + Robolectricで動かすにはDeperecatedになったライブラリを自前でカスタマイズする必要がある
ライブラリが大きいためKotest側のバグにより困る場面がある

### 2. jqwik

https://jqwik.net/

https://github.com/jqwik-team/jqwik

#### ここがいい！

JUnitのEngineを上手に拡張していてPrimitiveに見えるように使える
Kotlinでも使いやすいAPI

#### ここがいまいち！

JUnit5向け

### 3. jPopulator

https://github.com/feckertson/jPopulator

#### ここがいい！

乱数生成器としてはかなりPrimitive

#### ここがいまいち！

JavaBean向けのライブラリ
メンテナンス止まっている
fork元の[Easy Random](https://github.com/j-easy/easy-random)もメンテナンスモードに入っている

### 4. junit-quickcheck

https://pholser.github.io/junit-quickcheck/site/1.0/

https://github.com/pholser/junit-quickcheck

#### ここがいい！

JUnit4向け！

#### ここがいまいち！

テストランナーを`JUnitQuickcheck`にする必要があるため`AndroidJUnit4`や`RobolectricTestRunner`とかち合う
メンテナンス止まっている

### 5. QuickTheories

https://pholser.github.io/junit-quickcheck/site/1.0/

https://github.com/quicktheories/QuickTheories

#### ここがいい！

JUnit4向け！
実装がPrimitive！

#### ここがいまいち！

KotlinフレンドリーなAPIじゃない
メンテナンス止まっている

### 6. QuickCheck

https://mvnrepository.com/artifact/net.java.quickcheck

#### ここがいい！

JUnit4向け！
実装がPrimitive！

#### ここがいまいち！

KotlinフレンドリーなAPIじゃない
メンテナンス止まっている
VCSが見つからない・・・・・

# まとめ

androidはいつまでJUnit4にとらわれるんだ・・・・・・・
心の中のマリーアントワネットが囁くんです、**無ければ作ればいいじゃない**と・・・・
Docker コンテナからフォルダをローカルにコピーしたい

私の現場では、Ubuntuで仮想環境を構築していて、その中にDockerコンテナを積んでいるのですが、

先日、Dockerのappコンテナ内のフォルダを、デスクトップ（ローカル）に落としたい瞬間がありました。

Dockerに関して知識が薄かったため、解決法を備忘録として残しておきます。

```
# コンテナIDを調べる
$ sudo docker ps

$ sudo docker cp <コンテナID>:/app/dump/ /usr/local/tmp/
```

これでUbuntu上にコピーできるので、

そこからローカルに落とすことができます。

コンテナID+コロン以降のパスはtabキーで予測が出なかったのがびっくりしましたが、

まあなんだかんだ結構使うコマンドでありそうなので、

この備忘録を見なくても覚えられるようにしておきたいと思います。（備忘録とは…）
macOSでvmware-vdiskmanagerコマンドを実行

## はじめに

VMware ESXi上で動作する仮想マシンのディスク(vmdkファイル)が複数あり，それを統合する必要があった．その際にmacOSへvmware-vdiskmanagerコマンドをインストールする手順をメモする．

## 手順

### (1) VMware Fusionをインストール

VMware Fusionにvmware-vdiskmanagerコマンドは同梱されている．下記のリンクからダウンロードしてインストールする．

https://customerconnect.vmware.com/evalcenter?p=fusion-player-personal-13

### (2) ライセンスの取得

License & DownloadのタブからRegistration（登録）を行う．ライセンスの発行が終わると下記の画面にライセンスキーが表示される．ライセンスキーをVMware Fusionに登録する．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103672/d4b3938c-c0fb-43e7-ea1c-597a6fd352b9.png)

### (3) vmware-vdiskmanagerコマンドの実行

デフォルトではvmware-vdiskmanagerコマンドにパスが通っていない．コマンドのパスを調べるためlocateコマンドを使った．macOSではlocateコマンドの勝手が違うため，下記の記事を参照した．

[Macでlocateコマンドを使う #Mac - Qiita](https://qiita.com/soma21/items/bc9079204fb186faf10d)

locateコマンドを実行し，パス `/Applications/VMware Fusion.app/Contents/Library/vmware-vdiskmanager` にあることがわかった．必要に応じてこのディレクトリへパスを発行する．

```
$ locate vmware-vdiskmanager
/Applications/VMware Fusion.app/Contents/Library/vmware-vdiskmanager
```
三項演算子を利用せず、値がnilはnil / nil以外なら処理する方法

### モチベーション

ActiveRecordで深く潜った先の値に対して `nil` のときは `nil` 、そうでない時は値を用いて処理する場合、 `if` を用いると冗長になるし、三項演算子を利用するとめちゃくちゃ長くなる 😢

```ruby
# userに紐づく、最後の賃貸契約の契約月数を取得（契約月数はnullable）

user = User.first

# if
if user.lease_contract.last&.period_months
 p "#{user.lease_contract.last&.period}ヶ月"
else
 nil
end

# 三項演算子
p user.lease_contract.last&.period_months ? "#{user.lease_contract.last&.period}ヶ月" : nil
```

何かスッキリ書く方法ないかな？ 🤔

### 結論

[then](https://docs.ruby-lang.org/ja/latest/method/Object/i/then.html) を利用するとスッキリ書けます 🖊️

```ruby
# userに紐づく、最後の賃貸契約の契約月数を取得（契約月数はnullable）

user = User.first

# then
p user.lease_contract.last&.period_months&.then { |period_months| "#{period_months}ヶ月"}
```

point は `period_month&.then` の部分です。

1. `&.` （ぼっち演算子）はレシーバー（`period_month`）が `nil` の場合に `nil` を戻す
    - `period_month` = `nil` の場合は `nil` が取得できる
2.  then はレシーバーをブロックとして処理し、その結果を戻す
    - `period_month` の値に対して `{ |period_months| "#{period_months}ヶ月"}` を実行し、 `nヶ月` という文字列を取得する
【AWS】開発エンジニアがAWS CLF-C02を取得した所感

こんにちは！

実務経験1年ちょっとの開発エンジニアがAWS Certified Cloud Practitioner(AWS-C02)を受験し、合格してきたので、**受験動機や試験対策、所感**などについて書きたいと思います。

私は普段JavaでWebアプリケーションの開発をしていて、機能単位で設計~テストまでのタスクが割り振られるような環境で仕事をしています。
AWS経験は、受験を決めてからEC2のインスタンスを作成してみたり、Cloud9を活用してRailsの学習をしたりした程度です。
AWS含め、インフラの実務経験はありません。

同じような境遇にいる方が受験する際の参考になれば幸いです。

# 0. 試験のアップデート
2023年9月19日以降、AWS CLFの試験はC01からC02にアップデートされており、主な変更点として、<font color="DeepSkyBlue">試験対象のサービス数が約2倍</font>になっています。
C01用の模擬試験等を解いたことがないので比較はできませんが、覚える量は増えていると思います。
特に私はインフラ関係の知識がほぼ0だったので、慣れないワードも多く、想定していたよりも受験対策が大変でした。

# 1. 受験動機
主に以下の3点です。
- AWSの概要について知りたかった
- 会社で推されていた
- インフラ領域にも興味があった

AWSやインフラにも興味があり、今後深掘りしていきたいような内容かを見極めたかったのと、会社全体でAWS資格の取得が推奨されるような風潮だったので前々から受験したいと思っていました。
最近やっと開発関係のスキルが最低限身についたと感じたので、このタイミングで受験しました。

# 2. 試験対策
EC2のインスタンス作成やCloud9の使用について冒頭で触れましたが、
EC2のインスタンス作成に関しては公式のハンズオン、Cloud9の使用はRails Tutorialを通じて行いました。
(Rails Tutorialに関しては、最新バージョンではCloud9を使用しない方法に変わっているはずなので参考にならないかもしれないです。)

試験対策に使用した参考書と問題集は以下です。
- 参考書 
[AWS認定資格試験テキスト　AWS認定 クラウドプラクティショナー　改訂第2版 (ＡＷＳ認定資格試験テキスト) ](https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-AWS%E8%AA%8D%E5%AE%9A-%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%83%97%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%BC-%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88-%EF%BC%A1%EF%BC%B7%EF%BC%B3%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-%E5%B1%B1%E4%B8%8B%E5%85%89%E6%B4%8B/dp/4815622744/ref=asc_df_4815622744/?tag=jpgo-22&linkCode=df0&hvadid=655189692645&hvpos=&hvnetw=g&hvrand=17313064235438623950&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009282&hvtargid=pla-2198420669213&psc=1&mcid=c438007707a93ce2b1bba8423db830dd&th=1&psc=1)
- 問題集
[【CLF-C02版】この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集（6回分390問）](https://www.udemy.com/course/aws-4260/)

注意点として、<font color="DeepSkyBlue">参考書はC01対応</font>となっているため解説されているサービスの数が少ないです。
また、問題集に取りかかる前に1回目を通しましたが、それ以降使っていないので問題集だけ買えば十分な気がします。

問題集は、まず各章をほぼ完答できるようになるまで解いて、そのあとは1~6章を通しで2回解きました。
かかった時間は20時間くらい、期間は1~2週間です。

問題集は定価だとお高めなので、割引価格で購入することをおすすめします。
私は割引期間に2000円くらいで購入したと思います。

# 3. 受験結果
スコア：793/1000
(ボーダー:700/1000)

問題集を90％くらい解けるようになれば、ボーダーは余裕で上回ると思います。
問題集と似たような問題が割と多かったと思いますが、文言や選択肢が全く同じ問題はなかったです。

# 4. 所感
CLFに合格したからといってインフラ領域の基礎知識がつくわけではないと思いますが、どういうことをしているのかというイメージはもてたので受けて良かったです。
また、アプリケーションの開発やデプロイに便利なサービスがたくさん用意されていることもわかったので、今後どこかのタイミングで実際に利用してみたいです。

CLFを取得してみて、一旦アソシエイトレベルの受験はやめておきたいと思っています。
AWSに魅力を感じないというわけではなく、今は他の分野や技術の習得に時間を使いたいからです。
今後AWSサービスに深く関わる機会があったら、その時は受験を検討したいと思います。

---
以上
最後までお読みくださりありがとうございました！
Ubuntuのカーネルを最新化

## 1. インターネット経由での apt コマンドが実行できるように準備を行う
- OSがインターネットに接続可能か
- /etc/apt/sources.list の内容を確認

## 2. パッケージ情報をダウンロードする
この時点では何もインストールされない
```
# apt update
```

## 3. 最新のカーネルをインストール
この時点でインストールされる
```
# apt install linux-image-generic
```
新しいカーネルがインストールされた場合は、grub の内容も自動で書き換わる

## 4. OS再起動
```
# reboot
```
最新のカーネルで起動します


# 起動するカーネルを明示的に指定する場合

## 1. 起動したいカーネルのIDを確認する
```
# grep -e menuentry -e submeny /boot/grub/grub.cfg
```
/etc/default/grub を エディタで開き、「GRUB_DEFAULT」にデフォルト起動カーネルにする”ID”を設定します。
この”ID”は、/boot/grub/grub.cfg を開いて確認します。
“menuentry”に設定されている順番がそのまま”ID”となります。※0始まり
“submenu”により階層構造となっている場合は、"1>2" の様に”>”を使用して設定します。

## 2. GRUB_DEFAULTの値を起動したカーネルに変更する
```
# vi /etc/default/grub
GRUB_DEFAULT=0 の値を起動したいカーネルに書き換える
例)
GRUB_DEFAULT="1>2"
```

## 3. grubの設定変更を反映
```
# update-grub
```

## 4. OS再起動
```
# reboot
```

# インストールするカーネルを指定する場合
## 1. インストール可能なカーネル一覧を確認する
```
# apt list --all-versions|grep linux-image-[0-9]|grep generic
```

## 2. カーネルをインストールする
```
# apt install linux-image-<バージョン>-generic
```

以上

参考

https://hiiragi-works.sakura.ne.jp/linux-003/

https://blog.masu-mi.me/post/2020/12/05/switch-kernel-with-grub2/
モデルのバリデーションテストがREDにならない問題の解決

## 解決したい問題
Railsチュートリアルの6章を進めていて、テキストだとREDになるはずのテストがGREENになってしまう。

## 原因
どうやらビューに比べてモデルやコントローラの修正は反映されるのに時間がかかるらしい。
実際、他の方でも同じようなことが起きていた。
[Rails5でmodelやcontrollerの修正が反映されないやつ](https://qiita.com/uenoryo/items/5dd69436e9f5af6a752e)

## 解決した方法
### `config/environments/development.rb`に以下を追加
```
config.reload_classes_only_on_change = false
```
ファイルの変更検知の設定
> 依存関係のあるファイルに変更があった場合に、クラスを再読み込みするようになる
[Railsドキュメント](https://railsdoc.com/page/config_reload_classes_only_on_change)

### VSCodeを再起動
最初はGitHub Codespacesで進めていたけど、時間制限に引っかかりそうだったので、途中からVSCode＋Dockerで進めている。
ローカルだと`rails restart`、DockerだとDockerの再起動らしいけど、自分の環境ではどっちをやってもダメだったので、VSCodeを一旦閉じてやり直した。

そしたらテストやモデルの変更が反映されていて、無事テストがREDになった。
```
$ rails test:models     
Running 3 tests in a single process (parallelization threshold is 50)
Started with run options --seed 51857

 FAIL UserTest#test_name_should_be_present (0.01s)
        Expected true to be nil or false
        test/models/user_test.rb:15:in `block in <class:UserTest>'

 FAIL UserTest#test_email_should_be_present (0.02s)
        Expected true to be nil or false
        test/models/user_test.rb:20:in `block in <class:UserTest>'

  3/3: [================================================================================================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.01843s
3 tests, 3 assertions, 2 failures, 0 errors, 0 skips
```
javaでfor文を使った九九の表を作成


1月15日　学んだことのアウトプット

for文の2重ループを使って九九の表を作成していく！！
実行環境はEcllipseを使っています。


ソースコード
```java
package test_java;
public class FORTEST {
    public static void main(String[] args) {
        for (int i = 1; i < 10; i++) {
            for (int j = 1; j < 10; j++) {
                System.out.printf("%3d", i * j);
            }
            System.out.println("\n");
        }
    }
}
```
実行結果
```
  1  2  3  4  5  6  7  8  9

  2  4  6  8 10 12 14 16 18

  3  6  9 12 15 18 21 24 27

  4  8 12 16 20 24 28 32 36

  5 10 15 20 25 30 35 40 45

  6 12 18 24 30 36 42 48 54

  7 14 21 28 35 42 49 56 63

  8 16 24 32 40 48 56 64 72

  9 18 27 36 45 54 63 72 81

```

今回作ったプログラムの良いところはこちら
```
System.out.printf("%3d",i*j)
```
このコードによって3文字の間隔で文字が表示されるから九九がきれいに表示されています。
Laravel10にReactを導入しようとして詰まったので備忘録（Vite使用）

## 初めに
業務でlaravelにReact導入を行った際に、謎のエラーに遭遇したので備忘録です。
~~そして未だに、なぜエラーが解消されたのか理解できていないので、博識な方がいらっしゃいましたら教えていただけると嬉しいです 🙇‍♂️💦~~

:::note info
2025/01/07追記：解決方法分かりましたので、ぜひ読んでいってください！
:::


#### 参考にしたサイト
以下の記事を参考に、LaravelへReactの導入を試みました。
とても分かりやすくまとめられていて、初学者の私でも読みやすかったです！

https://reffect.co.jp/laravel/laravel9_vite_react


#### 私の開発環境

- Laravel 10
- PHP 8
- React 18.2.0
- vite 4.5.1


## 発生したエラー
今回、Reactを導入する過程で以下のようなエラーに遭遇しました。

```text:エラー 
Uncaught Error: @vitejs/plugin-react can't detect preamble. Something is wrong.
```

ぷりあんぶるが検出できない？ 初めましての単語すぎるけど、名前は可愛いですね笑
しかも「Something is wrong」なんて、かなりの初学者殺しエラーメッセージで困りました😇

何かが違うと突き放されたので、泣く泣くドキュメント検索の放浪旅に。。。

:::note info
2025/01/07追記：
「preamble」とは、Reactのホットリロード（Hot Module Replacement: HMR）、つまり自動リロードを機能させるために必要なスクリプト。これが検出できないと、自動リロードができずにエラーになる。
:::
→ @vitejs/plugin-react公式の「[Middleware mode](https://www.npmjs.com/package/@vitejs/plugin-react)」を参照すると上記エラーが発生する仕組みが説明されています！
つまり、laravelに組み込まれる@vitejs/plugin-react は Middleware mode という特別なモードで動いているんですね🧐



## 解決方法

:::note info
2025/01/07追記：
以下の解決方法は @nano5544 さんから提供いただいた情報を元に、修正しています。nanoさんありがとうございます！！
:::

#### 問題のあった部分
先ほど紹介した参考記事の中に、以下のようなvite.config.jsへの記述があります。

```js:vite.config.js 
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';

export default defineConfig({
    plugins: [
        laravel({
            input: [
                'resources/sass/app.scss',
                'resources/js/app.js',
            ],
            refresh: true,
        }),
         react(),
    ],
});
```

これはviteに **laravel-vite-plugin** と **@vitejs/plugin-react** をインポートして、接続の設定を行っているファイルなのですが、この **@vitejs/plugin-react** の方が上手く動作しないことが問題になっています。

#### 解決コード

```diff_php:app.blade.php
<!DOCTYPE html>
<html lang="ja">
  <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">

      <title>laravel</title>

      <!-- CSRF Token -->
      <meta name="csrf-token" content="{{ csrf_token() }}">

      <!-- Fonts -->
      <link rel="preconnect" href="https://fonts.bunny.net">
      <link href="https://fonts.bunny.net/css?family=figtree:400,600&display=swap" rel="stylesheet" />

      <!-- style -->
      <link rel="stylesheet" href="{{ asset('/assets/css/commonStyle.css') }}">

      <!-- viteの埋め込み -->
+     @viteReactRefresh
      @vite(['resources/sass/app.scss', 'resources/js/app.js',])
  </head>
  <body>
    （bodyが入ります）
  </body>
</html>
```
問題を解決するためには、Laravelプロジェクトの全てを司るblade（app.blade.phpにしていますが、ファイル名は環境によって異なります）に、**@viteReactRefresh** を記述します。
これによって、Reactのホットリロードが動くようになり、ぷりあんぶる見つからない問題が解決します！

:::note info
2025/01/07追記：
[Laravel9のアセット構築](https://readouble.com/laravel/9.x/ja/vite.html)に「React」のセットアップ方法がちゃんと載っていました。。。
@vitejs/plugin-reactプラグインのインストール後に、@viteReactRefresh Bladeディレクティブを入れろとのご教示が。（※最新のLaravel11にも記載あり）
:::
リーダブル読んでないのバレバレですね、改心します😇

## 最後に
~~今のところ問題なくReactを使うことができているので、原因詮索を行うのは諦めました。引き続き開発に専念していこうと思います。~~

実は以前紹介していたコメントアウトという力業でも問題なく1年動いていたのですが、明らかに邪道なので修正しました😅
自身のプロジェクトも上記の方法で修正を行ったところ、問題なく動いています！

nanoさん情報のご提供ありがとうございました🙇‍♂️

また何か進捗があり次第、更新します。

それではまたいつか！
AL2023学習メモ②　Apache2.4.58導入

# 前置き
学習メモをまとめています。
私と同じ初心者さんの助けになれば幸いです。

# この記事でわかること
1\. apache2.4.58のインストール方法
2\. ログの確認 - エラーの解決方法

:::note warn
2024年1月15日現在の情報です。
今後のアップデートで、Apacheのバージョンが上がっていく可能性があります。
:::

# 事前環境
* EC2
    * AL2023
# 1\.インストール方法
AL2023で、Apacheをインストールする方法は非常に単純です。
AWSで既にパッケージが用意されているため、そこからインストールすることになります。

* Apacheがパッケージとして用意されているかを確認
```
# yumのsearchコマンドでApacheに該当するパッケージを検索
$ sudo yum search httpd

#実行結果
==================== 名前 完全一致: httpd==================
httpd.x86_64 : Apache HTTP Server
```
* Apacheをインストール
```
# パッケージをインストール (-yオプションで、全ての項目をyesにする）
$ sudo yum install -y httpd
```
* Apacheのバージョン確認
```
$httpd -v
#実行結果
Server version: Apache/2.4.58 (Amazon Linux)
Server built:   Oct 24 2023 00:00:00
```
* Apacheの格納場所は、"/etc/httpd"
```
$cd /etc/httpd
$ls
#実行結果
conf  conf.d  conf.modules.d  logs  modules  run  state
```
* Apacheを開始してみる（今回は、systemctlコマンドを使用）
```
$sudo systemctl start httpd.service
$sudo systemctl status httpd.service
#実行結果（Active:activeなら問題なし）
● httpd.service - The Apache HTTP Server
     (中略）
     Active: active (running) since Mon 2024-01-15 18:39:36 JST; 2s ago
    （中略）
```
```
#接続確認
$curl http://localhost
#実行結果
（中略）
<h1>It Works</h1>
```
* URLより、HPが表示できることを確認
  URLに、http://[EC2のパブリックIPv4 DNS]を打って、tomcatのテストページが表示されることを確認

# 2\. ログの確認 - エラーの解決方法
* apacheのログ格納場所は、"/etc/httpd/logs/error_log"
```
#ディレクトリ移動
$cd /etc/httpd/logs
#「error」に一致するerror_logを閲覧
$cat error_log | grep "error"
```
下記のエラー文が表示されている可能性があるため、確認

* エラー文
　Cannot serve directory **/var/www/html**:
  No matching DirectoryIndex **(index.html)** found,
  and server-generated directory index forbidden by Options directive
* 原因
　ドキュメントルートである、**/var/www/html**に**index.html**が格納されていないというエラー
* 対処方法
  /var/www/htmlにindex.htmlを格納する

```
$cd /var/www/html
#index.htmlを作成
$vi index.html

#以下を記述
<DOCUTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Apache start Page</title>
</head>
<body>
    <h1>エラーログ解決！</h1>
</body>
</html>

$ls
#実行結果
index.html
```
```
#Apacheを再起動
$sudo systemctl restart httpd.service

#エラーログを確認し、エラーが発生していないことを確認
$cd /etc/httpd/logs
#「error」に一致するerror_logを閲覧
$cat error_log | grep "error"
```
## 補足
上記でindex.htmlを作成したが、セキュリティ上の観点から権限の変更をお勧めします。
rootユーザーからssm-userユーザーへ
```
#ディレクトリ移動
$cd /var/www

#権限変更(htmlディレクトリの権限を、ssm-userグループの、ssm-userユーザーに変更）
$chown -R ssm-user:ssm-user html

#権限確認
$ls -l
#実行結果（下記なら成功）
rwxr-xr-x. 2 root   root(略
drwxr-xr-x. 2 ssm-user ssm-user(略
```
# 後書き
以上がApacheをインストールしてから、実行するまでの手順です。
こうやって記事を書いてみると、やること多いですね。
セキュリティ面を気にするなら更にやることが多いらしいので、根気強く頑張りたいです。
TypeScriptのクラスについて

## 事前知識
### オブジェクト
コード上で扱うもの。変数、定数、メソッドなどあらゆるものを含み得る。

``` ts
const personData: {
    name: string;
    age: number;
    hobbies: string[];
    addHobby: (hobby: string) => void;
}  = {
    name: 'John',
    age: 30,
    hobby: ['sports', 'reading', 'travel'],
    addHobby: function (hobby: string) {
        this.hobbies.push(hobby);
    }
};

```

## クラスとインスタンス
### クラス
オブジェクトの設計図。

### コンストラクタ
クラスを基に宣言されたインスタンスに紐づくメソッド。
インスタンスの宣言時に実行される。
``` ts
// どんなプロパティ・メソッドを持つのかを記述する
class Person {
    name: string;
    age: number;
    // 初期値を宣言することも可
    hobbies: string[] = []:

    // オブジェクトの宣言時に実行されるメソッド
    constructor(name: string, age: number) {
        // プロパティの初期化
        this.name = name;
        this.age = age;
    }

    addHobby(hobby: string) {
        this.hobbies.push(hobby);
    }
};
```

### インスタンス
クラスの定義に基づいて作成されたオブジェクト。

```ts
// newでオブジェクトを宣言する
const personData = new Person('John', 30);
personData.addHobby('sports');
```

## privateとpublic
privateはプロパティへのアクセスを制限するための修飾子。
クラス内でのみアクセスが可能な状態にする。

publicはアクセスを制限しない。
初期値はこちらのため、publicにしたい場合は付与不要。

``` ts
class Person {
    // 頭にprivateを付ける
    private hobbies: string[] = []:
    ...
    addHobby(hobby: string) {
        this.hobbies.push(hobby);
    }
};
// Person外から値を追加しようとすると、エラーになる
personData.hobbies[0] = 'sports';
// Person内で定義されている関数からアクセスすると、正常に実行される
personData.addHobby('sports');
    
};
```
## プロパティ初期化のショートカット構文
class宣言時に設定するプロパティは、初期値を設定するか初期化を行う必要がある。
``` ts
class Person {
    private name: string;
    age: number;
    hobbies: string[] = []: // 初期値を宣言

    // オブジェクトの宣言時に実行されるメソッド
    constructor(n: string, a: number) {
        this.name = n; // nameの初期化
        this.age = a; // ageの初期化
    }
};
```

これについて、constructorの引数にアクセス修飾子を追記することで二重の定義を回避できる。
この方法を取る場合、渡す引数の変数名がそのままプロパティの名前になる。
アクセス修飾子を明示しなければならない。

``` ts
class Person {
    // 最初のパラメータの宣言を削除

    // public, privateどちらの場合でも明示的に記述する
    constructor(
        private name: string,
        public age: number,
        private hobbies: string[]
    ) {
        // パラメータの初期化用の記述も削除
    }
};
```

## readonly
初期化後に変更したくないものに付与するアクセス修飾子。
``` ts
// Objectの設計図、どんな値・メソッドを持つのかを記述する。
class Person {
    constructor(
        private readonly id :number, // idは初期設定後変更したくないため付与
        private name: string,
        public age: number,
        private hobbies: string[]
    ) {
    
    }
};

const personData = new Person(01, 'John', 30); // 01は後から変更できない
```


次の記事

https://qiita.com/toraguitar/private/57d600d208efd7d75121
【Salesforce】フローの命名規則

名前の付け方を統一しておくと保守性が高まります。
下記、命名規則の一例です。

# フロー名
| # | フロー種別 | 命名ルール | 例 |
|:-:|:-|:-:|:-|
| 1 | 画面フロー | SCR_ | SCR_EditAccount |
| 2 | レコードトリガーフロー | TRG_ | TRG_AccountUpdateTrigger |
| 3 | スケジュールトリガーフロー | SCH_ | SCH_ContactSendBirthdayEmails |
| 4 | プラットフォームイベントトリガーフロー | EVT_ | EVT_SalesFinished |
| 5 | サブフロー | SFL_ | SFL_CreateErrorLog |

# リソース名
| # | 種別 | 命名ルール | 例 | 備考 |
|:-:|:-|:-:|:-|:-|
| 1 | 変数 | var_ | var_TargetAccountId | recordIdはのぞく |
| 2 | 定数 | const_ | const_DraftRecordTypeName |
| 3 | 数式 | formula_ | formula_Today |
| 4 | コレクション選択肢セット | choice_ | |

# 要素名
## データ
| # | 要素 | 命名ルール | 例 |
|:-:|:-|:-:|:-|
| 1 | レコードを取得 | get_ | get_ActiveAccount |
| 2 | レコードを更新 | update_ | update_Contacts |
| 3 | レコードを作成 | create_ | create_Contacts |
| 4 | レコードを削除 | delete_ | delete_Contacts |
| 5 | ロールバックレコード | rollback_ | rollback_AllRecords |

## ロジック
### 割り当て
| # | 処理内容 | 命名ルール | 例 |
|:-:|:-|:-:|:-|
| 1 | 変数の更新（オブジェクト型の項目） | set_ | set_NextContactDay | 
| 2 | 変数の初期化、変数の更新 | assign_ | assign_TargetContactId |
| 3 | コレクションに要素を追加 | store_ | store_TargetDivisions |
| 4 | コレクションに要素を削除 | remove_ | remove_TargetDivisions |
| 5 | 計算や複雑なコレクション操作 | calc_ | calc_CountUpContacts |

### 決定（選択）
| # | 内容 | 命名ルール | 例 | 備考 |
|:-:|:-|:-|:-|:-|
| 1 | 要素名 | decision_{決める内容} | decision_NextStatus | | 
| 2 | 結果名 | {決める内容}_{判定} | NextStatus_Pending | | 
| 3 | デフォルトの結果 | エラー | エラー | デフォルトの結果はエラー処理に使用する。 |

### 決定（判定）
| # | 内容 | 命名ルール | 例 | 備考 |
|:-:|:-|:-|:-|:-|
| 1 | 要素名 | check_{確認する内容} | check_RecordType | | 
| 2 | 結果名 | {確認する内容}_{判定} | RecordType_Draft | |
| 3 | デフォルトの結果 | エラー | エラー | デフォルトの結果はエラー処理に使用する。 |

### ループ・変換（ベータ）・コレクションの並び替え・コレクション検索条件
| # | 要素名 | 命名ルール | 例 | 備考 |
|:-:|:-|:-:|:-|:-|
| 1 | ループ | loop_ | loop_TargetContact | 
| 2 | 変換（ベータ） | transform_ | transform_Order |
| 3 | コレクションの並び替え　| sort_ | sort_OrdersByDate |
| 4 | コレクションの検索条件 | filter_ | filter_OrdersByAmount |

## 相互関係
### 画面
| # | 内容 | 命名ルール | 例 | 備考 |
|:-:|:-|:-:|:-|:-|
| 1 | 要素 | screen_ | screen_AccountEdit | 
| 2 | 入力コンポーネント | input_ | |
| 3 | 出力コンポーネント | display_ | |

### アクション・サブフロー・カスタムエラー
| # | 内容 | 命名ルール | 例 | 備考 |
|:-:|:-|:-:|:-|:-|
| 1 | サブフロー | flow_ |  | 
| 2 | カスタムエラー | error_ | |

# 参照
- [Flow Naming Conventions | SFXD Wiki](https://wiki.sfxd.org/books/best-practices/page/flow-naming-conventions)
- [実装時に気をつけると良いこと | Salesforce Flow Recipes](https://shunkosa.github.io/lightning-flow-recipes-jp/design-guideline/)
【Docker】docker-composeでスクリプト実行したら`OCI runtime create failed...permission denied`となった場合

# エラー概要
`docker-compose.yaml`の`command`セクションからスクリプト実行するときに、以下のエラーに遭遇しました。
こちらの原因と解決方法を記載します。

```
Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "./sample-script.sh": permission denied: unknown
```


# 原因
上記エラーは、`sample-script.sh`スクリプトに実行権限がないために発生するエラー。
`ls -la`でパーミッションを確認。

```
-rw-r--r--  1 xxxxxxx  staff   33  1 15 18:09 sample-script.sh
```

`-rw-r--r--`は、ファイルのパーミッションを表すための記号表現ですね。
数値に直すと`644`になります。実行（`x`）権限がないのがわかりますね。

このスクリプトに実行権限を付与してあげる必要があります。

ちなみに`docker-compose.yaml`の`command`セクションは、コンテナが起動するときに実行されるデフォルトのコマンドが指定できます。
ここでスクリプトを起動する際に、実行権限がなくてエラーを吐いていたのです。

```docker-compose.yaml
##　略　##　
  web:
    build:
      context: .
      dockerfile: Dockerfile
    command: ["./sample-script.sh""] ## 実行権限がないスクリプトを実行させようとしている
    volumes:
      - ./myprojects:/code 
    ports:
      - "8000:8000"
   ##　略　##　
```

# 解決方法
以下コマンドにより、スクリプトに現在のユーザーに対する実行権限を付与できます。

```terminal
chmod +x sample-script.sh
```

「`+x`」が「実行権限を追加する」という意味になります。
この後に、`ls -la`で確認すると以下になりました。

```
-rwxr-xr-x  1 xxxxxxx  staff   33  1 15 18:09 sample-script.sh*
```

`-rwxr-xr-x`は、ファイルのパーミッションを表すための記号表現ですね。
これを数値で表すと「`755`」になりますので、`chmod 755`とかでもいけますね。

イメージを再度ビルドしてコンテナを立ち上げると、無事にスクリプトが走ったことを確認できました。

## 補足：`command`セクションの扱いについて

ちなみに、`docker-compose.yaml`の`command`セクションは以下のように複数書くと、後に指定されたものが優先されます。

```yaml
  web:
    build:
      context: .
      dockerfile: Dockerfile
    command: ["./sample-script.sh"]
    command: python manage.py runserver 0.0.0.0:8000　# こちらだけ実行される
```

以下のようにしても、スクリプトが終了するとコンテナも終了してしまうので後の方は実行されません（コンテナ内のコマンドは非同期的に実行されるため）。

```yaml
  web:
    build:
      context: .
      dockerfile: Dockerfile
    command: ["./sample-script.sh", "python", "manage.py", "runserver", "0.0.0.0:8000"]
```


複数使いたい場合は、それこそこのようなスクリプトファイルを使って、その中に実行したいコマンドを記載してあげると良いです。
以下は`echo`してるだけですが、このように複数のコマンドを実行させることもできます。

```sample-script.sh
#!/bin/bash

echo "Hi, this is sample command"

# Djangoのサーバーを起動
python manage.py runserver 0.0.0.0:8000

# そのほか以下に書く
```
【pnpm】pnpm自体をアップデートする

`pnpm install`を実行した際に、アップデートのお知らせが出たので、pnpm自体をアップデートしたときの手順をまとめます。

```
   ╭──────────────────────────────────────────────────────────────────╮
   │                                                                  │
   │                Update available! 8.14.0 → 8.14.1.                │
   │   Changelog: https://github.com/pnpm/pnpm/releases/tag/v8.14.1   │
   │                Run "pnpm add -g pnpm" to update.                 │
   │                                                                  │
   │      Follow @pnpmjs for updates: https://twitter.com/pnpmjs      │
   │                                                                  │
   ╰──────────────────────────────────────────────────────────────────╯
```

上記のようなお知らせが出たので、指示通り、 `pnpm add -g pnpm` を実行すると、エラーがでました。

```
Nothing to stop. No server is running for the store at /Users/XXXX/Library/pnpm/store/v3
 ERR_PNPM_NO_GLOBAL_BIN_DIR  Unable to find the global bin directory

Run "pnpm setup" to create it automatically, or set the global-bin-dir setting, or the PNPM_HOME env variable. The global bin directory should be in the PATH.
```

どうやら、`pnpm setup`を実行せよ、とのこと。
実行すると、以下のように表示される。

```
% pnpm setup
Appended new lines to /Users/XXXXX/.zshrc

Next configuration changes were made:
export PNPM_HOME="/Users/XXXXX/Library/pnpm"
case ":$PATH:" in
  *":$PNPM_HOME:"*) ;;
  *) export PATH="$PNPM_HOME:$PATH" ;;
esac

To start using pnpm, run:
source /Users/XXXXX/.zshrc
```

設定が書き換えられたようなので、再読み込みをおこなう。

```
% source /Users/XXXXX/.zshrc
```

再度、アップデートするコマンドを実行すると、成功する。

```
% pnpm add -g pnpm             
Nothing to stop. No server is running for the store at /Users/XXXXX/Library/pnpm/store/v3
The location of the currently running pnpm differs from the location where pnpm will be installed
 Current pnpm location: /opt/homebrew/bin
 Target location: /Users/XXXXX/Library/pnpm

Packages: +1
+
Progress: resolved 1, reused 0, downloaded 1, added 1, done

/Users/XXXXX/Library/pnpm/global/5:
+ pnpm 8.14.1

Done in 1s
```
PowerAutomateフローから20名を超えるメンバーにメンションを送る

今日もちょっとしたTIPSです。

# Problem

PowerAutomateのワークフローから、Teamsコネクターを使用して20名を超えるチームメンバー／グループチャットメンバーにメンションを送信しようとすると、エラーとなってしまう。

# Solution

原因はTeamsの仕様（制限）。

Microsoftの公式資料「[Microsoft Teams - 一般的な既知の問題と制限](https://learn.microsoft.com/ja-jp/connectors/teams/#%E4%B8%80%E8%88%AC%E7%9A%84%E3%81%AA%E6%97%A2%E7%9F%A5%E3%81%AE%E5%95%8F%E9%A1%8C%E3%81%A8%E5%88%B6%E9%99%90)」からの抜粋：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/005d66f9-d80c-d815-4208-c0bb7e797d3a.png)

これ自体はいかんともしがたいので、どうしても20名を超えるメンバーにメンションを送信したい場合は、複数回に分けて送信する。

この場合のワークフローのイメージはこんな感じ：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/2d8fb84e-afd7-074f-6589-a7173fe8a82c.png)

重要なのは後半の Do Untilアクションのところ。
用意した @mentionトークンの配列の先頭から20件ずつ要素を取り出して処理していく。
まず `take()`関数で配列の先頭20件を取り出す。それを使ってメンションを送信する。続いて `skip()`関数で配列の先頭20件を除いた残りを取り出す。それを変数に再代入する。

これで20名を超えるメンバーにメンションを送信することができる。
TexMaths の new Text mode を試してみる+α

「Ubuntu 上の LibreOffice を PPA 最新版に」
https://qiita.com/nanbuwks/items/d4208badac69141bca21

を施すことで、 最新の TexMaths が使えるようになったので、
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/46a62ae3-af5d-1aee-8d91-4712e29cc265.png)
0.51から搭載された new Text mode を試してみます。


# 環境

- Ubuntu Linux 22.04
- LibreOffice Version: 7.6.4.1 (X86_64)
-  TexMaths 0.52

# Impress で試す
 
タイトルページを編集して、このボックスに数式を入れ込んでみます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/1f7cad56-f25a-3153-881b-c6cb04e197a7.png)

ここで TexMaths で以下のように入力すると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/04555f3e-1384-645f-1333-1a72bd46a5e6.png)

インラインで記号が入りました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/ef9010b6-5a7a-cf57-33b8-f8ad4c920436.png)

さて、これから再編集するには!?

再度 TexMaths を呼び出すと中身が空っぽですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/4b5d9727-5762-91d2-640d-bcf12a8c9e4d.png)

「LaTeX」ボタンの近くに履歴ボタンができているので、これを使って前回の入力を呼び出すことができるようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/a9adc349-2890-beef-0c1a-0738a571bcf9.png)

同じ内容で「LaTeX」ボタンを押すと二重になりました。前の内容を消す必要があるみたいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/90cc7cca-1625-8eb0-577b-c121699ebdd9.png)

# Draw で使ってみる

Impress に限らず、任意のテキストボックスにも数式が入るようです。フキダシを作ってみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/9aa9eb7b-4f62-fec4-b81b-62e29b57c029.png)

数式記号ですが、使えないものが多くあります。この理由は・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/c8ae4940-2e28-e912-4324-e7d7cb7a9d1c.png)

分数が書けないので、スラッシュで代わりにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/12998b00-e729-136c-4a83-5a902d0da27c.png)

1行の数式が改行されて表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/94f0f35a-c985-feed-142b-12a5bdd414f9.png)

テキストボックスのプロパティを開き、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/eb29b05c-7a04-a095-bd50-cbb8d1faf269.png)
フォントサイズを変更すると1行に収まりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/585ac7f0-df9c-b9e9-cc96-decb25b2f7bb.png)

フォントサイズ変更が効くということはこれらの記号類は Unicode のグリフをつかっているっぽいです。それで 数式記号が限定されているのですね。


# おまけ 従来のモードで数式を書く

ちゃんと分数を書きたいので従来のモードの数式をフキダシに重ねることにしました。
```
\begin{eqnarray}
p'&=&p\frac{1-\frac{v}{u}}{\sqrt{1-\frac{v}{c}^2}} \\
&=&\frac{m(u-v)}{\sqrt{[1-(\frac{u}{c})^2][1-(\frac{u}{c})^2]}}
\end{eqnarray}

```

うーん、数式番号がついてしまいますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/92cf22c0-bfcb-03f9-6aa1-b09a498bfe63.png)

過去にはUIに番号つき数式ボタンがありましたが、今ではなくなっています。左揃えすると番号がつくようになっているのかな?

```

\begin{align*}
p'&=p\frac{1-\frac{v}{u}}{\sqrt{1-\frac{v}{c}^2}} \\
&=\frac{m(u-v)}{\sqrt{[1-(\frac{u}{c})^2][1-(\frac{u}{c})^2]}}
\end{align*}
```
`eqnarray` ではなく、 `align*` を使うと解決しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/143f0155-a379-ab0d-8d7d-bfd2d683a0e6.png)
mocopiのBVHファイルからFBX形式に楽に変換する(Mac)

# 概要
mocopi で取得した BVH ファイルを Unity上で再生する場合、一旦FBXに変換する必要があります。([変換する方法](https://qiita.com/SatooRu65536/items/557effbd5b31c4e3e58e#bvh-%E3%82%92-fbx-%E3%81%AB%E5%A4%89%E6%8F%9B%E3%81%99%E3%82%8B))
ただ、毎回実行するのは面倒なので、
Automator という MacOS デフォルトのアプリを使用して Finder のクイックアクション から簡単に変換できるようにします

Finder上で 右クリックし、クイックアクション > bvh2fbx を押して待つだけで FBXファイル が生成されます
<img width="1178" alt="スクリーンショット 2024-01-15 17.10.54.png (2.7 MB)" src="https://img.esa.io/uploads/production/attachments/13979/2024/01/15/148142/428946e1-96e0-412e-9ccb-423d490f6f1f.png">

# 手順
`Automator.app` を開き、クイックアクション を選択します
<img width="1434" alt="スクリーンショット 2024-01-15 17.27.55.png (1.5 MB)" src="https://img.esa.io/uploads/production/attachments/13979/2024/01/15/148142/e064561c-b239-4e6d-bda4-5732a7602ba6.png">

ウィンドウ上部の項目を以下のように設定します
- ワークフローが受け取る現在の項目: `ファイルまたはフォルダ`
- 検索対象: `Finder.app`
- 画像: 任意(クイックアクションのアイコンになります)
- カラー: 任意(クイックアクションのアイコンになります)

`シェルスクリプトを実行` ブロックを追加し、入力の引き渡し方法を `引数として` にします。
以下のコードを貼り付けてください。
ただし3行目の `<script>` は `mocopi_bvh_fbx_converter.py` の **絶対パス** に置き換えてください

```
for file in "$@"; do
  if [[ "$file" == *.bvh || "$file" == *.BVH ]]; then
    /Applications/Blender.app/Contents/MacOS/Blender -b -P <script> -- "$file"
  fi
done
```

<img width="1434" alt="スクリーンショット 2024-01-15 17.18.50.png (1.3 MB)" src="https://img.esa.io/uploads/production/attachments/13979/2024/01/15/148142/1e033a4a-e7a5-4280-ba51-8c44e4565eed.png">

保存することで画像のようにクイックアクションとして使用できます。
保存場所はデフォルト(`~/Library/Services/`) にしてください。
<img width="1178" alt="スクリーンショット 2024-01-15 17.10.54.png (2.7 MB)" src="https://img.esa.io/uploads/production/attachments/13979/2024/01/15/148142/428946e1-96e0-412e-9ccb-423d490f6f1f.png">

クイックアクション に表示されていない場合は 
システム設定 > プライバシーとセキュリティ > Finder
で有効になっているかを確認してください。
<img width="827" alt="スクリーンショット 2024-01-15 17.26.51.png (821.1 kB)" src="https://img.esa.io/uploads/production/attachments/13979/2024/01/15/148142/6e93d242-49f1-4967-aa9a-608328a34358.png">

# おわりに
最後までお読みいただきありがとうございました！
Automator を使って自動化すると幸せになれます 🐧
greenlet.error: cannot switch to a different threadが出たときの対処方法

flask_socketioのWEBアプリコードを動かそうとしたら、動作開始前に撃沈したときのメモです。

※ 以下はVSCodeを使用している場合の対処方法です。

#### 現象
エラー発生箇所：
　socketio.run(app, debug=True, host='0.0.0.0', port=8080)
　(諸事情によりデバッガの動きが怪しく、本当にここかは不明。)

エラーメッセージ：
　greenlet.error: cannot switch to a different thread

 (メッセージ画面)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/5eef6921-efe3-e1a1-d3dc-8b1a537ec0e5.png)

#### 対処方法
Stackoverflowを確認したところ、VSCodeを使用している場合はlaunch.jsonに"gevent":trueを追加すれば良さそう。

① [実行とデバッグ]のアイコンをクリックし、「launch.jsonファイルを作成します」を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/aed79f8a-8847-7e3f-6d3d-bcd1215a4c13.png)

もし[実行とデバッグ]のアイコンを押しても↑この画面ではない場合、既に存在していると思われるので、エクスプローラの.vscode下を見てみてください：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/87aa0670-dcd4-817d-2118-1634d28090fc.png)

② "gevent":trueを追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/c153bb62-c401-471f-5eed-6a055bef817b.png)

#### 再度実行してみた
別のエラーが出た。

エラーメッセージ：
　ModuleNotFoundError: No module named 'gevent'
(メッセージ画面)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/d6d6ceea-e3eb-8526-2eba-9a5df2eddb2d.png)

既にgeventを持っている人は出ないエラーなのだろう。
何はともあれ、geventが無いようなのでpip installし、再々度実行。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/86f85508-cae2-4c2c-ec82-99d2761eee00.png)

起動したっぽいので、ブラウザからlocalhost:8080にアクセスしたところ、無事表示ができました。

#### 新たな疑問
もしかしてgeventが無いことが問題だったのか？launch.jsonの変更は本当に必要だったのか？という疑問が・・・

ということで、再度launch.jsonのgeventの設定をコメントアウトして実行してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/99249109-5542-5b07-8473-08fd3a0d2892.png)

やはり冒頭のエラーになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/18e39895-c274-30eb-c700-0b7d4c7d4bc8.png)

疑ってスミマセンでした。

#### 結論
「greenlet.error: cannot switch to a different thread」が出たときは、launch.jsonの設定で「"gevent":true」を追加する必要がある。
【AWS】コンソールのトップページを素通りしている人へ

皆様、明けましておめでとうございます。
今年は発信に力を入れていきたいなあという思いで新年1発目の記事を書いていきます。

## 質問です

AWSマネジメントコンソールは、AWSリソースを管理するための重要なツールです。しかし、多くの人々がそのトップページを素通りしていませんか？

## デフォルトのAWSマネジメントコンソール

デフォルトのレイアウトではこんな感じです。
![ガジェット画像_デフォルト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471646/7dafcc8c-6c25-ecea-2109-4ff6276c6cc9.png)

私はこのトップページをちゃんと見たことはありませんでした。毎回ぜったい素通り。

どんなのがあるんだろう？と思って改めてよく見てみたら
- 「AWSへようこそ」って。今さらの挨拶過ぎん？あなたとわたし4年目よ。
- 「アプリケーション」なんも登録されていないのにデカデカ過ぎるやん><
- Healthとコストそこにいたんだ。。気づかなかったよ

とまあこんな感じです。

強いてこのページの利用シーンを上げるとしたら`最近アクセスしたサービス` に目当てのサービスがあった時にクリックするくらいです。それ以外は即検索窓。

そんな方、意外と多いんじゃないでしょうか？

## 実はレイアウトってカスタマイズ可能なんです

今日ふとコンソールを見てたら「なんだこのオレンジの」と思い `ウィジェットを追加` をクリックしてみました。
![ガジェット画像_デフォルト_ウィジェットを追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471646/a99b24b9-4753-b94d-f835-655fc2231672.png)

するとまあいくつか項目が出てきて、私はそこで「あーーーこのレイアウトってカスタマイズ出来るんだー」と知りました！！

詳細についてはもう既に紹介している記事があったのでそちらをご覧ください（丸投げ）

https://aws.amazon.com/jp/blogs/news/a-new-aws-console-home-experience/

https://dev.classmethod.jp/articles/update-manegement-console-20220112/#toc-4

## そして行き着いたマイ最強レイアウト
![ガジェット画像_カスタマイズ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471646/e9cfb315-968f-898c-8244-5685941c115a.png)

`最近アクセスしたサービス`
まあ引き続き利用頻度高いんでデカめに置いておきましょう。

`コストと仕様状況` 
毎回嫌でも目に入るように一番上に置いておこう。

`Seurity`
マジ大事。ここにSecurity Hubのスコアがパーセント表示されているからチェックしておきましょう。スコアが下がっているのに放置はしている人いないよね？（冷や汗）

`AWS Health`
AWS のインフラストラクチャとアカウントに影響を与える可能性のあるイベントを表示されているので何かあれば確認しましょう。

`Trusted Advisor`
推奨されるアクションや調査があれば確認しておきましょう。

`最新のお知らせ`
AWSはアップデートのサイクルが早すぎるのでここも要チェックですね。

これで素通り出来ないトップページが出来上がりました！

## さいごに
これからもどんどんウィジェットは追加されていくと思いますが、各サービスのダッシュボードとかも自由に配置できるようになってきたら面白いですね。

人によって、利用しているPCやディスプレイのサイズによっても最適なレイアウトは異なってくると思うので、みなさんオリジナルの配置にして快適なマネコンライフをお過ごしください。
【ズボラの家】アレクサに古いリモコンを操作してもらう【アレクサ、何もかもやって】

## WHats this?
面倒な家電の操作をアレクサにやってほしい、そういう思いでSwitchBot Hub2を買った。
SwitchBotHubへのリモコンの登録とアレクサの連携をするだけで、「アレクサ、寝室のライトをつけて」のような簡単な操作はすぐに使えたものの、そのままの設定では「寝室のライトを暗くして」のような操作は動かなかった。
それでは旨味半減ということで、色々試した結果、SwitchBotのシーン設定を使うことで古いタイプのリモコンも良い感じに設定できた。


## 注意点
SwitchBotHub2はあくまで赤外線操作をコピーするものであり、いわゆるリモコンの無いデバイスの操作はツメで物理ボタンを押下してくれるスイッチを別途用意する必要があります。

## 必要なもの
- SwitchBotHub2
- AmazonEchoなど「アレクサ〜」を受け付けてくれるもの
  - GoogleHomeでも可
- Wifi(2.5GHz)
- 家中のリモコン
- スマホ

## 前準備
- アレクサが使える環境を作っておく（各種設定）
- SwitchBotのアプリをダウンロードし、会員登録を行う
- SwitchBotHubをコンセントに挿す
- SwitchBotHubとアプリの連携をしておく
  - このときWifiが必要
- SwitchBotHubに家のリモコンを設定する

## 各ボタンの設定（アレクサに音声で反応させるまで）
ここでは「"アレクサ、おやすみ"と言ったら寝室のライトを常夜灯にする」を例とします。
※寝室のライトのリモコンに「常夜灯」ボタンがある場合です※

### SwitchBotアプリ
1. 右上の＋ボタンから「シーンを追加」をタップ
1. 「シーンを作成」画面で、分かりやすいシーン名を入力する。
今回はシーン名を「寝室を常夜灯に」とします
1. 「アクションを追加」ボタンをタップ
1. 【デバイス/プッシュ通知/タイマー実行（ベータ版）】というリストが表示されるので「デバイス」をタップ
1. デバイスの一覧から操作したいリモコンのデバイスをタップ
1. リモコンのボタンが表示されるので、今回操作したいボタンをタップする（例：常夜灯ボタン）
1. 「保存」ボタンをタップ

### Alexaアプリ
1. 「その他」→「定型アクション」を選ぶ
1. 定型アクションの「＋」ボタンをタップ
1. 新しい定型アクション画面で、実行条件を追加→「音声」を選ぶ
1. 開始フレーズ「アレクサ、＿＿＿＿＿＿」となっているところにフレーズを入力。
例：おやすみ
1. アクションを追加→スマートホーム→シーン→「寝室を常夜灯に」を選ぶ→確認画面が出てくるので「追加」ボタンをタップ
1. 「保存」ボタンをタップ

1分ほど待ってから「アレクサ、おやすみ」と話しかけてみてください。
常夜灯に切り替われば成功です！

## ちょいハマったところ

### アレクサにフレーズを言ったのに「おやすみなさい♪良い夢を♪」など独自の挨拶のほうを返してくる
- Alexaアプリの定型アクションの「▶（再生マーク）」ボタンを押して正しく動くか確認する
- フレーズの入力を漢字からひらがな、ひらがなであれば漢字に変えてみる
- しばらく待つ（同期されるまでに1分ほどかかる）

これでもダメなら一度定型アクションを削除して、もう一度定型アクションの追加からやり直す。
もしかしたらAlexaの挨拶をOFFにすることもできるのかもしれない。

### リモコンのボタンが「ON/OFF」のトグルスイッチになっている
「部屋の電気を消す」と「つける」が同じボタンに割り当てられている場合、あるいはONのボタンを３回押すと常夜灯になるなど、ボタンとデバイスの機能が1対多の関係にある場合

- これはどうしようもないので「Alexa、仕事部屋の電気を消して」「Alexa、仕事部屋の電気をつけて」どちらにも同じボタンを割り当てる
- （今の我が家は）電気を消したいのか、つけたいのかは目視で確認できるので、いずれにせよリモコンのON/OFFボタンを１回押せれば良い、という感覚で運用している
- ONボタンを3回押す、という定型アクションを作成することもできるが、部屋のライトが今どのモードかによっては「3回押した先のモード」が変化する（ピカピカに全点灯してしまってグワァ！目が！となるリスクがある）ため、愚直に「仕事部屋の電気を消して」を２回言っている。
なお、Alexaにしつこく語りかけている間にリモコンを手に取ったほうが早い。


## 人感センサーライトも良いぞ

余談だが、同じタイミングで人感センサーつきのバーライトも購入、玄関と洗面所に設置した。
充電式でコードレスだし、去年買った日除け兼モバイルソーラーパネルから給電も可能で実にエコ。
今までは灯りのスイッチなんて些細な労力でしょ、と思っていたが、いざセンサーライトに置き換えてみると、つけたり消したりを意識しなくて良いのは思いの外快適である。
特に玄関（靴箱の上）に取り付けた方は、ドアの開閉に反応するのか「ただいま〜」と開けた瞬間から明るいので、VIP待遇を受けているようなちょっと照れくさい気持ちになる。

うちのセンサーライトは20秒ほどで消えるタイプのため、家族がそこらじゅうの電気をつけっぱなしにするのを指摘したり、「も〜〜〜〜」と唸りながら消して回ることがなくなり、イラッとくることが減ったのも地味に良かった。


## あとがき

掃除しなくていいならしたくないし、料理しなくていいならしたくない。
お金を稼ぐこと、楽しいこと、刺激を得ることだけやっていたい。
我ながら言っていることが子供だな〜、と思うが、それが真の自分である。

そんなズボラな私なので、SwitchBotの存在を知った時は狂喜乱舞した。
シーンの設定を行うことで、リモコンの各ボタン操作をアレクサに代替させるだけでなく、アレクサ側の定型アクションを使えば

私「アレクサ、そろそろ寝るよ」
→　リビングのライトをOFF、各部屋のエアコンを「6時間後入」タイマーにしてOFF、寝室を常夜灯に

私「アレクサ、寒いね」
→こたつをON（スマートプラグ）、リビングのエアコンON

のような合せ技も行えるため、フレーズとリモコンのボタン運用を少し考えるだけでかなり快適に暮らせると思う。
各家庭のユースケースに合わせて、ぜひトライしてみてほしい。
ABC058 ARC071 の問題を解いてみました

## A問題
https://atcoder.jp/contests/abc058/tasks/abc058_a

if文で、$b-a = c-b$ かどうかを判定しましょう。

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

int main(void){
  int a, b, c;
  cin >> a >> b >> c;
  if(b - a == c - b){
    cout << "YES" << endl;
  }
  else{
    cout << "NO" << endl;
  }
}
~~~

## B問題
https://atcoder.jp/contests/abc058/tasks/abc058_b

奇数番目の文字と、偶数番目の文字を交互に出力すれば良いです。
ただ、奇数番目の文字を集めた文字列の方が長い場合があるので、それに対応する必要があります。


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

int main(void){
  string o, d;
  cin >> o >> d;
  for(int i = 0; i < o.size(); i++){
    cout << o[i];
    
    if(i >= d.size()) break; // o の方が長い場合を対処する
    
    cout << d[i];
  }
}
~~~

## C問題
https://atcoder.jp/contests/abc058/tasks/arc071_a

すべての文字列に含まれている文字を集めて出力します。

アルファベット26文字について、すべての文字列に含まれている個数だけその文字を出力することによって、この問題は解くことができます。


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

int main(void){
  int n;
  cin >> n;
  string s[n];
  for(int i = 0; i < n; i++) cin >> s[i];
  //受け取り完了
  
  for(char ch = 'a'; ch <= 'z'; ch++){ //すべての文字について試す
    int ans = 1e9; //とりあえず大きい数にしておく
    for(int i = 0; i < n; i++){
      int sum = 0;
      for(int j = 0; j < s[i].size(); j++){
        if(s[i][j] == ch) sum++; //ch という文字が出てきた回数を記録する
      }

      if(ans > sum) ans = sum;
      // すべての文字列に含まれている ch の数を記録しておく
    }
    
    for(int i = 0; i < ans; i++){
      cout << ch; //最小の ch の数 回出力する
    }
  }
}
~~~

## D問題
https://atcoder.jp/contests/abc058/tasks/arc071_b
ChromeをSelenide経由で動かすと何故かめっちゃ遅い問題の解消


# 自分のPCだけchrome激重でまともにテストできない

現在委託されている開発現場で、e2eの自動テストツールとしてgaugeとselenideを使用しているのですが、なぜか自分のPCだけ動作が遅く、ログイン画面開くだけで約10秒かかってしまい、まともにテストできなくなりました。。。

開発してるアプリが普通に重たいのかと思ったのですが、手元のchromeでlocalhostで開くと1秒もかからずに開けるので、明らかにselenideで開いたときだけ遅いっぽい

# 遅い原因
結論から言うと、自分はM1 macを使ってるのですが**selenideで開いたchromeはarm64ではなくx86_64で開こうとしてCPU使用率が激高になってた**模様。

手元のchrome
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987302/ae3246ac-46fc-1808-b907-c16e50f9b870.png)

selenideで開いたchrome
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987302/734611f3-8312-e136-d8a3-9943cba75a40.png)

# なんでこんな事が起きるのか
どうやらselenideもseleniumと同様に、開こうとする言語のアーキテクチャに沿ったブラウザで開こうとするみたい。

[参考] https://stackoverflow.com/questions/76957026/chromedriver-starts-chrome-as-x86-64-translated-on-m1-very-slow-performance

たしかに自分は元々Intelのmacを使っていて、最近M1 macに移行アシスタントでデータをそのまま乗り換えたのですが、前のIntel時代のmac(x86_64)で動かしていたJavaをずっと使ってたみたいです。。

```
$ java -XshowSettings:properties -version 
    :
os.arch=x86_64  <= ずっとx86のJavaで動かしてたっぽい
    : 
```

# 対応
１. まずは既存のJavaをuninstallしてarm64用のJavaをinstallし直します。
```
$ java -XshowSettings:properties -version 
    :
os.arch=aarch64 
    : 
```

２. brewで諸々インストールしてたので、homebrew自体をarm64のやつに入れ直しました。

３. brewでインストールした諸々をuninstallして、再度arm64用のbrewでinstllし直しました。自分はmavenとgauge-javaを使っていたので、この2つは入れ直しました。本当は色々入れ直したほうがいいんだけど取り急ぎ。
  - gauge
  - mvn

４. （mavenの場合）mvnをinstallし直したら一旦.m2をふっとばす

５. IntelliJ使ってる場合は、３でmvnを再インストールしたあとにpluginも一回uninstallして入れ直したほうが良いです。自分の場合は下記を入れ直しました
- gauge
- Kotlin
- maven helper

６.gauge-javaを入れ直す（これでようやくchromeがarm64で動くようになった）
``` bash
$ gauge -v
Gauge version: 1.5.6
Plugins
-------
html-report (4.2.0)
java (0.10.3)
screenshot (0.1.0)

$ gauge uninstall java
Successfully uninstalled plugin java 0.10.2.
Successfully uninstalled plugin java 0.10.3.
Successfully uninstalled plugin java 0.9.2.

$ which gauge 
/opt/homebrew/bin/gauge  # arm64用のやつになってるよねの確認。/opt/homebrewなのでOKそう。ちなみにx86の場合は/usr/local/binとかになってると思います

$ gauge install java 
........................
Successfully installed plugin 'java' version 0.10.3

$ gauge -v
Gauge version: 1.5.6
Plugins
-------
html-report (4.2.0)
java (0.10.3)
screenshot (0.1.0)
```

これでようやくサクサク動いてくれるようになりました

# 感想
思った以上にめちゃくちゃハマってしまいました。。。

macの移行アシスタントは便利なんですが、そのせいでIntelとarm64のものが混合してしまってるので、この辺の後処理ちゃんとやらないと無駄にハマってしまうなという教訓です。

この現象でハマっている人が一人でも救われれば幸いです。（ほとんどいないと思うけど）