OmniAICreator/Qiita-1.07M huggingface dataset:
SandoboxのHyperforceへの移行での障害　2024/12/7

**使っているクラウドなどの小ネタ Advent Calendar 2024 24日目**


前回と同じ現象ですが、エラーログにないんですよね。新しいインスタンスのIPアドレスが分からん

+ [AP0 インスタンスリフレッシュの影響【2023年11月20】](https://qiita.com/Keiji_otsubo/items/eb9f6b2faaa02c6446b3)

Apexのログ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/130f5f24-cff7-6351-f2ca-e0b9b7cb940f.png)

今回は503エラーなのでApachのログに出てこないのかな？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/1327a0c9-d3b4-7b11-c3fc-a7259b9091bb.png)



/etc/apache2/apache2.conf

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/cead7613-fb6e-53ea-ba5f-3038fcf95bcd.png)

+ [Salesforce インスタンスの場所](https://help.salesforce.com/s/articleView?id=000396845&type=1)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/f635424e-691a-1b53-9857-62c2f7798f93.png)


+ [ドメイン/IPアドレス サーチ 【whois情報検索】](https://www.cman.jp/network/support/ip.html)


前回エラーメッセージが返るようにしたところに追加しておきます。
しかし画面には出てこないのが...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/ef555601-3dc9-01f4-ccd1-a4b9a041a1a2.png)

新しいインタンスのIPアドレスが分からないので、HyperforceのIPアドレスを指定した方がいいかもしれません。
ただ今のapache2の設定の書き方だとIPの指定ができませんね。

### Apache 2.4 以降では Require ディレクティブを使ってアクセスを許可するか拒否するかの設定を記述します。

+ [Requireディレクティブ：アクセスの許可や拒否などのアクセス制限を行う](https://www.javadrive.jp/apache/allow/index1.html)
+ [ApacheでIPアドレスによる制限を設定する方法を解説【Webサイトへのアクセスを制限する】](https://engineer-ninaritai.com/apache-ip-restrict/)

社内のApacheで確かめたら以下の書き方で大丈夫みたい

```
ScriptAlias /test/ "/var/www/test/"
<Directory /var/www/test/>
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all denied
    Require ip 192.168.0.0/24
</Directory>
```

+ [サブネットマスク早見表](https://www.ahref.org/subnet.php)
GoのslogでOpenTelemetryのログを出す

## はじめに
OpenTelemetryではログ出力は既存のログライブラリに乗っかるという方針で、ログ出力ライブラリ用のブリッジが[contrib](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/bridges)リポジトリにあります。slogでもログを出力することができます。

OpenTelemetryでログを出力することの何が良いかというと、Traceと関連付けてログを出力できることです。一般的なバックエンド（Datadogなど）であれば特定のTraceを表示すると関連付けられたログだけを表示することができます。

GoのLogのステータスはBetaです。まあOpenTelemetryを使っているような人はBetaでも気にせず使う気がします。

## 設定

### otel側の設定
```go
// resourceはどこかで定義されているものとする
resource := getResource()

// 面倒なのでautoexportを使います
// go.opentelemetry.io/contrib/exporters/autoexport
logExporter, err := autoexport.NewLogExporter(ctx)
if err != nil {
    return nil, err
}

// ログレベルをminsevで指定
// go.opentelemetry.io/contrib/processors/minsev
severity = minsev.SeverityDebug

// sdklog "go.opentelemetry.io/otel/sdk/log"
lp := sdklog.NewLoggerProvider(
    sdklog.WithResource(resource),
    sdklog.WithProcessor(
        minsev.NewLogProcessor(
            sdklog.NewBatchProcessor(logExporter),
            severity,
        ),
    ),
)
// go.opentelemetry.io/otel/log/global
global.SetLoggerProvider(lp)
 ```

設定時にminsevを使わないとログ出力レベルが変更できません。slogのログ出力レベルは無視されます。

### slog側の設定

```go
logLevel := slog.LevelDebug
logger = slog.New(
    // stdoutにも出てほしいのでslog-multiを使う
    // slogmulti "github.com/samber/slog-multi
    slogmulti.Fanout(
        // go.opentelemetry.io/contrib/bridges/otelslog
        otelslog.NewHandler("slog-test"),
        slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
            Level: logLevel
        }),
    ),
)
slog.SetDefault(logger)
```

 ## ログ出力
 
 ```go
 slog.InfoContext(ctx, "hoge")
 ```

注意点として、Contextに関連付けられたTraceが終了しているとログが出力されません。

 これでTraceとLogが関連付けられた状態でDatadogなどで表示することができます。ローカルだとAspire Dashboardかotel-tuiが確認しやすいです。
【JavaScript】フォームの submit メソッドが上書きされる原因と解決方法

#### **エラー内容**
```HTML
<script language="javascript">
  document.write(
    '<input type="button" ' +
    'onClick="formChange(this.form, \'hogehoge\')"' +
    'value="入力欄を増やす">'
  );
</script>
<noscript>
  <a href="hogehoge">入力欄を増やす</a>
</noscript>
```
上記のように、押すたびに入力欄が増えるように設定したところ
ボタンが動かず、開発ツールに下記エラーが出ていた。

:::note alert
**Uncaught TypeError: frm.submit is not a function**
at formChange (XXX)
at HTMLInputElement.onclick (XXX)
:::

このエラーは、HTML内で `id="submit"` または `name="submit"` を使っているときに発生する。

これにより、フォームの `submit()` メソッドが上書きされ、JavaScript から `form.submit()` を実行しようとするとエラーが出る。

---

### **原因**

#### 1. `id="submit"` または `name="submit"` の影響 
   JavaScript では、HTML の `id` や `name` 属性で指定した名前が自動的にグローバル変数として登録される。

   今回の場合、同HTML内の送信ボタンが下記のように
   idがsubmitになってしまっていた。

   ```html
   <form id="myForm">
       <input id="submit" type="submit" value="送信">
   </form>
   ```

   これだと、`submit` はグローバル変数として定義され、フォームの `submit()` メソッドを隠してしまう。
結果として、JavaScript から `myForm.submit()` を呼び出すと、`submit` が関数ではないと解釈されてエラーになる。

#### 2. `document.write()` の使用
   サンプルコードでは `document.write()` を使っているけど、これはモダンなブラウザでは避けるべき方法。これも改善が必要。

document.write() はページの読み込み中にのみ動作し、他の DOM 操作との競合が生じる可能性がある。
（しかし、今回はこの書き方を業務内で使用していたため、変更不可。）

---

### **解決方法**

#### 1. `id` や `name` の変更
   `submit` の代わりに別の名前を使う。例えば、`btnSubmit` などに変更すると問題が解決する。

   ```html
   <form id="myForm">
       <input id="btnSubmit" type="submit" value="送信">
   </form>
   ```

#### 2. `document.write()` を廃止
   `document.write()` を使わず、代わりに DOM 操作を使ってボタンを動的に追加する方法に変更する。

---

### DOM操作とは
**`DOM操作`**（Document Object Model 操作）とは、
WebページのHTML要素をJavaScriptで動的に変更・操作すること。
これにより、ページの内容をリアルタイムで更新したり、新しい要素を追加したり、ユーザーのアクションに応じて反応させることができる。

例えば、ボタンを追加したり、クリックされたときに何かを表示したりすることができる。
`document.getElementById`で要素を取得し、`innerHTML`で内容を変更したり、`appendChild`で新しい要素を追加したりできうｒ。

DOM操作は、ページ全体を再読み込みすることなく、必要な部分だけを変更できるため、ユーザーにとってよりインタラクティブな体験を提供できる。

DOM操作を使うとできること：
- **HTML要素の取得**: ページにある要素（例えば、ボタンや入力フィールド）をJavaScriptで取得。
- **要素の変更**: 取得した要素の内容や属性を変更（例えば、ボタンのラベルを変更）。
- **要素の追加・削除**: 新しい要素をページに追加したり、既存の要素を削除したりする。
- **イベントの設定**: ユーザーの操作（クリックや入力）に反応するようにイベントを設定。

例えば、`document.write()` ではなく、DOM操作を使って動的にボタンを追加する場合、次のようになる：

```html
<script>
  // 新しいボタン要素を作成
  var button = document.createElement("input");
  button.type = "button";  // ボタンのタイプを設定
  button.value = "入力欄を増やす";  // ボタンのラベルを設定
  
  // ボタンがクリックされた時に実行する関数を設定
  button.onclick = function() {
    formChange(this.form, 'hogehoge');
  };
  
  // ページにボタンを追加
  document.body.appendChild(button);
</script>
```
---
「他者の助けを借りよう」クラウド移行準備のエピソード

:::note info
この記事は [アイスタイル Advent Calendar 2024 10日目](https://qiita.com/advent-calendar/2024/istyle) の記事です。
:::

# はじめに
アイスタイルでWebアプリケーションエンジニアをやってます、itohisです。
ふと気がついたんですが、昨年もアドカレ10日目に執筆をしていました。今年もよろしくお願いします。
私は今年もクラウド移行業務に関わる事が多くありました。
今回はそんな中でWEBアプリケーションをオンプレミスからクラウドへ移行リリースするにあたり、他チームの助けを借りて相談・準備をしておいて良かったお話をします。

# クラウド移行はわからないことだらけ🌩️
アイスタイルでは段階的にクラウド移行を進めていて、アプリケーションエンジニアが比較的広い範囲に責任を持ってクラウドリソースを構築します。 特別にAWSのスキルが高くなくても、皆「やったるで！」の精神で開発を進めるため、ぶっちゃけると本当にわからないことも多いです。

今回の私の担当はフロントエンドアプリケーション、つまり＠cosmeユーザーが利用する、とある画面を表示するシステムのクラウド移行でした。
このシステムはリクエスト経路上にオンプレミスのネットワークを経由していて、AWS Direct Connectというオンプレとクラウドをつなぐ専用線の利用が必要になることがわかりました。
組織内では既にDirectConnect利用の実績があり、契約している帯域制限があります。
この帯域制限により、クラウド移行リリースのタイミングで通信量が急増して通信量が上限に達し、通信ができなくなってしまう恐れがありました。
もし通信ができなくなれば、他のシステムにも大きく甚大な影響が出ると考えられます。
さて、こうなればリリース前に通信量増加の予測しておきリスクを回避したいですが、
**通信量の監視方法がまったくわからない！**

困ったなあ、という所でしたが幸いにもアイスタイルにはクラウド領域に特化したサポートチームが存在するので、今回はここに頼りつつ解決することにしました。

# 知らないことは知っている人たちに相談しよう👂️
私は一人で長時間悩みがちなのが悪いところですが、本当に相談してよかったです。
やはり、専門外の部分は専門家に相談してみるべきでした。

相談の結果、リリース前のクラウドリソースに通信量の負荷をかけて計測し、通話しながら同時監視していただけることになりました。
あまり具体イメージがつかないかもしれないので、例を紹介します。
以下のような形で計測しました。

実際にユーザーからのアクセスされた場合と同等、もしくはそれ以上負荷シナリオを作成します。
これをJMeterなどの負荷試験ツールで一定時間継続してリクエストする形で負荷を掛け続けます。

```
◆ 計算例
秒間リクエスト数 × 1Reqeustあたりの通信量 × 通る回数 x 8(ビット換算)
例）10 × 200KB x 2回 x 8 = 通信量は 32Mbps
```

- 通信量はSSR(サーバーサイドレンダリング)されたレスポンス容量から計算、リクエスト容量は軽微なので無視
- 通信量計算はビットで取り扱うのでバイトから換算します
- 「通る回数」は、オンプレ⇔クラウド間を往復するのは1度ではなかったので、その回数

以上の点などを考慮しながら、複数パターンを想定しました。
1シナリオにつき短くても600秒(10分)などの時間がおすすめです。(理由は後述)

# サポートしてもらって判明したこと💡
実際に試験を行うと、きれいな予想通りの通信使用量グラフが出ました。
「これだけやれば安心かな」と私もサポートチームも納得のいく形に落ち着きました。

![dc_up.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572621/3587456c-b086-b580-369a-eb5905428e87.png)

※監視はNewrelicによって行っています
実際の通信量は伏せますが、10分間 × 4度のシナリオを実施し、4つの山ができています。
予想通りの結果が得られました。

結果だけでなく専門チームと通話しながら進めることで以下のようなことがわかりました。

### 通信量の監視方法を教えてもらった
私が問い合わせた段階で、実は通信量を監視するダッシュボードの用意がありました。
どうしましょう...と相談したら「実はそれ見れるようになってますよ」っと教えてもらいました。
調べることも大事ですが、専門化にまず聞いてみるというのも場合によっては有効です。

### 帯域制限は上りと下りと別の回線制限がある
帯域制限と聞いて、私は勝手に上り下りの容量の合算だと思い込んでいました。
自宅のネット回線と同様に上り下りがあり、それぞれの制限が独立していて試算より余裕があることがわかりました。
よくよく考えたら当然でしたが、相談しなかったら試算を見誤るところでした。

### 試験実施時間は長いほうが良い(10分以上)
監視ツールではリアルタイムに通信量のメトリクスが監視できますが、表示まで5分程度のラグがありました。
これを前提に進行するのが重要で、10分以上の実行で、かつインターバルも5分程度設けます。
これで非常に監視がわかりやすくなりました。

実は試験1回目はスムーズに進行せず、2回目の実施でグラフのようなきれいな結果が測定できました。
この結果を元に安心してリリースに挑むことができました。
リリース後の通信量も概ね負荷試験通りの結果となりました。

# 相談のすすめ🤝
他者と相談することで一人では気づかない懸念点や新しい工夫が見つかります。
私は **「三人寄れば文殊の知恵」** という言葉が好きなのですが、まさにこれだと感じました。
わからないことにチャンレジすることも重要ですが、時には他者を頼ることで解決する課題もあります。
「話すの億劫だけど、俺も相談してみよっかな～...」という方の助けの一歩になれば嬉しいです！

本日の記事は以上となります。
引き続き [アイスタイル アドベントカレンダー 2024](https://qiita.com/advent-calendar/2024/istyle) をお楽しみください！
python一筋3年がA Tour of Goで詰まったこと

## この記事 is 何
いつもはPythonを使用して機械学習やデータ分析を行っています。
最近後輩がGoを使いだしたらやめられないと言っていたのでGoのチュートリアルを受けてみることにしました。


https://go-tour-jp.appspot.com/list

というわけで、Pythonとの違いや詰まったところをまとめていこうと思います。

## TL;DR
以下の部分で詰まりました。
- ポインタ
- 型宣言
- 使用しない変数を許さない

## ポインタ
C言語などでポインタは出てくると噂でしたが、Goでも出てくるとは。。。
避けては通れないですね。

ポインタは値のメモリアドレスを示すもので、以下のようにして使用します。

```go
i := 42
p := &i 
fmt.Println(*p) //42
```

pythonでは基本的に変数などは参照渡しですが、Goではポインタを用いることで参照渡しをすることができるらしいです。

こちらの記事がわかりやすかったので、メモしておきます。

https://qiita.com/Sekky0905/items/447efa04a95e3fec217f


## 型宣言
でた。。型宣言。。
Pythonは自動で推論してくれるから楽ですよね。

なんでいちいち書かなきゃいけないんだって思うけど、多くのエンジニアは型がないと気持ち悪いって言いますよね。。

見慣れない表記だったのは、型だけ宣言して初期化しなかったときにゼロ値が与えられることです。

```go
func main() {
	var i int
	var f float64
	var b bool
	var s string
	fmt.Printf("%v %v %v %q\n", i, f, b, s)
    // 0 0 false ""
}
```

## 使用しない変数を許さない
この機能はpythonにも実装してほしいなと思いました。
（すぐコードを散らかしてしまうタイプなので、、、）

Goは使用しない変数があるとビルドできません。
例えば先ほどのコードに変数tを含めておくと`declared and not used`というエラーがでます。

```go
func main() {
	var i int
	var f float64
	var b bool
	var s string
    var t string
	fmt.Printf("%v %v %v %q\n", i, f, b, s)
    // declared and not used: t
}
```

使用していないインポート等も同様にエラーがでるので、コードの可読性が強制的に上がりますね！

## まとめ
A Tour of Goを通して、Pythonでいかに楽してきたかがわかりました。

型宣言などは最近Pythonの関数等で使用している人も増加していたり、参照渡しを行っていると意識できたりと、Pythonの理解度も深まった旅でした。

また、使わないインポートなどはPythonでも整理しようと思います（笑）
Linear Regression With Time Series tutorial 解説 part2

https://www.kaggle.com/code/ryanholbrook/trend

に関する解説と感想を書いていきます。

ここでの時系列データの例としてよくでてくるものは、株価のデータでしょう。とくにはある企業の株価ではなく何らかの指数などを見るとノイズが減り、わかりやすく解析できると思います。

Moving Average:移動平均
株でいうと25日線と75日線の話がよく出ます。

DeterministicProcess:データをN次関数で近似

trendはrandom forestやXGBoostでは学習できません。
でーたの差分を取って、その差分を学習したり
trendを認識するモデルと組み合わせて学習してください。
研究室訪問のすすめ：大学生だけの特権を最大限活用しよう

## はじめに
大学1、2年生のみなさん、「大学生にしかできないこと」と聞かれたら、何を思い浮かべますか？
学祭で模擬店を出すこと、サークルの仲間と夜遅くまで遊ぶこと、はたまた自由な時間を使って旅行すること？答えはさまざまでしょう。

でも、私が挙げるとすれば「今行われている研究にアクセスすること」です。大学生の皆さんには、研究の最前線に触れる特別なチャンスがあります。それを活用せずに過ごしてしまうのは、あまりにももったいない！この記事では、そんな大学生活の特権を活用する第一歩として、**研究室訪問**をおすすめします。

## 大学という「知の宝庫」の価値
まず、みなさんは知っていますか？大学のキャンパス内であれば、ほとんどの論文に無料でアクセスできることを。
実はこれは、大学が高額なライセンス料を支払っているおかげです。大学の外に出た瞬間、同じ論文を読むには莫大な費用がかかることも珍しくありません。例えば、1本数千円する論文や、購入自体が不可能な場合もあります。

さらに、大学図書館には膨大な量の書籍や資料がそろっています。これも、卒業後は自由に使える環境ではなくなります。社会人になれば、図書館で探しても読みたい本がない、あるいは取り寄せるのに時間がかかる、なんてことが日常茶飯事です。

加えて、大学の最大の資源は、**研究の最前線にいる先生方**です。先生方に直接話を聞けるのは、学生という立場ならではの特権。卒業して社会に出てから、「あの分野の研究者に質問したい！」と思っても、メールを送って返事をもらえる可能性は非常に低いのが現実です。しかし、学生である間は、先生から「いつでも質問に来ていいよ」と声をかけてもらえることさえあります。このような特権、学びたいと願う多くの社会人が羨むものです。

## 大学はいらない？ その考えにどう答える？
最近、「大学なんていらない」という声を耳にすることがあります。その主張の裏には、「講義の内容は独学でも学べるから、大学に行く必要はない」という考え方があります。確かに、インターネットを活用すれば、講義内容を自学自習することも可能でしょう。

でも、大学の本当の価値は「講義」に限ったものではありません。大学は、「研究の最前線にアクセスできる」という広義の学びの場です。

大学生の皆さんには、自由にアクセスできる知識の宝庫があります。そして、その場を最大限活用できるのが**研究室訪問**なのです。

## 研究室訪問を始めるには？
- **興味のある研究室を見つける**
まずは大学のホームページや教授の研究概要を調べて、興味のある研究室をリストアップしましょう。どの研究室に行くべきか迷ったら、自分が関心を持っているテーマやキーワードから探してみるのがおすすめです。

ちなみに私は1年生のとき、物理学科のほとんどの研究室を訪問しました。訪問を通じて、先生方がどんな研究をしているのかを知ることができて、とても刺激的で良い経験でした。

また、自分の学科だけでなく、他の学科の研究室にも訪問してみるのも良いアイデアです！実際、私は経済学部や工学部の研究室にも訪れました。自分の専門分野から一歩踏み出してみると、新しい視点や発見が得られるかもしれません。

- **メールや訪問でアポイントを取る**
研究室訪問をする際には、事前にメールでアポイントを取るのが基本です。丁寧な言葉で、自分が訪問したい理由や興味を伝えましょう。メールの書き方がわからない場合や不安な場合は、ぜひ相談してください！メールの文例などもお教えできます。

また、研究室訪問は意外と気軽にできるものです。直接研究室を訪ねてみるのも一つの方法ですが、アポイントを取るほうがスムーズに話を聞ける可能性が高いです。

⭐️さらに、多くの**先生方は学生の訪問を非常に歓迎**しており、質問に対してもとても親切で丁寧に答えてくれます。ですので、緊張せずにまずは一歩を踏み出してみましょう！
先生方は研究内容を詳しく説明するだけでなく、学生が興味を深められるよう配慮してくれることが多いので、恐れる必要はありません。

- **質問を用意していく**
訪問時には、研究内容や教授に聞きたいことを事前に考えておきましょう。例えば、「この研究がどのように応用されるのか」「普段どんなデータを扱っているのか」など具体的な質問があると会話が深まります。

## サポートします！
もし研究室訪問に関して相談したいことがあれば、いつでも連絡してください！メールの書き方から、訪問の準備に関する具体的なアドバイスまで、できる限りお手伝いします。

連絡は、**Discord**または [**X（旧Twitter）**](https://x.com/quantum_walker "X")のDMで受け付けています。お気軽にご連絡くださいね！

## おわりに
研究室訪問は、大学生活をより豊かにするための大きな一歩です。他学科や異なる分野の研究室を訪れることで、学びの視野をさらに広げることができるはずです。あなたもぜひ挑戦してみてください！

あなたの一歩が、これからの学びをさらに豊かにすることを願っています！
Mac版DBeaverでpg_dump、pg_restoreした記録

# はじめに

Gakken LEAPのエンジニアのnishidaです。

今までMySQLばかり使っていたので、GUIツールはSequel Aceばかり使っていましたが、今回初めてDBeaverを使ったところかなりハマってしまったので、原因と対応方法を残しておきたいと思います。

# 概要

今回の唯一にして一番のどハマりポイントはDBeaverの「クライアントのホームが接続用に指定されていません」というエラーが意味不明だった点につきます。
このエラーで困っている人を一人でも多く救えればと思い記事にしました。

![qiita_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954249/b841865b-b7fc-5bc1-2778-605f72683b96.png)

# 一応原因の解説

DBeaverをデフォルトでインストールした状態だと、SELECTやUPDATEなどの一般的なSQLコマンドは利用出来るので「クライアントツールも入っているんだ」という認識でした。そもそも、初めてPostgresqlに接続をした時にプラグインのインストールも走りますし。
しかし、実際はダンプ、リストアコマンドであるpg_dump、pg_restoreはこの時にインストールされていないようです。
原因がわかれば対応は簡単で、コマンドをインストールして、DBeaverに設定してやればいいだけです。

というわけで、以下インストールからダンプ、リストアの手順までを解説します。

# 具体的な手順

## コマンドのインストール＆設定

1. pg_dumpなどのコマンドのインストールは下記のURLが詳しいので、手順通りにlibpqをインストールする
  参考URL：https://zenn.dev/bisque/scraps/d97952787f8d33
2. DBeaverのサーバのコンテキストメニューを表示して接続の編集を選択
![dbeaver_1_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954249/647758a4-9978-a1bc-6710-103f3b8ce1aa.png)
3. 接続設定→一般タブ→ドライバの設定を編集をクリック
![dbeaver_1_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954249/fb31773b-cad7-9594-b2c2-442be6413c28.png)
4. ドライバの編集ウィンドウが開くので、ネイティブクライアントタブを開く
![dbeaver_1_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954249/5bc89696-5077-60a0-dd69-fc612acb5e91.png)
5. ホームを追加をクリックして、手順1でpg_dumpをインストールしたフォルダを選択
  →ここで「/opt」とかの特殊なフォルダは「Command + Shift + .」を押さないと表示されないので注意です
6. OKをクリックしてホームの追加とドライバの編集を閉じる

これで、DBeaverの「クライアントのホームが接続用に指定されていません」というエラーが解消されます！

## バックアップ手順

以下、具体的なバックアップの作成手順について記載しますが、ダイアログに従ってぽちぽちボタンを押すだけです。

1. DBeaverでバックアップを取りたいデータベースのコンテキストメニューのツール ＞ バックアップをクリック
![dbeaver_2_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954249/a6381835-3331-e918-8eb9-aa9ce8d56691.png)
2. exportのウィンドウが表示されるので、Objectsでpublicを選択
　→下に全てのテーブルがチェックされた状態になる
![dbeaver_2_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954249/d3a9b661-eb43-053e-7d69-2611a1b809a4.png)
3. 「Next」をクリックして、次の画面で出力先を選択
![dbeaver_2_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954249/71dc47cb-afe6-1ab6-deb1-db83de169223.png)
4. 「開始」をクリックすると、指定した出力先にバックアップのsqlが出力される

## リストア手順

以下、バックアップ手順で取得したバックアップを使ったリストア手順について記載します。

1.リストア対象のDBの下にあるpublicスキーマを削除するなど空にしておく
2.バックアップをリストアしたいデータベースのコンテキストメニューのツール ＞ リストアをクリック
![dbeaver_3_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954249/bf65f7de-c415-2689-b168-3686e615e093.png)
3. Backup fileでバックアップしたsqlファイルを選択
　→ファイル種別でsqlに変更しないと選択出来ない
![dbeaver_3_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954249/283665fd-2ab2-d689-2c50-5c79cb3c3a3c.png)
4. 「開始」をクリックするとリストアされる

# 最後に

気がつけばなんてことはないのですが、ズバっとこの答えにたどり着ける情報がなく、また「どの画面のこと言っているの？」ということも多くて結構苦戦しました。
どなたかの役に立てば幸いです。

## エンジニア募集

Gakken LEAP では教育をアップデートしていきたいエンジニアを絶賛大募集しています！！
ぜひお気軽にカジュアル面談へお越しください！！

https://gakken-leap.co.jp/recruit/
ちょっとした積み重ねが育児と転職活動の両立を助けてくれた

# 概要
今回の転職活動は育児との両立でした。
独身時の転職活動と比較すると、かなり時間の制約があるなかで、ちょっとした自身の活動が転職活動を有利にしてくれたので、備忘録として残そうと思います。
また、これをやっておけばよかった　と思ったことも書きたいと思います。

# TL;DR
- 技術ブログは低頻度でもいいから**継続**して発信しよう
- 勉強会に参加したり開催したりしよう
- プロジェクトメンバーに自分の評価(どう見ているのか)を聞いておこう
- アルゴリズム系は勉強しておこう

# 育児の隙間時間で転職活動
履歴書作成や職務履歴書の作成
企業によっては入社課題的(コーディングテスト)なものを実施する必要があるなど、やるべきことが山積みです
独身時代は休日や終業後にやっていましたが、子供がいたらそうはいきません
極力、定時に上がってそこから、子供の遊び相手をして気づけば22時
求人内容に目を通せればいい方です
休日は基本的に対応しているので、子供が朝寝や昼寝をしている2時間程度の時間が取れれば良い方です
時間はないが、できることは精一杯して悔いのない転職活動にしたかったので、以下の点を気をつけました
1. しっかりと短時間で集中してタスクを終わらす
2. 企業ごとの優先順位をしっかりと定めて無駄にエントリーしない

# やっておいてよかったこと
今回の転職活動で全体的に評判が良かったことを書きます
これは別に転職活動を有利に進めるためにやっていたわけではなく、なんとなくやっていたことが功をそうしたことです
## 技術ブログの継続的発信
私は今年の3月から月一のペースでQiitaに技術ブログを書いていました。
面接頂いた全ての企業で良い評価を頂きました。
おそらく更新頻度よりは、継続性の方を評価して頂いたのかなと思ってます。

面接の質問で「なぜ技術ブログを書いているんですか？」という質問が多かったです。
自分的には以下の目的がありました
- inputした内容をまとめてoutputすることで理解内容を整理できて、逆に理解できていない部分が分かる
- 自分が悩んだ内容は世界中のどこかに同じ内容で悩んでいる人がいるはず
- 外部リソースとして(同じ内容で困った時の引き出しとして)
## 勉強会の開催/主催
社内で率先して研修をやってきました
社内のメンバーで講師ができそうな人を見つけて、講師をお願いする感じです
僕は講師の準備系を担当して、当日のアテンド等もやったりしてました
もちろん、私自身が講師をしたこともあります

能動的に組織のスキルを高める活動をしていたのを評価して頂いたのかなと思ってます

## プロジェクトメンバーから見た自分の評価を知る
面接を受ける前にプロジェクトメンバーで飲んだ際に「僕の仕事ぶりだったり、〇〇さんから見てどんな評価ですかね」と聞きました。
この聞いた内容が本当の意味で第三者評価を得ることができて、よかったと感じてます

今回の面接で何回か「あなたは周りからどんな評価/自分だと思われていますか？」と聞かれたことがありました。
この質問が来た時にプロジェクトメンバーに聞いていて良かったと思いました。
自分の評価と第三者者からの評価が一致していれば尚よいですね

# やっておけばよかったこと
以下2点かなと思います
- アルゴリズム
- ソフトウェアアーキテクチャ

## アルゴリズム
一定の企業では、コーディングテストを実施ことがあります
僕はアルゴリズム系を一切勉強してこなかったのでコテンパンにされました
実務で絶対に使う！ということではないですが、少し勉強しても便利な発見が結構あったので、中長期的に少しずつ勉強してもいいかもですね
- [leetcode](https://leetcode.com/)
- [書籍](https://gihyo.jp/book/2022/978-4-297-12521-9)

## ソフトウェアアーキテクチャ
全体の思想をどう考えるか、フォルダ構成をどうするかを決める場面もありました
自分自身でしっかりと考えるためにも、知識は必要だなと思いました。
自分で考えて決定しないと、面接で質問された時につみますからね
- [ソフトウェアアーキテクチャの基礎](https://www.oreilly.co.jp//books/9784873119823/)
- [デザインパターン](https://www.techscore.com/tech/DesignPattern/)

# 最後に
育児が始まると中々自分の時間が取ることが難しいですが、少しの時間でちょっとずつ活動していけば、良いことがあるんだなと思いました。

転職活動の一環でやってしまうと、途中で止めてしまうかもしれないので、楽しみながら趣味の一環として継続していきたいですね。
## 独り言
転職回数としては今回を含めて2回目なのですが、独身時の転職活動より遥かに忙しい状態ではありましたが、妻や周りの人達の支えがあってなんとか、両立出来ました
上には書いていませんが、どうしても時間が欲しい時は妻に転職活動時間をもらってました。。
インフラの基礎知識

## **インフラ基礎知識まとめ**

### **1. DNSの仕組み**
- **階層構造**:
  - ルートDNS → TLD（例: `.com`, `.jp`）→ 権威DNSサーバー。
- **DNSレコードの種類**:
  - **Aレコード**: ドメイン名 → IPv4アドレス。
  - **AAAAレコード**: ドメイン名 → IPv6アドレス。
  - **CNAMEレコード**: ドメイン名 → 別名（リダイレクト）。
  - **MXレコード**: メールサーバー指定。
- **DNSSEC**:
  - デジタル署名を使ってデータの改ざんを防止。

---

### **2. HTTPSと暗号化**
- **TLS/SSLの仕組み**:
  - 公開鍵暗号で共通鍵を安全に交換。
  - データの暗号化は共通鍵暗号方式を使用。
- **ハイブリッド暗号化**:
  - 公開鍵暗号（鍵交換）＋ 共通鍵暗号（データ通信）。
- **ECDHEとRSAの違い**:
  - ECDHE: 完全前方秘匿性を持つ（過去の通信を解読されない）。
  - RSA: サーバーの秘密鍵が漏れると過去の通信も危険。

---

### **3. Webサーバーとリバースプロキシ**
- **Webサーバーの役割**:
  - 静的ファイルの配信。
  - 動的リクエストのアプリケーションサーバーへのルーティング。
- **リバースプロキシのメリット**:
  - 負荷分散。
  - バックエンドサーバーのIP秘匿。
  - HTTPS終端で通信コストを軽減。
- **負荷分散の方法**:
  - ラウンドロビン方式: 順番に振り分け。
  - 最小負荷方式: 負荷が軽いサーバーを優先。
  - IPハッシュ方式: クライアントIPを基に振り分け。

---

### **4. プロキシサーバーとリバースプロキシサーバー**
- **プロキシサーバー**:
  - 社内ネットワークから外部への通信を中継。
- **リバースプロキシサーバー**:
  - 外部からの通信をバックエンドサーバーに中継。
- **DMZ配置**:
  - 両者ともDMZ（非武装地帯）に配置し、セキュリティを強化。

---

### **5. その他セキュリティと効率化**
- **セッション再利用**:
  - セッションIDやチケットを利用して再接続を高速化。
- **キャッシュ**:
  - 静的ファイルをWebサーバーやCDNでキャッシュして、応答速度を向上。
API Best Practices ~リードリクエストにフィールドマスクを含める , 一貫した読み取りを可能にするためにバージョンフィールドを含める

## リードリクエストにフィールドマスクを含める
GetやListなど読み取り専用のリクエストにフィールドマスクを含めることを推奨します。

- 推奨される方法:
  - google.protobuf.FieldMask を使用します
  - FieldMaskUtil (Java/C++) ライブラリを使用して、プロトを自動的にフィルタリングできます

- 代替案:

  - 代替案1:
    - 読み取りたいフィールドごとに boolean フラグを持つメッセージを定義します
  - 代替案2:
    - 読み取りたいフィールドのタグ番号をリストするメッセージを定義します

- 利点:
  - クライアント側で明確な期待を設定できます
  - クライアントが必要なデータ量を制御できます
  - バックエンドはクライアントが必要なデータのみフェッチできます

- 欠点:
  - すべてのフィールドを常に設定する必要があるため大きくなるにつれてコストが高くなる
  - フィールドマスクが暗黙的 (宣言されていない) であり、メッセージを設定したメソッドによって異なる場合は最悪の失敗
      - このアンチパターンは、レスポンスからローカルキャッシュを構築するクライアントでデータ損失が発生する原因となります

## 一貫した読み取りを可能にするためにバージョンフィールドを含める

クライアントがオブジェクトの書き込み後に同じオブジェクトの読み取りを行う場合、たとえ基盤となるストレージシステムにとって合理的な期待でなくても、書き込んだ内容が返ってくることを期待します。

サーバーはローカル値を読み取り、ローカルの version_info が期待される version_info より小さい場合、リモートレプリカから最新の値を読み取ります。通常、version_info は、ミューテーションが行われたデータセンターとコミットされたタイムスタンプを含む文字列としてエンコードされたプロトです。
https://qiita.com/bushiyama/items/47a7368b98dbb94feffe

一貫性のあるストレージでバックアップされているシステムであっても、すべての読み取りでコストがかかるのではなく、より高価な読み取り一貫性のあるパスをトリガーするトークンが必要な場合もあります。
Gmail 抽出＆ラベル移動

Gmailで受信したメールでお気に入り（スター）を付けたメールの情報をスプレッドシートにリストアップしたのち、特定のラベルへ移動するApps Scriptをご紹介します
# 経緯
案件をピックアップするのにメーリングリストに登録していただいたのですが、毎日大量の案件情報が届くなか、自分が気になったものをひとまず分別出来ないかと思い、拾って来たスクリプトを調整して使用していたので共有させていただきます

# 準備
Gmailで振り分け先のラベルを作ります
新規でスプレッドシートを作成しメニューの「拡張機能」から「Apps Script」を選択し、 コード.gsにコードを書きます

# 使い方
対象にしたいメールを受信トレイでスターをつけ、準備していたコードを実行します
これでスプレッドシートのシート1に連番、受信日付、受信元、件名が転記されて、受信トレイから指定したラベルへメールが移動されます

# コード
```
function myFunction() {
  // 検索条件に該当するスレッド一覧を取得
  var threads = GmailApp.search('label:移動元ラベル is:starred');
  
  // スレッドを一つずつ取り出す
  threads.forEach(function(thread) {
    // スレッド内のメール一覧を取得
    var messages = thread.getMessages();
    
    // メールを一つずつ取り出す
    messages.forEach(function(message) {

      //メール受信日
      var date = message.getDate();

      //件名
      var subject = message.getSubject();+

      // メール本文
      var plainBody = message.getPlainBody();

      // From
      var mailFrom = message.getFrom();
      
      // 書き込むシートを取得
      var sheet = SpreadsheetApp.getActive().getSheetByName('シート1');
  
      // 最終行を取得
      var lastRow = sheet.getLastRow() + 1;

      // セルを取得して値を転記
      sheet.getRange(lastRow, 1).setValue("=row()");
      sheet.getRange(lastRow, 2).setValue(date);
      sheet.getRange(lastRow, 3).setValue(mailFrom);
      sheet.getRange(lastRow, 4).setValue(subject);
    });
    
    // 移動処理
    var label = GmailApp.getUserLabelByName('移動先ラベル');
    thread.addLabel(label);
    thread.refresh();
    label = GmailApp.getUserLabelByName('移動元ラベル');
    thread.removeLabel(label);
    thread.refresh();
  });
}
```

# コード説明
大体コメントの通りですが、カスタマイズできる部分について追加で解説します


* 検索条件に該当するスレッド一覧を取得</b>
var threads = GmailApp.search('label:移動元ラベル is:starred');

    受信トレイから条件に合うメールを取得します
    上の例だと移動元のラベル（これは標準の振り分け機能でつけてます）の中でスターが付いたメールを取得しています
    検索の条件はクエリで細かく指定出来るので、GmailAppのsearchを調べればより細かい指定の仕方がわかるかと思います
    参考：
    https://tetsuooo.net/gas/1267/
<br />

* メールを一つずつ取り出す</b>
    messages.forEach(function(message)

    このループでメールを1つずつ取り出して処理しています。
    message.getXXX()
    でメール内のいろいろな情報が取れるので、詳細はGmailAppのヘルプを参照してみてください
    https://developers.google.com/apps-script/reference/gmail/gmail-message?hl=ja
<br />

* 書き込むシートを取得
    var sheet = SpreadsheetApp.getActive().getSheetByName('シート1');

    メール情報を書き込むスプレッドシートの書き込み先のシートを指定しています
    この例だと「シート1」に書き込まれます
<br />

* 最終行を取得
    var lastRow = sheet.getLastRow() + 1;

    シートの最後の行に追記する形にするために行を取得しています
<br />

* セルを取得して値を転記
    sheet.getRange(lastRow, 1).setValue("=row()");
    sheet.getRange(lastRow, 2).setValue(date);
    sheet.getRange(lastRow, 3).setValue(mailFrom);
    sheet.getRange(lastRow, 4).setValue(subject);
    
    メールから取得したタイトルなどをシートの最終行の指定した列へ書き込んでいます
<br />

* 移動処理
    var label = GmailApp.getUserLabelByName('移動先ラベル');
    thread.addLabel(label);
    thread.refresh();
    label = GmailApp.getUserLabelByName('移動元ラベル');
    thread.removeLabel(label);
    thread.refresh();
    
    最後に移動したいラベルへ移動しています
    上の例だと移動したメールに「移動元ラベル」から「移動先ラベル」へ複製をして元のメールを削除しています。
<br />

以上になります。
カスタマイズすればより細かい情報の取得や振り分けも出来るかと思いますので参考にしていただければ幸いです。
Firefox ブラウザ拡張機能でOSネイティブな通知をする

# 概要

これは[初心者のブラウザ拡張機能 Advent Calendar 2024](https://qiita.com/advent-calendar/2024/browser-extension)の7日目の記事です。

拡張機能からOSネイティブ通知を行う方法を記載します。

# ソースコード

右クリックで表示されるメニューへ`sample menu`という項目を追加し、クリック時に通知が呼び出されるようにしました。

```javascript:background.js
browser.menus.create(
    {
      id: "sample",
      title: "sample menu",
      contexts: ["page"],
    }
  );

function createNotification() {
    browser.notifications.create({
        type: "basic",
        iconUrl: browser.runtime.getURL("icons/icon-48.png"),
        title: "Clicked!",
        message: "クリックしました",
    });
}

browser.menus.onClicked.addListener((info, tab) => {
    if (info.menuItemId === "sample") {
        createNotification();
    }
});
```

# 通知に関する説明

通知は`browser.notifications.create`で作成します。

通知内に作成できるコンテンツは色々ありますが、Firefoxでは基本的なものしかサポートされていません。


:::note info
Firefox currently: only supports the type, title, message, and iconUrl properties; and the only supported value for type is 'basic'.

[notifications.NotificationOptions](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/notifications/NotificationOptions)
:::

| 項目 | 説明 | 備考 |
| ---- | ---- | ---- |
| type | 通知のタイプ | Firefoxではbasicのみサポート | 
| iconUrl | アイコン画像のURL | - |
| title | 通知のタイトル | - |
| message | 通知内に入れるメッセージ | - |

※Firefoxでは上記4つのみサポート

# 参考

[notifications](https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions/API/notifications)
初海外学会で、ストライキ巻き込まれたけど、楽しみながら帰ってこれた件

みなさん、ストライキに巻き込まれたらまず**喜んでください**！！
何言ってるだ？と思ってるかもしれないですが、この記事を最後まで読めばわかると思います笑
ぜひ、海外に将来1度は行くかもという人は、ブックマークで保存して、必要な時に読み返していただけたら！！

まず、大前提として焦る必要はありません！
実際に今回の学会の帰国日にストライキに巻き込まれましたが、無事帰って来れた体験も元にお話できたらと思います〜
ストライキは過剰に心配しすぎず、巻き込まれたら帰ってから話す「特大ネタ」が手に入ったと喜ぶくらいがちょうどいいと思ってます！
日本で馴染みがないだけですが、初海外で(フランスに1ヶ月滞在した時に)散々巻き込まれてた時に感じたものとして、日本人的な感覚だと「地震」に近いと思っています笑
中確率でたまに起きる天災だけど、現地の人は慣れてるのであまり動じてない
(ストライキがなんで起きてるのか「仕組み」を理解すると、むしろいろいろ納得する部分があるので一度調べてみたり、勉強してみたりするといいです。ちなみにデモとストライキは明確に違うので、そこも気をつけて！)
(なにごとにも例外はありますので、大きすぎるストの時はどうにもならないかもしれないですが、もうそうなったら超大型台風・超巨大地震が来たと思って諦めましょう笑)


# ストライキに巻き込まれてた時の対処法

ストライキがなぜ起きるのか？と言う仕組みを調べるのは各々に任せるとして、おそらく調べてもあまり出てこないであろう「ストライキに巻き込まれてた時の対処法」をまとめていきます！！

ここでいうストライキは、交通機関のストライキを指しますが、基本は鉄道会社に対して従業員が何かの権利を主張したいがために交渉として、電車を止めるという方法(ストライキ)で抗議しています。
なので、
## ① 配車アプリは動く！
Uberなどのタクシーは問題なく使うことができます(基本的には)
ここで、最終手段をまず確保しておきます！(ただし、学会会場からシドニー空港まではUberで¥15000〜20000くらい。というように高いケースもあるので、それは②以降へ)

## ②ストライキの適用範囲・規模を把握する
これを知る手段として良い方法は2つ
(1)現地の人に聞く
ストがよく行われる場所だったりすると、現地の人も「またか😅」と慣れてるので、行きたい場所を言うと代替手段を教えてくれます笑
(2)鉄道会社の運行ページを見る
日本でも台風や大雨の時は新幹線止まりやすいので、新幹線の運行ページを見ますがそれと一緒です！ストは天災なので笑
最新情報かつ1次情報を取得できるので1番おすすめです！周りに聞ける人がいなくても状況確認できるのが良い！！

それを踏まえて考えるとよい基本方針しては、「とにかく目的地(今回の場合は空港)の近くに行ける手段を確保する！+2手先を考える！」

まず、ありとあらゆる可能性を探ります！！
ストライキと言ってもいろんな電車の止め方があって、自分が把握してるのはこんな感じ
### 電車の本数を少なくする
(今回の場合、市内から空港に向かう電車が普段は6分に1本のところ、15分に1本に)
→ これもストライキですけど、中身を知ると全然動じないですよね！(元々が便利すぎる笑)
でも鉄道会社には打撃与えられるはずなので、有効な手段ではあると思います

### 主要駅を飛ばして運行する
東山線でストが起きるとしたら、名古屋駅、栄駅、本山駅(東京で言うと、新宿駅、池袋駅、品川駅)が止まりません。
それ以外は動きます。みたいなストのタイプです！
これも少し困りますけど、隣の駅で降りれば移動できるので、不便なだけで移動自体はできます。

###  路線を完全に止める or 一部区間だけ止める
一部区間の場合は、その区間を把握した上で、動いている場所までどこやっていけばいいかを考えます！
ただ、今回巻き込まれたストは学会・ホテルの最寄駅から空港周辺(シドニー)まで80kmあるのですが、そこに向かう電車が路線ごと止まるタイプのストで代替手段がない😭、バス乗り継げばもしかしたら行ける？と言う状態でした…
これだけ聞くと深刻のように見えますが、安心してください！「代替バスが用意されてました！」
これはケースバイケースだと思うので、止まった時に現地の人に代わりの手段がないかをよく聞くといいのですが、今回の場合は
駅からバスが文字通りひっきりなしに(前のバスが出発したら次のバスがすぐ来る)来てくれたので、問題なくシドニーの中心駅まで辿り着くことができました！
実際電車でも1時間半くらいかかる道のりを1時間半〜2時間くらいで移動できたので、結果的にはさほど影響があったわけではなかったです！
しかも車内は観光バスのような革シートの良いバスで快適に移動できました笑

このように時間さえかければなんとかなることが多いので、ストが起きたらかなり余裕を持って行動することにしています！！
基本は最悪タクシーで移動できる圏内になるべく早く移動する(そうすればひとまず安心)
あとは、なるべく目的地に近くに行くのが良いと言いましたが、2手先を読むのが大事です！！
と言うのも交通機関の組み合わせがスト起きてる時は、普段以上に複雑になってることが多いので、利用者が少なすぎる駅で降りるor下ろされてしまうと移動したけど前にも後ろにも動けない…となってしまいます。

なので、これが合ってるかわかんないですけど、私は目的地の方面にある主要そうな駅をチェックポイントとして、近くへ移動していくのがいいかなと思ってます。主要駅であれば、人も多いので現地の人にも聞きやすいですし、その他の人も困っている人が多いはずなので、それを解決する手段がある確率が高そうと！😁
でもそもそも、主要駅ってどうやって知るの！？という方、安心してください！私たちにはどこの地域でも対応してくれる最強の相棒「ChatGPT」があります！！
ぜひ使いこなしましょう笑

# おわりに

実はこの文章、初海外学会体験記の一部として軽く書こうと思ったのですが、書いてみたらすごいボリュームになったので、独立した記事にしてみました笑
おそらく、ストライキのイメージや、そんなに怖がる必要ないじゃん！とわかってもらえたかと思います。
旅好きバックパーカーエンジニアとして、いろんなところを回っていた経験がまさかの学会で活きるとは思いませんでしたが、結果的に焦らずに済んだのでよかったです〜
この記事がみなさんのお役に立てれば！！
【axios】で【独自ヘッダー】を追加する3つの方法

## はじめに
HTTPリクエストに独自ヘッダーを追加するという要件が業務で発生しました。
axiosインスタンスの生成後にヘッダーを追加する必要があったのですが、その時にやり方を調べました。
本記事では、上記の要件だけでなくaxiosで独自ヘッダーを追加する3つの方法をご紹介します。

## 3つの方法 
1.importしたaxios自体のdefaultsプロパティにヘッダーをセット
```ts
axios.defaults.headers.common['X-Custom-Header'] = 'hoge';
```
2.axiosインスタンス生成時にヘッダーをセット
```ts
const instance = axios.create({
  baseURL: 'https://api.example.com',
  headers: {'X-Custom-Header': 'hoge'}
});
```

3.axiosインスタンスを生成した後にヘッダーをセット
```ts
// axiosインスタンスを生成
const instance = axios.create({
  baseURL: 'https://api.example.com'
});

// 生成したaxiosインスタンスにヘッダーをセット
instance.defaults.headers.common['X-Custom-Header'] = 'hoge';
```

## ヘッダーで日本語を含めたい場合
HTTPリクエストのヘッダーはASCII（アスキー）文字しか含めることが出来ません。
ASCII文字はアルファベットの小文字、大文字、数字、一部の記号、一部の特殊文字で構成されています。
つまり、日本語はASCII文字ではないので日本語をそのまま含めては送信時エラーになってしまいます。
```ts
// 日本語の「ほげ」が入っているのでエラー！
axios.defaults.headers.common['X-Custom-Header'] = 'ほげ';
```

日本語を含めたいのであれば、エンコードした値をヘッダーにセットして、サーバでは受け取った値をデコードする必要があります。
下記の記事も参考にご覧ください。

https://qiita.com/kazuki235/items/b9481f4a8b349b70a5e6


## さいごに
公式のリンクも載せておきます。
本記事がどなたかの助けになれば幸いです。

https://axios-http.com/docs/config_defaults
API Best Practices ~関連するフィールドは新しいメッセージにグループ化し凝集性の高いフィールドのみを入れ子にする

## 関連するフィールドは新しいメッセージにグループ化し凝集性の高いフィールドのみを入れ子にする

フィールドが密接に関連している場合、サーバー内部で一緒にやり取りすることがよくあります。
その場合、関連するフィールドをまとめた新しいメッセージを定義すると簡単です。

関連するフィールドを新しいメッセージにグループ化する様子：
```proto
message Foo {
  // Bad: 関連フィールドを個別に追加していくのはよくない
  optional int price;
  optional CurrencyType currency;

  // Better: 関連するフィールドは新しいメッセージにグループ（カプセル）化する
  optional CurrencyAmount price;
}

message CurrencyAmount {
  optional int price = 1;
  optional CurrencyType currency = 2;
}
```

このような疎結合が一般的にベストプラクティスとして受け入れられていますが、.proto ファイルを設計する際には必ずしも当てはまるわけではありません。
後で特殊なフィールドを追加することを想定して、2 つの情報単位を緊密に結合する (一方をもう一方の中にネストする) ケースがあるかもしれません。

たとえば、現時点ではかなり汎用的なフィールドのセットを作成している場合でも、後で専用のフィールドを追加することを想定している場合は、そのメッセージをこの .proto ファイルまたは他の .proto ファイルの別の場所から参照しないように、メッセージをネストさせることで抑制できます。

```proto
message Photo {
  // Bad: MetadataはPhotoの範囲外で再利用される可能性が高いので、ネストせずにアクセスしやすくするのが良いだろう。
  message Metadata {
    optional int32 width = 1;
    optional int32 height = 2;
  }
  optional Metadata photo_metadata = 1;
}

message FooConfiguration {
  // Good: RuleをFooConfigurationのスコープ外で再利用することは、無関係である可能性の高いコンポーネントと密結合させることになるが、ネストすることでそれを防ぐことができる。
  message Rule {
    optional float multiplier = 1;
  }
  repeated Rule rules = 1;
}
```
SAP-BTPのルーティング

「ルーティング」の領域は複数あり、それぞれ所管が異なる。
①認証依頼先のルーティング
②画面やAPIの対応関係
③-a)  通信先のルーティング：アプリケーションのroot URL 以降
③-b)  通信先のルーティング：「URLの、ドメイン部分」

--------------------------------------------
①認証依頼先のルーティング：Destinationの管轄

②画面やAPIの対応関係：CDS のアノテーションの管轄　or　xs-app.jsonの所管
　　（他の方法もあるが、SAP-BTPの強みであるためこの方法が採られる）

③-a)  通信先：アプリケーションのroot URL 以降：xs-app.jsonの所管。
　　（正規表現で該当したものを、特定の資材にルーティングする）

③-b)  通信先：「URLの、ドメイン部分」：Destinationの管轄

**************************************************************

◆よくあるエラー
　https://fiori-app.com　→ FIORIアプリをホストしているオリジン
　https://bpa-api.com　　→ BPAのAPIのオリジン

　　⇒　CORS問題が起きる。

◆解決方法（概要）
　xs-app.json のルーティング設定で解決させる。

◆解決方法（詳細）、および、メカニズム

　◆App Routerを使用することで「同じオリジンからの通信」にする
　　　App Routerが、FIORIアプリのリクエストを中継し、
　　　xs-app.json のルーティング設定に基づいてDestinationへ転送する。

　　　FIORIアプリ → App Router (同じオリジン) → Destination (BPAのAPI)

　　　ブラウザはApp Routerとの通信しか認識しないため、
　　　「BPAとFIORIが同じオリジンか？」という問題は解消される。

　◆JavaScriptからのHTTP通信
　　　パターン①：絶対パス（URLのフルパス）　を指定
　　　パターン②：相対パス（FioriのROOTからの相対パス）　を指定

　　　で「②」にする必要がある。
　　　xs-app.jsonの設定（※Destinationを取りたい）

　　　②相対パスなら、
　　　xs-app.json「source」の設定の正規表現にマッチするかどうかで、
　　　Destinationの設定をリダイレクト先のROOTとして、「target」の相対パスに、
　　　通信が置き換わるが、

　　　①絶対パスなら、正規表現のマッチが行なわれないため、
　　　通信を置き換えられない。
　　　（もし①絶対パスで通信するなら、
　　　　CORS対応したリクエスト方法にする必要がある）

◆通信を置き換えるための設定例

　◆JavaScript側（HTTP通信）　※fetchではなくて、.$ajaxでもよいが前者推奨
　　fetch("/api/v1/trigger"); // App Routerへの相対パス

　◆正規表現マッチング（xs-app.json）
    "routes": [
      {
        "source": "^/api/(.*)$",
        "destination": "bpa_api",
        "csrfProtection": false
      }
    ]
【おすすめプロンプト紹介】ChatGPTで英語ライティングを鍛える

今回紹介するプロンプトはこちら。

:::note info
You are a professional businessperson who can speak and write English suitable for the American business scene. Please correct any grammatical errors or parts that are not appropriate for professional English in the English sentences I write. Clearly indicate the parts that need correction and show both the original and corrected versions. Additionally, explain in simple Japanese why these corrections are necessary.
:::

このプロンプトをChatGPT-4oに入力すれば、それ以降にあなたが入力した英語の文章に対して、**文法的な間違いの訂正**、**より丁寧な表現への変更**を行った文章が提示され、なおかつ、訂正と改善が行われたそれぞれの箇所について、**「なぜ変更が必要なのか」を日本語で説明させる**ことができる。

この手の学習には反復練習が最も効果的だと思うが、会社の同僚や英会話の先生など生身の人間が相手では、時間も長くは取れないし、コストも高い。しかし、相手がChatGPTならば何度繰り返そうとも迷惑になることもコストがかさむこともない。現状、最適解なのではないかと考えている。
集中と俯瞰の切り替えについて

この記事は、[適応型ソフトウェア開発 アドベントカレンダー 2024](https://qiita.com/advent-calendar/2024/adaptive-software-development) の 8日目です。

## 集中と俯瞰の切り替えについて

スクラムフレームワークは全員で目的に向かって集中＝フォーカスして突き進み、より早く価値を提供する目的で使うものだと筆者は理解している。

では、適応型ソフトウェア開発ではどうだろうか？

## 適応型ソフトウェア開発における目線
適応型ソフトウェア開発では、発散・俯瞰=マルチタスクでカオスに向き合っていくことで、何が必要で大切なのかを明らかにしていく目的で使うものだと理解した。

### 発散的に進める
そもそもつくるべきもの・提供するべき対象がわからない状態で進めなければならない、プロダクトディスカバリー段階のプロジェクトで特に進化を発揮する。

プロダクトディスカバリー段階では、大きな達成したい文脈だけ存在しており、そのほかは何も定まっていない自由な状態であることが多い。

その中で制約と誓約をしながら、おぼろげに造形を見つけていくものだ。

### カオスの淵
適応型ソフトウェア開発では、「カオスの淵」というキーワードが良く出てくる。
この「カオスの淵」というものがとても重要だ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629928/7b979679-dfd1-a8fb-772a-18c6ff6ab6e1.png)

このカオスの淵を前提として、何を俯瞰し、何に集中するのかを解説する。

### 俯瞰
得たい結果に到達するため、適応度地形を意識する必要がある。
どんな縛りがあり、難しさがあるのか、どこが歩きやすいのかをまず知る必要がある。

適応度地形については、こちらの記事を参照。
https://qiita.com/h-kinocoboy/private/24e9d27f4796a4e419e8

#### 得たい結果への道筋
これは足元ばかり見ていても何もわからない。
常に頂上付近を観たり、いろいろな角度からの情報を使いながら進行しなければならない。

そのため、案件全体を多角的に様々な粒度で把握し続けることが大切になる。

つまり、適応型ソフトウェア開発では、達成したい目的を多角的に様々な解像度を使って俯瞰することが大切である。

それでは、集中はどうだろうか。


### 集中
得たい結果を見るために、あちこちから俯瞰するのはまぁよい。
ただし、先ばかり見ていても足元がおろそかになってくる。

大きな文脈を相手にしていたとしても、実は今すぐに手を付けられる領域も存在している。

それが、「カオスの淵」である。

このカオスの淵の解像度を上げていくことで、より具体的に大きな目標への距離が明確になっていく仕組みだ。

つまり、適応型ソフトウェア開発では、速攻で手を付けられるタスク=カオスの淵に対して、集中することが求められる。


## マルチタスク
ここで大切になってくることが、マルチタスクであることだ。

俯瞰を解説する際にもキーワードとして出てきた「多角的」という概念が大切になる。

### 多角的
多角的に進行することで、さまざまな視座から目標を俯瞰することができたり、集中した結果解像度を多方面から上げていくことができるようになる。

このように目的までに解像度をとにかく早く上げていくことに特化する事が大切なことだ。

ではどうやってこの多面的なものを観測していけばいいだろうか。
それはシンプルである。

カオスの淵をとにかく同時多発的に触り続けることだ。


## カオスの淵を並列で理解していく
この手始めに進めることができるタスクを並列で理解していくことが重要である。

実際に「完了」するタスクではないことが多いため、ここで使う完了の定義としては、
学習・思案・協調といった状態を前に進めることを使って進める。
https://qiita.com/h-kinocoboy/private/606781082146d8c29474


このようにカオスの淵に対して、状態を意識し、前進させていくことで、
目的達成のために何が必要で、何をしなければいけないかが多角的に理解することができるようになる。

これが適応型ソフトウェア開発の強みだ。
Raycastで便利なショートカットキー

Raycastはランチャーに分類されることが多く、さまざまなアプリを簡単に起動できます。
アプリ名の一部を入力するだけでアプリを絞り込んでEnterキーで起動できます。

その他、便利なショートカットキーが、公式マニュアルに記載されています。

https://manual.raycast.com

しかし、上記のマニュアル内に見つけられないようなキー操作を紹介します。

この記事は[Raycast Advent Calendar 2024](https://qiita.com/advent-calendar/2024/raycast)に参加しています。

昨日は @se_eiji さんによる「[RaycastからどうAIが使えるのか？](https://qiita.com/se_eiji/items/ca51a200a675b8c45574)でした。

## ↑キー

まずは最近実行したコマンドを履歴から探せる機能です。
Raycastを起動し、何も入力していない状態で「↑」キーを押すか、「Ctrl + P」を押すと、最近実行した履歴が表示されます。
そしてさらに「↑」を押すことで、順に辿れますし、関連するコマンドがサジェストされます。

## 「~」と「/」キー

Raycastのコマンド欄に記号を入力しても、ほとんどのキーは特に割り当てられていませんが、便利なのが「~」と「/」です。
「~」はホームディレクトリをFinderで開きます。
つまり、ユーザー名が「masuipeo」であれば、「/Users/masuipeo」を開けます。

また、「/」はルートディレクトリをFinderで開きます。
つまり、「Macintosh HD」などが開きます。

これらはターミナルを使うITエンジニアであれば、「`cd ~`」でホームディレクトリに移動したり、「`cd /`」でルートディレクトリに移動したりするため、直感的に使えるでしょう。

## Command + 数字

Safariなど複数のタブを開けるアプリでは、「Command + 数字」を押すと複数のタブの中から切り替えられます。
たとえば、「Command + 2」で2つ目のタブ、「Command + 4」で4つ目のタブを開けます。

これと同様に、Raycastでは「Command + 数字」で一覧から選択できます。
たとえば、次のように表示されていると、「Command + 2」で2つ目の「Maximize」を、「Command + 4」で4つ目の「Almost Maximize」を実行できます。

![window.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309006/fc44ea28-37ca-16c0-aee7-361fe6362298.png)

なお、「Command」キーを長押しすると、それぞれのメニュー番号が表示されるので、いくつ目かを数える必要はありません。

## 「:」

Raycastでは、絵文字を検索する機能が用意されています。たとえば、コマンドとして「emoji」のように入力すると、次のように「Search Emoji & Symbols」という機能を選択できます。

![search_emoji1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309006/0d664856-4424-5eba-8afd-91cfb5025fec.png)

そして、これを選択すると、多くの絵文字から検索して入力できます。

![search_emoji2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309006/d65fafb1-a9d9-0f3e-72ed-9258eb74ca07.png)

よく使う絵文字を手軽に入力できるのが「`:`」というキーです。
Slackなどでも「:」に続けて文字を入力することで絵文字を入力できますが、Raycastでは「:」を使うことでemoji pickerが表示されます。
これはRaycast Notesだけでなく、Action Panelでも同じです。

![emoji.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309006/46047ab1-066c-0e65-6ceb-b527a68e14e3.png)
【Unity】ScriptableObjectを用いたデータベース作成

# Unityメモ
### データベース作成
以下の二つのスクリプトを用います。
```C#:Item.cs
using UnityEngine;
using System;
[Serializable]
public class Item
{
    [SerializeField] private string name;
    [SerializeField] private float value;
    public string GetName(){ return name; }

    public float GetValue(){ return value; }
}

```

```C#:ItemList.cs
using UnityEngine;
using System.Collections.Generic;

[CreateAssetMenu(fileName = "ItemList", menuName = "List Objects/ItemList")]
public class ItemList : ScriptableObject
{
    [SerializeField] private List<Item> itemList = new List<Item>();
    public float GetStatus(string _name)
    {
        string name;
        float value;
        foreach(Item item in itemList)
        {
            name = status.GetName();
            value = status.GetValue();

            if (_name == name) return value;
        }
        return -1;
    }

    public List<Status> GetList(){ return itemList; }
}

```
Serializableを用いることで、インスペクターからItemListクラスで作成したリストのItemクラスの変数に書き込むことが可能になります。
Imandraを用いて形式検証を触ってみた

## 概要
この記事では、形式検証の概要や意義について説明するとともに、形式検証ツールImandraの使用例を紹介します。読者の想定としては、形式検証やImandraに馴染みのない方を考えています。


## 形式検証について
情報化が進んだ現代、プログラムにおけるバグは社会に深刻な悪影響を及ぼすことがあります。特に医療・航空・宇宙・金融等、安全性や正確性が重要視される分野ではなおさらです。また最近では、AIが生成したプログラムにおいて、いわゆる「ハルシネーション」（生成内容が正しくない現象）が発生し、常に正しいプログラムが生成されるわけではないという課題も浮き彫りになっています。

このような課題に対する解決策の一つとして注目されているのが、**形式検証**です。形式検証は、プログラムが特定の仕様を満たしていることを数学的に証明する手法です。一般的なテストでは作成したテストケースに対してしかプログラムの正当性を保証できませんが、形式検証を用いると任意の入力値に対してもプログラムの正当性を保証することが可能となります。


## Imandraについて
Imandraは、プログラムの形式検証を支援するツールで、関数型言語OCamlをベースに開発されています。Imandraでは、プログラムやその仕様をOCamlで記述し、数学的手法を用いてその正当性を検証します。

[公式サイト](https://www.imandra.ai/)では、近年のAI技術の普及に伴う課題に対応するため、AI生成コードに関連する問題点とそれに対する形式検証の有効性が強調されています。


## 実際にImandraを触ってみる
今回は、[Imandraが提供するJupyter Notebook形式のオンライン環境](https://try.imandra.ai/)を利用して、簡単な形式検証を試してみました。

### 検証対象のプログラム・仕様
#### プログラム
以下の条件を満たす関数$\mathit{sum}$
- 入力: 整数$n$
- 出力: 
    - $n \leq 0$ の場合、$0$
    - $n \gt 0$ の場合、$1$から$n$までの総和 $1 + 2 + \cdots + n$

#### 検証したい仕様
任意の整数$n$に対し、$n \leq \mathit{sum}(n)$ が成り立つ

### OCamlでの実装
```ocaml
(* 検証対象のプログラム *)
let rec sum n =
  if n <= 0 then
    0
  else
    n + sum (n - 1)

(* 検証したい仕様 *)
verify (fun n -> n <= sum n) [@@auto]
```

### 検証結果
![sum.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3933474/8a46911f-fea7-7972-ac75-9b72e58400c1.png)
中央に`Proved`と表示されていることから、このプログラムが仕様を満たしていることをImandraが証明したことが分かります。さらにログを見ると、数学的帰納法に基づき以下の2つの命題に分割して証明したことを確認できます。[^sum]
[^sum]: それぞれの命題の証明の詳細に関しては、ログに記載されていないため省略します。
- (Subgoal 1.2) $n \leq 0$ ならば $n \leq \mathit{sum}(n)$
- (Subgoal 1.1) $n \gt 0$ かつ $n - 1 \leq \mathit{sum}(n-1)$ ならば $n \leq \mathit{sum}(n)$

このように、Imandraを用いることで簡単にプログラムの正当性を保証することができました。

### エラー検出の例
次に、else節内の`+`演算子を誤って`-`に書き換えてしまった場合を試してみましょう。
```ocaml
(* 検証対象のプログラム *)
let rec sum_err n =
  if n <= 0 then
    0
  else
    n - sum_err (n - 1)

(* 検証したい仕様 *)
verify (fun n -> n <= sum_err n) [@@auto]
```
![sum_err.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3933474/dbf5711a-5a67-e3fb-a438-f831e6ebd01d.png)
Imandraはこのプログラムが仕様を満たさないことを検出し、反例として $n=2$ の場合を提示します。このようにして、潜在的なバグを未然に防ぐことができます。


## 最後に
この記事では、形式検証とその重要性、さらにツールImandraを用いた具体例を紹介しました。形式検証は、特に安全性や正確性が求められる分野で大きな価値を持つ手法です。

この記事では簡単な例しか扱いませんでしたが、[Imandra公式サイトのデモページ](https://www.imandra.ai/demos)ではさらに応用的で興味深い例も紹介されていますので、ぜひそちらも参考にしてみてください。
- [Analysing Web-app Authentication Logic](https://docs.imandra.ai/imandra-docs/notebooks/webservice-auth-logic/)
- [Solving Sudoku with Imandra](https://docs.imandra.ai/imandra-docs/notebooks/sudoku/)
- [Verifying Merge Sort in Imandra](https://docs.imandra.ai/imandra-docs/notebooks/verifying-merge-sort/)
- 等々
タッチタイピングの練習に寿司打しかやってないの？

これは「Happiness Chain Advent Calendar 2024」の9日目の記事です。
https://adventar.org/calendars/10341

完全未経験からWebエンジニアへの転職を目指して[Happiness Cahin](https://happiness-chain.com/)というオンラインプログラミングスクールで学んでいるryutaと申します。

今回はエンジニアにとって必要不可欠な能力であるタッチタイピングの練習サイトを紹介します。
# そもそもタッチタイピングとは？
すでにご存じの方が多いとは思いますが。
> タッチ‐タイピング【touch-typing】
> 読み方：たっちたいぴんぐ
> 
> パソコンなどで、キーボードのキーを見ないで、正しく文字を打ち込むこと。タッチタイプ。ブラインドタッチ。タッチメソッド。

引用：[デジタル大辞泉：「タッチ-タイピング」の項](https://www.weblio.jp/content/touch+typing)


キーボード上の運指に関しては下のイラストがわかりやすいです。

![touchtyping.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3639605/3b541744-8014-aa7a-39d2-277bd706a81a.png)
引用：https://happylilac.net/sy-keyboard03.html

この図を見る度に個人的には
「右手小指の守備範囲やたら広すぎじゃね？」
と思ってしまいます(笑)

タッチタイピングの重要性に関してはこちらのブログを是非読んでいただきたいです。

[【プログラミングを学ぶ全ての人に知ってほしい】タッチタイピングの練習方法(と重要性)](https://datawokagaku.com/typing_practice/#google_vignette)
引用：https://datawokagaku.com/typing_practice/#google_vignette

# 寿司打
[寿司打](https://sushida.net/)に関しては説明不要かと思います。
[e-typing](https://www.e-typing.ne.jp/)と並ぶ国内タイピング練習サイトの二大巨頭ですね。
私も毎日お世話になっています。
グラフィックも可愛いしゲーム性も高いし大好きなサイトです。
しかし、日本語入力に特化しているので記号文字等は登場せず、プログラミングにおけるタイピングスピードが速くなるかといえば厳しいものがあります。
もっとも、先輩エンジニア方の話を聞いていると実務ではテキストコミュニーケーションを多用するそうなので、日本語入力のスピードも速くなっておくにこしたことはありませんが。

# typing.ioって知ってますか？
私が情弱すぎるからかもしれませんがつい最近まで知りませんでした。
[typing.io](https://typing.io/)とは現時点で16のプログラミング言語に対応したタッチタイピング練習サイトです。
https://typing.io/
![スクリーンショット 2024-12-01 19.48.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3639605/4049489c-4503-c109-1513-005f580efa95.png)
透かし文字で書かれたコードをなぞるようにタイピングしていきます。
いわゆる写経ですね。
間違えると訂正するまで先に進めません。
タイムのみならず色々と細かいデータも提供してくれます。
課金するとオプション機能が充実しているのですが、私は当分の間は無課金勢としてやっていきたいと思ってます。
まあ、詳細はサイトにサインアップしてお確かめください。

# 最後に
私は約1年前にWebエンジニアを志して学習を始めるまで本格的にタッチタイピングの練習をしたことがありませんでした。
毎日コツコツ寿司打で練習してきて多少はマシになってきましたが、今のままでは実務に差し支えるのでは？と思う程、まだまだタイピングスピードが遅く、毎日、強い危機感を覚えながら練習しています。
タイピングスピード　=　エンジニアの実力
ではないかもしれませんが、現役エンジニアの方や周囲の優秀なスクール生を見ていても皆、総じてタイピングスピードが速いです。
私自身、Udemyなどの動画で学習する際も講師のタイピングスピードにまるでついていけず、度々、一時停止しなくてはならないので既に学習にも支障をきたしています。
どう考えてもタイピングスピードは速いに越したことはないと個人的に考えています。
この記事の目的は素晴らしいサイトなのに、寿司打と比べてあまりにも知名度が低いtyping.ioを1人でも多くの方に知っていただくことでした。
寿司打を貶める意図は微塵もありませんし、上述したように両方とも素晴らしいサイトで私自身、2つのサイトを毎日、併用しています。
これからもプログラミング学習と並行して、タッチタイピングの練習に励んでいきます！
入力文字数チェックで使用するテキストを作成できるマクロを作ってみた

　単体テストでテキストボックスやラベルなどに入力できる最大文字数を確認する時、いちいち文字を入力し、その結果をスクリーンショットでエビデンスとして保存するという手法でテストを行うことがあります。そのため、テストで使用する入力用テキストを作成する作業の負担を軽減させるマクロを作ってみました。
 　　　　　ボタンをクリックするだけでテキストを作成できます！

## 機能説明
![macro.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3918175/8f1da0b7-8562-0720-39f1-da042fd21ff5.png)
レイアウト↑

###### ①文字数入力欄
 E2セルに作成したいテストデータの桁数を入力します。1以上10000以下の間で好きな桁数を指定できます。
 
:::note warn
<dl>
<dt>バリデーション</dt>
0以下又は、10001以上入力すると、<strong>「1から10000までの値を入力してください。」</strong>というエラーメッセージが出ます。
  
数字以外を入力すると、<strong>「数字のみ入力してください。」</strong>というエラーメッセージが出ます。
</dl>
:::

###### ②実行ボタン
実行ボタンを押下すると、各種類のテストデータがE2セールに入力した桁数で作成されます。
例：![eg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3918175/70113457-88ff-a541-03a5-d7e14942d0cf.png)

###### ③クリアボタン
クリアボタンを押下すると、入力した桁数と結果のデータが削除されます。

## VBA開発
<strong>クリアボタン</strong>
```vba:qiita.vba
Sub クリア()
    ' 値をクリアする
     Range("E2").Value = ""
     Range("E5").Value = ""
     Range("E6").Value = ""
     Range("E7").Value = ""
     Range("E8").Value = ""
     Range("E9").Value = ""
     Range("E10").Value = ""
End Sub
```
<strong>実行ボタン</strong>
```vba:qiita.vba
Sub 実行()
    ' 変数宣言
    Dim num1 As Double
    Dim result1 As String
    Dim result2 As String
    Dim result3 As String
    
    ' エラーハンドル
    On Error GoTo ErrorHandler
    
    ' 文字数の値
    num1 = Range("E2").Value
    
    ' セールの初期化
    Range("E5").Value = ""
    Range("E6").Value = ""
    Range("E7").Value = ""
    Range("E8").Value = ""
    Range("E9").Value = ""
    Range("E10").Value = ""
     
    If num1 > 10000 Or num1 < 1 Then
        MsgBox "1から10000までの値を入力してください。"
    Else
        ' 数字
        For i = 1 To num1
          If i / 10 = 0 Then
            result1 = result1 & "0"
          Else
            result1 = result1 & CStr(i Mod 10)
          End If
        Next i
        ' 英字
        For i = 1 To num1
            result2 = result2 & "N"
        Next i
        ' カナ
        For i = 1 To num1
            result3 = result3 & "ア"
        Next i
    End If
    
    Range("E5").Value = StrConv(result1, vbWide)
    Range("E6").Value = StrConv(result1, vbNarrow)
    Range("E7").Value = StrConv(result2, vbWide)
    Range("E8").Value = StrConv(result2, vbNarrow)
    Range("E9").Value = StrConv(result3, vbWide)
    Range("E10").Value = StrConv(result3, vbNarrow)
    
    Exit Sub
    
ErrorHandler:
    MsgBox "数字のみ入力してください。"
End Sub
```
:::note info
<strong>構文 </strong>
Sub：サブルーチンの始まり。
End Sub：サブルーチンの終わり。
Dim：変数を宣言するためのキーワード。
Range("セル")：セルオブジェクト。
:::
## 最後に
テストで入力文字数のチェックをする時、今回作ったマクロを利用することで、少しでも作業の負担を軽減できればと思います。

Excelマクロ（VBA）については下記を参考に：
[Excelマクロ（VBA）の基本的な作り方・使い方を解説](https://suisui-office.com/excel-macro/")
Expoを使ったiOSアプリ開発環境構築・トラブルシューティングまとめ (WSL2 + Docker編)

## 概要

本記事は、Windows環境で「Dockerを使ってExpoベースのiOSアプリ開発」をやりたいと考えたところからスタートし、様々な問題に直面しつつ、最終的にWSL2上にNode.js/npmをインストールして環境を整えた過程をまとめたものです。

「Dockerで全部完結させたい」と考えていたらネットワークやバージョン、ファイアウォールの壁にぶつかり、結果としてWSL内でのnpm利用へシフトすることで解決に近づいた、という開発ストーリーです。

  
## 前提環境

- Windowsマシン
- WSL2（Ubuntu等）
- Node.js / npm（最終的にWSL上にインストール）
- Expo CLI（`npx`経由で使用）
- Docker（当初はDocker内でNode/npmを完結させたかったが、のちにWSL側でnpm installする流れに変更）

  
## 目標と経緯

- **当初の目的**: Dockerを使い、コンテナ内で`expo start`などを実行し、iOS実機でアプリをプレビューしたい  
- **問題発生**: ネットワークやファイアウォール、Node.jsバージョン、`expo doctor`コマンド非対応など、様々なトラブル  
- **方針転換**: Dockerのみで環境完結を断念し、WSL上でNode.js/npmを使って`npm install`を行う  
  - ホスト(WSL)側で`npm install` → Dockerは最小限のセットアップのみ  
  - Node.jsを最新化（14以上）でオプショナルチェイニング問題解消  
  - ネットワーク問題が改善し、iOS実機で画面表示可能に

  
## よく遭遇した問題

1. `expo start`でiPhoneからアクセス不可  
   - ファイアウォールやLAN設定、Docker-WSL間のネットワーク、`--lan`や`--tunnel`の使い分けがカギ

2. `Unexpected token ?` / `Unexpected token .` SyntaxError  
   - Node.jsバージョンが古い → Node.jsを14以上に更新で解消

3. `expo doctor`が使えず`expo-doctor`が必要  
   - `npm install expo-doctor`後、`npx expo-doctor`で診断可能

4. `@types/react-native`不要警告  
   - `npm uninstall @types/react-native`で対応、`react-native`本体に型定義あり

  
## 対処アプローチ

### Node.js / npm をWSL上にインストール

当初はDockerコンテナ内で`npm install`等を完結させたかったが、  
ネットワークやOSレイヤ差異で詰まりやすく、WSL上（Ubuntu）でNode.js/npmを用いて`npm install`する方針に転換。  
`node -v`でNode.jsバージョンを14以上に上げることでオプショナルチェイニング問題も解消。

  
### Dockerfileの簡略化
```
FROM node:18-bullseye

RUN apt-get update && \
    apt-get install -y --no-install-recommends \
    git \
    watchman \
    python3 \
    make \
    g++ \
    && rm -rf /var/lib/apt/lists/*


WORKDIR /app EXPOSE 19000 19001 19002 CMD ["bash"]
```


以前はDocker内でグローバルインストールや`npm install`をしていたが、  
WSLで`npm install`を完了した状態で`-v $(pwd):/app`マウントし、`npx expo start`を実行する流れに変更。  
Dockerは最低限のツールセットのみ。

  
### コマンド例（Docker使用時）

```
bash
# WSL上で依存関係インストール
cd /mnt/c/k-iizuka000/cat-calorie-planner/expo-app
npm install

# Dockerで起動
docker run -it --rm \
  -v $(pwd):/app \
  -p 19000:19000 -p 19001:19001 -p 19002:19002 \
  expo-env npx expo start --lan
```

WSL上で準備した`node_modules`を利用。
`--lan`で局所的なネットワーク接続を試し、それでもダメなら`tunnel`モードを検討。

### トンネルモード

`npx expo start --tunnel`でngrokを介したアクセスが可能になります。

LAN問題やファイアウォールによるブロックを回避できる可能性があり、  
`--lan`モードでうまくいかない場合は`--tunnel`を試してみるとよいです。

  
### iOS実機までの道のり

- ファイアウォール無効化や別ネットワーク（テザリング）での接続確認
- `expo-doctor`で依存関係チェック、`@types/react-native`削除など細かい改善
- 結果的にWSLでnpm管理、Dockerは補助的環境として機能し、iOS実機で画面表示に成功

  
## 最終的な成果

- Dockerだけで完結させるのは困難だったが、WSL上でnpmを利用しNode.jsアップデートで問題解消に近づいた
- ExpoでQRコード表示→iOS実機で実際に画面表示を確認
- 多方面からのアプローチ（Nodeバージョンアップ、ファイアウォール確認、tunnel使用、`expo-doctor`利用）で一歩ずつ前進

  
## まとめ

- Windows + WSL + Docker + ExpoでiOS実機テストはハードルが多い
- 当初「Dockerですべて完結」の考えを改め、WSL上でnpmを利用する方針に変更したことで道が開けた
- ネットワーク・バージョン・依存関係を一つずつ解消すれば、最終的にiOS実機でのプレビューまで可能
- 同様の環境構築に挑む方が参考になるよう、本記事で得た知見を共有