OmniAICreator/Qiita-1.07M huggingface dataset:
ABC308回答メモ

0.はじめに
　コンテストの予選のせいか、難しめだった気がします。
　A~Cは解けましたが、Dはちょっと見ただけで無理そうな
　雰囲気を感じてしまいリタイヤ。

　まぁレートが751→735と下がったので、予選のため難しかったとかは
　いいわけなのですが・・・。


1.A - New Scheme
　条件複数あるけどそれほどややこしくないので
　リストを頭から読んでいき、条件を満たしているかを判定。
```
    if(i>0):
        if(S[i-1]>S[i]):
            print("No")
            exit()
    elif(S[i]<100 or S[i]>675):
        print("No")
        exit()
    elif(S[i]%25!=0):
        print("No")
        exit()
print("Yes")
```
　最初、↑のように書いたら昇順チェックしかしないという
　単純なバグを発生させてしまい、5行目をifと別条件式にして
　ACを頂きました。

　https://atcoder.jp/contests/abc308/submissions/43096262

2.B - Default Price
　3種のリストに文字列を扱うというBにしては珍しい問題。
　DとCの組み合わせを辞書登録して
　Cのリストを頭から読んでいき
　辞書になかったらP[0]の値、あったら辞書の値を回答用変数に加算
　最後に回答用変数を出力して終了。

　https://atcoder.jp/contests/abc308/submissions/43102496

3.C - Standings
　最初の実装は10分強でできまいたが、WAが4つ発生
　Pythonは小数の比較が正確でない時がある（意訳）ような説明を
　どっかで見た気がしたので、そこをどうにかしようと試行錯誤・・・。
　
　5～6回いろいろあがいて、最後には
　おそらく、小数点の小さい方がごにょごにょとなってしまうんだろうなと思い（感覚派）
　成功率の計算をA/（A+B）から、（A*10**20）//(A+B)と、強引に整数の域まで持ってきて
　計算することで、ACにたどり着きました。

　https://atcoder.jp/contests/abc308/submissions/43137050

以上
【Github】iPadでソースコードを確認・編集する方法【テキストエディタ】【VSCode】

# 出先で実装方法を確認できないジレンマ
外出中に「ここの実装、どうしてたっけ…？」と気になったことはありませんか…？
もちろんGithub上で確認することも出来ますが、検索しづらいですし若干不便さを感じますよね。

なんとかテキストエディタで確認する方法はないかな…と調べていた時に発見しました。
GithubのCodespace機能を活用することで、ブラウザ上でVSCodeを使うことが出来ます。

ちゃんと拡張機能も使えるらしいので、活用方法次第ではとても便利ですね！

## Codespaceの使い方
# 1. iPadのブラウザでGithubの画面を開き、該当プロジェクトのリポジトリを開く

![IMG_0082.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653721/e161dcc4-114e-7c29-2f99-d0e2ff655b49.png)

# 2. Codeボタンを押し、Codespacesを押下

![IMG_0083.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653721/3cc98210-0620-1629-0076-1c6ee90ae46a.png)

たったこれだけの手順で、以下のようなVSCodeの画面が表示されます。
拡張機能も使えるらしく、簡単に操作することが出来ます。
ソースコードの確認はもちろん、簡単な内容ならその場で編集することも出来そうです。

![Fz_W6ptacAAAlJP.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653721/062fb53f-33dc-873a-1c64-e8941826e487.jpeg)



# おまけ
Twitterもやってます。
https://twitter.com/minnasinario
開発したアプリの一覧はこちらから！
https://lit.link/taminaryousuke

一番バズったアプリは「ガチャメーカー」です！

https://apps.apple.com/jp/app/%E3%82%AC%E3%83%81%E3%83%A3%E3%83%A1%E3%83%BC%E3%82%AB%E3%83%BC-%E3%81%82%E3%81%AA%E3%81%9F%E3%81%A0%E3%81%91%E3%81%AE%E3%82%AA%E3%83%AA%E3%82%B8%E3%83%8A%E3%83%AB%E3%82%AC%E3%83%81%E3%83%A3%E3%82%92%E4%BD%9C%E3%82%8B%E3%82%A2%E3%83%97%E3%83%AA/id1617490189

# 参考URL

https://zenn.dev/ningensei848/scraps/9b70bfb09c8c64

https://kght6123.page/posts/GitHub/Codespace/iPad%E3%81%A7GitHubCodespace%E3%82%92%E8%A9%A6%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F%EF%BC%81/
Linuxのディレクトリ構造をPlantUMLのコンポーネント図に変換する

# 1.この記事の内容

``tree``コマンドで取得できるディレクトリ構造をPlantUMLのコンポーネント図として出力するプログラムを作成しました
　→ [directory_tree_drawer](https://github.com/ryoma-jp/directory_tree_drawer/tree/main)

# 2.背景

ディレクトリ構造を資料にまとめることが時々あるのですが，構造図として出力する術が見つからず，自分で作りました．

# 3.仕組み

1. ```tree -J```でディレクトリ構造をJSONで出力する
    - 出力例
    ```
    [
      {"type":"directory","name":".","contents":[
        {"type":"file","name":"LICENSE"},
        {"type":"file","name":"README.md"},
        {"type":"file","name":"directory_tree_drawer.py"},
        {"type":"directory","name":"sample","contents":[
          {"type":"file","name":"plantuml_sample.png"},
          {"type":"file","name":"plantuml_sample.pu"}
      ]}
      ]}
    ,
      {"type":"report","directories":1,"files":5}
    ]
    ```
1. JSONファイルからディレクトリとファイルを抽出し，PlantUMLのコンポーネント図のスクリプトへ変換する
    - 出力例
    ```
    @startuml
    folder "." {
    [LICENSE]
    [README.md]
    [directory_tree_drawer.py]
    folder "sample" {
    [plantuml_sample.png]
    [plantuml_sample.pu]
    }
    }
    @enduml
    ```
1. PlantUMLのスクリプトを画像データ(png，svgなど)へ変換する
    - ここは``directory_tree_drawer``ではなく[plantuml-server](https://hub.docker.com/r/plantuml/plantuml-server)を使用する
        ```
        $ docker run -d -p 8080:8080 plantuml/plantuml-server:jetty
        ```
    - 出力例
![plantuml_sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/983907/25c6d392-43c9-41ff-efa7-6685b059d6b5.png)

# 4.さいごに

[directory_tree_drawer](https://github.com/ryoma-jp/directory_tree_drawer/tree/main)から直接構造図を出力しようと思い，PNGファイルを出力する機能拡張を予定していましたが，実際に使ってみるとPlantUMLで十分な気もしてきました． 
PlantUMLのスクリプトをバージョン管理するとディレクトリ構造の差分管理もしやすいので．

PNGファイルを直接出力できるようにするより，各ディレクトリやファイルの説明を加筆できる仕組みの方を考えるかもしれません．
（あとは，インデントをつけるのをサボったので，体裁面の修正もいつか…）
【Flutter】Flutterで開発されたアプリを見分ける方法【iOS】【Android】

# Flutter製のアプリが増えてきた実感
最近ご飯を食べにいった飲食店で、Flutterで開発されたアプリが使われているのを発見しました。Flutterアプリの開発も行なっている私にとっては喜ばしいことです。

この他にも最近はFlutterを活用したアプリの例はかなり増えてきている印象があります。アプリストアで適当にインストールしてみると、結構な確率でFlutterが使われているとわかります。


# 見分け方はとっても簡単
見分ける方法はとっても簡単なのですが、意外と知られていないかもしれません。

「このアプリ、Flutterで作りましたか？それともswiftですか？」
といった質問を頂いたことがあったので、見分け方の需要がもしかしたらあるのかもしれないと思い、今回まとめてみました。

## 1. アプリの縦に長い画面を二本指でスクロールする
「このアプリ、Flutter製かな？」と気になったら、そのアプリの画面を二本指でスクロールしてみてください。Flutter製の場合、なんとスクロール速度が二倍になります！

スクロール速度が早くなったらFlutter、そうでなければネイティブ実装（swift）のような見分け方ができるということです。

一本指の場合…

https://twitter.com/handwritingchat/status/1675302315937665025

二本指の場合

https://twitter.com/handwritingchat/status/1675302503997644800

ちなみに三本指で試すともっと早くスクロールします。これは指の本数に応じて移動距離を定めているため、**指の本数×距離**分スワイプされることになるという仕組みらしいです。

三本指の場合

https://twitter.com/handwritingchat/status/1675302881078169600




# このアプリで試してみてください
Flutter製のアプリを触ってみたいという方は、このアプリでぜひ試してみてください。
私が先日リリースしたFlutter製アプリです。

https://apps.apple.com/jp/app/%E6%89%8B%E6%9B%B8%E3%81%8D%E3%83%81%E3%83%A3%E3%83%83%E3%83%88-%E3%83%94%E3%82%AF%E3%83%88%E3%83%BC%E3%82%AF-%E6%83%B3%E3%81%84%E3%82%92%E5%B1%8A%E3%81%91%E3%82%8B-%E3%81%A4%E3%81%AA%E3%81%8C%E3%82%8B%E3%82%A2%E3%83%97%E3%83%AA/id6449237575

こちらのアプリは、最近個人的にとても気になっているアプリです。本来直接会ってコミュニケーションを取りながら進めていく「マーダーミステリー」というゲームを、オンラインで行えるようにするというコンセプト。UX体験がとても優れていて、感動したアプリなのでぜひ試してみてください。

https://apps.apple.com/jp/app/%E3%82%A6%E3%82%BA-%E3%83%9E%E3%83%BC%E3%83%80%E3%83%BC%E3%83%9F%E3%82%B9%E3%83%86%E3%83%AA%E3%83%BC%E3%82%A2%E3%83%97%E3%83%AA/id1529068001

# おまけ
Twitterもやってます。
https://twitter.com/minnasinario
開発したアプリの一覧はこちらから！
https://lit.link/taminaryousuke

一番バズったアプリは「ガチャメーカー」です！

https://apps.apple.com/jp/app/%E3%82%AC%E3%83%81%E3%83%A3%E3%83%A1%E3%83%BC%E3%82%AB%E3%83%BC-%E3%81%82%E3%81%AA%E3%81%9F%E3%81%A0%E3%81%91%E3%81%AE%E3%82%AA%E3%83%AA%E3%82%B8%E3%83%8A%E3%83%AB%E3%82%AC%E3%83%81%E3%83%A3%E3%82%92%E4%BD%9C%E3%82%8B%E3%82%A2%E3%83%97%E3%83%AA/id1617490189


# 参考URL

https://flutter.salon/flutter/identify-flutter-app/
Vue.jsで共通処理を一箇所にまとめる最適な手法とは？

# はじめに

Vue.jsで開発を進めていると、多くのコンポーネントで共通の処理が存在することがあります。そのため、共通の処理を一箇所にまとめて効率的に管理する方法を調査することにしました。その結果、いくつかの方法が見つかりました。それらの方法を一覧にし、各方法の概要、使用例、適用シナリオ、そして注意点を挙げていきます。

# 共通処理の管理方法の一覧

以下に見つけたVue.jsにおける共通処理の管理方法を挙げます：

1. Mixin
2. Vue.component（グローバルコンポーネント）
3. 状態管理（例：Vuex）
4. Custom EventBus
5. Provide / Inject

# 各方法の詳細と使用例

それぞれの方法について、詳細を見ていきましょう。

## 1. Mixin

**概要**: Mixinは複数のコンポーネントで再利用したいメソッド、ライフサイクルフック、あるいはデータプロパティなどをまとめるために使用します。

**コード例**:

```javascript
export const myMixin = {
  created: function () {
    this.hello()
  },
  methods: {
    hello: function () {
      console.log('hello from mixin!')
    }
  }
}

new Vue({
  mixins: [myMixin]
})
```

**想定場面**: データのバリデーションやフォーマット、特定のAPI呼び出しのような処理を複数のコンポーネントで再利用したい場合に適しています。

**注意点**: Mixinはメソッド名やデータプロパティの衝突を引き起こす可能性があり、また、Mixinがどのコンポーネントで使用されているかを追跡するのは難しいため、注意が必要です。

## 2. Vue.component（グローバルコンポーネント）

**概要**: Vue.componentを使用すると、全体で再利用可能なUIコンポーネントを簡単に作成できます。

**コード例**:

```javascript
Vue.component('my-button', {
  template: '<button @click="handleClick">Click me</button>',
  methods: {
    handleClick: function () {
      alert('Button clicked!')
    }
  }
})
```

**想定場面**: カスタムボタンやモーダル、ツール

バーのようなUIコンポーネントは全体で再利用可能にすると効率的です。

**注意点**: 名前衝突を避けるために、コンポーネントの名前は明確でユニークにする必要があります。また、グローバルコンポーネントは、使用されていない場合でもメモリを消費します。

## 3. 状態管理（例：Vuex）

**概要**: Vue.jsの状態管理ライブラリを使用すると、アプリケーション全体の状態を一元管理することができます。ここでは一例としてVuexを紹介します。

**コード例**:

```javascript
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})
```

**想定場面**: ユーザーのログイン情報、テーマ設定、共有データキャッシュなど、多くのコンポーネントでアクセスや変更が必要なデータを扱う場合に適しています。

**注意点**: 状態管理ライブラリは大規模なアプリケーションで役立ちますが、小規模なアプリケーションではオーバーヘッドとなる可能性があります。また、全体の状態に影響を及ぼす可能性があるため、誤った操作には注意が必要です。

## 4. Custom EventBus

**概要**: Custom EventBusを使用すると、任意のコンポーネント間でデータを送信することができます。

**コード例**:

```javascript
var bus = new Vue()

// in component A's method
bus.$emit('id-selected', 1)

// in component B's created hook
bus.$on('id-selected', function (id) {
  // ...
})
```

**想定場面**: コンポーネント間で直接的な親子関係がないが、データをやり取りしたい場合に適しています。

**注意点**: EventBusは全体のコンポーネント間でデータをやり取りするときに使うので、どこからどこへのデータの流れをしっかりと理解しておくことが重要です。また、EventBusの使用はスパゲッティコードを生む可能性があるため、使用は慎重に。

## 5. Provide / Inject

**概要**: `provide`と`inject`を使用すると、祖先コンポーネントから全ての子孫コンポーネントへデータを渡すことができます。

**コード例**:

```javascript
var Provider = {


  provide: {
    foo: 'bar'
  },
  // ...
}

var Consumer = {
  inject: ['foo'],
  created() {
    console.log(this.foo) // => "bar"
  },
  // ...
}
```

**想定場面**: あるコンポーネントの下位にある全てのコンポーネントで特定のデータを利用したい場合に適しています。

**注意点**: `provide` / `inject`の組み合わせは依存性の注入を可能にしますが、これによりコンポーネント間の結合度が高まる可能性があるため、適切な使用が重要です。

# まとめ

以上、Vue.jsにおける共通処理の管理方法としてMixin、Vue.component（グローバルコンポーネント）、状態管理（例：Vuex）、Custom EventBus、Provide / Injectを紹介しました。それぞれには適用シナリオと注意点があり、適切に使い分けることでコードの再利用性とメンテナンス性を向上させることができます。

今後もVue.jsの開発に役立つ情報を提供していきますので、ぜひチェックしてみてください。
2023年6月振り返り〜変化とリフレクション〜

※この文章の1部はchatGPTに作ってもらいました。
どこがchatGPT作か当ててみてください笑

## はじめに
もう1年の半分が経ちました。ほんとに？時間の流れがはやすぎる説、、
先月は「毎週1記事投稿する」と宣言しておきながら、結局は1本しか投稿できなかった、、汗

## 2023年6月のざっくり振り返り
社内外、いろんな方とお話する機会が多かったです。
本を読むより何倍も記憶に残るし、学びになるな〜と改めて。
一方でもくもくと学ぶ時間はもう少し確保したかったところです。

エンジニアの面談/面接にも入らせていただき、**話しながら今何を求められているか**を
考える機会が増えたり。（常にできるようにしたい）

GWから始めた写経も6月初めに終わりました！ぱちぱち
もう1冊まるごとはやらない←ですが、経験としてはよかったです。
記事したので読んでいただければと思います。

https://qiita.com/makky/items/c0fb0244b152c744d9d3


#### 今月おもしろかった、気になった記事、本など
**■ アジャイルなチームをつくる ふりかえりガイドブック**
次のトピックで記載する振り返りについて、目的や手法まで基本のき、が書かれていました。
もっと早く読めばよかった、、、

https://www.amazon.co.jp/%E3%82%A2%E3%82%B8%E3%82%A2%E3%82%A4%E3%83%AB%E3%81%AA%E3%83%81%E3%83%BC%E3%83%A0%E3%82%92%E3%81%A4%E3%81%8F%E3%82%8B-%E3%81%B5%E3%82%8A%E3%81%8B%E3%81%88%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%E3%83%96%E3%83%83%E3%82%AF-%E5%A7%8B%E3%82%81%E6%96%B9%E3%83%BB%E3%81%B5%E3%82%8A%E3%81%8B%E3%81%88%E3%82%8A%E3%81%AE%E5%9E%8B%E3%83%BB%E6%89%8B%E6%B3%95%E3%83%BB%E3%83%9E%E3%82%A4%E3%83%B3%E3%83%89%E3%82%BB%E3%83%83%E3%83%88-%E6%A3%AE-%E4%B8%80%E6%A8%B9/dp/4798168793

**■プロンプトにも興味を持って、少しずつ手を出し始めています。**
テクニカルサポート的なこともしていたりするので、
chatGPTにお任せできるところは増やしていきたいなと思いキャッチアップ中、、
人間の仕事はどんどんなくなるな〜と改めて思ったり。

https://www.promptingguide.ai/jp

https://learnprompting.org/ja/docs/intro

## 印象に残ったトピック
今月は3点。
５月で一度案件が落ち着いたこともあり、開発業務以外の印象が強いです。

#### ①案件の振り返り
jamboard使って振り返り。（↓は一部ですが）
![](https://storage.googleapis.com/zenn-user-upload/38429aa4ec86-20230701.png)

CTOのレビューいただき、やり直し→レビュー→やり直し、、と繰り返し。
カレンダー見返すと**8時間**以上時間をかけていました。ひぇぇ


そもそも振り返りは何のためにするのか。
単純に「次に活かすため」だけでは浅い（振り返りができない）なと、
**成果を出すための行動の選択肢を増やすため**　だと今回で理解をしました。

極論ですが例えば、**ペアプロしてみてよかった→ペアプロしよう**だと振り返りではないんですよね。
なぜよかったのか、なぜ良かったのかまで深めることでやっと次に転用ができる。
確実に学びは多かったなと。次の案件で活かしていきます。

#### ②機能のもくもく会
こちらは6/30のホヤホヤ話。
カスタマーサクセスのメンバーと一緒にユーザーさんのもくもく会を開催しました。
機能の使用方法を画面共有しながらやってみせる。その場でユーザーさんにもやってもらう。

ユーザーさんが**どこでつまずくのか、どこに時間がかかるのか**痛みを知れる場だったなと。
このページにこんなに時間かかるんだとか、結構をリアルに体感できました。
この感覚、開発者は麻痺してしまいがちなので、大切にしていきたいです。

#### ③社外の勉強会に参加
エンジニアとしての職歴が今の会社からスタート、
かつ普段社内のメンバーとしか話す機会がないので、とても貴重でした。
うちでも取り入れたいと思うこともあり、刺激になります。また定期的に参加できたらと。
（来月は社外で初めてLTに挑戦します。ワクワク。）

## 終わりに
もう1年の半分終わったのか早いな〜、、と毎年言っている気がする。
もはや毎月、今月もあっという間だったと言っている気もする。
充実しているからこそだとは思いますが、もう少し噛み締めて生きたいところ
Power Apps で入力必須や表示を動的に切り替える

# はじめに

Power Apps でアプリを作成する際、入力必須や表示を動的に切り替えたいという相談をいただくことが結構あります。

例えば、以下のようなアプリで、休暇理由で`[その他]`を選択した際に、備考の入力を必須にする、それ以外を選んだ際は備考の表示を非表示にしたいといった感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/1da06374-838e-166e-3f61-3a3c6baba5b3.png)

そのため、今回は、こちらの例をベースに方法を紹介します。

# 入力必須を動的に切り替える

今回は、フォームコントロールを利用します。フォームコントロールを利用する際、項目の入力を必須にするかどうかについては、`[Required]`プロパティで指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/334d6f64-65de-83d7-dc34-9601e600cab5.png)

今回は、その他の項目で選択された値を元に動的に入力必須かどうか切り替えたいので、以下のような書き方になります。

```
If(
    DataCardValue9.Selected.Value = "その他",
    true,
    false
)
```

:::note
今回は、休暇理由を選択する部品の名前は、DataCardValue9 のため、DataCardValue9.Selected.Value が、休暇理由で選択された値という意味になります。`[DataCardValue9]`の部分は、部品の名前に応じて変わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/ce1f0d5e-d63e-c923-c67f-895b16e5c852.png)
:::

# 表示を動的に切り替える

表示を動的に切り替える方法も似たようなアプローチになります。部品を表示させるかを決めるプロパティは、`[Visible]`です。既知値は true のため、表示させるかどうか条件式に変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/99182ade-ba51-7cc4-cae3-d45c80c8db1e.png)

今回も、休暇理由の部品で選択された値を元に切り替えたいので、`備考_DataCard1`という部品の`[Visible]`プロパティお以下のように記載します。

```
If(
    DataCardValue9.Selected.Value = "その他",
    true,
    false
)
```

以下の通り、休暇理由で選択された値次第で表示が切り替わります。今回は、非表示になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/b544eb85-fab2-a6f1-ac09-7b24081acf00.png)

# まとめ

今回は、Power Apps で入力必須や表示を動的に切り替える方法について紹介しました。個人的に良く聞かれますし、入力漏れにより二度手間が発生することを防止するためや、入力を少しでも楽にするためによく利用するアプローチのため、少しでも参考になれば幸いです。
Elixirの対話モードで入出力とファイルシステムの動作を確認してみた

# 概要
Elixirの対話モードで入出力とファイルシステムの動作を確認してみました。以下のページを参考にしました。

https://dev.to/gumi/elixir-12--4og6

# 対話モードで実行
以下のコマンドを実行しました。
```
$ iex
Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> IO.puts "hello world"
hello world
:ok
iex(2)> IO.gets "yes or no? "
yes or no? hello
"hello\n"
iex(3)> IO.puts :stderr, "hello world"
hello world
:ok
iex(4)> {:ok, file} = File.open("hello", [:write])
{:ok, #PID<0.111.0>}
iex(5)> IO.binwrite(file, "world")
:ok
iex(6)> File.close(file)
:ok
iex(7)> File.read("hello")
{:ok, "world"}
iex(8)> {:ok, file} = File.open("hello", [:read])
{:ok, #PID<0.116.0>}
iex(9)> IO.binread(file, :line)
"world"
iex(10)> File.close(file)
:ok
iex(11)> File.read("hello")
{:ok, "world"}
iex(12)> File.read!("hello")
"world"
iex(13)> File.read("unknown")
{:error, :enoent}
iex(14)> File.read!("unknown")
** (File.Error) could not read file "unknown": no such file or directory
    (elixir 1.12.2) lib/file.ex:355: File.read!/1
iex(14)> defmodule Example do
...(14)> def read_file(file) do
...(14)> case File.read(file) do
...(14)> {:ok, body} -> IO.puts(body)
...(14)> {:error, reason} -> IO.puts("error: #{reason}")
...(14)> end
...(14)> end
...(14)> end
{:module, Example,
 <<70, 79, 82, 49, 0, 0, 6, 168, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 228,
   0, 0, 0, 24, 14, 69, 108, 105, 120, 105, 114, 46, 69, 120, 97, 109, 112, 108,
   101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:read_file, 1}}
iex(15)> Example.read_file("hello")
world
:ok
iex(16)> Example.read_file("unknown")
error: enoent
:ok
iex(17)> {:ok, body} = File.read("unknown")
** (MatchError) no match of right hand side value: {:error, :enoent}

iex(17)> Path.join("elixir", "test")
"elixir/test"
iex(18)> Path.expand("/elixir/test/../config")
"/elixir/config"
iex(19)> {:ok, file} = File.open "hello", [:write]
{:ok, #PID<0.140.0>}
iex(20)> pid = spawn fn ->
...(20)> receive do: (msg -> IO.inspect msg)
...(20)> end
#PID<0.144.0>
iex(21)> IO.write(pid, "hello")
{:io_request, #PID<0.106.0>, #Reference<0.2008531481.1106247684.113083>,
 {:put_chars, :unicode, "hello"}}
** (ErlangError) Erlang error: :terminated
    (stdlib 3.17) io.erl:94: :io.put_chars(#PID<0.144.0>, "hello")
iex(21)> {:ok, pid} = StringIO.open("hello")
{:ok, #PID<0.147.0>}
iex(22)> IO.read(pid, 4)
"hell"
iex(23)> IO.puts :stdio, "hello"
hello
:ok
iex(24)> IO.puts Process.group_leader, "hello"
hello
:ok
iex(25)> IO.puts '拝啓' ++ [25964, 20855]
拝啓敬具
:ok
iex(26)> IO.puts [104, 'ello', ?\s, "world"]
hello world
:ok
iex(27)> 
```

# まとめ
何かの役に立てばと。
Power Apps でデータ処理中の画面を表示する


# はじめに

Power Apps でアプリを作る際、何らかの処理をしていることを知らせる画面を表示したい、データが二重で登録される対策をしたいという相談を受けることがあります。

例えば、データの送信処理に時間を要す可能性がある場合、アプリの利用者からすると、データの送信が上手く行われていないと誤認識して再度送信ボタンを押してしまい、結果的に二重登録されてしまうような可能性があるためです。

私が作成しているアプリでも、以下の記事で紹介した、働き方を共有するアプリでは、一人一日一レコード登録されることを想定しています。仮に一日に複数レコードが登録されると、データの表示がずれるなどの問題が発生するため、データ処理中であることを知らせる画面を表示し、**データ送信中に誤って複数回ボタンを押して、データが二重登録されないよう対策を取るようにしています。**

https://qiita.com/Takashi_Masumori/items/7db650461849b8dab820

今回は、そのような対策をする方法について紹介します。

■ボタン押す前

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/d53e5920-ec7b-d302-38e8-c048198f1b5a.png)

■ボタンを押して処理をしている最中
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/5a593407-d2b1-2660-c9d5-7f94e2ecc1c2.png)

# アプローチ

まず、以下のような処理中に表示する画面を作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/654b7f07-ad65-2e95-c915-7b0fcb91b886.png)

部品としてはシンプルで、例えば、ラベルと、gif 画像を用意してグループ化します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/55502f21-051a-5e00-5157-6d623de51a83.png)

ラベルは、`[Fill]`プロパティの透明度を調整することで、ポップアップぽくなると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/402d315e-15c1-26a1-80c7-64e9683a3948.png)
 
今回は gif 画像を利用していますが、シンプルに文字を表示させたりしても良いかと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/f8d195e2-ce91-1ec1-24a7-76581b6f0689.png)

:::note
他の部品より前に表示されるよう、部品を最前面に移動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/0ecaa81e-df11-eccd-14eb-e439d7f6b8ec.png)
:::

用意した部品の`[Visible]`プロパティを変数にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/1735c46b-40e4-f0a8-24f9-194667c14187.png)

処理中画面を表示したい側で、処理開始前に変数を true にして、処理終了後に、false にします。こちらにより、処理に時間を要している際に上記のような画面が表示され、その間、後ろにあるボタンを再度押すことは出来ません。

そのため、仮にデータの送信処理に時間を要しても、データ処理中の画面を表示しているため、アプリの利用者が、データの送信が上手く行われていないと誤認識して再度送信ボタンを押すこと、結果的にデータが二重登録されることを防ぐことが出来ます。

```
UpdateContext({locShowProcessingNow:true});

間の処理

UpdateContext({locShowProcessingNow:false});

```

# まとめ

今回は、Power Apps でデータ処理中の画面を表示する、データの二重登録対策をする方法について説明しました。データ処理に時間を要す場合、データ処理中である旨を知らせるのは利用者にとって親切だと思いますし、何かの予約をするアプリなど、データが二重で登録されると困るようなケースは沢山あると思うので、少しでも参考になれば幸いです。
Power Apps で SharePoint リストの参照列を利用する際の既定値の指定でちょっとはまった


# はじめに

Power Apps でアプリを作成時、データソースとして SharePoint リストを利用する際、複数のリストを作成する場合があります。このような場合、データの整合性を保つため、参照列を利用することがあります。

例えば、何らかの注文を管理したい場合、商品のリストを作成します。次に、その商品の注文依頼を管理するリストを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/5c44b330-cf9f-0431-4968-0d3c8c420ac0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/43e87beb-4f96-19ff-bccd-25396f753b4f.png)


この際、注文を依頼する際に選択する商品は、商品のリストから選択させるようにしたいという要件があります。こちらがテキスト型の自由入力の場合、想定していない商品が注文されたしまうためです。このような要件がある際、一つの選択肢として、参照列を利用する方法があります。

参照列を使用することで、以下のように、注文依頼を行う際、選択できる商品が、商品リストに存在するものだけになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/b629646e-776d-4a2a-8969-1abd2e78ba06.png)

:::note

作成自体は、列を作成する際、以下のように、参照という種類を選び、参照先のリストと列を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/a80b8013-5431-f88c-6a42-0ab263e69e0b.png)
:::

今回は、このような参照列を使用している際、少しハマってしまったことがあるため、備忘のために紹介します。

# アプローチ

まず、フォームコントロールにコンボボックスを追加します。そのままでもいいですが、前方一致の検索結果しかヒットしなかったので、Search が機能するよう、コンボボックス追加します (最終的には、元々のコントロールが隠れるようにします) 。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/8e5ae5b2-e2a5-94f7-c69b-9912e055173f.png)

■(元々の部品) モバイルの検索結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/248f143a-ef5c-b6d5-d02a-446b5c711447.png)

■(元々の部品) バッテリーの検索結果

ヒットしません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/1d0b84b8-df25-10cc-44e9-a9757cdffb1e.png)

■(追加した部品) バッテリーの検索結果

ヒットします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/e627560e-5b2b-c947-0db0-421f08897975.png)

そして、追加した側のコンボボックスで設定した値を元に、元々のコンボボックスの`[DefaultSelectedItems]`を以下のように変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/2885541e-a0f8-7ead-8f69-748b3f90e974.png)

```
{
    '@odata.type':"#Microsoft.Azure.Connectors.SharePoint.SPListExpandedReference",
    Id: ComboBox1.Selected.ID,
    Value: ComboBox1.Selected.タイトル
}

```

追加したコンボボックスで選択した値に応じて元々のコンボボックスの値が変わります。

:::note warn
Id を ID にしていたことで、Power Apps のアプリの見た目上は値が入っており、データの送信も成功しますが、SharePoint 側を見ると何も入っていない状態になり、はまりました。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/d941d1d9-2da2-6c46-fa16-aa10c3538d37.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/d01b3d71-1cc1-efc7-aa64-e98099a05eb3.png)

:::

# まとめ

今回は、Power Apps で SharePoint リストの参照列を利用する際にハマってしまったことについて紹介しました。SharePoint リストベースでアプリを作成する際、複数のリストを用いることもあるため、少しでも参考になれば幸いです。
スプレッドシートに記入した予定をGoogleカレンダーに一括登録する

GASとGoogleカレンダーを連携した時の個人的な備忘録

これまで生徒のレッスン実施日時をスプレッドシートで管理していたが
Googleカレンダーに定期的に流し込んで事前通知などを受けられるようにしたかった

```Javascript:コード.gs
function setSchedule() {

  var calendar = CalendarApp.getCalendarById('ｘｘｘｘｘ@group.calendar.google.com')
  var ss = SpreadsheetApp.openById('ｘｘｘｘｘ')
  var sheet = ss.getSheetByName('ｘｘｘｘｘ')

  //スプレッドシートの最終行を取得
  var lastRow = sheet.getLastRow()
  Logger.log(lastRow);

  //順に予定を作成
  for (let i = 0; i < lastRow-1; i++) {

    //TRUEでない場合はfor文を継続
    let check = sheet.getRange(i+2, 23).getValue()
    if (check == true) {continue}

    //開始終了日時・顧客名
    let startTime = new Date(sheet.getRange(i+2, 19).getDisplayValue())
    let endTime = new Date(startTime);
    endTime.setHours(startTime.getHours()+1)

    //顧客・担当講師情報
    let student = sheet.getRange(i+2, 3).getValue()
    let teacher = sheet.getRange(i+2, 14).getValue()
    let memo = sheet.getRange(i+2,3,1,9).getValues().flat().filter(String).map(String)
    memo = memo.join(',')
    let options = {description: memo} //values

    try {
      //予定を作成後、カレンダー登録後trueに
      calendar.createEvent(student+"様 体験レッスン 講師:"+teacher,startTime,endTime,options) 
      sheet.getRange(i+2, 23).setValue(true)
    } catch (e) {
      // 例外処理
      Logger.log(e)
    }
  }
}
```


カレンダーの詳細メモまで含めて一括で転記することができた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319121/b7356f7b-a417-30d0-0dae-ae10dc644243.png)

GASの定期実行を設定して完了

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319121/456b40c7-63b5-168d-a041-7f24579252fa.png)
サーバの通知メールがGmailにはじかれてハマった話

大した話ではないので結論から言うと、SPFレコード登録のポカミスが原因でした💦

# 経緯
月に1回ペースでMAILER-DAEMON宛に`Undelivered Mail Returned to Sender`が届いていました。
送信元はサーバのrootから、内容も大したものではないので優先度は低かったものの、気持ちも悪いので対応することに。

エラーは「認証されていないよ～、SPFかDKIM設定してね～」ということで、SPF設定していなかったかなぁ、、と思いつつ対象ドメインのゾーンファイルを確認。

SPFレコード既に設定してある、、書き方やIPは、、間違ってなさそうだけどな～と数分にらめっこし、原因がわからないまま「優先度低いし、ま、いっか」と諦め。

そこから早数ヶ月。。。

相変わらずMAILER-DAEMONに`I'm sorry to have to inform you that your message could not be delivered to one or more recipients.`とGoogleからメールが来るので重い腰を上げて再度調査。

ググったりChatGPTに相談したり色々調べるも怪しいところが見当たらず・・

あらためてメールログを眺めていると、「あれ？送信元のドメイン部分、、もしかして？」と気が付きました。
そう、**送信元アドレスのドメイン名にサーバのホスト名が付いていた**のです。

つまり、

- 元々登録していたSPFレコードは `@example.com`用のもの
- 今回エラーになっていたメールの送信元は `@server.example.com`

だったのです。

新たに`server.example.com`用のSPFレコードを追加したところ問題なく配送されるようになりました。😅

# まとめ
結果は簡単なことではありますが、それ故に灯台下暗しというか、気が付きにくいことって多いです。
どこかでSPFレコードはサブドメインにも効いている、、という思い込みが私の中にあったのかもしれませんね。

サーバ君たちにもバイアスなく向き合ってあげられるように修業が必要だなぁと感じた出来事でした。
React+Typescriptアプリをgithub pagesにデプロイする

# はじめに
Vite React Typescriptで作成したアプリをgithub pagesにデプロイする方法。
今更感がありますがメモしておきます。
# 前提条件
yarn、viteは導入済み

# プロジェクト作成
下記のコマンドを実行。
``` cmd
yarn create vite
```
1. プロジェクト名を入力
1. Reactを選択
1. Typescriptを選択
1. 作成したプロジェクトのディレクトリに移動

# package.jsonの編集
homepageとdeployを追加
``` json
{
    ...
    "homepage": "https://villhell.github.io/リポジトリ名",
    "scripts": {
    ...
    "deploy": "yarn build && gh-pages -d build"
  },
}
```

# vite.config.tsの編集
baseを追加。
``` typescript
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

// https://vitejs.dev/config/
export default defineConfig({
  base: '/githubのリポジトリ名/',
  plugins: [react()],
});

```

# git
``` git
git init
```

* .gitignoreファイルからdistをコメントアウト


``` git
git add .
git commit -m "first commit."
```
ここで一旦Pushしておきます。
githubにアクセスしてリポジトリが作成できているか確認して下さい。

# gh-pagesブランチを作成
このブランチはサブディレクトリで管理したいので以下の手順を実行。

``` git
git checkout --orphan gh-pages
git reset --hard
echo 'Hello' > index.html
git add index.html
git commit -am 'Create gh-pages'
```
ここでも一旦pushしておいてgh-pagesにindex.htmlがあることを確認してください。


# git worktreeを使う
``` git
git checkout master
git worktree add dist gh-pages
```

これでmasterからブランチを切り替えずにgh-pagesブランチをコミットすることができるようになります。

# package.jsonの内容をインストール
```cmd
yarn
```
# viteをインストール
```cmd
yarn add vite
```
# buildする

``` cmd
yarn build
```
buildができればコミットしてプッシュします。

# githubの設定
githubで先程プッシュしたページにアクセスします。

「Setting」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/9c9dea52-1894-92dd-9652-4fea445397b6.png)

左側のメニューから「Pages」をクリックして、ブランチをgh-pagesにしてSaveしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/bb289a22-d97e-dacc-3fc9-9133246dcc69.png)

少し待つとページへのリンクが表示されるようになるので「Visit Site」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/0d3e25c3-6992-fb71-0ca7-bdc445fcc351.png)

画面が表示されていればOKです！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/568946a8-22f5-1032-6e4f-b92309b03602.png)
【Node.js】NewRelicでサービス間を中継するSQSの監視を行う

## 概要

SQSを中継したAWSサービス間の連携・分散トレーシングの取得方法についてまとめ
サービス間を中継するSQSの監視を実施することによって以下のことが実現できます

- プロダクトで利用しているAWSサービス間の連携をEntity Mapとして可視化
- 各サービスごとの処理速度を可視化（Transaction）

## 前提

:pencil2: アプリケーションの使用言語
`TypeScript`

:pencil2: アプリケーションの構成
`ECS -> SQS -> Lambda`

:::note info 
上記の構成はあくまで例であり、
Lambda -> SQS -> Lambdaのような構成でも今回紹介する方法は実施可能です。

:::

:pencil2: ECSではAPM監視・分散トレーシングの設定済み

:pencil2: LambdaではnewrelicライブラリのsetLambdaHandlerで監視設定を導入済み

:pencil2: newrelicライブラリのバージョンは`10.1.2`

:pencil2: LambdaのトリガーとしてSQSが設定されている

## SQS送信側のコード

AWS SDKでSQS送信時に、newrelicライブラリ経由で取得した情報を`messageAttribute`属性として付与します

ここで必要な手順は2つです
① NewRelic上で分散トレーシングを実施するため、トレース情報を送信する
② 上記で取得したトレース情報(Traceparentなど)をSQS登録時にパラメータとして持たせる


まず、①を実施し、②で使用するパラメータを返す関数を作成します
```typescript
  getMessageAttributes(): AWS.SQS.MessageBodyAttributeMap {
    const currentHeaders: Record<
      string,
      string | number | string[] | undefined
    > = {};

    // newrelicライブラリを用いて分散トレーシングを実施する上で必要な情報をNewRelicに送信
    newrelic.getTransaction().insertDistributedTraceHeaders(currentHeaders);

    // 上記で取得した情報をSQSに送信するデータ用に加工する
    Object.entries(currentHeaders).forEach((header) => {
      if (typeof header[1] === 'string') {
        this.attributes[header[0]] = {
          StringValue: header[1] || '',
          DataType: 'String',
        };
      }
    });

    return this.attributes;
  }
```

SQSにキューを登録する処理では、上記で取得したトレース情報を`messageAttributes`として設定します（②の手順）
```typescript
{
    id: id,
    body: body,
    messageAttributes: getSQSMessageAttributes(),
}
```
## SQS受信側のコード

受信したSQS EventからmessageAttributesを取得し、newrelicライブラリを用いて、SQSのヘッダ情報取得処理を実装します。

```typescript
// event: SQSEvent
const previousHeader: {[key: string]: string} = {};

Object.keys(event['Records'][0].messageAttributes).forEach(key => {
    previousHeader[key] = String(event['Records'][0].messageAttributes[key].stringValue);
});

newrelic.getTransaction().acceptDistributedTraceHeaders('Queue', previousHeader);

```

## 分散トレーシングの確認

実装・デプロイが完了した後、NewRelicの管理画面から分散トレーシングが取得できているかを確認します。


① NewRelicのメニューから以下のページを確認する
`APM & Services > ECSサービス > Distributed Tracing`

② SQSキューを登録する処理のパスを選択する

③ Entity Mapを確認する
![スクリーンショット 2023-06-24 7.38.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689205/8327c628-9eb8-7d53-e0b0-f65a0272ed0c.png)

ECSサービスがSQSを経由してLambda関数を呼び出している図が確認できればOK！




## 参考・関連記事


https://docs.newrelic.com/jp/docs/apm/agents/nodejs-agent/api-guides/nodejs-agent-api/
【自作】簡易シューティングゲームを大きくアップデートしてみた

## 今回の内容
前回、コチラの記事[「【HTMLのみ】簡易シューティングゲームを作ってみた」](https://qiita.com/Rekt-Order/items/91a9051e6a199775662f)で紹介した通り、ブラウザで動くシューティングゲームを作成しました。前回制作したプロトタイプ版から、かなり進化しましたので、今回はアップデートを紹介致します。

ここでは、アップデート内容とコードの一部を紹介させ頂きます。

**下記画像をクリックすると、プレイ動画を閲覧することができます**

[![](https://miuradonuts.com/wp-content/uploads/2023/07/スクリーンショット-2023-07-02-7.27.55.jpg)](https://miuradonuts.com/wp-content/uploads/2023/07/TGD-プレイ動画.mp4)

### アップデートの詳細
#### 見た目のアップデート
- 攻撃時の弾の色を変更
- ゲームプレイエリアのサイズを縦長へ変更
- 敵オブジェクトのパターンを２種類へ変更（1種類は+10pt、1種類は-10pt）

#### GAME内容のアップデート
- 「-10pt」の敵の出現確率を調整、落下速度を通常よりも速く設定
- 敵オブジェクトと接触すると、GAME OVERになるように変更
- 1,000ptを獲得すると、GAME CLEAR。秘密のリンクボタンが出現するように設定。


#### ファイル構成
- index.html（ゲームのメインプログラムです）
- 背景画像（ゲームの背景となる画像です）
- 敵オブジェクト1（敵の画像1です）
- 敵オブジェクト2（敵の画像2です）
- Playerオブジェクト（味方の画像「ドーナツ部長」です）


#### 動作仕様
- 移動：左右の矢印ボタンで移動します（移動は左右のみ）
- 攻撃：スペースで弾を発射します（押しっぱなしで連続発射も可能）
- 得点システム１：「著者の顔」を1体撃破につき、＋10点
- 得点システム2：「ドーナツ蟲」を1体撃破につき、-10点
- ゲームオーバー：敵と接触すると、ゲームオーバー
- ゲームクリア：1,000点を獲得すると、ゲームクリア

※ゲームのソースコードは、私が運営するDiscord「ドーナツ部長のサーバー」内で、限定公開の予定です（7月上旬頃を予定）。


## ゲームパッケージ

前回の記事では、ゲームカセットを入れる箱風のパッケージデザインを公開しましたが、今回もパッケージを制作しています。

◯パッケージデザイン
![](https://miuradonuts.com/wp-content/uploads/2023/07/NINJA-牡蠣.jpg)

そして…今回は、カセットケースとして箱まで制作をしてしまいました（！）

◯カセットケース／表面
![](https://miuradonuts.com/wp-content/uploads/2023/07/IMG_8652.jpg)

◯カセットケース／裏面
![](https://miuradonuts.com/wp-content/uploads/2023/07/IMG_8658.jpg)

○並ぶと結構…いい感じ？（笑）
![IMG_8673.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416622/205fb5b3-e2c2-40a8-4524-c053ea924737.jpeg)


自作のゲームも、ここまでくると面白いですね（笑）カセットの代わりに、このカセットケースにQRコードやアクセスコードを記したカードを入れて配布する…そんなことを考えています。

この記事は、著者が運営するメディア「ぬるぺでぃあ」でも読むことができます（記事は[コチラ](https://miuradonuts.com/2023/07/02/note-003/)）
![](https://miuradonuts.com/wp-content/uploads/2023/06/ヘッダーエリア画像作成.png)
RHEL9系から sshd で RSA/SHA1 が使えないらしい件

# alimalinux9 から sshd で RSA/SHA1 使えないらしい
Proxmox での運用に切り替えようと思いつつ古い資産を刷新すべく alimalinux9 いわゆる RHEL9系を新規に入れてみました。あまりハマらないだろうと思ったらまさかの SSH で・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/c62a18fa-1246-8678-3212-bb05524890b3.png)

どうやら OpenSSH のセキュリティポリシーが変わっていたようです、今後はRSA/SHA1 徐々に廃止していくそうですね。

・[OpenSSH、今後はRSA/SHA1をデフォルトで無効に](https://thinkit.co.jp/news/bn/18734)
・[Ubuntu Server 22.04 LTSのSSH鍵認証でRSA認証が無効化されていて躓いた話](https://blog.hitsujin.jp/entry/2022/04/24/010000)

なんだか下記を定義すれば SHA1 を継続して使用することもできるらしい。

```
PubkeyAcceptedAlgorithms=+ssh-rsa
```

# 折角なので新しく鍵ペアを作成する
なんだか大分前に作成した鍵ペア・・・なので新しく鍵ペアを作成してみます。使える種類は以下のとおり。
　SHA-2アルゴリズムを利用するRSA(rsa-sha2-256/512)
　ED25519アルゴリズム(ssh-ed25519)
　RFC5656 ECDSAアルゴリズム(ecdsa-sha2-nistp256/384/521)

ED25519 を使ってみるかね！！

## ED25519 を作成してみる
どうやら SSHのクライアントである「RLogin」で鍵ペアを作成できるらしい（簡単でしたｗ）。

・[「RLogin」でSSH用の秘密鍵と公開鍵のペアを作成する方法](https://www.server-memo.net/memo/rlogin/rlogin_create_key_pair.html)

authorized_keys に張り付ける 公開鍵も簡単に作成できますね。便利やね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/ba5a846c-36e7-0cb9-725d-24eae4ede42b.png)

## sshd_config の PermitRootLogin = no が反映されない
root に よる ssh禁止は `PermitRootLogin = no` で指定できるのですが、何度設定ファイルを見直してもおかしいところがないのに、root でログインすることができる・・・。

どうやらOSインストール時に 「パスワードによるroot SSHログインを許可」にチェックをいれると 
`/etc/ssh/sshd_config.d/01-permitrootlogin.conf` のファイルが作成され `PermitRootLogin = prohibit-password` となるそうです。ちぇっ。

・[RHEL9系からsshdのPermitRootLoginがYesでない経緯を辿る](https://happy-nap.hatenablog.com/entry/2022/10/08/220946)
nodejsでsqlite3のデータを表示する

## やりたいこと
sqliteにテストデータを作成しconsoleに表示する。


## 書いたコード
```terminal:install
npm install sqlite3
```

```typescript:テストデータの作成と表示
const sqlite3 = require('sqlite3').verbose();

// データベース接続の作成
const db = new sqlite3.Database('mydatabase.db');

// テーブル作成のクエリ
const createTableQuery = `
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT,
    email TEXT
  )
`;

// テーブルの作成
db.run(createTableQuery, function(err) {
  if (err) {
    console.error(err.message);
  } else {
    console.log('テーブルが作成されました');
  }
});

// ユーザーの挿入クエリ
const insertUserQuery = `
  INSERT INTO users (name, email)
  VALUES (?, ?)
`;

// ユーザーのデータ
const user = {
  name: 'John Doe',
  email: 'john@example.com',
};

// ユーザーの挿入
db.run(insertUserQuery, [user.name, user.email], function(err) {
  if (err) {
    console.error(err.message);
  } else {
    console.log('ユーザーが追加されました');
  }
});

// ユーザーの取得クエリ
const getUsersQuery = 'SELECT * FROM users';

// ユーザーの取得
db.all(getUsersQuery, function(err, rows) {
  if (err) {
    console.error(err.message);
  } else {
    rows.forEach(row => {
      console.log(row);
    });
  }
});

// データベース接続のクローズ
db.close();
```



上記コードを実行すると、2回目以降は正常にuserが取れているが、初回はエラーになっている...
db.runの中身が非同期で動いているのが原因なので、同期的に動くように修正してあげる。

```console:初回
SQLITE_ERROR: no such table: users
SQLITE_ERROR: no such table: users
テーブルが作成されました
```

```console:2回目以降
テーブルが作成されました
ユーザーが追加されました
{ id: 1, name: 'John Doe', email: 'john@example.com' }
```

db.serializeを使うと同期的にクエリを流すことができます。

```typescript: 修正後
const sqlite3 = require('sqlite3').verbose();
// データベース接続の作成
const db = new sqlite3.Database('mydatabase.db');


// テーブル作成のクエリ
const createTableQuery = `
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
email TEXT
)
`;

// ユーザーの挿入クエリ
const insertUserQuery = `
INSERT INTO users (name, email)
VALUES (?, ?)
`;

// ユーザーのデータ
const user = {
name: 'John Doe',
email: 'john@example.com',
};

// ユーザーの取得クエリ
const getUsersQuery = 'SELECT * FROM users';

db.serialize(() => {
    // テーブルの作成
    db.run(createTableQuery, function(err) {
        if (err) {
            console.error(err.message);
        } else {
            console.log('テーブルが作成されました');
        }
    });

    // ユーザーの挿入
    db.run(insertUserQuery, [user.name, user.email], function(err) {
        if (err) {
            console.error(err.message);
        } else {
            console.log('ユーザーが追加されました');
        }
    });

    // ユーザーの取得
    db.all(getUsersQuery, function(err, rows) {
        if (err) {
            console.error(err.message);
        } else {
            rows.forEach(row => {
            console.log(row);
            });
        }
    });

    console.log('end serialize');
});
console.log('after serialize');


// データベース接続のクローズ
db.close();
```


```console:
end serialize
after serialize
テーブルが作成されました
ユーザーが追加されました
{ id: 1, name: 'John Doe', email: 'john@example.com' }
{ id: 2, name: 'John Doe', email: 'john@example.com' }
```

クエリ自体は同期的に動いてくれるが、クエリの完了を待つ訳ではないのでそこは注意が必要です。
JSONCのABNFを作る

JSONにコメントを入れたい、という声もある。
自作JSON Parserは主にABNFで作ってあるのでABNFを拡張する必要がある。
MicrosoftがJSONCというものを作ったようだがABNF構文がないので考えてみることにした。
出来上がったらコメントのみの変更なのでABNF Parserを通せばそのままJSON Parserとして使える。
YAMLという形もあるが複雑そうなのであとで考える。

## JSONC の差分

/* */ のコメントが書ける
// の1行コメントが書ける
, をObject, Array末尾につけられる
でいいだろうか。曖昧。

## ABNF

基礎となるのはRFC 8259 JSONのABNF構文。
コメントが入りそうな場所はJSONのABNFでwsを拡張することで対応できそうというところまで目安にする。
コメントは2種類、// からはじまる行単位のコメントと、/* */ で囲むコメント。
// からはじまる行は改行を目安にコメントを終了すればよさそう。

### ws拡張

RFC 8259 Section. 2 のwsは次のようになっている。

      ws = *(
              %x20 /              ; Space
              %x09 /              ; Horizontal tab
              %x0A /              ; Line feed or New line
              %x0D )              ; Carriage return

スペース(SP %x20)、垂直タブ(HT %x09)、改行(LF %x0A)、復帰(CR %x0D)の4文字がスペース文字として扱われている。
複数行書けるコメント /* */ をとりあえず comment という名にする。1行コメントを linecomment という名にする。

      ws = *( 
              linecomment /       ; single line comment
              comment /           ; multi line comment
              %x20 /              ; Space
              %x09 /              ; Horizontal tab
              %x0A /              ; Line feed or New line
              %x0D )              ; Carriage return

この方向でいいんじゃないかな?
開始と終了を決める。

    linecomment = "//" inslcomment ( %x0A / %x0D )
    comment = "/*" inmlcomment "*/"

中身に書ける文字を決める。
基本的に何でも書けるがCの終端文字0x00などは避ける方がいいのかな。

    inslcomment = %x01-09 / %x0b / %x0c / %x0e-%x10ffff
    inmlcomment = %x01-29 / %x2b-10ffff / ( %x2a ( %x01-%2e / %x30-10ffff ) )

これでひとまず中身は何でも書けるという形にできた。ただしエスケープなどを考慮する場合はもう少し拡張が必要。考慮する必要があるのかどうか不明。
ScriptableObjectのScript名を記憶しておくEditor拡張

### ScriptableObjectのScript名を記憶しておく方法
・背景
プロジェクトをパッケージで複数人とやり取りするシチュエーションでScriptableObjectのクラスを誤って削除してしまった場合とデータコンテナの関係性が分からなくなってしまう場合があったからです。

##### ScriptableObjectを以下のように記述
```
using UnityEngine;
using System;

[Serializable]
[CreateAssetMenu(fileName = "EnemyData", menuName = "CreateEnemyData")]
public class EnemyData : ScriptableObject
{
    public enum EnemyType
    {
        ENEMY_1,
        ENEMY_2,
        MAX_ENEMY
    }

    // 敵の種類
    [SerializeField] private EnemyType enemyType;
    // 敵の名前
    [SerializeField] private string enemyName;
    // 敵のHP
    [SerializeField] private int maxHp;
    // 敵の攻撃力
    [SerializeField] private int ATK;
    // 敵の防御力
    [SerializeField] private int DEF;

    // 敵の種類取得
    public EnemyType GetEnemyType() => enemyType;
    // 敵の名前取得
    public string GetEnemyName() => enemyName;
    // 敵のHP取得
    public int GetHp() => maxHp;
    // 敵の攻撃力取得
    public int GetATK() => ATK;
    // 敵の防御力取得
    public int GetDEF() => DEF;
}
```

##### ↑このスクリプトでは、ScriptableObjectの追加と削除を管理します。

##### 次に、ScriptableObject を管理するスクリプトを作成します。このスクリプトでは、ScriptableObject を管理するためのリストを作成し、シーン実行時、適切なログを表示します。
```
using UnityEngine;

public class ScriptableObjectCreator : MonoBehaviour
{
    public EnemyData enemyDataTemplate; // Inspectorで設定

    void Start()
    {
        // ScriptableObjectのインスタンスを作成
        EnemyData newEnemyData = Instantiate(enemyDataTemplate);
        // スクリプト名を設定
        newEnemyData.scriptName = newEnemyData.GetType().Name;

        // 確認のためスクリプト名をログに出力
        Debug.Log("Script Name: " + newEnemyData.scriptName);
    }
}
```

##### 作成手順
ScriptableObjectを管理するスクリプト(ScriptableObjectCreator)をゲームオブジェクトにタッチします。その後、EnemyDataを使用して、ScriptableObjectを作成します。シーンを実行すると、コンソールにスクリプト名が表示されます。

##### ScriptableObject
ScriptableObjectは通常のクラスと同じように変数を定義できます。変数を定義したらその変数から.を使いつなげることで定義済みのパラメータを取得する事ができます。

↓
```
using UnityEngine;

public class EnemyInfo : MonoBehaviour
{
    public EnemyData enemyData;

    void Start()
    {
        if (enemyData != null)
        {
            Debug.Log("Enemy Type: " + enemyData.GetEnemyType());
            Debug.Log("Enemy Name: " + enemyData.GetEnemyName());
            Debug.Log("Enemy HP: " + enemyData.GetHp());
            Debug.Log("Enemy ATK: " + enemyData.GetATK());
            Debug.Log("Enemy DEF: " + enemyData.GetDEF());
        }
        else
        {
            Debug.LogError("EnemyData is not assigned");
        }
    }
}
```
ICLR2023の量子化論文 (1)

# 概要

この記事では、[ICLR02023](https://iclr.cc/)の量子化論文を紹介します。[^1]

[^1]: 画像や数式は論文から引用しています。

# Accurate Neural Training with 4-bit Matrix Multiplications at Standard Formats

https://openreview.net/forum?id=yTbNYYcopd

- 概要：LUQ. 4bit行列積
- 新規性：Unbiasedかつlog scaleな量子化を提案
- キモ：4bitで精度を高めるために必要なUnbiasedかつlog scale量子化を実現した。
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/11a49c9a-c77e-6b8c-851b-14e84a19e6bd.png)
- 評価：ResNet, MobileNet, Transformer等で実験した。


# OPTQ: Accurate Quantization for Generative Pre-trained Transformers

https://openreview.net/forum?id=tcbBPnfwxS

- 概要：OPTQ. GPTの3~4bit One-shot量子化
- 新規性：従来のOne-shot量子化の2倍以上圧縮できる
- キモ：Optimal Brain Quantization (OBQ, Hessianベース) で量子化の順序を変えないようにする。(Arbitrary Order Insight)など。


# Towards Understanding Ensemble, Knowledge Distillation and Self-Distillation in Deep Learning

https://arxiv.org/abs/2012.09816

- 概要：ディープラーニングにおけるアンサンブルの効果と、アンサンブル蒸留の関係について
- 研究機関：Meta
- 新規性：(1)アンサンブルで精度が上がることを示した。(2)アンサンブル後のDNNが蒸留や自己蒸留に有効であることを示した。
- キモ：アンサンブルの結果に合うように学習すると、共通の特徴も学習する。これがDark knowledgeとなりアンサブルからの蒸留がうまくいくことが分かった。


# FIT: A Metric for Model Sensitivity

https://openreview.net/forum?id=PDG4-Y3aboN

- 概要：FIT. 量子化に対してどれくらい影響するか
- 新規性：量子化がどれくらい影響を与えるかの指標
- キモ：FITはFisher情報量の量子化ノイズに対する期待値で計算する。
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/23aefa56-e9b4-779a-bc51-af2863a5d8f9.png)
- 評価：QRやBNと、精度の相関を比較した。


# PowerQuant: Automorphism Search for Non-Uniform Quantization

https://openreview.net/forum?id=s1KljJpAukm

- 概要：PowerQuant. Data free非一様量子化
- 新規性：Data free量子化で、非一様なもの。
- キモ：量子化は自己同型であるべきという考えから量子化として指数関数を採用する。パラメータは量子化の2乗誤差最小化で決める。
Nuxt3入門 ~インストール編~

## はじめに

Nuxt3を触ろうと思い、その内容をまとめていきます。
今回は、Nuxt3のインストール、開発環境の起動までです。
[公式のインストールドキュメント](https://nuxt.com/docs/getting-started/installation)を見ながら進めていきます。

## 開発環境

ドキュメントによると、下記が必要なようです。

- Node.js: v16.10.0以上
  - 偶数バージョン(16, 18, 20など)の使用
- 【推奨】Editor: VSCode
  - 拡張機能
    - [Vue Language Features (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.volar)
      - takeover modeを有効にする
        - cmd + shift + p でコマンドパレットを開き、`Extensions: Show Built-in Extensions`を選択
        - `TypeScript と JavaScript の言語機能` を選択し、`Disable(workspace)`を選択してVSCodeをリロード

![VSCodeのTypeScriptの設定をオフにする](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166596/50ab8b31-f1c7-d76d-8685-77d1241e9004.png)

筆者は下記環境で試しています。

- Node.js: v18.16.0
  - パッケージマネージャは`pnpm`を使用しています。適宜読み替えてください:pray:
- Editor: VSCode

## Nuxt3のインストール

### プロジェクトの作成

`nuxi` コマンドを使ってプロジェクトを作成します。
(筆者が初めてNuxtを触った時は`create-nuxt-app`を使っていましたが、)

```shell
$ npx nuxi@latest init .
Nuxi 3.6.1
✨ Nuxt project is created with v3 template. Next steps:
 › Install dependencies with npm install or yarn install or pnpm install
 › Start development server with npm run dev or yarn dev or pnpm run dev
```

カレントディレクトリに、シンプルな構成のNuxt3プロジェクトが出来上がるようです。

```txt
.
├── README.md
├── app.vue
├── nuxt.config.ts
├── package.json
├── public
│   └── favicon.ico
├── server
│   └── tsconfig.json
└── tsconfig.json
```

依存パッケージをインストールしましょう

- `pnpm install`

### 開発環境の起動

`pnpm run dev`

localhost:3000 にアクセスすると、Nuxt3のデフォルトページが表示されます。
レンダリングまでに時間がどれだけかかったのかが、表示されます。

![Welcome to Nuxt!](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166596/e4fe1f96-f63e-366f-85b3-454583f31830.png)

### 【VSCode + Volarの場合】nuxt.config.tsの設定を変更する

ドキュメントで、`nuxt.config.ts`の設定を変更するように書かれているので対応します。

```typescript:nuxt.config.ts
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  devtools: { enabled: true },
  typescript: {
    shim: false
  },
})
```

`defineNuxtConfig`の型情報が無いのでVSCode上で赤線出てますが、後々解消していきます。

### Hello, Worldを表示する

```diff:app.vue
<template>
  <div>
-   <NuxtWelcome />
+   <p>Hello World!</p>
  </div>
</template>
```

![Hello, World!](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166596/fa0c1e0a-572a-a62b-a692-fad2026d0ddf.png)

## 作ってみて

筆者は古に`create-nuxt-app` を使ってプロジェクト作成をした覚えがあるので`nuxi`コマンドに少し驚きました。
`nuxi`は対話などはなく、シンプルな構成を作る形のようですね。
自分でいろいろカスタマイズする必要がありそうなので、次はその辺をまとめてみようと思います。
JAppletの除去に苦労したこと

　昔々、ウェブ上でアプリケーションを実行するのにJava Appletが使われていた。デスクトップアプリケーションと開発を一緒にするために、両方で動くような書き方があった。だが、今のJavaはJAppletが削除されたために、動かすたびにエラーメッセージが出るようになってしまった。
　JAppletを削除するのに苦労した点を書こうと思う。AozoraEpub3からJAppletを削除した


https://github.com/kyukyunyorituryo/AozoraEpub3/commit/87bd933f34e1dbd60303cdd1cc2c9ede1b368e2c

なんとなくの知識としてJAppletをJFrameに置き換えたらいいのではとどこかに書いてあったので、そうしてみた。

public class AozoraEpub3Applet extends JApplet
public class AozoraEpub3Applet extends JFrame

ただ、そうするとJFrameをJFrameに入れようとしているというエラーが出た。原因はJAppletに部品を入れたやつをJFrameに入れるという処理をしていた。そのために二重にJFrameに入れることになった。

final JFrame jFrame = new JFrame("AozoraEpub3");
final AozoraEpub3Applet applet = new AozoraEpub3Applet(jFrame);
だったのをappletを削除してjFrameに統一
final AozoraEpub3Applet jFrame = new AozoraEpub3Applet();
こうした。
そのほか、appletをjFrameに置換。

そのほかの問題は、appletからframeを呼び出す処理があったので、frameに置き換えたら、呼び出す側が正しくなくなっていた。
jFrameParent.getLocation()というのがそれで、getLocation()に変えた。
AWS CloudFront Functionsを使ったIP制限の実装方法

AWS CloudFront Functionsを使って、IP制限を実装する方法を記載します。
これにより、特定のIPアドレスからのアクセスのみを許可し、それ以外のアクセスをブロックすることができます。

# CloudFront Fucntionの作成
1. AWS Management Consoleにログインし、CloudFrontサービスにアクセスします。
1. 左側のナビゲーションパネルで「Functions」を選択し、「Create function」をクリックします。
1. 関数名を入力し、次のようなJavaScriptコードを入力してください。ALLOWED_IPS変数に許可するIPアドレスを追加してください。


```javascript
function handler(event) {
    var request = event.request;
    var sourceIP = request.headers['x-forwarded-for'].value.split(',')[0];

    const ALLOWED_IPS = ['xxx.xxx.xxx.xxx', 'yyy.yyy.yyy.yyy'];

    if (ALLOWED_IPS.includes(sourceIP)) {
        return request;
    } else {
        return {
            statusCode: 403,
            statusDescription: 'Forbidden',
        };
    }
}

```

1. 「Create」ボタンをクリックして関数を作成します。
1. 関数が作成されたら、「Publish」をクリックして関数を公開します。

# CloudFrontディストリビューションに関数を関連付ける
1. CloudFrontディストリビューションの設定を開き、「Behavior」タブ（「Distribution Settings」の下にあります）で適切なキャッシュビヘイビアを選択し、「Edit」をクリックします。
1. 「Function associations」セクションで、「Add function」ボタンをクリックし、イベントタイプとしてviewer-requestを選択し、作成したCloudFront Functionを選択します。
1. 「Save changes」をクリックして、ディストリビューションの設定を更新します。

# 参考記事
https://dev.classmethod.jp/articles/cloudfront-functions-ip-control/
AppleScriptでダイアログで休憩開始を教えてくれるポモドーロタイマーを作成してみた

# ポモドーロタイマーとは
ポモドーロテクニックを実践するためのタイマーである。

## ポモドーロ・テクニックとは
ポモドーロテニックとは、下記の手順で作業を行うことで、効率的に作業を行うテクニックである。
1. タイマーを25分に設定して作業を開始する
2. タイマーが鳴ったら、3～5分の休憩をとる
3. 4～5回に1回は、15～30分の長めの休憩をとる

# よくあるポモドーロ・タイマーの欠点
ポモドーロタイマーのアプリはたくさんあるが、ほとんどがアラーム音で休憩時間の到来を教えてくれる仕様となっている。アラーム音がなるとびっくりしてしまうため、できれば画面に休憩時間が到来したことを表示してくれるアプリが欲しかった。そこで、AppScriptを使用して、アプリを作成してみた。

# アプリの内容
## アプリの仕様
１. 作業時間を設定するダイアログを表示
2. 短い休憩時間を設定するダイアログを表示
3. 長い休憩時間を設定するダイアログを表示
4. 作業を開始のダイアログを表示
5. 休憩時間開始のダイアログを表示
6. 休憩時間終了のダイアログを表示
7. 4番〜6番の繰り返し

## ソースコード
```applescript:pomodoroTimer.applescript
set defaultWorkDuration to 25 -- デフォルトの作業時間（分）
set defaultBreakDuration to 5 -- デフォルトの休憩時間（分）
set defaultLongBreakDuration to 15 -- デフォルトの長い休憩時間（分）
set pomodoroCount to 0

set workDuration to text returned of (display dialog "作業時間（分）を入力してください。" default answer defaultWorkDuration)
set breakDuration to text returned of (display dialog "休憩時間（分）を入力してください。" default answer defaultBreakDuration)
set longBreakDuration to text returned of (display dialog "長い休憩時間（分）を入力してください。" default answer defaultLongBreakDuration)

repeat
    set pomodoroCount to pomodoroCount + 1
    
    -- 作業開始時のメッセージを設定
    set pomodoroCountStr to pomodoroCount as string
    set workStartmsg to pomodoroCountStr & "回目の作業を開始しますか？"

    -- 短い休憩開始時のメッセージを設定
    set breakDurationStr to breakDuration as string
    set shortBreakStartmsg to breakDurationStr & "分間の休憩を開始しますか？"

    -- 長い休憩開始時のメッセージを設定
    set longBreakDurationStr to longBreakDuration as string
    set longBreakStartmsg to longBreakDurationStr & "分間の休憩を開始しますか？"
    
    display dialog workStartmsg buttons {"OK"} default button "OK"
    delay (workDuration * 60)
    
    if pomodoroCount mod 4 is 0 then -- 4回目のポモドーロ
        display dialog longBreakStartmsg buttons {"OK"} default button "OK"
        delay (breakDuration * 60)
        display dialog "休憩時間終了です。" buttons {"OK"} default button "OK"
    else
        display dialog shortBreakStartmsg buttons {"OK"} default button "OK"
        delay (longBreakDuration * 60)
        display dialog "休憩時間終了です。" buttons {"OK"} default button "OK"
    end if
end repeat

```

## アプリの実行方法
ターミナルで以下のコマンドを実行する。
```
osascript pomodoroTimer.applescript
```
helm lsコマンドで焦った話

こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。
今回は軽く書きます。

前回Helmを使ってMetalLBの環境をk8sクラスタにデプロイしました。

https://qiita.com/ohtsuka-shota/items/f8f2c1d9a447d4c122ee


Helmで何をデプロイしたかはhelm lsコマンドで確認することが出来るのですが、デプロイしたはずのMetalLBが表示されず、少し焦りました。
```
root@k8s-master:~# helm ls
NAME    NAMESPACE       REVISION        UPDATED STATUS  CHART   APP VERSION

root@k8s-master:~# kubectl get pod -n metal-lb
NAME                                  READY   STATUS    RESTARTS      AGE
metallb-controller-5cd9b4944b-hdbkj   1/1     Running   0             98m
metallb-speaker-k84gr                 4/4     Running   0             98m
metallb-speaker-pvc82                 4/4     Running   0             98m
metallb-speaker-pzqdg                 4/4     Running   0             98m
metallb-speaker-s7vk2                 4/4     Running   0             98m
metallb-speaker-t86kq                 4/4     Running   3 (38m ago)   98m
metallb-speaker-xsgsf                 4/4     Running   0             98m
metallb-speaker-zfptn                 4/4     Running   0             98m
```

実はこのhelm lsコマンドってデフォルトだとdefault namespaceを見に行っており、上記のMetalLBはmetal-lb namespaceにデプロイしたからそれは表示されるわけないよねって話です。
kubectl get ●● -n ▲▲とノリは同じなのですね。helmなので仕様が違うのだと勝手に思っていました。。。
```
root@k8s-master:~# helm ls -A
NAME    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART           APP VERSION
metallb metal-lb        1               2023-07-01 14:01:52.7948106 +0000 UTC   deployed        metallb-0.13.10 v0.13.10
```