OmniAICreator/Qiita-1.07M huggingface dataset:
rememberPermissionStateでパーミッションリクエスト時にダイアログが表示されなかったことを検出する

Jetpack ComposeでAndroidのパーミッションをリクエストする場合、accompanistの`rememberPermissionState`を利用するのが便利です。

https://google.github.io/accompanist/permissions/

パーミッションリクエストでは、ユーザーが「許可しない」を2回選択した場合、リクエストしてもダイアログが表示されず、即座に失敗してしまいます。ユーザーが「許可しない」と選択したのだからそれ以上要求すべきではないというのは分かるのですが、その場合はユーザに別の案内をする必要があるのに、これを直接判定する手段が提供されていません。これはJetpack Composeだからとか、accompanistの機能不足、ということではなく、Androidシステムが提供していません。
その回避策としてActivityResultContractを直接使う場合の方法は以下で解説しています。

https://qiita.com/ryo_mm2d/items/613747a3c1be5ed8b549

では`rememberPermissionState`ではどうやれば良いのかというのが今回の話題です。（`rememberPermissionState`は内部的にはActivityResultContractが使われています）

# ダイアログが表示されなかったことの判定方法

そもそも、直接的な検出方法が提供されていないのにどうやって検出するか、ですが
まずは`shouldShowRequestPermissionRationale`の戻り値（`permissionState.status.shouldShowRationale`）の変化を観測します。
これは、パーミッションリクエスト時により詳細な説明をせよというフラグですが、ユーザーが何回「許可しない」を選択したかで変化します。
0回ならfalse、1回ならtrue、2回ならfalse、と変化します。
リクエスト前と後の変化をまとめると以下になります。

|許可しない回数|リクエスト前|ダイアログの選択|コールバック時|
|--|--|--|--|
|0回|false|キャンセル|false|
|0回|false|許可しない|true|
|1回|true|キャンセル|true|
|1回|true|許可しない|false|
|2回|false|ダイアログが表示されない|false|

すなわち、リクエスト前も後もfalseの場合、一度も「許可しない」を選択されていない時にダイアログがキャンセルされたか、ダイアログが表示されなかったか、の2択に絞ることができます。

2択のうち後者であることを判定するには、`shouldShowRequestPermissionRationale`がtrueになったことがないと判定できれば確実ですが、それには永続化保存が必要になるため、あまりお手軽な方法とは言えません。

ここでは、ダイアログが表示されたユーザー操作が行われた場合と、ダイアログが表示されず即座に終了してしまった場合では、経過時間に大きな隔たりがある。と想定し、結果が返ってくるまでが一定時間以下である場合にダイアログが表示されなかったと判定することとします。
この方法はもちろん完璧ではなく、誤判定の可能性はありますが、表示されなかったと判定するほど短い時間しか表示されなかった場合なので、表示されなかった場合のダイアログが出てきてもそれほど違和感を覚えられないので十分かなと考えています。

# rememberPermissionStateWrapper を作る

前述の方法で判定できるにしても、リクエストの度に実装するのは面倒なので、ダイアログが表示されなかった場合の判定機能を持ったラッパーメソッドを作ってみます

判定方法は決まっているのでその通り実装して以下のようになるかと思います。
ダイアログが表示されなかったと判定する時間として300msを設定していますが、何か根拠がある訳でありません。経験上このぐらいの時間で判定すればうまくいくというだけのことです。

```kotlin
private const val ENOUGH_DURATION = 300L

@Composable
fun rememberPermissionStateWrapper(
    permission: String,
    onPermissionResult: (granted: Boolean, failedToShowDialog: Boolean) -> Unit = { _, _ -> },
): PermissionState {
    val activity = LocalActivity.current!!
    var shouldShowRationaleBefore = false
    var start: Long = 0
    val permissionState = rememberPermissionState(permission) {
        val elapsedEnoughTime = System.currentTimeMillis() - start > ENOUGH_DURATION
        val shouldShowRationaleAfter = ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)
        val failedToShowDialog = !(shouldShowRationaleBefore || shouldShowRationaleAfter || elapsedEnoughTime)
        onPermissionResult(it, failedToShowDialog)
    }
    return object : PermissionState {
        override val permission: String = permissionState.permission
        override val status: PermissionStatus = permissionState.status
        override fun launchPermissionRequest() {
            shouldShowRationaleBefore = permissionState.status.shouldShowRationale
            start = System.currentTimeMillis()
            permissionState.launchPermissionRequest()
        }
    }
}
```

`rememberPermissionState`のコールバックはgrantedの引数一つですが、第二引数でダイアログ表示がなされなかったか表示されたかが渡されるようにしています。

---

以上です
Linux重要コマンド10選

## **pwd（print working directory）**
現在の作業ディレクトリを絶対パスで表示する。


## **cd（change directory）**
作業ディレクトリを変更する。


## **ls（List）**
作業ディレクトリのフォルダやファイルを表示する。  
### オプション一覧
- -a  
　隠しファイルを表示できる。  
- -l  
　詳細情報を表示できる。  
- -lh  
　容量の表示がKB表記になる。
- ‐lt  
　最終更新日でソートされる。


## **touch**
作業ディレクトリに空ファイルを作成する。


## **cp(copy)**
引数で渡したファイルをコピーできる。  
「cp コピー元 コピー先」で指定できる。  
コピー先のフォルダは相対パスで指定できる。  
コピー元とコピー先が同じファイルの場合、上書きされる。  
### オプション一覧
- -i  
　コピー先に同じファイル名が存在する場合確認を求めるようになる。
- -r  
　フォルダごとコピーできる。
- -u  
　コピー元がコピー先よりも更新日時が最新の場合にコピーが実行される。  
　バックアップの際に有効。
- -v  
　コピー元とコピー先を表示することが出来る。


## **mv(move)**
ファイルやフォルダを移動できる。  
「mv ファイル　移動先」で指定できる。  
移動先はファイル名まで指定できる。


## **rm(remove)**
ファイルやディレクトリを削除する。
### オプション一覧
- -i  
　削除する前に確認を求めるようになる。
- -r  
　ディレクトリを削除できるようになる。  
　サブディレクトリも同時に削除されるようになる。


## **mkdir(make directory)**
ディレクトリを作成することが出来る。
### オプション一覧
- -p  
　階層的なディレクトリを作成できるようになる。


## **cat**
指定したファイルの中身を表示する。  
下記のように記載すると引数のファイルの内容を結合して新しいファイルを作成できる。  
「cat hoge.txt piyo.txt > hogepiyo.txt」


## **grep**
ファイルの内容から特定の文字列やパターンに一致する行を検索出来る。
「grep searchKeyword fileName」で指定できる。  
検索ワードにスペースを含めたいときは''（シングルクォーテーション）囲う必要がある
### オプション一覧
- -i  
　大文字と小文字の区別をしなくなる。
- -r  
　指定したディレクトリ内のすべてのファイルを検索する。
90年代～2000年代初頭の日本のインターネット接続サービスの歴史を簡単に振り返る

# はじめに
先日、趣味の勉強会のなかで、こんな登壇をさせていただきました。

https://speakerdeck.com/shotashiratori/mosi90nian-dai-nodi-fang-zhu-mixiao-xue-sheng-ni14-dot-4knomodemuwoyu-etara

https://loghstudy.connpass.com/event/341727/

資料作成の中で90年代のインターネット接続サービスを調べていたので各サービスの最初のサービスを調べていました。

# ダイヤルアップ接続サービス
これまで学術用のネットワークや一部の大企業が専用線を用いて接続していた中、1994年3月1日にIIJから商用のインターネットサービスが始まります。
当時のベンチャーだったIIJは当時の規制を乗り越え、特別第2種電気通信事業者として認可を得ての出発だったようです。
当時のダイヤルアップIP接続は、IIJのようなインターネットサービスプロバイダ（以下、ISP）とNTT等からの電話回線（アナログ回線又はISDN）の2つの契約を必要としており、データ利用時間による従量課金制でした。
また、アクセスポイントと呼ばれるISPの接続に紐づいた電話番号へ接続しに行く方式で、
地方で近くにアクセスポイントがない場合、市外料金（距離別で変動）を払っての接続となり非常に高額となるケース（10万円以上）もありました。

こうしたケースもあり、1995年に深夜早朝帯（23時～翌8時）に電話料金が定額となる「テレホーダイ」がNTTからサービス開始、インターネットは定着していきます。

また、当時のアナログ回線に使用するモデムと呼ばれるアナログ信号とデジタル信号を変換する機器の性能によって帯域も変わり、1994年ごろでは14.4Kbps、最終的に56Kbpsまでなっていきます。

# 常時接続サービス
常時接続サービスとして専用回線を利用していたサービスが64Kbpsで20－50万円していた中、商用サービスとして1996年12月に「OCNエコノミー」128Kbpsの速度で月額38,000円という破格のスペックで登場しました。
この回線は高価なATM回線や専用線を引くことなく、既存のメタル回線を利用して接続できることから、
また、法人向けには1.5Mbpsの「OCNスタンダード」、6Mbpsの「OCNエンタープライズ」が登場しています。
1.5Mbps／6Mbpsというと光ファイバーの専用線でSONET/SDHとピンときた方もいらっしゃるかもしれません。

# CATV
ケーブルテレビの回線を利用したインターネット接続サービスは1996年10月に武蔵野三鷹ケーブルテレビ（現：ジェイコム東京）がスタートになります。
この頃はCATVのインターネットサービスも時間課金でしたが、最大10Mbpsの帯域になっています。
CATVの常時接続サービスは1997年9月のタウンテレビ金沢（現：ジェイコム湘南・神奈川）で、この時の速度は下り最大30Mとなっていました。

# ADSL
ADSLの実験は、1997年4月に伊那市で
商用ADSLの開始は1999月9月の川中島町有線放送(KUHK)とJANISネットにより、長野県で始まりました。
長野市川中島町の限られた地域での開始となりましたが、上りが272Kbps、下りが1.5Mbps、定額接続で月額5,500円となっておりました。
都内では2000年1月、東京めたりっく通信（現：ソフトバンク）によって開始されました。アクセス回線はNTTのものを利用していましたが、交換機を介さずにプロバイダへ接続できるため、安価に開始できるというメリットがありました。
遅れること数か月、イー・アクセス、アッカ・ネットワークスといったADSL時代のベンチャーがADSLサービスを開始し、同年12月末に、NTT東西からフレッツ・ADSLが提供開始になります。

# FTTH
今でも固定回線の主流となっている光ファイバーを使ったFTTHサービスは、2001年3月に有線ブロードネットワークス（現：USEN）から最初にリリースされました。回線速度は100Mbpsで、家庭用のインターネット接続サービスとしては世界最速となっていました。
NTTは2000年12月から試験サービスとして「光・IP通信網サービス」として試験提供してきたものを、同年8月からBフレッツとしてリリース、関西ではケイ・オプティコムが分譲マンション向けにeoメガファイバーとして6月にリリースしたのを皮切りにFTTHのサービスを開始しますが、FTTHがADSLの契約数を超えるのは2008年となりますので、本格化はもう少し先の話になります。

# モバイルインターネット
モバイルインターネットの商用サービスは、1999年のNTTドコモのiモードとなります。
パソコンからの接続の場合、回線、モデム、プロバイダなど準備のステップが多いのに対し、携帯電話から直接インターネットに接続できることが特徴でした。
最初はモノクロ画面でしたが、カラー液晶の機種ができると、その後は高精細化と画面の大型化も相まって、急速に広がっていきました。

# まとめ
こうしてみてみると、家庭のインターネット速度が1995年ごろから2000年代前半に14.4Kbpsから100Mbpsと、一気に約10000倍になっており、技術の進化を肌で体験できた時期だと思います。
また、その100Mbpsも今日の5Gではモバイル通信で優に超えてくるため、こうした進化はまだまだ続いていくものと思います。

# 参考文献
https://www.soumu.go.jp/johotsusintokei/whitepaper/ja/r01/html/nd111120.html

https://group.ntt/jp/group/history/

https://hct.lab.gvm-jp.groupis-ex.ntt/panel/pdf/C-3-5.pdf

https://www.nic.ad.jp/ja/newsletter/No64/0320.html

https://www.iij.ad.jp/30th/view/

https://bb.watch.impress.co.jp/cda/special/16691.html

https://ascii.jp/elem/000/000/313/313492/
基本的にコード修正の前にリファクタリングするべき

## はじめに
バグ修正や機能改修の際、汚れたコードに直面することは珍しくありません。そのまま手を加えると、さらなる技術的負債を生むだけでなく、開発者に大きなストレスがかかります。結果として、生産性が低下し、将来的な保守コストが増大するリスクが高まります。

コードが乱雑なまま修正を繰り返すと、理解に時間がかかるだけでなく、バグの温床となる可能性があります。そうした負のスパイラルを防ぐために、修正前にリファクタリングを行うことが非常に重要です。

本記事では、なぜコード修正の前にリファクタリングを行うべきなのか、そのメリットや具体的なアプローチについて解説します。

## なぜコード修正前にリファクタリングするべきなのか

### 1. **コードの可読性を向上させるため**
コードが理解しづらい状態では、どこをどのように修正すればよいのかの判断に時間がかかり、修正ミスのリスクが高まります。以下のような状況では、修正前にリファクタリングを行うことで、コードの可読性を向上させ、修正作業をスムーズに進めることができます。

- 変数や関数の命名が曖昧
- 一つのメソッドが長すぎる
- ネストや条件分岐が多すぎて読みづらい
- 一つのファイルに多くの責務が集中している

リファクタリングにより、コードの意図が明確になり、修正作業の効率が向上します。

### 2. **バグの発生を防ぐため**
可読性が低いコードでは、バグを生みやすい状態になっています。特に、以下のようなコードには注意が必要です。

- 副作用の多い関数
- グローバル変数への依存
- 無駄な複製コード
- 長大なメソッド内で複数の異なる処理が混在

こうしたコードをそのまま修正すると、意図しない動作が発生しやすくなります。リファクタリングを行うことで、コードの構造を整理し、安全な修正を行える環境を整えることができます。

### 3. **修正の工数を削減するため**
「今すぐ直したいからリファクタリングは後回し」と考えがちですが、結果的に修正コストが増大することがあります。可読性の低いコードに手を入れるたびに時間を取られるよりも、

- まずリファクタリングで構造を整理
- その後に修正を実施

という流れを採ることで、結果的に作業の工数を削減できます。

また、構造が整理されていれば、次回以降の修正時にもスムーズに対応でき、長期的な開発コストを抑えられます。

### 4. **開発者のストレスを軽減するため**
汚いコードを読むこと自体が開発者にとって大きな負担となります。スパゲッティコードを読むだけで疲弊し、修正作業のモチベーションが低下することもあります。リファクタリングによってコードを整理することで、開発者の心理的負担を軽減し、作業の効率を向上させることができます。

## 具体的なリファクタリング手法

### **1. 関数の抽出（Extract Method）**（IDEの機能で対応可能）
長すぎるメソッドは、適切な単位で分割することで可読性が向上し、修正が容易になります。処理全体の流れが追いやすくなるので、コードが格段に読みやすくなり、コード修正が捗るようになります。

### **2. 変数・関数のリネーム（Rename）**（IDEの機能で対応可能）
意図が分かりにくい名前の変数や関数は、適切な名称に変更することで理解しやすくなります。

### **3. 重複コードの削除（Remove Duplication）**
類似するコードが複数存在する場合、それらを統合することでメンテナンス性を向上させます。リスクもありますが、大幅にコードの行数を削減できるのでおすすめです。

### **4. 条件分岐の整理（Simplify Conditionals）**
複雑なif文やswitch文を整理し、シンプルな構造にすることで、意図を明確にします。特に不要な条件分岐は開発者の認知負荷を増大させるため、アーリーリターンなどを活用してシンプルなコードを目指しましょう。

### **5. コメントの整理**
冗長なコメントを削除し、コード自体が意図を説明するようにリファクタリングします。わかりにくい部分には適切なコメントを追加します。

### **6. マジックナンバーの除去**
数値や文字列リテラルを直接書かず、定数や列挙型を使用して意味を明確にします。

### **7. 不要なコードの削除**
不要な変数や関数、未使用のコードを削除することで、コードの可読性を向上させます。

### **8. AIによるリファクタリング**
AIを活用してリファクタリングの提案を受けることも可能ですが、人のチェックは必須です。AIは大幅な修正を提案することが多いため、段階的にコミットを分けて適用することが重要です。

## リファクタリングを後回しにすべきケース

### **1. 緊急のバグ修正が必要な場合**
例えば、サービスのダウンやセキュリティ脆弱性の対応が必要な場合は、最優先で修正を行い、リファクタリングは後回しにするべきです。

### **2. 影響範囲が大きすぎる場合**
リファクタリングによってコード全体の構造が大きく変わる場合、影響を最小限に抑えるために段階的なアプローチを取るべきです。その場合でも、現在のコードの状況を示すようなコメントを記述し、他の開発者が誤って参考にしないように注意を促しましょう。

## まとめ
- **コード修正の前にリファクタリングを行うことで、可読性が向上し、バグの発生を防げる**
- **リファクタリングを行うことで、結果的に修正の工数を削減できる**
- **緊急対応時や影響範囲が広い場合は、リファクタリングを慎重に計画する**

リファクタリングを適切に行うことで、開発の効率と品質を向上させ、長期的な技術的負債の削減につながります。修正作業の前に、一度立ち止まってリファクタリングを検討する習慣をつけましょう。
AWS認定 AIF資格試験 受けてみた！

やっとこさ時間ができたので、記事を書けます。:sweat_smile:

https://qiita.com/buchi_org/items/e324a0981629e1b63ef5

にありましたように、先日AIF-C01試験を受験してきました。


また、先日社内のAWSユーザイベントでのLT登壇予定リストに
「**AIF資格取得してみた(仮)**」と記載されてまして、
**"AIF資格受けてみた"** で申し込んだつもりが **"受からなかった世界線のLT登壇"** ができなくなりました。。。。💦

なので、**年度末なのに、寝ずの試練(お勉強)** が待っておりました。。
<BR/>「**で、結果はどうなのよ？笑**」
<BR/>
<BR/>
<BR/>
<BR/>
なんとか、合格することができました。

また、社内でAIF取得の３番目 かつ　**Early Adopter** の称号
<img width="70" src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2713444/e0f31248-64e7-1773-ee51-a2c14d8b9845.png' style='width:100px;height:250px' /> も、なぜかついてきました。

ということで、めでたしめでたし。。。。
<BR/>
<BR/>

ここで教訓「**次から資格ネタのLTは受かってから申し込もうな**」

ではまた。:sweat_smile:
Pythonでリングバッファを実装するクラスを作成してみた

# はじめに
こんにちは！今回はPythonでリングバッファ(Ring Buffer/Circular Buffer)を実装するプログラムを紹介します。
リングバッファは、一定のサイズのバッファを使用してデータを循環的に管理するデータ構造です。特に、メモリを固定サイズで管理したいときやキューのような操作を効率よく行きたい場合に役立ちます。
# リングバッファとは？
リングバッファは、配列を循環的(リング状)に扱うデータ構造です。配列の末尾に達した場合でも、先頭に戻ってデータを格納できるため、一定サイズ内のメモリ管理に最適です。
例えば、サイズが5のリングバッファに対して以下のような操作を行った場合:
・enqueue:データを追加(末尾に追加)
・dequeue:データを削除(先頭から取り出し)
バッファは常に新しいデータで上書きされます。
# 実装コード
以下のpythonクラスRingBufferでは、バッファの初期化、データの追加(engueue)、データの取り出し(dequeue)、バッファの状態を表示するdisplayメソッドを実装しています。
```py:ringbuffer.py
class RingBuffer:
    def __init__(self, size, initial_values: list = None):
        self.size = size          
        self.buffer = [None] * size  
        self.head = 0             
        self.tail = 0             
        self.count = 0            
        self.operation_count = 0  
        self.dequeue_count = 0    
        self.hoge = []            

        if initial_values:
            for i, value in enumerate(initial_values):
                self.buffer[i] = value
            self.tail = len(initial_values)
            self.count = len(initial_values)
            self.hoge.append(list(self.buffer))

        print("=== 初期状態 ===")
        self.display()

    def enqueue(self, item):
        if self.count == self.size:
            print("バッファが満杯です。エンキューできません。")
            return
        self.buffer[self.tail] = item
        self.tail = (self.tail + 1) % self.size
        self.count += 1
        self.operation_count += 1
        print(f"{self.operation_count}. enqueue(Q, {item})")
        self.hoge.append(list(self.buffer))
        self.display()

    def dequeue(self):
        if self.count == 0:
            print("バッファが空です。デキューできません。")
            return None
        item = self.buffer[self.head]
        self.buffer[self.head] = None
        self.head = (self.head + 1) % self.size
        self.count -= 1
        self.operation_count += 1
        self.dequeue_count += 1
        print(f"{self.operation_count}. {self.dequeue_count}回目のdequeue(Q): {item}")
        self.hoge.append(list(self.buffer))
        self.display()

        return item

    def display(self):
        print(f"  Q[i]: {self.buffer}\n")
```
# 使用例
以下のコードでリングバッファを初期化し、データを追加・削除する操作を試します。
```py:ringbuffer.py
# 使用例
Q = RingBuffer(5, [17, 43, 86])
Q.enqueue(71)
Q.dequeue()
Q.enqueue(19)
Q.enqueue(61)
Q.dequeue()
Q.enqueue(34)
Q.dequeue()
Q.dequeue()

import pandas as pd
pd.DataFrame(Q.hoge, index=list(range(len(Q.hoge))), columns=list(range(len(Q.hoge[0]))))
```
# 実行結果の例
```
=== 初期状態 ===
  Q[i]: [17, 43, 86, None, None]

1. enqueue(Q, 71)
  Q[i]: [17, 43, 86, 71, None]

2. 1回目のdequeue(Q): 17
  Q[i]: [None, 43, 86, 71, None]

3. enqueue(Q, 19)
  Q[i]: [None, 43, 86, 71, 19]
  ・
  ・
  ・
```
# まとめ
このリングバッファの実装は、キューのような操作を循環的に行きたいときに便利です。今回のプログラムを応用して、例えばリアルタイムログやセンサーのデータストリームなどを管理する際にも利用できます。最後まで読んでくださり、ありがとうございました。もし改善点や質問があれば、ぜひコメントしてください！
Windows 11 で休止状態を有効にする方法（最終的に休止状態は使わなかった話）

Windows 11 ではデフォルトで休止状態が無効になっています。それを有効にする方法を調べました。

→ しかし、SSD に負荷がかかることが判明したため、最終的にスリープを使うことにしました。

## やり方だけ知りたい人向け

1. 管理者権限で cmd.exe を開く
2. `powercfg /H on` を実行
3. **休止状態が有効になる！**

休止状態を無効化したい場合は、`powercfg /H off` を実行すれば OK です。

---

## 休止状態を有効にしようと思った理由

PC を AC アダプターに繋いだままずっと起動させていたのですが、**バッテリー寿命が短くなる** という話を知りました。

それなら「使わないときはスリープや休止状態にして、AC アダプターを外せばいいのでは？」と思い、手軽にスリープ・休止状態へ移行できるように **[Claunch](https://sites.google.com/site/craftware/clnch)** にコマンドを登録しようと考えました。

調べたところ、コマンドラインからスリープ・休止状態にする方法は以下のとおり。

- **スリープ**: `rundll32.exe powrprof.dll,SetSuspendState 0,1,0`
- **休止状態**: `shutdown /h /f`

スリープのコマンドが面倒だったため、休止状態を試してみることにしました。しかし、

```sh
❯ shutdown /h /f
このシステムでは休止状態が有効になっていません。-h オプションを使うには、休止状態を有効にしてください。(126)
```

とエラーが発生。ここから「休止状態を有効にするまでの旅」が始まりました。

---

## Google で調べた

### 情報は多いが肝心なところに手が届かない

シンプルに「Windows 11 休止状態 有効」と検索すると、

[【Windows 11】なぜだか消えた「休止状態」を電源メニューに復活させる - ＠IT](https://atmarkit.itmedia.co.jp/ait/articles/2204/11/news020.html)

という記事が見つかりました。手順通りに進めると、以下の画面になり

![期待される画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740499/48351b08-3987-a96d-118d-ac444b2b1b61.png)

「休止状態」を ON/OFF するオプションが表示されるはずです。が、私の PC では **そんな項目すら存在しない…**。

**実際の画面:**

<img width=400 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740499/434b77a8-b933-681a-d921-72d623c4edbf.png">

記事には「この項目がない場合、`powercfg` コマンドで休止状態を有効にする必要がある」と書かれていました。しかし、会員登録しないと続きを読めない…。

NEC や富士通の公式サイトの Q&A も確認しましたが、

- [NEC LAVIE 公式 Q&A](https://faq.nec-lavie.jp/qasearch/1007/app/servlet/qadoc?QID=023761)
- [富士通公式 Q&A](https://www.fmworld.net/cs/azbyclub/qanavi/jsp/qacontents.jsp?PID=6711-3873)

いずれも **「休止状態の項目がない場合の対処法」には触れていない** ため、この日は諦めました。

---

### 解決策を発見！

翌日、改めて「Windows 11 スリープ コマンドライン」で検索したところ、

[Powercfg のコマンドライン オプション | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows-hardware/design/device-experiences/powercfg-command-line-options)

という **Microsoft 公式のガイド** を発見。そこに `powercfg /H on` の説明があり、試してみました。

```sh
❯ powercfg /H on
```

特にメッセージは出ませんでしたが、成功したようです。

さらに `powercfg /availablesleepstates` コマンドで利用可能なスリープ状態を確認。

```sh
❯ powercfg /availablesleepstates
以下のスリープ状態がこのシステムで利用可能です:
    スタンバイ (S3)
    休止状態
    ハイブリッド スリープ
    高速スタートアップ
```

**「休止状態」が有効になっている！** 🎉

コントロールパネル → 電源オプション → システム設定を開くと、「休止状態」が表示されていました。

<img width=400px src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740499/056cd335-d9dc-f027-24fc-576a7f33ab24.png">

（なぜか「高速スタートアップ」も増えていましたが、それはさておき…）

---

### コマンドラインで休止状態に移行できるようになった

`shutdown /h` を実行すると、すぐに休止状態に入れるようになりました。

```sh
> shutdown /h
```

**やったー！…と思ったのですが、ここで問題発生。**

---

## 休止状態は SSD に負荷がかかる…！？

調べたところ、**休止状態を使うと SSD の寿命を縮める可能性がある** ことが判明。

参考: [SSD や NVMe で絶対にやってはいけない『禁止行為』 | 株式会社アークブレイン](https://www.arcbrain.jp/support/NVM_Express/Prohibited_acts/)

**結論:**
休止状態は使わず、スリープを利用することにしました。

**スリープモードにする方法（再掲）**

```sh
> rundll32.exe powrprof.dll,SetSuspendState 0,1,0
```

最初からスリープにしておけば良かったですね…😅
**注意！**： 休止状態が有効だと、スリープの代わりに休止状態になることがあるので`powercfg /H off`しておきましょう。
MacbookからUbuntuサーバへSSH接続手順

# はじめに
最近mini pcを購入し、ubuntu24.04をインストールしました。そこで、Macbookからmini pcへssh接続する手順を紹介します。

# 概要
全体の流れは以下です。

![macssh.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693671/974667a9-2a47-ae88-051b-026f3cfd149b.png)

macbookから、ubuntuにssh接続するためには、ubuntuにopensshというサービスをインストールする必要があります。また、家のローカルネットワーク内で稼働するシステムとしているため、ubuntuのipアドレスを固定に設定しておくことをお勧めします。

# 手順
## mini pc側の処理
以下コマンドにて、`openssh`をインストールします。
```
sudo apt install openssh-server
```

以下コマンドで、opensshが起動しているか確認できます。
```
systemctl status ssh
```

macbook側の公開鍵をauthorized_keysに設定
```
cat id_rsa.pub >> authorized_keys
```

## macbook側の処理

公開鍵ペアを以下コマンドで作成します。
```
ssh-keygen -l -f ~/.ssh/id_rsa.pub
```


公開鍵を以下コマンドで`tmp`ディレクトリに転送します。
```
scp ~/.ssh/id_rsa.pub <user name>@<mini pc ip address>:/home/<username>/.ssh/
```

macbook側の`config`ファイルを設定します。
```
sudo vim ~/.ssh/config
```
以下文言を足してください。
```
Host <host name>
  HostName <IP address>
  IdentityFile ~/.ssh/id_rsa
  User <ubuntu user name>
```

上記設定ができたら、macbook側で以下コマンドを実行してください。
```
ssh username
```

おそらく、アクセス可能なはずです。

以上。


# 参考
[SSH](https://zenn.dev/uchidaryo/books/ubuntu-2204-server-book/viewer/openssh)
[お前らのSSH Keysの作り方は間違っている](https://qiita.com/suthio/items/2760e4cff0e185fe2db9)
Jetpack ComposeのBasicTextFieldのUndoとRedo

`BasicTextField` は Jetpack Compose 1.7.0 のタイミングで `BasicTextField2` からリネームされて新しいものに切り替わりました。
その新しくなった `BasicTextField` で入力内容の Undo/Redo の API が追加されています。
その Undo/Redo 機能の紹介です。
material の `TextField` と `OutlinedTextField` は compose-material 1.7.7 or compose-material3 1.3.3 時点では `TextFieldState` を直接操作しない形になっているため、現時点では `BasicTextField` のみでの使用が可能となっています。

## 使い方

`TextFieldState` から `UndoState` を使って操作します。

```kotlin
val textFieldState = rememberTextFieldState()
Column {
    BasicTextField(
        state = textFieldState,
        modifier = Modifier.weight(1f)
    )
    Row {
        Button(
            onClick = {
                state.undoState.undo()
            },
            enabled = state.undoState.canUndo
        ) {
            Text("Undo")
        }
        Button(
            onClick = {
                state.undoState.redo()
            },
            enabled = state.undoState.canRedo
        ) {
            Text("Redo")
        }
    }
}
```

## できること
- `BasicTextField` に対して入力された内容の Undo/Redo 
- 残せる履歴は 100 件まで
- 履歴のクリアはできるが、一覧の取得はできない
- 物理キーボードでの Undo/Redo のショートカットに対応している

## 入力時の挙動例
### 共通の挙動
- 最後に入力してから 5000ms 以上経過した地点までを入力中であっても履歴に追加する
- 改行は履歴に追加する

### Gboard の日本語入力の場合
- 基本的には入力した内容が履歴に追加されるが、履歴に追加されるタイミングが難しい
- フリック入力ではなく連打して入力された文字は全て履歴に残る
    - "お("あ"のキーを連打して入力)" - 確定 -> ["あ", "い", "う", "え", "お"]
- 小書きや濁音半濁音に変換された地点までの入力が履歴に追加される
    - "やばい" - 確定 -> ["やは", "やば", "やばい"]
- 入力中に対してキーボードの "変換" が押下されると表示が切り替わった分だけ履歴に追加される
    - "きょう" - 変換 - "今日" - 変換 - "2025/02/07" - 確定 -> ["きよ", "きょう", "今日", "2025/02/07"]
- 入力中のテキストに対して候補から選択したときは入力中のものと候補から選択したものの両方が履歴に追加される 
    - "あした" - 候補から選択 - "2025/02/08" -> ["あした", "2025/02/08"]


### Gboard の英語入力の場合
- 日本語に比べると変換パターンが少なく癖なく履歴に追加される
- スペースが入力されるまでをひとまとまりで履歴に追加する
    - "tomorrow" - スペース -> ["tomorrow "]
- 入力中のテキストに対して候補から選択したときは候補から選択したものが一つの履歴に追加される
    - "to" - 候補から選択 - "tomorrow " -> ["tomorrow "]
- なぞり入力の場合はなぞりで入力したものが履歴に追加され、なぞり入力後に候補から選択した時にはそれぞれが履歴に追加される
    - "help(なぞりで)" - 候補から選択 - "hey " -> ["help", "hey "]



### 実装

この辺りがその実装になっています。

https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/TextUndoManager.kt;l=140-241

## 手動でのテキスト操作時の挙動
以下のように `BasicTextField` ではコードからもテキストの操作ができます。

```kotlin
textFieldState.edit {
    insert(5, "inserted text")

    delete(12, 13)

    append("appended text")

    replace(0, 5, "replaced text")
}
```

テキストの操作はできますが、これらの操作は履歴に追加されません。
ユーザの操作のみが履歴に追加されます。
#0037（2024/02/07）RAID0, 1, 5, 6

# RAID レベルの解説

RAID (Redundant Array of Independent Disks) は、複数のハードディスクを組み合わせて、**性能向上**や**冗長性（データ保護）**を実現する技術です。  
ここでは、代表的な RAID レベルである **RAID 0**、**RAID 1**、**RAID 5**、**RAID 6** について解説します。

---

## RAID 0

**概要:**  
RAID 0 は「ストライピング」と呼ばれる手法で、データを複数のディスクに分散して書き込む方式です。  
これにより、読み書きのパフォーマンスが大幅に向上しますが、冗長性は一切なく、1 台のディスクが故障すると全データが失われるリスクがあります。

**特徴:**  
- **メリット:**  
  - 高速な読み書き性能を実現  
  - 全ディスクの容量を利用可能  
- **デメリット:**  
  - 冗長性がないため、データ保護ができない  
  - 1 台のディスク故障で全体のデータが失われる

**用途:**  
- 一時的なデータ処理やキャッシュ用途  
- 高速性が最重要な環境（ただし、データの安全性は他の手段で担保する必要がある）

---

## RAID 1

**概要:**  
RAID 1 は「ミラーリング」と呼ばれ、同じデータを複数のディスクに同時に書き込む方式です。  
1 台のディスクが故障しても、他のディスクにデータがそのまま存在するため、高い冗長性が確保されます。

**特徴:**  
- **メリット:**  
  - 高いデータ冗長性  
  - 1 台のディスク障害時でもシステムが継続可能  
- **デメリット:**  
  - 使用可能な容量はディスク容量の半分に制限される  
  - コスト効率が低い（同じデータを複数保存するため）

**用途:**  
- ミッションクリティカルなシステム  
- 高いデータ保護が求められるサーバーやワークステーション

---

## RAID 5

**概要:**  
RAID 5 は、データとパリティ情報を複数のディスクに分散して格納する方式です。  
1 台のディスクが故障しても、パリティ情報を元に故障ディスクのデータを再構築できるため、冗長性とストレージ効率のバランスが取れています。

**特徴:**  
- **メリット:**  
  - 冗長性と容量効率のバランスが良い  
  - 1 台のディスク障害に対してデータ保護が可能  
- **デメリット:**  
  - パリティ計算による書き込みオーバーヘッドが存在する  
  - 書き込み性能が RAID 0 や RAID 1 に比べて低下する場合がある

**用途:**  
- ファイルサーバーや一般的なサーバー環境  
- バランスの取れたパフォーマンスと冗長性が必要なシステム

---

## RAID 6

**概要:**  
RAID 6 は、RAID 5 の仕組みに加え、**ダブルパリティ**を使用することで、同時に 2 台のディスク障害に耐えることができる方式です。  
より高い冗長性が求められる環境で採用されますが、その分、パリティ計算の負荷が増し、書き込み性能に影響を及ぼすことがあります。

**特徴:**  
- **メリット:**  
  - 同時に 2 台のディスクが故障してもデータが保護される  
  - 非常に高い冗長性を提供  
- **デメリット:**  
  - RAID 5 よりもパリティ計算のオーバーヘッドが大きい  
  - 使用可能な容量がさらに低下する  
  - 書き込み性能が低下しがち

**用途:**  
- データセンターや大規模ストレージシステム  
- 重要なデータを扱う環境で、極めて高い冗長性が必要な場合

---

## まとめ

| RAID レベル | 主な特徴                            | メリット                         | デメリット                             |
|-------------|-------------------------------------|----------------------------------|----------------------------------------|
| **RAID 0**  | データをストライピング              | 高速な読み書き、全容量利用         | 冗長性なし、1台故障で全データ損失         |
| **RAID 1**  | ミラーリング                         | 高い冗長性、障害時も継続可能         | 容量効率が低い、コストが高い              |
| **RAID 5**  | 分散パリティによる冗長性と容量効率の両立  | バランスの取れた性能と冗長性         | 書き込みオーバーヘッド、1台障害に限定         |
| **RAID 6**  | ダブルパリティによる高冗長性           | 極めて高い冗長性（2台故障耐性）       | 書き込み性能の低下、容量効率がさらに悪化        |

それぞれの RAID レベルは、**パフォーマンス**、**冗長性**、**容量効率** のトレードオフを考慮して選択する必要があります。  
システムの要件や利用目的に応じて、最適な RAID 構成を採用することで、データ保護と性能向上のバランスを実現できます。
ゲーマーによるゲーマーのためのdebounceとthrottle解説 🔮🧙🔥

## はじめに
プログラミングの世界でよく出てくるdebounceとthrottle。
これらは連続して発生するイベントを制御する手法ですが、ゲームのスキルシステムと非常によく似た動作をします。
## Debounce = スキルの詠唱時間 🔮
debounceは、RPGゲームでよくある「詠唱スキル」のような動作をします。
```ts
// 詠唱魔法のイメージ
const castFireball = debounce(() => {
  console.log("ファイアボール発動！🔥");
}, 500); // 0.5秒の詠唱時間
```
  - 0.5秒の詠唱時間
  - 詠唱スキルの特徴
    - 詠唱中に他のアクションを取ると、詠唱がキャンセルされて最初からやり直し
    - 詠唱完了まで待たないと発動しない
    - 最後の入力から指定時間が経過した後に1回だけ発動
    

例えば、ファイアボールという魔法があり、0.5秒の詠唱時間があるとします。

    詠唱開始 → 0.3秒後に移動 → 詠唱キャンセル
    再度詠唱開始 → 0.5秒間何もしない → ファイアボール発動！
    
## Throttle = スキルのクールタイム ⏱️
throttleは、アクションゲームでおなじみの「クールタイムのあるスキル」のような動作をします。
```ts
// クールタイムのあるスキルのイメージ
const useSlash = throttle(() => {
  console.log("斬撃スキル発動！⚔️");
}, 1000); // 1秒のクールタイム
```
 - 1秒のクールタイム
 - クールタイムスキルの特徴
   - 即座に発動する
   - 発動後は一定時間、再使用不可
   - クールタイム中の入力は無視される

   
例えば、斬撃というスキルがあり、1秒のクールタイムがあるとします。

    スキル使用 → 即座に発動！
    クールタイム中（1秒間）は何回ボタンを押しても発動しない
    クールタイム終了後 → 再度使用可能

## 実際のコード例
```ts
// debounce（詠唱スキル）の実装例
const castSpell = debounce((spellName: string) => {
  console.log(`${spellName}の詠唱完了！`);
}, 500);

// throttle（クールタイムスキル）の実装例
const useSkill = throttle((skillName: string) => {
  console.log(`${skillName}を発動！`);
}, 1000);

// 使用例
castSpell("メテオ");    // 0.5秒後に発動
useSkill("突進攻撃");   // 即座に発動、その後1秒間は使用不可
```

## まとめ
- Debounce（詠唱スキル）: 最後の入力から一定時間待って発動
- Throttle（クールタイムスキル）: 即座に発動し、一定時間は再使用不可

このように、ゲームのスキルシステムと対応させて考えると、debounceとthrottleの違いがより直感的に理解できますね！
【paiza】廃マンションの一室(Cランク)でコードゴルフをやってみた【電脳少女プログラミング2088 ─壊レタ君を再構築─】

## 問題の概要
三進法の特殊な例として、2を-1として扱う平衡三進法で任意の数を表せという問題です。
例えば表したい数値が2であれば2=3+(-1)なので12となり、7であれば7=3^2+(-3)+1なので121です。一見、負数を使っていることから表し方が一意に定まらないようにも見えますが、実はこの方法で任意の整数を一意に表すことができます。

## 実際のコード
```python
t=lambda n=int(input()):[t(n//3)+"0",t(~-n//3)+"1",t(-~n//3)+"2"][n%3]if-~n//3 else str(n%3)
print(t())
```
ワンライナーで見づらいので成形します。
```python
t=lambda n=int(input()):
    [t(n//3)+"0",t(~-n//3)+"1",t(-~n//3)+"2"][n%3]
    if-~n//3 
    else str(n%3)
print(t())
```
012の文字を条件に従って再帰的にプッシュしていくというプログラムです。もっとわかりやすくすると、
```python
def t(n):
    if -~n//3:
        if n%3==0:
            return t(n//3)+"0"
        elif n%3==1:
            return t(~-n//3)+"1"
        else:
            return t(-~n//3)+"2"
    else:
        return str(n%3)
print(t(int(input())))
```
です。余りが2のときには結果に1を足して2をプッシュし、余りが1のときには結果から1を引いて1をプッシュします。ちなみに文字数はビット演算の方が少ないです。
ここから短くしていく作業です。余りが012の3通りしかないため、リストの012番目を参照する形にすれば、returnをリストに書き換えできます。つまりは、
```python
def t(n):
    if -~n//3:
        return [t(n//3)+"0",t(~-n//3)+"1",t(-~n//3)+"2"][n%3]
    else:
        return str(n%3)
print(t(int(input())))
```
と書き換えが可能です。
あとはラムダ式を使ってif文を1行にまとめれば、1番上のコードになります。結果としては150byte程度から103byteまで短縮できました。
```python:103byte.py
t=lambda n=int(input()):[t(n//3)+"0",t(~-n//3)+"1",t(-~n//3)+"2"][n%3]if-~n//3 else str(n%3)
print(t())
```
残りの短縮可能なポイントは単なる難読化になるので、これを個人的な解答として置いておきます。それでは。
NextでbuildするとUnexpected end of JSON inputのエラーが出た

<!-- title: NextでbuildするとUnexpected end of JSON inputのエラーが出た -->
<!-- tags: Next, Typescript, Node -->

# Next.js プロジェクト開発備忘録

## エラー内容

`Unexpected end of JSON input` のエラー発生

### 状況

- **Local 環境:** 表示問題なし
- **API データ:** 確認済み、異常なし
- **ビルド時:** エラー発生

## 原因

どうやら **Node.js 23 系** で `build` すると発生するエラーの模様

## 解決策

Node.js のバージョンを **20.10.0** に変更

```
nvm install v20.10.0
nvm use v20.10.0
```

これでエラーは消えた
Docker をワンライナーでインストール

# 背景
新規でセットアップする仮想マシン上の Linux や WSL の Linux に Docker を素早くインストールしたい。
インストールのコマンドをググったりするけど、すぐに見つからないことが多いのでメモ代わりに。

#### インストール可能ディストリビューション
* CentOS
* Debian
* Fedora
* SLES (SUSE Linux Enterprise Server)
* Ubuntu

<font color="lightgray">今は亡きCentOS...</font>


# コマンド
```bash:bash
$ curl -fsSL https://get.docker.com | sudo sh -
```

# 利用に際して
本番環境でのワンライナーでのインストールは注意してください。
本番環境で利用する場合は、依存関係やパッケージバージョンを気にする必要があります。

# 参考リンク
https://matsuand.github.io/docs.docker.jp.onthefly/engine/install/ubuntu/#install-using-the-convenience-script
[Next.js] Next.jsなのにSSRができない！？静的ページが表示される場合の簡単な解決策

Next.jsを使っている際、練習環境では動的にページを生成できたのに本番環境でSSRができず、静的ページが表示される問題に遭遇した。

調べたところ、Next.jsでは特に明示しなければビルド時に静的ページが表示されるようにできていることがわかった。

参考 : キャッシュで理解するNext.js App Routerのデータ取得

https://zenn.dev/tasugi/articles/d05c445bc79f09

解決策は公式ドキュメントにあった。以下の1行を追加すればいいとのことである。

```js
export const dynamic = 'force-dynamic'
```

https://nextjs.org/docs/app/building-your-application/data-fetching/fetching#fetching-data-on-the-server-with-an-orm-or-database

Next.jsといえばSSRというイメージを持っている人もいると思うが、この1行がないと動的にページが生成されないので気をつけよう。
Nutanix CE2.0クラスターでバックプレーンLANを分離

構築したクラスターに使用したミニPCはNICが２つあるので
ノード間の通信(バックプレーンネットワーク)を物理的に分けてみようと思います。

参考URL

https://juliendumur.fr/en/nutanix-setup-the-backplane-network/







## AHVをメンテナンスモードに
本作業を行う前にCVMを除く仮想VMは全て停止しておきます。
その上でAHVのモードを変更
```
# 1つのCVMから全AHV操作可能
acli host.enter_maintenance_mode <AHV_IP>
```



黄色い[！]がついてればよい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741824/f7be13f8-0d07-1eeb-a9f3-f54ecd767ede.png)



















## 仮想スイッチ作成準備
デフォルトだと全てのNICはvs0に属しているので
先にそれを解除します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741824/8830054b-994e-ce05-cedb-379e18d4a927.png)












・Bond Type：Active-Backup ⇒ No Uplink Bond
・NICは未使用(3ノード分)のチェックを外す
　※Select UPlink Ports Show項目で
 　　Only Connected Uplink Portsを選択すると未接続NICが消えるので判断できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741824/42b6d670-8812-8c91-3d55-7594a3e67f6b.png)




































処理が終わるまで放置
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741824/ebc4d013-8a72-0f31-23b5-60b285870237.png)











## 仮想スイッチ作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741824/2e7cc20f-3c94-951a-8928-f664c83abfd5.png)








名前は適当に・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741824/f745aa53-2271-df5b-323b-06ad6a5f3432.png)




















・Bond Type：No Uplink Bond
・NICは未使用(3ノード分)のeth1をチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741824/21a4dfa3-3344-768e-692d-4b26db5c6145.png)










































## バックプレーンLAN
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741824/2be7f20c-dfe5-8dd0-3cda-36c9499938d6.png)















![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741824/98da223f-d9ee-18c5-361f-810a25d8a04f.png)








![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741824/2723effc-52d3-18da-0772-3febbda2aabd.png)








完了しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741824/a516be06-9d56-3bef-cb7b-1f7203cf6314.png)















## AHVのメンテナンスモードを解除
```
# 1つのCVMから全AHV操作可能
acli host.exit_maintenance_mode <AHV_IP>
```


## IP確認
eth2が動作している。
```
#確認
nutanix@NTNX-CVM:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 50:6b:8d:f6:04:cb brd ff:ff:ff:ff:ff:ff
    inet 172.16.0.5/24 brd 172.16.0.255 scope global eth2
       valid_lft forever preferred_lft forever
    inet6 fe80::526b:8dff:fef6:4cb/64 scope link
       valid_lft forever preferred_lft forever
```
【AWS Kinesis】使わないデータストリームは削除しておこう

# はじめに
AWSデビューをした矢先、思いのほか高額な請求額がきていたため、ここで供養させていただきます。
# 原因
原因を調べたところ、**どうやら Kinesis Data Analytics がコストを消費していることが判明**しました。
「意図的に」使った覚えはありませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/5750defa-feeb-5754-6d5b-24ad92dacc8f.png)


さらに調査すると、**Kinesis AnalyticsのStudioノートブックを作成していたことが判明**しました。

### ～Kinesisとは～

**リアルタイムでデータの取り込み・集約を行い、その後の分析やレポート作成に活用できるサービス**です。
その中でも Studioノートブック は、Apache Zeppelinベースのインターフェースを使用して、SQLやPythonをリアルタイムで試すことができるツールです。便利ですが、その分コストも高めに設定されています。

***
そして、このStudioノートブックには以下の課金ポイントがあるため、**使用していなくても課金が発生する場合があります**。

**１．オンデマンドモードの課金**
Kinesis Analytics Studioは、デフォルトではオンデマンドモードに設定されています。このモードでは、**ノートブックがアクティブであるかどうかに関係なく**、以下のリソース使用量に基づいて課金されます

**～処理ユニット（KPU: Kinesis Processing Unit） の利用時間～**
1KPUは、1vCPU＋4GBのメモリに相当します。
（vCPU: 仮想マシンのCPU）
**オンデマンドモードでは、ノートブックを作成しただけで、KPUが割り当てられた状態になり、課金が発生**します。

**２．ノートブックのステータス**
**Studioノートブックのステータスが「STOPPED（停止）」でない限り、課金が発生**します。
たとえ**ノートブックを開いて作業をしなくても、アクティブまたは未削除の状態であれば課金され続け**ます。

詳しい料金体系はこちらです。

https://aws.amazon.com/jp/kinesis/data-streams/pricing/

# 解決策

・**不要なKinesis Analyticsやデータストリームは必ず削除**する
・請求アラート設定を行っておく

https://se-kowaza.com/aws-billing-alert/

# おわりに
初歩的なミスでお恥ずかしい限りですが。。とにかく、学習後のお片付けは必須です。
そして定期的にダッシュボードも確認しましょう！
# 参考

https://qiita.com/Aichi_Lover/items/3d346788305b630712e5
Websocketを理解する

## 目次

#### 1. I/Oとは？
#### 2. 同期処理と非同期処理の違い
#### 3. WebSocketとは？
#### 4. WebSocketの動作の流れ
#### 5. 非同期通信のメリットと活用シーン
#### 6. DjangoでWebSocketを扱うには？
#### 7. WSGIとは？
#### 8. ASGIとは？
#### 9. Django Channelsとは？
#### 10. Consumerとは？



## I/Oとは？

**Input**（入力）と**Output**（出力）の略。

コンピュータでは、データのやり取りをするときに「I/O処理」が発生。 たとえば、以下のような動作が「I/O処理」です。I/Oは 時間がかかる処理 であり、この待ち時間をどう処理するかが重要。

| I/O | 例 |
|:---------|:---------------------------|
| **Input**  | キーボード入力、ネットワークからのデータ取得、データベースアクセス |
| **Output** | 画面への表示、ファイルへの書き込み、クライアントへのレスポンス送信 |

## 同期処理と非同期処理の違い

I/Oが発生したとき、コンピュータの処理方法には 「同期（同期的）」 と 「非同期（非同期的）」 という2つの方式があります。

#### 1. 同期処理

- 1つの処理が終わるまで次の処理を待つ
- I/Oの待ち時間中は他の処理ができない
- シンプルだけど遅い

#### 2. 非同期処理
- I/Oの待ち時間中に、他の処理を進める
- 効率的に動作する
- WebSocketのようなリアルタイム通信に向いている

## WebSocketとは？

#### 1. WebSocketは「双方向通信」の仕組み
- WebSocketは、クライアント（ブラウザ）とサーバーがリアルタイムで通信できる仕組み。

#### 2. WebSocketの特徴
- 一度接続を確立すると、サーバーからもデータを送信できる
- リアルタイムにデータをやり取りできる
- 非同期通信で効率的に処理

#### 3. なぜWebSocketが必要？
- 通常のHTTP通信（リクエスト & レスポンス）では、クライアントからリクエストを送らないとサーバーはデータを送れない。→ リアルタイム通知やチャットには向いていない！

- しかし、WebSocketを使えば… → クライアントもサーバーも、自由にデータを送れる！

## Websocketの動作の流れ

#### 1 通常のHTTP通信
- クライアントがサーバーにリクエストを送る
- サーバーがレスポンスを返す
- 新しいデータが欲しいときは、またリクエストを送る（待ち時間が発生）

#### 2. WebSocketの通信
- 最初に1回だけ接続（ハンドシェイク）
- その後、自由にデータを送受信
- クライアントもサーバーも、好きなタイミングでデータを送信可能

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3895655/2c0d37f8-dfc3-ddc9-d45f-513113a8985f.png)

 ## DjangoでWebSocketを扱うには？
 
Djangoでは、**「Django Channels」**を使うとWebSocketを実装できます。

##### 1. Django Channelsをインストール

```nginx
pip install channels
```

###### 2. asgi.py を設定
###### 3. Consumer（WebSocketの処理を書くクラス）を作成
###### 4. ルーティングを設定
###### 5. RedisなどのChannel Layerを活用して効率化

## WSGI（Web Server Gateway Interface）とは？

- WSGI（Web Server Gateway Interface）は、PythonのWebアプリケーションとWebサーバーの間の「接続ルール」のこと
- Djangoの基本的な仕組みは、WSGIに基づいて動いている
- どんな時に使われるか
    - 通常のHTTPリクエスト（ページを開く、フォームを送信する）
    - 同期的な処理（リクエストが終わるまで次の処理が待つ）

## ASGI（Asynchronous Server Gateway Interface）とは？

- ASGI（Asynchronous Server Gateway Interface）は、WSGIの後継で、非同期通信をサポートするために作られた仕組み
- WebSocketのようなリアルタイム通信にはASGIが必要
- どんな時に使われるか
    - WebSocket（リアルタイム通信）
    - 非同期HTTPリクエスト（速く処理したい）
    - 長時間接続が必要な処理（ストリーミングやチャット）

## Django Channelsとは？

Djangoは WSGI（同期処理）に基づいているので、デフォルトでは WebSocketを扱えない。
そこで登場するのが **Django Channels！** → DjangoをASGI対応にして、WebSocketを使えるようにするライブラリ。

####  Django Channelsの役割
- Djangoを ASGI対応 にする
- WebSocketを扱えるようにする
- 非同期処理を簡単に実装できるようにする

## Consumerとは？

Djangoの**Consumer**は、WebSocketのリクエストを処理するクラス。
**View**のWebSocket版！ 通常のHTTPリクエストに対して「View」を作るように、WebSocketには「Consumer」を作る。

 #### Consumerの役割
- WebSocketの接続・切断を管理
- メッセージの送受信を処理
- データベースと連携する
Notionデータベースをノーコードでモバイルアプリ化できるサービスを探しています。おすすめはありますか？

現在、Notionでタスク管理と情報共有用のデータベースを運用しています。
チームメンバーから「スマホで手軽にデータを追加・編集したい」という要望が増えているのですが、
以下の条件を満たすツールがあれば教えていただきたいです。

■ 希望する機能
・Notionデータベースと自動連携
・ノーコードでUIカスタマイズ可能
・検索/フィルター機能付きのリスト表示
・PWA対応（アプリのようにインストール可能）
・複数データベースの混在表示
・ユーザーごとの権限設定

以前「Notion APIを使えば可能」と聞きましたが、技術的なハードルが高く断念しました。
有料ツールでも構いませんので、実現方法があればご教示ください。

ちなみに、NotionApps（https://www.notionapps.com）というサービスを見つけたのですが、
こちらを使ったことがある方はいらっしゃいますか？実際の使い心地や機能についても知りたいです。
Go言語で長さ0のスライスを作る方法を徹底解説！make関数とその代替方法の違いとは？

## はじめに 

Go言語でスライスを扱う際、長さ0のスライスを作成する方法としてよく使われるのが`make`関数です。しかし、Goでは`make`関数を使わない方法でもスライスを初期化できます。本記事では、それぞれの方法の違いや使用する場面について詳しく解説します。

## スライスの基本：スライスは何が特別なのか？

Go言語のスライスは、可変長の配列のようなものです。ただし、スライスには以下の3つの要素が含まれています。

1. **ポインタ**: 実際の配列データへの参照
2. **長さ**: スライス内の要素数
3. **容量**: 配列の最大要素数

これを理解した上で、長さが0のスライスを作成する方法を見ていきましょう。

## 方法1: make関数を使う

`make`関数を使うことで、長さが0のスライスを作成することができます。以下はその具体例です。

```go
package main

import "fmt"

func main() {
    s := make([]int, 0)  // 長さ0、容量0のスライスを作成
    fmt.Println(s)       // => []
    fmt.Println(len(s))  // => 0
    fmt.Println(cap(s))  // => 0
}
```

### 特徴
- **長さと容量を明示的に指定**できる。
- 内部的には空の配列を指すスライスが作成される。

`make`関数を使う場合、長さと容量を同時に指定可能なため、将来的に要素を追加する場面でも役立ちます。

## 方法2: リテラルを使う（makeを使わない）

もう一つの方法として、スライスリテラルを使って長さ0のスライスを作成することができます。

```go
package main

import "fmt"

func main() {
    s := []int{}          // スライスリテラルで長さ0のスライスを作成
    fmt.Println(s)        // => []
    fmt.Println(len(s))   // => 0
    fmt.Println(cap(s))   // => 0
}
```

### 特徴
- より簡潔で直感的。
- `make`関数と異なり、容量を指定することはできない。
- `nil`ではないスライスが作成される。


## 方法3: nilスライスを使う

特定の条件で、`nil`スライスも長さ0のスライスとして動作します。

```go
package main

import "fmt"

func main() {
    var s []int           // nilスライス
    fmt.Println(s)        // => []
    fmt.Println(len(s))   // => 0
    fmt.Println(cap(s))   // => 0
}
```

### 特徴
- メモリ割り当てが行われないため効率的。
- 要素を追加する際に内部で新たな配列が作成される。

## 各方法の違いを比較

| 方法           | 長さ | 容量 | メモリ割り当て | 特徴                                       |
|----------------|------|------|----------------|--------------------------------------------|
| make関数       | 0    | 任意 | あり           | 長さ・容量を明示的に指定可能              |
| スライスリテラル | 0    | 0    | あり           | シンプルかつ直感的                        |
| nilスライス     | 0    | 0    | なし           | メモリ効率が良いが、利用時に注意が必要    |

---

## どの方法を使うべき？

- **明示的な容量管理が必要**な場合 → `make`関数
- **簡潔さを優先**する場合 → スライスリテラル
- **効率性を重視**する場合（空の状態で保持） → nilスライス


## おわりに

Go言語で長さ0のスライスを作成する方法には、それぞれの特徴と利点があります。使用する場面や目的に応じて適切な方法を選ぶことで、効率的なコードを書くことができます。
Vimの設定ファイル(_vimrc)、私はこうしてる(初心者)


Vim は非常に強力なテキストエディタですが、初期設定のままでは使いにくいと感じることも多いでしょう。そこで、多くのユーザーは `.vimrc` (Windowsでは `_vimrc`) を設定して自分好みにカスタマイズしてるようです。

今回は、具体的な `_vimrc` の設定内容を解説しながら、快適な Vim 環境を作るためのポイントを紹介します。Windowsでvim を使うときはChocolatey（パッケージマネージャー）が必要

---

## 1. 基本設定

### 行番号を表示

```vim
set number "行番号を表示
```

コードの可読性を向上させるために、行番号を表示します。

### タブの設定

```vim
set tabstop=4 "タブ幅を4に設定
```

タブの幅を 4 スペースに設定し、インデントを統一しやすくします。

---

## 2. ファイル管理の設定

### バックアップファイルを作成しない

```vim
set nobackup " バックアップファイルを作成しない
set nowritebackup " 上書き時のバックアップファイルも作成しない
```

デフォルトでは、Vim はファイル編集時に `.bak` などのバックアップファイルを作成しますが、これを無効化することで、不要なファイルの作成を防ぎます。

### スワップファイルを無効化

```vim
set noswapfile " スワップファイルも作成しない
```

スワップファイルは Vim のクラッシュ時に復旧できる利点がありますが、環境によっては不要な場合もあります。

---

## 3. 検索関連の設定

### インクリメンタル検索

```vim
set incsearch " インクリメンタル検索 (検索ワードの最初の文字を入力した時点で検索が開始)
```

キーワードを入力すると即座に検索が始まり、目的の単語を素早く見つけることができます。

### 検索結果のハイライト表示

```vim
set hlsearch " 検索結果をハイライト表示
```

検索結果を視覚的に強調し、見落としを防ぎます。

### 検索の循環

```vim
set wrapscan " 検索がファイル末尾まで進んだら、ファイル先頭から再び検索
```

検索がファイル末尾まで到達した場合、自動的に先頭に戻って検索を続けます。

---

## 4. 便利なカスタマイズ

### Vi互換モードをオフ

```vim
set nocompatible " Vi互換モードをオフにし、Vimの拡張機能を有効化
```

Vim の豊富な機能を活用するため、Vi 互換モードを無効化します。

### Backspaceの動作を改善

```vim
set backspace=indent,eol,start " Backspaceキーの動作を通常のテキストエディタと同様に設定
```

デフォルトでは Backspace で削除できる範囲が制限されていますが、この設定により、より直感的な操作が可能になります。

### 入力中のコマンドを表示

```vim
set showcmd " 入力中のコマンドを表示
```

コマンド入力時に現在の入力内容を表示し、誤入力を減らします。

---

## まとめ

これらの設定を `_vimrc` に記述することで、より快適な Vim 環境を構築できます。

Vim の設定はカスタマイズ性が高く、用途に応じてさらに細かく調整可能です。自分の使い方に合った設定を試しながら、快適な Vim ライフを送りましょう！
【Linux】/etc/rc.d/rc.local is not marked excutable,skippingの解決法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3761139/be9c92d4-827a-5ab2-83ba-9c5ef35dcdfc.png)

# 現象
しばらく時間が経つと、仮想マシンのプロンプト画面に「/etc/rc.d/rc.local is not marked excutable,skipping」と表示される。

# 原因
/etc/rc.d/rc.localに実行権限がついていないこと。
実際に確認します。
```
#ll /etc/rc.d/rc.local
-rw-r--r--. 1 root root 474  1月 14 21:18 /etc/rc.d/rc.local
```
たしかに実行権限(x)がありません。

# 対処
/etc/rc.d/rc.localに実行権限をつける。
```
# chmod 755 /etc/rc.d/rc.local
```
⇒エラーとならないこと
```
# ll /etc/rc.d/rc.local
-rwxr-xr-x. 1 root root 474  1月 14 21:18 /etc/rc.d/rc.local
```
⇒「所有ユーザ」「所有グループ」「その他のユーザ」に実行権限(x)が付されたこと

▼参考URL
https://fullstacklife.net/linux/linux-rclocal-is-not-executed/
Unity(Android) Firebaseのgoogle-services.xmlが生成されない

# 環境

Unity6000.0.34f1
External Dependency Manager for Unity 1.2.183
Firebase App (Core) 12.4.1

# はじめに

コマンドラインでAndroidビルドするときに、google-services.xmlが生成されず、アプリ実行時にFirebaseの初期化できない問題があったのでメモ書き程度に残しておきたいと思います。
**Assets/External Dependency Manager/Android Resolver/Force Resolve**を手動で実行した時には以下の場所に生成されたので、これをスクリプトから実行できるかを調べました。

```
Assets/Plugins/Android/FirebaseApp.androidlib/res/values/google-services.xml
```

## 初期化できないときにでたエラー

```
Failed to read Firebase options from the app's resources. Either make sure google-services.json is included in your build or specify options explicitly.
```

# 手順

## 1. google-services.jsonをAssets/の中にいれる

そもそも、このファイルが無いと生成されないので一応確認します。

## 2. 自動Resolveをオフにしておく

**Assets/External Dependency Manager/Android Resolver/Settings**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188476/f4a9a2bc-011a-c910-16db-9861644f5a0e.png)

手動でResolveするので、Enable Auto-ResolutionとEnable Resolution On Buildをオフにしておく

## 3. ビルド前に以下の処理を実行する

```csharp
private static void ForceResolveGoogleService()
{
    PlayServicesResolver.ResolveSync(true);

    // Firebase の google-services.json から XML 生成
    GenerateXmlFromGoogleServicesJson.ForceJsonUpdate();
}
```
PHP学習者から見るJavaについて



## はじめに
私は普段PHPを使って開発をしていますが、今までよく聞くもののあまり触れたことがないJavaについて、この機会に仕様や違いを調べて言語の理解を深めてみました。


## Javaとは
「Write Once, Run Anywhere（WORA）」というスローガンを掲げたオブジェクト指向のプログラミング言語です。Java仮想マシン（JVM）によってどのプラットフォームでも実行できるので、Webアプリケーション開発以外にスマホアプリ開発等幅広く使用されています。

殆ど同じ時期に登場したのに、PHPはWebアプリケーション開発に特化しているのに対して、Javaは開発幅が広いのは意外でした。

## Hello,Worldしてみる
JDK（Java Development Kit）をインストールした上で、下記のコードをHelloWorld.javaに保存します。

 ```java:HelloWorld.java
public class HelloWorld { 
     //ここでメインメソッドを指定（プログラムが開始される）
    public static void main(String[] args) {
        // System.out.printlnはコンソールに文字列を出すためのメソッド
        System.out.println("Hello, World!");
    }
}
```

その後、HelloWorld.javaのファイルが保存されたディレクトリで下記のコマンドでコンパイルします。

```
javac HelloWorld.java
//このコマンドにより、同じフォルダ内にHelloWorld.class というクラスファイルが生成されます。
```

コンパイルが成功後、下記のコマンドでHello, World!と表示されます。

```
java HelloWorld
```

一方PHPだと、例えばHelloWorld.phpに下記のコードを保存します。

```php:HelloWorld.php
<?php
echo "Hello, World!";
?>
```

その後下記コマンドで表示することが出来ます。

```
php HelloWorld.php
```

PHPでは数行のコードで出力でき、コマンドもJavaと比べるとコンパイル分少ないので直観的に理解しやすいんだな、と気付きを得ました。

## 変数の宣言
他にも違いはあり、Javaは静的型付け言語なので、変数を宣言する際、データ型を指定する必要があります。

```
int num = 5;
string sample = “Hello”;
```

PHPは動的型付け言語なので、変数を宣言する際にデータ型を特に指定する必要がないです。

```
$num = 5;
$sample = “Hello”;
```

## プロジェクトの規模傾向
Javaは開発幅が広いと書きましたが、厳密なオブジェクト指向なので保守性が高く、セキュリティコントロールもしやすいため、傾向として大規模プロジェクトに使われることが多いです。オブジェクト指向自体が大規模プロジェクトに適しているのも理由として大きいでしょう。
PHPの場合、スピーディーに開発できるので小中規模のプロジェクトに使われることが多いです。

## まとめ
Javaがなぜ色々なところで使われているのか、それを理解できたので良かったです。また、Javaを知ることで、PHPについても改めて理解を深めることができました。



## 参考資料：
[The Java™ Tutorials](https://docs.oracle.com/javase/tutorial/)
[PHP マニュアル - Manual](https://www.php.net/manual/ja/index.php)

## 採用拡大中！

アシストエンジニアリングでは一緒に働くフロントエンド、バックエンドのエンジニア仲間を募集しています！
少しでも興味ある方は、カジュアル面談からでもぜひお気軽にお話ししましょう！

お問い合わせはこちらから↓  
[https://official.assisteng.co.jp/contact/](https://official.assisteng.co.jp/contact/)
AI-102 学習メモ (7) : Azure AI 音声を使用して音声を処理する

# はじめに
この投稿は AI-102: Microsoft Azure AI エンジニア の学習をした内容のメモです。

投稿の一覧は以下のリンク先にあります。

https://qiita.com/atsmin77/items/5235dfe16ad1bed065ca

# 前の投稿

https://qiita.com/atsmin77/items/018a7fe76c753f71455f


# Azure AI 音声を使用して音声を処理する

以下のような Azure AI 音声 サービスを実際に [Azure Speech Studio](https://speech.microsoft.com/portal) から利用してみます。
※ 新しい [Azure AI Foundry](https://ai.azure.com/explore/models/aiservices/Azure-AI-Speech/version/1/registry/azureml-cogsvc/tryout?tid=ac2852a6-88d6-4ddc-9a63-93391e191144#realtime)からも同様に利用できます。

| 名前 | 説明 |
|:-:|:-:|
|音声からテキスト|リアルタイムまたは非同期バッチ処理で音声をテキストに文字起こし|
|テキスト読み上げ|テキストを自然な人間のような音声で読み上げ|

https://learn.microsoft.com/ja-jp/azure/ai-services/speech-service/overview

## テキスト読み上げ

Speech Stdio から [テキスト読み上げ] - [音声ギャラリー] を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/57d9b702-9d8c-acf3-aae2-99a1ff0b3b43.png)

[言語] のプルダウンで 「日本語」を選択します。日本語に対応している音声が表示されます。同じ音声でも複数の話し方のスタイルが用意されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/e51044e2-88af-304e-adbd-9ca3300f57f1.png)

[試してみる] からテキストを入力して任意のテキストを読み上げることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/977a4882-b307-4f81-28d9-c487568e5f71.png)

https://learn.microsoft.com/ja-jp/azure/ai-services/speech-service/how-to-custom-speech-test-and-train

## 音声テキスト変換

[音声テキスト変換] - [リアルタイム音声テキスト変換] を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/1fd99179-26f8-b6ef-c04b-a2be0c44f6c5.png)

今回は以下のページ公開されているサンプルの音声データを使用させていただき試しました。

https://pro-video.jp/voice/announce/

プルダウンから言語を「日本語」に設定し、サンプルのオーディオファイルをアップロードします。右側に音声がテキストに変換された結果が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/c80258b6-8d52-a32a-183b-1315e9ca32d1.png)

::: note
**語句リスト** に専門用語などの単語を登録しておくと、テキスト変換の精度を向上させることができます。
:::

## 音声合成マークアップ言語 (SSML)

SSML を利用すると、音声の読み上げ方法を XML 形式で制御することができます。
読み上げ方法は **\<voice\> 要素**で指定します。

* style 属性：陽気、落ち着きなど、音声の感情表現方法を指定します
  * assistant
  * calm
  * chat
  * angry
  * sad
  * ...
* role 属性：男性、女性、声の高さなど、音声の年齢と性別を指定します
  * Girl
  * Boy
  * YoungAdultFemale
  * YoungAdultMale
  * ...

### SSML の例
```xml
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="ja-JP">
    <voice style="assistant" role="YoungAdultMale">
        ここに読み上げるテキストを記載します。
    </voice>
</speak>
```

https://learn.microsoft.com/ja-jp/azure/ai-services/speech-service/speech-synthesis-markup-voice#use-voice-elements

# 次の投稿

https://qiita.com/atsmin77/items/47afd9e2893a6f59ec8f
Reactでハマッた`&&`の罠　~JSとJSXを正しく理解しよう~

### **はじめに**

Reactでは、`&&`を使って条件付きレンダリングをすることがよくあります。  
しかし、`&&`の動作を誤解していると、**意図しない表示**につながることがあります。  
今回は、「`0`が表示される問題」を例に、Reactの`&&`の仕組みを解説します！

---


### **基本の`&&`の挙動**
`&&`（論理積）は、左側の値が`falsy`（`false`とみなされる値）の場合、左側の値をそのまま返します。  
**falsyな値の例**:
```javascript
false, 0, "", null, undefined, NaN
```

▼繰り返しですが、左側の値が`falthy`（`falthy`とみなされる値）の場合、左側の値を返します。

```javascript
console.log(false && "Hello"); // false
```

▼逆に、左側の値が`truthy`（`true`とみなされる値）の場合、右側の値を返します。

```javascript
console.log(true && "Hello");  // "Hello"
console.log(false && "Hello"); // false
console.log(0 && "Hello");     // 0
```

---

### **Reactでの条件付きレンダリング**
Reactでは、`&&`を使って要素を条件付きで表示することができます。

#### **✅ 一般的な例**
```jsx
const isLoggedIn = true;
return <div>{isLoggedIn && <p>ログイン済み</p>}</div>;
```
* ✅ `isLoggedIn = true` の場合 → `<p>ログイン済み</p>` が表示される  
* ✅ `isLoggedIn = false` の場合 → 何も表示されない  

     * これは、`false && <p>ログイン済み</p>` の結果が `false` になるためです。

---

### **❌ `0`が表示される問題**
#### **❌ 予想外の動作をする例**
```jsx
const itemCount = 0;
return <div>{itemCount && <p>カートに{itemCount}個の商品があります</p>}</div>;
```

💡 **期待する動作**  
- `itemCount > 0` のとき → `"カートにN個の商品があります"` が表示される  
- `itemCount === 0` のとき → **何も表示されないはず**

💥 **実際の動作**  
- `itemCount === 0` のとき、**`0` が表示される！！！**

---

### **🧐 なぜ `0` が表示されるのか？**
```javascript
console.log(0 && "Hello");  // 0
```
`0 && "Hello"` の場合、`0` は `falsy` なので `&&` の評価はここで止まり、**`0` がそのまま返る**。  

🛑 **ここで重要なのは、JSX のレンダリングルール！**  
| 値       | JSXでのレンダリング |
|----------|------------------|
| `false`  | 何も表示されない |
| `null`   | 何も表示されない |
| `undefined` | 何も表示されない |
| `0`      | `0` が表示される |
| `""`（空文字）| `""`（空白として） |

💡 JSX では `false` / `null` / `undefined` は **レンダリングされない** が、  
**`0` は普通の値としてそのまま表示される！**

つまり、`itemCount && <p>カートに{itemCount}個の商品があります</p>` の評価結果が `0` になるため、JSX 内で **`0` がそのまま表示されてしまう！**

▼React公式ドキュメントより引用
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909033/392ea617-2e6c-afe1-ebbf-37a10b5c6bdf.png)


---

### **✅ 正しい条件付きレンダリングの方法**
この問題を防ぐには、`0` をレンダリングしないようにする工夫が必要です。

#### **✅ 方法1: 三項演算子 (`? :`) を使う**
```jsx
return <div>{itemCount ? <p>カートに{itemCount}個の商品があります</p> : null}</div>;
```
💡 `itemCount === 0` の場合、`null` が返るため、何も表示されない。

---

#### **✅ 方法2: `Boolean()` で明示的に変換**
```jsx
return <div>{Boolean(itemCount) && <p>カートに{itemCount}個の商品があります</p>}</div>;
```
💡 `Boolean(0) === false` なので、`&&` の左側で評価が止まり、何も表示されない。

---

#### **✅ 方法3: `??`（Nullish Coalescing Operator）を使う**
```jsx
return <div>{itemCount ?? <p>カートに{itemCount}個の商品があります</p>}</div>;
```
💡 `??` は `null` や `undefined` の場合にのみ右側を評価するため、`0` の場合は影響を受けない。

---

### **💡 `if` 文の条件式の`&&`との違い**
実は、**if文の条件式の`&&`とReactの`&&`に違いはない**！  
どちらも「左側が`false`なら左側の値を返し、`true`なら右側の値を返す」だけ。

📌 **ただし、if文は`true`のときにブロックを実行するが、ReactのJSXは`&&`の結果をそのまま表示するため、`0`が表示されることがある。**  

---

### **まとめ**
✔ `&&` は「左側が`falsy`ならそのまま返し、`truthy`なら右側を返す」  
✔ JSX内では `&&` の結果がそのままレンダリングされる  
✔ `false` / `null` / `undefined` は JSX で **何も表示されない**  
✔ `0` は `falsy` だけど **JSX では普通の値として表示される！**  
✔ `? :` や `Boolean()` で意図しない表示を防ぐ  

▼`&&に慣れるための`問題集もあるので是非！

https://qiita.com/arunbababa/items/c5151d69ff698a2e22dd

---