OmniAICreator/Qiita-1.07M huggingface dataset:
【JavaScript】Shadow DOMを取得しGoogle Earthの地球儀を自動回転する方法

### 【概要】
Google Earthの地球儀表示部分はShadow DOMで生成されています。
Shadow DOMの要素はgetElementByIdなどを使用して取得することができませんが、開発者ツールから取得できます。
取得したShadow DOMに対して、キーボードの"→"キー押下のイベントを発火させることで地球儀を自動回転します。

### 【環境】
Google Chrome

### 【実行手順】
#### 1. Google Earthを起動する
下記リンク先へ遷移します。
[Google Earth](https://www.google.com/intl/ja/earth/)

`Earth を起動`ボタンをクリックします。

![Google Earth](https://user-images.githubusercontent.com/15062128/212417082-86f0ecb6-ab58-45e1-b2d5-4672603c7206.png)

新しいタブが開き、地球儀が表示されます。

![Google Earth](https://user-images.githubusercontent.com/15062128/212417519-a161eea7-89f2-4a5f-bea1-c328e1a6febf.png)

#### 2. 地球儀要素の特定をする

開発者ツールを開き地球儀の要素を選択します。

![developer tool](https://user-images.githubusercontent.com/15062128/212417920-7a753cd5-3d50-4e93-a710-e355eb644ae8.png)

地球儀の要素を選択すると自動的にElementsタブが開き、canvas要素にフォーカスが当たります。

![canvas](https://user-images.githubusercontent.com/15062128/212419298-29a8aac7-de94-4b2d-a2e8-8c7fe647ff57.png)

#### 3. Shadow DOMを取得する
canvas要素のすぐ上にある`shadow-root`要素を右クリックし、`Store as global variable`の項目をクリックします。

![Shadow DOM](https://user-images.githubusercontent.com/15062128/212419483-49e114de-98e8-4754-b154-634003dee3f7.png)

クリックすると`temp1`という変数名でShadow DOMが取得できます。

![Shadow DOM](https://user-images.githubusercontent.com/15062128/212419724-45270893-c727-4835-a247-a0d6e6f133c6.png)

#### 4. 地球儀を自動回転する
コンソールに下記コマンドを入力し、実行します。
実行すると地球儀が自動回転します。
```javascript
temp1.getElementById('canvas').dispatchEvent(new KeyboardEvent("keydown", { keyCode: 39 }));
```

※ちなみに原因はわかりませんが、上記コマンドと同じ意味合いの下記コマンドでは自動回転することはできませんでした
```javascript
temp1.getElementById('canvas').dispatchEvent(new KeyboardEvent("keydown", { key: "ArrowRight" }));
```

![animation](https://user-images.githubusercontent.com/15062128/212429453-60a251f2-ca29-4fd7-93f6-09c6eb78ae1a.gif)


### 【参考サイト】
[Javascriptで疑似的にKeyUpイベントを発火させる方法](https://lightgauge.net/language/javascript/4913/)
[JavaScript で矢印キーの押下を検出する](https://www.delftstack.com/ja/howto/javascript/javascript-arrow-keys/)
学習メモ　Unity パーティクル

少しずつでも進捗を残すため、また振り返った時の自信につなげるため作業メモを残す

今日はUnityでパーティクルについて学んだ
バージョンは2021.3.4f1を使用した

「Game Object」→「Effects」→「Particle System」からパーティクルシステムは利用することができる

パーティクルシステムはプレビューパネルというのが表示され動作チェックができる

パーティクルシステムのInspectorより細かな設定を調整することができる

・Looping　チェックを入れることで処理がループする　同じ処理を続けることで連鎖している印象を与えることができる

・Gravity Modifier　数字を大きくすることでパーティクルに重さを付与することができる　重さが付与されるとパーティクルは下に向かって落ちるようになる　
【個人的考え】何かが降り注ぐ描写に使えそう　例えば雨や雪など

以下の記事を教材として参考にした
https://docs.unity3d.com/ja/2019.4/Manual/class-ParticleSystem.html
https://styly.cc/ja/tips/unity-introduction-particle/
【Laravel】アクセサ/ミューテタの基本

# アクセサとは

アクセサは、Eloquentのプロパティにアクセスが合った時に値を変換する処理のこと

# ミューテタとは

ミューテタは、Eloquentのプロパティを設定するときに、その値を変換する処理のこと。

# どういう時に便利か

例えば、ユーザ追加APIがあったとします。その機能では、ユーザテーブルにメールアドレスを登録するとき、暗号化して登録する必要があるとします。

その場合、メールアドレスを暗号化する処理をコントローラもしくはサービスに実装するかと思います。復号処理についても同様です。

しかし、仮に友達追加APIみたいなのがあった場合、上記の方法だと友達追加APIのコントローラ、サービスにも暗号化の処理を実装する必要があります。

見ての通り、各機能ごとに毎回記述するのは冗長した記述とも言えます。

そこで、メールアドレスを登録する際に**ミューテタ**を使用すれば、暗号化部分の処理を毎回記述する必要がなくなるのでシンプルになります。

# ミューテタの記述方法

ミューテタの記述方法は以下の通りです。

```php:User.php
/**
 * emailの登録
 *
 * @param  string  $value
 * @return void
 */
public function setEmailAttribute($value)
{
    $this->attributes['email'] = Crypt::encryptString($value);
}
```

ミューテタを設定したいカラム名が「キャメルケース」でEmailの場合、UserモデルにsetEmailAttributeメソッドを作成します。

# アクセサの記述方法

アクセサの記述方法は以下の通りです。

```php:User.php
/**
 * emailの取得
 *
 * @param  string  $value
 * @return string
 */
public function getEmailAttribute($value)
{
    return Crypt::decryptString($value);
}
```

アクセサを設定したいカラム名が「キャメルケース」でEmailの場合、UserモデルにgetEmailAttributeメソッドを作成します。

# Laravel9での書き方

またLaravel9以降では以下の記述が可能です。（メソッド名はプロパティ名を「キャメルケース」にしたものです。）

```php:User.php
public function email(): Attribute
{
    return new Attribute(
        // アクセサ
        get: fn($value) => Crypt::decryptString($value),
        // ミューテタ
        set: fn($value) => Crypt::encryptString($value),
    );
}
```

# サンプル実装

実際に、任意のユーザのメールアドレスを登録する処理を書いてみます。

内容は以下の通りです。

```php
$user = User::find(1);
$user->email = 'test@example.com';
```

メールアドレスの設定が終わり、ユーザテーブルを見ると以下の通り、メールアドレスが暗号化されています。

つまり、ミューテタが実行されていることがわかります。


| id | email |
|:-:|:-:|
|  1 |  eyJpdiI6IndrckpyQm9yUXlaWWpSRU1pemU4VWc9PSIsInZhbHVlIjoiWUl（…以下省略） |


プロパティにアクセスした時は以下の通り、きちんと復号化されています。

```php
>>> User::find(1)->email
=> "test@example.com"
```

アクセサが実行されていることがわかります。

以上
[python]Seleniumでの待機処理

# はじめに
pythonでSeleniumを遊び半分で触っていて発生したエラー第一弾です。
#### 前回までのあらすじ
PythonでChromeDriverを操作してyoutubeの特定の画面へ遷移し、条件に合ったyoutube動画の情報をスクレイピングするコードを紹介しました。

https://qiita.com/Oyama-Kohei/items/3b4153ea5f699f28042c
#### 今回発生したエラー
下記のコード実行中に発生
```python
# ChromeDriverでurlを起動
driver = webdriver.Chrome(CHROME_DRIVER_PATH)
driver.get(url)

xpath = '//*[@id="tabsContent"]/tp-yt-paper-tab[2]'
driver.find_element_by_xpath(xpath).click()
```
エラー内容としては以下
```
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[@id="tabsContent"]/tp-yt-paper-tab[2]"}
```
xpathのクリック処理が入っているのにpathが見つからねーよと言われています
原因はwebページの読み込みが完了していない状態でxpathを探しに行っているためです。。。
ということでwebページの読み込みが完了するまで待機処理を追加する必要があります。

# 解決案検討（待機処理をいくつか）
### time.sleep()
まずは単純に待機する方法としてtime.sleep()を試してみましょう
```python
# ChromeDriverでurlを起動
driver = webdriver.Chrome(CHROME_DRIVER_PATH)
driver.get(url)

# 3秒待機
time.sleep(3)

xpath = '//*[@id="tabsContent"]/tp-yt-paper-tab[2]'
driver.find_element_by_xpath(xpath).click()
```
自分の環境ではこれでも問題なく動作しますが結論あまり良くありません。
なぜなら3秒間で読み込みが完了するということを保証するものではないからです。

### implicitly_wait()
次に要素が見つかるまで待機する方法です
```python
# ChromeDriverでurlを起動
driver = webdriver.Chrome(CHROME_DRIVER_PATH)
driver.get(url)

# 最大10秒待機
driver.implicitly_wait(10)

xpath = '//*[@id="tabsContent"]/tp-yt-paper-tab[2]'
driver.find_element_by_xpath(xpath).click()
```
上記の場合、xpathが見つかるまで最大10秒の待機処理が入ります。
もし10秒以内に見つかれば以降待機されることはないし、見つからないまま10秒経つとタイムアウトします

### until
最後にwebコンテンツが全て読み込まれるまで待機する方法です。
```python
# ChromeDriverでurlを起動
driver = webdriver.Chrome(CHROME_DRIVER_PATH)
driver.get(url)

# 全てのコンテンツが読み込まれるまで待機
try:
    # 全てのコンテンツが読み込まれるまで待機
    WebDriverWait(driver, 10).until(expected_conditions.presence_of_all_elements_located)
except TimeoutException:
    # 例外処理

xpath = '//*[@id="tabsContent"]/tp-yt-paper-tab[2]'
driver.find_element_by_xpath(xpath).click()
```
個人的にはimplicitly_wait()かこの方法が有力なのかなという予想です（python初学者なので自信なし。。。）
presence_of_all_elements_locatedがloadされるまで最大10秒待機する方法です.
読み込みが完了していない場合はtry/catchでTimeoutExceptionをcatchしています
# まとめ
待機処理って色々あるんだなーという感想
スクレイピングならこの方法という話であって、用途によって使い分けられるようになるといいですね
Xcode Cloud を iOS アプリ（個人開発）に導入した際の所感

## 記事の内容
### この記事で書くこと
* 個人開発の iOS アプリに **Xcode Cloud** を導入した際の所感

### この記事で書かないこと
* Xcode Cloud とは
* Xcode Cloud の設定方法

※ Xcode Cloud の設定方法は、下記の動画等を参考にした。

https://www.youtube.com/watch?v=bNvUPb6K5jI

## 前提
下記 リポジトリの `main` ブランチに変更があれば、Xcode Cloud を利用して自動的にビルドし、**App Store Connect** に UP するように設定している。

https://github.com/tanakadaichi1989/Thermometer-Hygrometer

## 所感
### 便利なところ
* 手動で ビルド番号の設定 > クリーン　> ビルド > アーカイブ > App Store Connect に UP する手間がなくなるのは凄く便利

### 注意すること
* Swift Package Manager を利用してライブラリを導入しているアプリを Xcode Cloud を利用してビルドする場合、下記のファイルを `.gitignore` で追跡対象から外さないこと。

```
*.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
```

* Xcode Cloud を使ってビルドおよび App Store Connect に UP した iOS アプリのビルド番号は、Xcode で設定した番号と異なる。
* 既に App Store Connect に UP したアプリのビルド番号を連続にしたい場合は、**設定 > ビルド番号 > 次のビルド番号** （下記画像） を編集する必要がある。
![スクリーンショット 2023-01-14 5.10.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199441/3812079f-add6-ef23-d637-b0689711ec55.png)

## 参考
https://developer.apple.com/jp/xcode-cloud/
[SwiftUI]複数行のTextFieldで位置が変えたい時対処法


結論から伝えるとTextFieldではなくTextEditorを使いましょう

## TextEditorの場合

ちゃんと左上から表示される

<img width="400" alt="スクリーンショット 2023-01-14 3.40.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/3f9ef8f4-5d89-6ac5-8901-508f1ac47360.png">

    @State var text = ""

    TextEditor(text: $text)
        .frame(width: 400, height: 100)




## TextFieldの場合
textを入力する際に真ん中に表示されてしまう

<img width="400" alt="スクリーンショット 2023-01-14 3.34.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/50f76807-8afb-9f08-553b-feb2ef6af0ff.png">


    @State var text = ""

    TextField("", text: $text,axis: .vertical)
        .frame(width: 400, height: 100)

なんで真ん中に表示されるんだーーーーって少し悩んでいたのですが、ググってみたら便利なのあったので忘備録も兼ねて共有です。

どなたかの参考になれば幸いです。
フリーランスに移行するまでに経験しておいて良かったこと

## 注意
酔っ払った勢いで自分語りします。
また、本記事は面談の際に感じたことをベースに記述します。
なお、フリーランスとしては動き始めたばかりであり、将来的には意見が変わるんだろうとも思っています。

## 自己紹介
### これまでの経験
文系学部出身で、2019年から2022年末まで3年半SESの会社に所属していました。
前職では要件定義～保守運用まで、フロントエンド（React, Wordpress構築）からバックエンド（Serverless Framework + Lambda(Typescript)や業務アプリから呼ばれるPL/SQL）まで広く浅く経験しました。
得意な領域はReactです。
Reactに関しては長期の案件や人数が多い案件の経験はないものの、小規模な開発、趣味の領域での使用、新人教育などで3年以上触れ続けてきました。

### 志向
エンジニアになったからには自分が作りたいと思ったWebサービスを要件定義から運用まで一気通貫で対応できるようになりたいと思い、前職では領域を散らしてアサインしてもらいました。
しかし、それゆえに経歴書を見たときに「どの領域、何の技術の人」なのか分かりにくい状況になっています。
よって、まずはフロントエンドに特化して経験を積みたいと考えていましたが、前職ではフロントエンドの案件を取るのが難しいとのことだったのでフリーランスとして活動することにしました。
また、面談において僕が重視していることは以下3点です。
- 自分の成長, 活躍できるか
- プロジェクトの健全性
- 長期的なお付き合いが見込めそうか

### キャリアプラン
2023年中に下記2つのうちどちらかを達成したいと思っています。
- 自信があるReactの経験を積み、「僕といえばReact」と胸を張って言えるようにする
- 現在は自信がないバックエンド領域において、参画案件を通じてReactと同程度まで成長する

## フリーランスの面談について
こちらの記事に詳しいです。
https://qiita.com/turmericN/items/e248d8ac30ca5c21650e
イメージを掴むためにぜひ。

## 経験してよかった事
PGとして面談に望んだ時に思ったことです。
### 上流工程
上流工程を経験したことにより、健全度が低いプロジェクトを察知できるようになりました。
例えば、業務アプリにおいて要件定義～基本設計のフェーズで異様に時間が掛かっている案件。
エンドユーザからの要望と開発スコープの狭間で揺れ動き、プロジェクトをコントロールできなくなると要件定義に時間がかかってしまう傾向にあると思っています。
基本設計までの遅れを取り戻そうとエンジニアの数を揃えますが基本設計の理解と詳細設計に時間を割くことができずリテイクの嵐に……といった結末を迎えることも少なくないでしょう。
僕はFirefighterではないので上記の兆候のある案件は辞退しました。

### SQL案件
意外なことに、React案件の面談の中でもSQL案件の経験について質問をいただくことが多かったです。
というのも、面談の機会を頂いた会社さんは複数の案件を持っており、ありがたいことにバックエンドの案件にスライドする可能性も考慮してくださっているようでした。
Node.jsだけではなくSQLの経験もあることで+αを期待してくださっているのかな……といった様子でした。
長期的なお付き合いの中で信頼を獲得できれば、まだ自信がない領域でもお仕事をいただきながら成長できる機会があるかもしれません。
ありがたい限りです。

### 各種シチュエーションのプロジェクト
ざっくりとした書き方で恐縮です。
要するに以下の3つを指します。

- 新規開発
- レガシーのリプレイス
- 既存プロダクトへの機能追加

それぞれのシチュエーションで、時間配分や難しいポイントは変わってきます。
たとえばリプレイスであれば要件定義フェーズにおけるレガシーの機能把握や新システムに移行するデータ整理に時間がかかり、機能追加であればエンジニアの裁量が大きめでスピーディな実装を求められる傾向にあると感じています。
それぞれのシチュエーションの経験があれば、面談でプロジェクトについて説明していただいた時の解像度が違います。
それにより、面談中に確認すべきことや自分に求められている役回りが明確に把握できました。

## 最後に
`志向`の項で記述した3項目（自信の成長と活躍, プロジェクトの健全性, 長期的なお付き合いが見込めそうか）を判断するのに役立った経験を記載しました。
酔っ払いの戯言ですが、誰かの役に立てば嬉しいです。
Yolov7をtfjsでの実装方法の解説

Yolov7をtfjsで試したのでメモ
モデルのコンバートとJSでの処理について書きました。
Non-Maximum Suppression(NMS)は未実装です。

## PytorchからONNXへのConvert

PytorchのモデルからONNXに変換して動かすPythonコードは本家に置いてあります。
コンバートから試す方はこちらを参考ください。


https://github.com/WongKinYiu/yolov7/blob/main/tools/YOLOv7onnx.ipynb

tfjsにコンバート済みのモデルはこちらにあります。


https://github.com/otmb/wasm_hpe_decoder/tree/main/yolov7-tiny_tfjs_fp16

## ONNX以降のtfjsへのConvert手順

onnx-tfと、tensorflowを実行できる環境を用意します。
protobufのバージョンがコンフリクトするので環境は分けて作るのがオススメです。
なお、数少ないM1 Macユーザーはtfjsを入れるのは非常に手間です。こちらを参考ください。

https://github.com/tensorflow/tfjs/issues/6845


実行環境ができればコマンドを叩けば直ぐに作れます。
オプションで半精度(fp16)を指定するのは精度の影響が少ない割にファイルサイズが半分になるのでオススメです。

```bash
// onnx to tensorflow
$ onnx-tf convert -i yolov7-tiny.onnx -o yolov7-tiny_tensorflow

// tensorflow to tfjs
$ tensorflowjs_converter \
--input_format tf_saved_model yolov7-tiny_tensorflow ./yolov7-tiny_tfjs_fp16 \
--quantize_float16
```


## 実装方法

画像の読み込み、前処理、推論、後処理を実装します。

### 画像の読み込み

```js
// canvasに処理したい画像を読み込む
// getImageDataでUint8ClampedArrayを取り出す
async function loadImage(src) {
    const imgBlob = await fetch(src).then((resp) => resp.blob());
    const img = await createImageBitmap(imgBlob);
    const canvas = document.createElement('canvas');
    canvas.width = img.width;
    canvas.height = img.height;
    const ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0);
    console.log(img.width, img.height);
    return ctx.getImageData(0, 0, img.width, img.height);
}
```

### 画像の前処理
```js
// padAndResizeToで画像をモデルの入力と同じ縦横比になるようアスペクト比でリサイズして0埋めする
const {resized, ratio, padding} = padAndResizeTo(image, 640, 640);
// 返り値のtensorを255で割ってモデルの入力になるよう転置する
const x = resized.div(255).transpose([2,0,1]).reshape([1, 3, 640, 640]);
```

padAndResizeToはこちらから拾ってきました。

https://github.com/tensorflow/tfjs-models/blob/master/posenet/src/util.ts


### 推論


```js
const feedDict = {"images": x };
let preds = await detModel.executeAsync(feedDict, "output");
```

### 後処理


```js

// 推論結果をスライスしてバウンディングボックスの座標を取り出す
const data = await preds.data();
for (let i=0; i<data.length / 7; i++){
const [ batch_id,x0,y0,x1,y1,cls_id,score ] = data.slice(i*7, i*7+7);
let box = [
  (x0 - padding.left) / ratio,
  (y0 - padding.bottom) / ratio,
  (x1 - padding.left) / ratio,
  (y1 - padding.bottom) / ratio,
];
}
```


### コードとサンプル

https://github.com/otmb/wasm_hpe_decoder/blob/main/bbox.html

https://otmb.github.io/wasm_hpe_decoder/bbox.html

以上です。

## その他

別で姿勢推定のトップダウンの処理を実装しました。
物体検出の後に姿勢推定処理を走らせると、M1 Macのブラウザで3fpsしか出ないのでとても悲しい。
今回の物体検出の処理はこの成果物の派生になります。

サンプル実装（カメラが起動するのでご注意ください）

https://otmb.github.io/wasm_hpe_decoder/
アクツクMV：データベース（デフォルト、レコードで反映）を使う


今回はデータベースの基本的なところを見ていきたいと思います。

まず前回の続きから説明します。前回未読の方は、
前回　https://qiita.com/havin_nothin/items/039d955d39fcedaa93bd
を参照して、テキストで体力と最大体力が表示されているようにしておいてください。

１．インデックス用の変数（レベル）を作る。
まず、変数を追加します。データベースの何行目かを示すために使う変数です。
「プレイヤー」の変数「レベル」にしました。
![Database01Variable.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3103492/6a618c39-050d-f6c6-0f34-da2d675f4004.png)


２.テキストを書き換える。
テキスト素材「変数表示」を以下のように書き換えます。

レベル　\V[プレイヤー,レベル,0]
体力　\V[プレイヤー,体力,0]
最大体力　\V[プレイヤー,最大体力,0]

これで変数「レベル」の値も表示できるようになりました。
![Database02Text.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3103492/b59dc66c-caab-9d54-540b-4409f48ab404.png)


３．データベースを作る。
ここまでは準備で、ここからが本編です。
データベースのタブをクリックし、データベースを新規追加します。
「デフォルト」か「オブジェクト」か訊かれるので「デフォルト」を選びます。
名前は変えずに「database_001」で行きます。
こんな画面になります。
![Database01Sheet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3103492/cd73a3cd-c1aa-c23e-cb32-9e8c25534cd4.png)

二つある「＋」をおすと、行、列が増えます。「－」を押すと消えます。
２列×５行にしてください。
「カラム００１」「カラム００２」というところをダブルクリックすると名称が変えられるので、
それぞれ「体力」と「最大体力」にしてください。
（プレイヤーの変数と完全に同じ名称にしてください；ここ重要）
数字を図か下記を参照に入れてください。（適当になんでもいいですが、半角数字で入れてください）

名前　　　,体力,最大体力
レコード001,5,10
レコード002,10,20
レコード003,15,30
レコード004,20,40
レコード005,25,50

４．アクションを登録する。
オブジェクト「変数表示」の初期アクション「アクション0001」に「データベースを反映」を追加します。
設定は以下のとおり：

データベース一覧から選択：database_001
レコードで反映
レコード：変数：プレイヤー：レベル
変数と反映方法を選択：プレイヤー：全体：＝

最後に「データベースを反映」を、１番最初に実行されるよう上に移動します。
![Database03DatabaseRead.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3103492/193a0247-9824-dc01-655d-4896b05b3ae8.png)

５．プレイヤーのレベルの初期値をいろいろ変えて実行してみます。
レベルが０のとき、データベースの１行目の「体力」と「最大体力」の値が反映され、
レベルが４のとき、同じく５行目の値が反映されているのがわかるでしょう。
レベルが５以上の場合は、データベースの値ではなく、「体力」「最大体力」の初期値のままです。
![Database03Level0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3103492/d31ecbf8-1bf0-2bb7-4c10-0b40d3463372.png)
![Database03Level4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3103492/ae0f9da8-a67f-3422-fd9f-7c870c204b20.png)
![Database03Level5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3103492/3cbada74-eb86-ef1b-828f-ace5f89a0fb8.png)


変数「レベル」が０～４に変化すると、それに対応して、データベースの「カラム名と同じ名前の変数」の値が、１～５行目の値に変化する、というのが、「データベースを反映」のアクションの働きになります。
登録されていない行数を指定したり、セルに値が無い場合には、値は変更されないままになります。
（あと値として、-1が入っているときも、データベースの値が変数に反映されないようです。-1を使いたいときは、999を入れておいて、そこから1000を引くといった方法を用いたほうが安全と思います）

変数名はかならず同じにしなければなりません。（「体力」「最大体力」といった）変数名をデータベースのカラムに登録するときは、コピーペーストするのが無難です。

データベース（デフォルト、レコードで反映）の働き、わかってもらえたでしょうか。
次回はデータベースのオブジェクト用を使って、画像を変化させてみます。→　https://qiita.com/havin_nothin/items/b0c0695292bff7e9fdbd

ではまた。
Nuxt3 画面読み込んだ際にuseFetchを実行するとError: fetch failed ()エラーが発生する

# 環境
* Node：18.12.1
* Nuxt：3.0.0
* Vue：3.2.45

# 発生した際の状況と原因
画面読み込みこんだ際に`useFetch()`を実行すると`Error: fetch failed ()`というエラーが発生して`fetch`できませんでした。

調べてみたところ、どうやらNodeのバージョンが18系、またはSSRを使用していると発生するようです。

https://github.com/nuxt/framework/issues/9885

pages配下のファイルで下記のように記述していました。
```vuejs
<script setup>
const fetch = async () => {
  const { data, error } = await useFetch('http://localhost/api/foo')
}
fetch()
</script>
```

# 解決方法
SSRを無効にすると解決しました。
```nuxt.config.ts
export default defineNuxtConfig({
    ssr: false
})
```
Nodeのバージョンも関係しているようでしたので16系にダウングレードして確認したのですが、解決せずSSRを無効にした時のみ正常に動作しました。
nginx tcpフォワード(Almalinux)

# 背景
 Almalinuxのdnfでインストールされるnginxにはtcpフォワード(stream)の機能がない。
 使用したい場合はソースコードからビルドする必要がある。

# 前提・環境
 OS：AlmaLinux 9.1
 本作業はrootユーザで行う
クローズドの環境ではないこと
 ファイアーウォールおよびSELinuxは考慮しないものとする
 受信ポートを8000/tcp、転送先を192.168.1.1の10000/tcpとする

# パッケージのインストール
### 必要なパッケージをインストールする
 ```
dnf -y install wget tar gcc pcre-devel zlib-devel
 ```

### インストールするパッケージについて
|  パッケージ  |  用途  |
| ---- | ---- |
|  wget  |  nginxの公式ページからソースコードをDLするため  |
|  tar  |  ソースコード(tar.gz)を展開するため  |
|  gcc  |  ソースコードをビルドする場合に必要  |
|  pcre-devel  |  ソースコードをビルドする場合に必要  |
|  zlib-devel  |  ソースコードをビルドする場合に必要  |

# nginxのダウンロード
　[ダウンロードサイト](http://nginx.org/en/download.html)

### wgetでダウンロード
ダウンロードするバージョンはStable versionを対象とする
 ```
wget http://nginx.org/download/nginx-1.22.1.tar.gz
 ```

# ビルド
### 展開する
 ```
tar zxvf nginx-1.22.1.tar.gz
 ```

### 展開先に移動する
 ```
cd nginx-1.22.1
 ```

### コンパイルするために"Makefile"を作成する
 ```
./configure --with-stream --without-stream_geo_module --without-stream_map_module
 ```

### コンパイルおよびインストール
 ```
make && make install
 ```

### インストール先に移動
 ```
cd /usr/local/nginx/
ls -l

["ls-l"の結果]
drwxr-xr-x 3 root root 4096  1月 13 01:13 conf
drwxr-xr-x 2 root root 4096  1月 13 00:07 html
drwxr-xr-x 2 root root 4096  1月 14 00:45 logs
drwxr-xr-x 2 root root 4096  1月 13 00:07 sbin
 ```

# tcpフォワード(stream)の設定
### コンフィグファイル編集
 ```
cd conf
cp -p nginx.conf nginx.conf.org
vi nginx.conf
 ```

編集画面が表示されるので以下の内容を最終行に追加する
 ```
stream {
    upstream testserver {
       server 192.168.100.1:10000;
    }

    server {
       listen       0.0.0.0:8000;
       proxy_pass   testserver;
    }
}
 ```

# nginx起動
 ```
cd /usr/local/nginx/sbin
nginx -c /usr/local/nginx/conf/nginx.conf
 ```

# ポートの確認
 ```
ss -nate | grep ":8000" | grep LISTEN
 ```
「0.0.0.0:8000」が表示されていることを確認する。
アクツクMV：テキスト表示で変数内容を表示する


今回は、変数の表示をテキストに埋め込んでみようと思います。
今回は、トップビューのチュートリアルが終了した時点でのプロジェクトを使ってみます。

「プレイヤー」（と敵）のオブジェクトしかない状態です。
この「プレイヤー」の、あらかじめ設定されている変数「体力」と「最大体力」を画面に表示してみます。

１．まずフォントを設定します。
前回の記事
https://qiita.com/havin_nothin/items/3b11653050709a93ced5
でしたように、素材の、フォントで、TrueTypeフォントを登録し、３２ポイントにして、名前を「font32」とします。
（ポイント数は好きな数字でいいです。前回３６で、今回３２にですが深い意味はありません；）

２．素材で、テキストを登録する。
![Text01Material.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3103492/31d3b08c-3ecb-c2bc-5a21-21f735f8a522.png)
素材のテキストで、テキストを追加して、名前を「体力表示」にしました。
フォントを「font32」にして、白い枠に以下の文字を入力します。

体力　\V[プレイヤー,体力,0]
最大体力　\V[プレイヤー,最大体力,0]

\V[プレイヤー,体力,0]と書くと、オブジェクト「プレイヤー」の変数「体力」の値を表示します。最後の0は少数点以下の桁数です。小数点以下は不要なのでゼロにしています。
右横にどんなふうに表示されるか反映されています。
（右下のゲーム画面は、最終的に表示される画面です）

３．オブジェクトを作ります。
![Text01Object.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3103492/1ee41e2d-bbcc-ba6a-1871-338bf0e7c3a7.png)

新しいオブジェクトを追加して「変数表示」という名前にしました。
アクションプログラムは、念のため「重力の影響を受けない」をチェックし、
下の＋を押して、実行アクションの「テキストを表示」を追加します。
テキスト素材を「体力表示」にします。
自動的に先ほど入力した文字列が出てきます。
フォントを「font32」にします。
~~レイアウトと動作の「表示時間」の「時間制限なし」をチェック、~~
表示領域の背景を「無し」にします。
（この後、時間制限なしにして、何度もアクションを実行すると、ゲームが遅くなることを発見しました。変化するテキスト表示はかならず制限時間を設定して消えるようにしてください）

４．メニューをシーン設定で表示させるようにし、オブジェクトを配置する。
前回の記事
https://qiita.com/havin_nothin/items/3b11653050709a93ced5
の、４．と５．でしたように、シーン設定で、メニューを表示できるようにして、
そのメニューに、作ったオブジェクト「変数表示」を配置します。

すると、画面に

「体力　１
　最大体力　１」と表示されます。

プレイヤーの体力や最大体力を変更して、表示が変わるか試してみてください。
以下は、プレイヤーの体力を３、最大体力を１０にした時のゲーム画面です。
![Text01GameScreen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3103492/8e462286-7d0a-6b34-0c1d-1a8b7ce02bab.png)

次回は今回のテキスト表示を使って、データベースの働きを見ていきます。→https://qiita.com/havin_nothin/items/6413c41ec711c0964321

ではまた。

（補足）上記のままだと、変数がゲーム中に変化しても、リアルタイムで反映されません。ゲーム中にリアルタイムで変化させるには、下記のように、アクションをコピーして、無条件で両方をつなげて、ループするようにしてください。
![textV009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3103492/ebde6694-658b-9225-17f8-47fce40b5972.png)
MacのGas Maskというhostsファイル管理アプリ

macのGas Maskというhostsファイル管理アプリを入れたので、参考サイトをメモ。

## Gas Maskについて
https://softantenna.com/blog/gas-mask/

## ダウンロードサイト(git hub)
https://github.com/2ndalpha/gasmask/releases

## hostsファイルの場所
http://onocom.net/blog/mac-hosts-file/

## hostsファイルについて（後半に記載あり）
https://oku-log.com/blog/mac-hosts/
githubにあげた後のnode_modulesディレクトリに.gitignoreを適用させる。

## やりたいこと
githubリポジトリにあげてしまったnode_modulesディレクトリを.gitignoreでcommitの対象から外したい。

## 実行手順
1\. .gitignoreを作成する
2\. .gitignoreに除外したいディレクトリを記載する
3\. gitの追跡対象からはずす
4\. 変更をgithubにpushする

### .gitignoreを作成する
```
$ touch .gitignore
```

#### .gitignoreの配置場所

プロジェクトの最上位のディレクトリに作成する

```
├ index.html
├ style.css
├ node_modules
└ .gitignore
```

### .gitignoreに除外したいディレクトリを記載する
```.gitignore
# node_modulesディレクトリを指定する
node_modules/
```
### gitの追跡対象からはずす

インデックスからのみファイルを削除する（追跡対象からはずす）
```
$ git rm -r --cached node_modules  
```

### 変更をgithubにpushする

```
$ git add .
$ git commit
$ git push origin main
```

これでgithubにあげたnode_modulesは削除され、今後のcommitの対象からも外れます。
C++で計算型プロパティ

PythonやSwiftにある計算型プロパティ（Computed Property）をC++でも使いたい！

### 計算型プロパティもどき
```c++
template <typename T>
class Property {
 public:
  Property(std::function<T(void)> get, std::function<void(T)> set) {
    this->get = get;
    this->set = set;
  }

  std::function<T(void)> get;
  std::function<void(T)> set;

  operator const T() {
    return get();
  }
  void operator=(const T newValue) {
    set(newValue);
  }
};
```

### 使用例

```c++
class Circle {
public:
  Property<double> radius = {
    [this]() {
      return radius_;
    },
    [this](double newValue) {
      radius_ = newValue;
    }
  };
  Property<double> diameter = {
    [this]() {
      return radius * 2;
    },
    [this](double newValue) {
      radius = newValue / 2;
    } 
  };
  Property<double> circumference = {
    [this]() {
      return diameter * 3.14;
    },
    [this](double newValue) {
      diameter = newValue / 3.14;
    }
  };

  Circle(double radius) {
    radius_ = radius;
  }

private:
  // 格納型プロパティ (Stored Property) としては1つしか持っていない状態
  double radius_;
};

int main(void) {
  Circle circle(5.0);  // 半径5
  std::cout << "radius: " << circle.radius << std::endl;                // 5
  std::cout << "diameter: " << circle.diameter << std::endl;            // 10
  std::cout << "circumference: " << circle.circumference << std::endl;  // 314

  circle.diameter = 1;  // 直径1
  std::cout << "radius: " << circle.radius << std::endl;                // 0.5
  std::cout << "diameter: " << circle.diameter << std::endl;            // 1
  std::cout << "circumference: " << circle.circumference << std::endl;  // 3.14

  circle.circumference = 314;  // 円周314
  std::cout << "radius: " << circle.radius << std::endl;                // 50
  std::cout << "diameter: " << circle.diameter << std::endl;            // 100
  std::cout << "circumference: " << circle.circumference << std::endl;  // 314

  return 0;
}
```

初投稿でした。
Beancount/Favaで自分の出費を可視化する (できなかった)

# Beancount Fava

コツコツプレーンテキストで家計簿つけてるわけですが、やっぱりグラフとかみたいですよね？今日はそれです。

## setup

必要なパッケージを入れます。favaはvisualization用のソフトウェアですが、Beancountという微妙に違うsyntaxを要求します。なのでledger2beancountという変換用のソフトも導入します。

```shell-session
$ sudo apt install python3-fava ledger2beancount
```

大量に依存パッケージが入りますが見なかったことにします。気に入らない人はvenv+pipとかで入れたらいいと思います。

## conversion

自分の書いてるledgerファイルをまず`print`コマンドで一つの巨大なファイルにします。

```shell-session
$ ledger -f root.ledger print > /tmp/inline.ledger
```

次にこれをBeancountにしてみます。

```shell-session
$ ledger2beancount /tmp/inline.ledger > /tmp/inline.beancount
```

なんかエラーがいくつか出ますが気にしないことにします。

## visualization

```shell-session
 % fava /tmp/inline.beancount
Traceback (most recent call last):
  File "/usr/bin/fava", line 33, in <module>
    sys.exit(load_entry_point('fava==1.18', 'console_scripts', 'fava')())
  File "/usr/bin/fava", line 25, in importlib_load_entry_point
    return next(matches).load()
  File "/usr/lib/python3.9/importlib/metadata.py", line 77, in load
    module = import_module(match.group('module'))
  File "/usr/lib/python3.9/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 790, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "/usr/lib/python3/dist-packages/fava/cli.py", line 11, in <module>
    from fava.application import app
  File "/usr/lib/python3/dist-packages/fava/application.py", line 67, in <module>
    app.jinja_options["extensions"].append("jinja2.ext.do")
KeyError: 'extensions'
```

おっと、pipの出来損ないが入ってたみたいです。消してやり直し。

```shell-session
 % rm -rf ~/.local/lib/python3.9/site-packages/
 % fava /tmp/inline.beancount
Running Fava on http://localhost:5000
```

これをSSHのポートフォワーディングしつつ見ます... エラーだらけですね。

```
/tmp/inline.beancount 	14616 	syntax error, unexpected NUMBER, expecting end of file or EOL
/tmp/inline.beancount 	14621 	syntax error, unexpected NUMBER, expecting end of file or EOL
/tmp/inline.beancount 	20553 	Duplicate posting metadata field: KeyValue(key='payee', value='CH')
/tmp/inline.beancount 	22252 	syntax error, unexpected EOL
/tmp/inline.beancount 	22338 	syntax error, unexpected EOL
/tmp/inline.beancount 	22452 	syntax error, unexpected EOL
/tmp/inline.beancount 	14665 	Balance failed for Assets:Banks:Sony:Gaika: expected 33.50 CHF != accumulated 0 CHF (33.50 too little)
```

1400個もエラーが出てます。ちょっとめんどくさいですね。見てみたところ、タグの期待するフォーマットがより厳格だったり、balanceが一日複数あったら警告が出るみたいで、これは私の場合かなり致命的です。諦めて自分で可視化するかフォーマットをなんとか適合させるか。私はとりあえずほかを探します。


```shell-session
% sudo apt purge python3-fava ledger2beancount
% sudo apt autoremove --purge
```
Go でホストのプライマリ IP アドレスを取得する (Linux)

[`github.com/google/gopacket/routing`](https://pkg.go.dev/github.com/google/gopacket@v1.1.19/routing) パッケージを使う．  
インターネット上のホストへの経路とソース IP アドレスを取得することができる．

:::note warn
Linux しか対応していない模様
:::

```main.go
package main

import (
	"fmt"
	"net"

	"github.com/google/gopacket/routing"
)

func main() {
	router, _ := routing.New()
	internetHost := net.IP{8, 8, 8, 8}
	_, _, primaryIp, _ := router.Route(internetHost)

	fmt.Printf("ip = %v\n", primaryIp)
}
```

## `out of order iface...` のエラーが出る時

Docker などの環境では，以下のようなエラーが出る場合がある．

```
out of order iface X = {14 1500 ethX XX:XX:XX:XX:XX:XX up|broadcast|multicast}
```

これは `routing` の [バグ](https://github.com/google/gopacket/issues/698) のようで，修正の [PR](https://github.com/google/gopacket/pull/739/files) が Close されていて放置されている． 　
Workaround として， Close された PR のコードを使わせてもらうことができる．

```go.mod
//require github.com/google/gopacket v1.1.19
// 以下に変更
require github.com/google/gopacket v1.1.20-0.20210429153827-3eaba0894325
```
inetOrgPerson、organizationalPerson、personの主な属性

inetOrgPersonの基底クラスは「organizationalPerson」(構造型)、「organizationalPerson」の基底クラスは「person」(構造型)。inetOrgPersonを使用する場合は、organizationalPersonとpersonの属性も使用できる。

●オブジェクトクラスinetOrgPerson(構造型)の主な属性
・departmentNumber 部署コード
・employeeNumber　社員番号
・employeeType 雇用形態
・givenName 名前(GivenName)
・homePhone 自宅電話番号
・homePostalAddress 自宅住所
・mail メールアドレス
・manager 管理者
・mobile 携帯電話番号
・o 組織名
・roomNumber 部屋番号
・uid ユーザID(ログイン名)

●オブジェクトクラスorganizationalPerson(構造型)の主な属性
・title 役職
・street 番地
・postOfficebox 私書箱
・postalCode 郵便番号
・ou 部署などの組織単位
・facsimileTelephoneNumber　Fax番号

●オブジェクトクラスperson(構造型)の主な属性
・cn　一般呼称。必須。
・sn　名字。必須。(SurName)
・userPassword パスワード
・telephoneNumber 電話番号
・description エントリの説明

※3つのオブジェクトクラスの必須属性は、personに設定されている「cn」と「sn」。
ホスティングとは




# ホスティングとは

>ホスティングとは、サービス事業者がデータセンター内で運用保守するサーバの一部、または全領域を、インターネット経由でレンタルすることです。


https://www.itscom.co.jp/forbiz/column/office-environment/8569/

ホスティングサービスをマンションに例えると各部屋をそれぞれサーバーとして貸し出すような感じです。


イメージとして、大きなスペースの内の一部を借りることをホスティングといい、そのようなサービスをホスティングサービスというようです。

例えば、Githubもホスティングサービスに入っているようですが、Githubの場合、リポジトリをホスティングしてGithub上で公開したり色々操作したりできるわけです。
（Githubは、Webサービスであり、ホスティングサービスでもありですね。）



# まとめ

ホスティングとは、サーバーを借りることです。（借りたサーバーに何らかのサービスを立てます。）

イメージとして大きなスペースのうちの一部を借りることをホスティングといい、このようなサービスをホスティングサービスといいます。
【Bash】変数に値が設定されていない場合にエラーにする方法

## `set -u`

`set -u`を記述しておくと未定義の変数があるとエラーになります。

## `${sample:?message}`
変数を参照する際に以下のように記述することで変数に値が設定されていない場合に`message`を出力してエラー終了するようにできます。

```bash
$ {SAMPLE:?message}

```
音声ツール作成　

● [inputText.txt]は読み取りファイル。

```音声ツール-wav.vbs

Option Explicit

if False then ' Windowsの音声合成エンジン
  'Microsoft Haruka - Japanese (Japan)
  'Microsoft Ichiro - Japanese (Japan)
  'Microsoft Sayaka - Japanese (Japan)
  'Microsoft Ayumi - Japanese (Japan)
end if

'::::::::::::::::::::::::::::::::::
' 必要に応じて、音声合成エンジンを設定
'::::::::::::::::::::::::::::::::::

Const target = "Microsoft Ayumi"
Const speed = 1 '--話すスピード

Dim fso
Dim sapi
Dim cat
Dim token
Dim fs
Dim oldv
Dim inputFile
Dim lineStr

Set fso = WScript.CreateObject("Scripting.FileSystemObject")

' 読み込みファイルの指定 (相対パスなのでこのスクリプトと同じフォルダに置いておくこと)
Set inputFile = fso.OpenTextFile("inputText.txt", 1, False, 0)
lineStr = inputFile.ReadAll

Set sapi = CreateObject("SAPI.SpVoice")
Set cat  = CreateObject("SAPI.SpObjectTokenCategory")
cat.SetID "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech_OneCore\Voices", False
For Each token In cat.EnumerateTokens
    If token.GetAttribute("Name") = target Then
        Set fs = CreateObject("SAPI.SpFileStream")
        fs.Open target & ".wav", 3
        Set sapi.AudioOutputStream = fs
        Set oldv = sapi.Voice
        Set sapi.Voice = token
        sapi.Rate = speed '--話すスピード
        ' sapi.volume = 100   '--声のボリューム
        sapi.Speak lineStr
        Set sapi.Voice = oldv
        fs.Close()
        Exit For
    End If
Next

' オブジェクトを廃棄します。
Set fso = Nothing
Set sapi = Nothing
Set cat = Nothing
Set fs = Nothing
Set oldv = Nothing
```
Hashableに出てくるHasherとは (Swift)

<h1><a href="https://developer.apple.com/documentation/swift/hashable">Hashable</a>と関係のある<a href="https://developer.apple.com/documentation/swift/hasher">Hasher</a>とは (Swift)</h1>

<a href="https://developer.apple.com/documentation/swift/hasher">Hasher</a>は構造体で、バイト列をハッシュ値に変換する機能を有しています。combineメソッドを呼び出して、最終的にfinalizeメソッドを呼び出せば、ハッシュ値を生成できます。具体例を見ていきましょう。

```Swift
var hasher = Hasher()
hasher.combine(100)
hasher.combine("Hello")
let hashValue = hasher.finalize()
```

hashValueがハッシュ値です。combineメソッドに、ハッシュ値の元となる値を渡していきます。combineに渡す値の順番で、ハッシュ値が変化します。hasher変数はvarで宣言していることに注意してください。

以下はハッシュ値が一致しない例です。

```Swift
    var hasher1 = Hasher()
    hasher1.combine("hello, world")
    hasher1.combine(1)
    let hashValue1 = hasher1.finalize()
        
    var hasher2 = Hasher()
    hasher2.combine(1)
    hasher2.combine("hello, world")
    let hashValue2 = hasher2.finalize()
    XCTAssertEqual(hashValue1, hashValue2)
```

hashValue1とhashValue2は一致しません。

順番を合わせると、hashValue1とhashValue2は一致します。

```Swift
    var hasher1 = Hasher()
    hasher1.combine(1)
    hasher1.combine("hello, world")
    let hashValue1 = hasher1.finalize()
        
    var hasher2 = Hasher()
    hasher2.combine(1)
    hasher2.combine("hello, world")
    let hashValue2 = hasher2.finalize()
    XCTAssertEqual(hashValue1, hashValue2)
```

終わり。
スイッチロールについて

## スイッチロールとは
**通常の複数のAWSアカウントの管理方法**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/2bc6313b-d66a-53b5-b91f-559f12cddedb.png)
**Switch Role方式**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/722e07ef-1423-304e-9e3e-67e22d8f5076.png)



## スイッチロールのやり方

①スイッチロール先での作業
IAMロールの作成
- 信頼されたエンティティタイプ：AWSアカウント
- AWSアカウント：別のAWSアカウント
　　アカウントIDにスイッチロールを許可したいIDを入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/4da3a70a-5734-d977-7fdd-5ac96dacf427.png)

ポリシーを選択
※今回は**AdministratorAccess**を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/fee52e86-a9b9-2f6d-e988-777444ef99be.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/15a78bba-b37a-b184-7cf1-e254e1e908b8.png)
ロールの詳細
任意のロール名を入力
今回は**switchrole-test**と入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/ee4f7cdc-b51c-cebd-d0c2-887313615523.png)
作成を押してロールの完成。これでスイッチロール先での作業は終了。

②スイッチロール元での作業
ロールの切り替えを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/a649c189-7be0-577b-fd96-0132ccd31022.png)

アカウント：スイッチロール先のアカウントID
ロール：作成したロール名
表示名：任意の名前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/45380314-0ae2-c887-6f3c-68901338a5ba.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/e17edaf0-de85-9387-b759-60e655638310.png)

スイッチロール先のアカウントIDとスイッチロールが表示されていれば成功。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/d0b0ad43-c2a1-91f9-b88e-1d6bf8de530d.png)

以上とても簡単です。

## スイッチロールのメリットデメリット

**メリット**
- アカウント管理の簡素化
　アカウント毎(開発/テスト/本番)にユーザーの作成・追加・削除する手間がなくなる。
- アカウントログインの手間がなくなる

**デメリット**
- IAMロールをアカウントごとに作成・管理するのは煩雑
- 請求管理が各アカウントをスイッチしてまわることになるので煩雑
M1 Macでtfenv installする際に、「curl: (22) The requested URL returned error: 404」となる場合について

# はじめに
最近、Terraformの勉強をしています。
Terraformのバージョン管理ツールである
tfenvでエラーが出たので対処方法を残します。

# エラー内容
実行コマンドとエラー内容
```
% tfenv install 0.13.6
Installing Terraform v0.13.6
Downloading release tarball from https://releases.hashicorp.com/terraform/0.13.6/terraform_0.13.6_darwin_arm64.zip
curl: (22) The requested URL returned error: 404                                                                      

Tarball download failed 
```
始まりかけて失敗しているようです。。

# 対処
以下のコマンドでインストールする
```
% TFENV_ARCH=amd64 tfenv install 0.13.6
  inflating: /opt/homebrew/Cellar/tfenv/3.0.0/versions/0.13.6/terraform  
Installation of terraform v0.13.6 successful. To make this your default version, run 'tfenv use 0.13.6'
```
成功しました！

# 終わりに
引き続きTerraformの勉強を進めていきます。
UbuntuにNode.js LTSをインストールする方法

UbuntuにNode.jsのLTS版をインストールする方法を個人的なメモとしてここに置いておきます。
2023年1月13日現在、LTS版は、v18.xになります。

```
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - &&\
sudo apt-get install -y nodejs
```
本当に複数形を使う?

新しい現場の識別子に関する規約が "~List などではなく複数形を使う" であった。
まあそれはいい。だが本当に複数形を使う覚悟がおありだろうか?

# 複数形にするというのは末尾に s を付ければいいという話ではない
child の複数形が children だという辺りはさすがに知っているだろうけど、
index の複数形は indicies だし、英単語の information には複数形がない(他の印欧語の現代語で information と同語源の単語は複数形を許しつつあるようだが)。
data はそもそも本来複数形になっていて、語源的にいうと単数形は datum だ。

fish は単数形も複数形は fish なんだけど fishes という言い方もあり、複数形としての fish と fishes では意味が異なる (魚が複数いるのか、複数の種類の魚なのか、という違いのようだ)。

you は文法上は複数形として扱われるが英語ネイティヴの言語感覚的には単数形で、複数形なら you guys のようになるし、本来の単数形は thou だ。

くらいの事情は理解した上で複数形を使いましょうという話であろうか?
その問いへの回答が yes であれば特に問題はない。


# 多分コレクションとしての単数形を使う方が間違いがない
そもそも我々ネイティヴ日本語話者にとって、単数形と複数形をちゃんと区別する事が難しいだろう。
そしてよく使われがちな ~info とか ~data がそもそも単数形か複数形かの意味で非常にやっかいな類いなのだ。
確かに map なのか dictionary なのかで Java の人と C# の人が喧嘩する、みたいなシナリオは容易に想像できるが、複数形をちゃんと使う方がもっと修羅の道だと個人的には思う。
AppleWatch使用記録――その真価と課題――

## 使ってますか、アップルウォッチ
iPhone3GSからスマホデビューのはずが、しばらくAndroidに浮気して、近年はMacと共にずっと林檎ユーザーです。とはいえX以降のようなモダンな機種は持っていません。20万円を持ち歩くと思うと怖くて。
さておき、アップルウォッチはいまのところ結構いい感じです。レビュー類は無限にあると思いますが、声はあればあるほどいいと思いますので、簡単に投下しておきます。

### 使用機種など
- アップルウォッチSE
- 40mm
- ミッドナイトなんとかみたいなバンド（純正を使用）
- 2022年夏ごろより半年くらい使用

## ここがGood
- アプリのプッシュ通知機能を見逃したくない人にはマスト以上のマスト
- ウォーキングをなんとなく記録しておける
- タイマー機能も何気にいい スマホで設定したタイマーもアップルウォッチで止められる
- バッテリー、めちゃくちゃもつ。1日以上余裕
- Siriも使える。手元にスマホがないときに。

## ここがややBad
- たまーーーに再起動しなければならないことになる
- カバー必須。身長175cmの腕の長さか、ドアノブにモロにガチンとぶち当てることがあるので、カバーがなかったらどうなってたことか。ダイソーの200円のやつで十分
- 夏場は弱化ムレ感がある
- 冬場は袖で隠れて通常の腕時計以上に捲くる作業が煩わしく感じられる
- 手首の手寄りに装着すると、バンドの止め金具がMac下部にガチガチ当たる ので、手首の肘寄りに装着する必要がある
- 文字盤が常にうっすら出ている上位機種にすればよかった。手首を上げないと見えないのは結果的にマイナス
- バッテリーは24H以上長持ちするけど通知を常に受け取りたい場合はいつ充電するかが問題になるので結果的に夜は外すことになる

## おわりに
総合的には非常に満足しています。Androidならもっと安い中華製スマートウォッチで済んだんでしょうけども、そこはもう林檎のOSの密連携にお金を払ってると思えば。SE2みたいな感じで文字盤常時表示の機種が出たら買い換えると思います。
ギリギリダイヤルアップ世代のプログラミング初心者だったN=1がAtCoderで入茶を果たすまで

## はじめに
プログラミング学習開始直後くらいから密かに続けていた競技プログラミング「AtCoder」にて無事入茶を果たしましたので、どのようにしてレーティングを上げていったのかの備忘録・・・というか、私のような
- ギリギリダイヤルアップ世代（戦隊モノはカクレンジャー前後）
- プログラミングを長年触れているわけではないがある程度理解した初中級者
- Python好き（「使い」というほどではない）

が入茶に至った経緯などをお伝えできればと思います。
また、見出しにもあるようにN=1の記録ですので、あくまで一つのお話として。

## 前置きとして
ギリギリダイヤルアップという表現をしたように、PC自体には疎くありあせん。なんならプログラミングをまともに触らないタイプながらも情報科出身ですし、PCは自作するしAdobeも触れるしタッチタイピングは1分400文字だし、という感じ。何らかソフトウェアを使う、ということは問題なく、苦手意識からプログラミングだけは避けてきたという感じです。
卑下したいわけでは決してありませんが、ずっとパソコンを触らないような業務に就いていてIT系目指そうぜ系情報商材やインフルエンサーに感化されたされたか何かで突然この何年かでパソコンごと触り始めたような方とは多少は素地が違うということです。
ある程度ITに関しての疑問が積年した上でプログラミングやネットワークを学び始めたので、完全にゼロイチではないというほうが手短かもしれません。

したがって例に上げたようなものに沿う方には本当に参考にならないと思いますし、そもそも本当にあくまで一つのお話として。
まあハリケンジャーくらいの世代なら今からでも何やっても余裕だとは思います。

## JavaScript、Paizaから出会う
実はプログラミングの開始はJavaScriptでした。「ひらがなプログラミング」という入門書名著で学習し、テキトーにChromeの拡張機能を作りましたが、地力UPということでPaizaを勧められたところゲーム性にドはまり。もともとゲーマーだったのもありますが。
で、こういうのは「競技プログラミング」と呼ばれ、Pythonのほうが向いており、個人開発の面でもPythonしかないでしょくらいの勢いだったので（もちろんJavascriptも個人開発向きだとは思います）、今度はひらがなプログラミングのPython版を読んでパイソニスタにジョブチェンジ。
以降はずっとPythonです。{}を使う言語を今見ると「おおふっ」となります。Pythonも文字列系で使いますけど、そういうことではなく。
で、本格的な競技プログラミングとしてAtCoderと出会ったことで、茶色を目指す旅が始まったのです。

## アルゴリズムは学んだほうがいい、けども
私が始めた2021年4月頃にはなかった良書、「競技プログラミングの鉄則」が最近リリースされましたが、これはもう初学者マストバイとしても、アルゴリズムとはどう向き合うべきなのでしょうか。
競技プログラミングをやっているとある程度傾向があるのが見て取れますが、その全てはアルゴリズムの学習で完全にカバーできません。
それよりは、まず基本的な操作を難なくこなせて、最低限「あんな操作があったなあ」とあやふやでもググってnkmkさんの記事を参照してすぐに使えるくらいは必要です。でなければABCのAすら怪しいかもしれません。
最近は難化しているのでBでもややこしいのが来ると詰むと思います。
ですので、まずはアルゴリズムよりも過去のABCのAとBをひたすらやるといいと思います。
過去問は[このページ](https://kenkoooo.com/atcoder#/table/)にまとまっています。
その後に、灰色のC問題にチャレンジして、当然全然解けないでしょうけども、なんとなく惜しいところまで行ってから、アルゴリズムと計算量について学ぶのがいいと思います。

私個人は、AとB問題は上記の通りですが、C問題はアイデアとひらめきだけで無理やり突破できるものを突破するというランボースタイルでしたので、かなり無駄足を踏みました。

## アルゴリズムでは突破できない問題は
残念ながらアルゴリズム系書籍ではカバーされていないC問題があります。
むしろこれこそが崖というか一つのマターなのではと思います。
例えばラジアン角みたいなキーワードが出てくる図形問題、辞書で何番目的な問題がパッと思いつくところです。
これらの頻出の図形辞書問題までカバーしつつ、せいぜいDくらいまでに留めた競技プログラミングxPython特化の書籍が待ち望まれるところです。
これはもうそれらのC問題を集めておいてまとめて解きまくるのがいいかなあと思います。

## アルゴリズムを学んでからはコツとテンプレ
先述の良書「競技プログラミングの鉄則」は基本的なアルゴリズムの勉強に非常に役立ちました。
ですがYouTube動画等のほうがわかりやすいものもありますので、いろいろ横断的に見てみるといいと思います。
グラフ（DFS,BFS）、DPあたりが理解できればこっちのもんです。

## 入茶は開催運もある
2022年末ごろのABCは、Cまで異様に簡単でDから崖（難しくなる）でした。
すると、Cまで高速で解いた者勝ち（順位の妙でレーティング爆上がり）という現象がありました。
もちろん、その「簡単とはいえCまで高速で解ける」という技量こそトータルの力量ということになるので、開催運が大きなマターではないものの、入茶にはいいタイミングだったのかもしれません。
Cすら難しい回だとなかなかレーティングが変動せず嫌になる可能性は高いと言えます。

## まとめ
- ある程度参加しないとそもそもレーティングは上がっていかない。いきなり入茶とかは絶対に？無理。
- ある程度問題の感じに慣れたら早めにアルゴリズムを学ぶ。闇雲は長続きしない。
- 余計なことを考えなくていい分、入茶はやはりPythonが無難か

今後は落ち着いたらまた再開して、より上位の色を目指していきたいです。
草莽Erlang ── 24. lists:min

口で言うより行うことがErlang習得への近道と信じています。

https://qiita.com/mnishiguchi/items/9237780e849d80a85e11

## 異なる型の比較

Erlangではどんな型の組み合わせでも大小の比較判定が可能です。

```erlang
number < atom < reference < function < port < pid < tuple < map < list < bitstring
```

https://www.erlang.org/doc/reference_manual/expressions.html#term-comparisons

## lists:min

```
min([term, ...]) -> term
min(リスト) -> 最小値
```

リストの最小値を求めます。どんなリストに対しても実行可能です。

https://www.erlang.org/doc/man/lists.html#min-1

練習してみます。

```erlang
> lists:min([1, 2, 3, 4]).
1

> lists:min([1.0, 2, 3, 4]).
1.0

> lists:min(["1", {2, 3}, '4', #{x => 5}, 6]).
6
```

## Elixirにも挑戦したい

闘魂ElixirシリーズとElixir Schoolがオススメです。

https://qiita.com/torifukukaiou/items/3b65e5c04fa8c55f526e

https://elixirschool.com/ja

https://qiita.com/piacerex/items/09876caa1e17169ec5e1
[Android] M2 Mabcookで開発環境を作る

大変沼ったのでメモ
先に書いておくと先人様の記事を2023年1月になぞった時のメモになります。

# 環境

- M2 Macbook Air
- Ventura 13.1
- Intellij IDEA

# JDKのインストール
本項ではこちらを参考にします。
https://zenn.dev/sasakiki/articles/d331b611f29c68
```
brew tap homebrew/cask-versions
brew install --cask temurin11
```
私の環境ではv19と同居する状態になったので下記を追記してv11を利用するように
```.zshrc
export JAVA_HOME=`/usr/libexec/java_home -v "11"`
PATH=$JAVA_HOME/bin:$PATH
```

# SDK Managerのコマンドラインツールのインストール
本項ではこちらを参考にします。
https://qiita.com/kazokmr/items/22ab227643b472fc5016

下記のCommand line tools onlyセクションのSDK tools packageをダウンロードする。
https://developer.android.com/studio/#downloads

解凍するとこんな感じになりますが、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306146/9fc721f0-14af-9658-6ee3-e28be54c8999.png)

これを次の画像のような構造に変えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306146/3fb374d6-cbc3-893f-72b7-6257506c18fe.png)

次に都合のいい場所へ移動します。
今回は`/Library/Android/sdk/`までディレクトリを準備して、その中に入れました。
こんな感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306146/198eb101-f631-b9c0-36c3-64981528e21e.png)

次にパーミッションの設定をします。
```zsh
sudo chown -R root:wheel /Library/Android/sdk
sudo chmod -R 777 /Library/Android/sdk
```

# sdkmanagerコマンドで、必要なパッケージをインストールする

さっき作った`cmdline-tools/latest/`のような構造にしないとここで動かなくて沼ります([参考](https://stackoverflow.com/questions/65262340/cmdline-tools-could-not-determine-sdk-root))
```zsh
# 最新のパッケージ情報に更新する
/Library/Android/sdk/cmdline-tools/latest/bin/sdkmanager --update
# パッケージリストを表示し、Android platformとbuild toolのバージョンタグを確認する
/Library/Android/sdk/cmdline-tools/latest/bin/sdkmanager --list
# Android Platformをインストールする
/Library/Android/sdk/cmdline-tools/latest/bin/sdkmanager "platforms;android-33"
# Android BuildToolをインストールする
/Library/Android/sdk/cmdline-tools/latest/bin/sdkmanager "build-tools;33.0.1"
```

# SDK追加等
以降の操作は下記と同じでできます。
https://qiita.com/kazokmr/items/22ab227643b472fc5016#intellij-idea%E3%81%ABsdk%E3%82%92setup%E3%81%99%E3%82%8B
Rubyのローカル変数とインスタンス変数の違い

# はじめに
#### <font color="red">※以下の内容には誤りが含まれる可能性があります</font>


Rubyには使える変数が4種類あります。なかでもローカル変数とインスタンス変数の違いが重要です。





### <font color="blue">参照範囲が違うんですね</font>


# 具体的な内容


### ・ローカル変数

変数名が小文字または`_'で始まる変数。


ブロック内またはメソッド定義内でしか参照されない。

```ruby:ローカル変数
class Human
name = “太郎”
def myName
puts name
end
end
human = Human.new
human.myName
```



### ・インスタンス変数

変数名が@で始まる変数。


newメソッドで作成したオブジェクトの中に限り、どこからでも参照


できる。通常オブジェクトの外からは参照されない。

```ruby:インスタンス変数
class Human
def initialize(name)
@name = name
end
def myName
puts "私の名前は#{@name}です。"
end
end

human1 = Human.new("太郎")
human1.myName #"私の名前は太郎です。"
human2 = Human.new("二郎")
human2.myName #"私の名前は二郎です。"
```




## 変数のスコープとは

スコープとは変数の有効な範囲のこと。


その変数がスコープの外に出てしまえば参照できず、


たとえ名前が同じでも違う変数として扱われる。






# まとめ










| 変数の種類　　 　 |特徴　
|:-----------|------------:|
| インスタンス変数       | 同一クラス内のメソッドであればどこでも使用できる。インスタンス変数はインスタンスごとに値が異なる。        | 
|  ローカル変数    | 変数の有効な範囲(変数のスコープ)が局所的(ローカル)で、有効な範囲を越えていれば同じ名前の変数でも違う変数として扱われる。     | 





# 最後に
なぜインスタンス変数が存在するのか。


メソッドの中だけであればローカル変数で十分ですが、


オブジェクトが複数あった場合、ローカル変数では足りないからです。
Next.jsのプロジェクトを作る

記載日 : 2023/1/13

備忘録として、Next.jsでプロジェクトを新規作成する手順を記載します。

## 環境
OS : Ubuntu 22.04
node.js : 18.12.1　（nodenv使用）
VSCodeインストール済（拡張機能からGit Graphをインストール済）

## 作業 (計5分)
### 0.プロジェクトを作成する (5分)
新規プロジェクトを作成する。作成中にESLintを使うか質問されるので矢印キーを使って Yes/No 選択する。

<details>
<summary>npxを直接使用する場合</summary>
<div>

~~~command
npx create-next-app react_try --ts
~~~

</div></details>

<details>
<summary>yarnを使用する場合</summary>
<div>

~~~command
yarn create　next-app react_try --typescript
~~~

</div></details>


### 1.Webサーバ起動する
Webサーバ起動する。

<details>
<summary>npxを直接使用する場合</summary>
<div>

~~~command
npx run dev
~~~

</div></details>

<details>
<summary>yarnを使用する場合</summary>
<div>

~~~command
yarn dev
~~~

</div></details>

`http://localhost:3000`へブラウザからアクセスするとデフォルト画面を見ることができる。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1381309/255486c0-83e4-ac1c-5300-0bb9697a9be2.png" width=80%>

### 2.GoogleFontのダウンロードFailedについて
最初のうち、サーバを起動するとGoogleFontsのダウンロードが失敗してしまう事象が起きて悩んだ。（`yarn dev`を実行してから数分待たないと、サーバが起動しなかった。）
以下を試しても上手く動かなかったが、後日再起動したら問題なく動いた。`apt update`をしていなかったのが原因だったのかもしれない。
現在は、2.1と2.2のどちらも実施せずとも、問題なくサーバ起動できる。

#### 2.1.optimizeFontsをfalseにする
参考サイトを見て、next.config.jsのnextConfigに`optimizeFonts: false`を追加した。
~~~typescript
const nextConfig = {
    reactStrictmode: true,
    optimizeFonts: false // 追記分。
}
~~~

#### 2.2.global.cssでGoogleFontをimportする
参考サイトを見て、globals.cssにimportの記述を追加した。
（参考サイトを見ると、推奨できないやり方らしい。）
~~~css
@import url('https://fonts.googleapis.com/css2?family=Kurale&display=swap');
~~~


## 参考にさせて頂いたサイト
・Google Fontがダウンロードできないエラーについて
https://stackoverflow.com/questions/72399203/google-fonts-not-loading-in-next-js-when-deployed-to-vercel
https://stackoverflow.com/questions/69388400/nextjs-google-font-is-not-loading-or-displaying-on-the-website

・Next.jsプロジェクトを作る際に、typescriptのものを作るやり方について
https://nextjs.org/docs/basic-features/typescript
https://qiita.com/ekzemplaro/items/a73bb2b1181cd1b5f466
Install ROS easily

# Get and save .sh file

Move Github ROBOTIS-GIT/robotis_tools
[ROS2 Dashing](https://github.com/ROBOTIS-GIT/robotis_tools/blob/master/install_ros2_dashing.sh)
[ROS2 Foxy](https://github.com/ROBOTIS-GIT/robotis_tools/blob/master/install_ros2_foxy.sh)
[ROS Noetic](https://github.com/ROBOTIS-GIT/robotis_tools/blob/master/install_ros_noetic.sh) 
[ROS Melodic](https://github.com/ROBOTIS-GIT/robotis_tools/blob/master/install_ros_melodic.sh)
[ROS Kinetic](https://github.com/ROBOTIS-GIT/robotis_tools/blob/master/install_ros_kinetic.sh)
and click `Raw`, then save .sh file by `Ctrl + S` to Dowloads folder.

# Install ROS
Run .sh file, then you rename {ROS_DISTRO}=ros version you got.
```
cd ~/Downloads
sh install_ros_{ROS_DISTRO}.sh
```

Check your ros environment.
If you cannot run the following command and get error,
```
User@PC:~$roscore
The program 'roscore' is currently not installed. You can install it by typing:
sudo apt install python-roslaunch
``` 
let's try the following command.
```
echo "source /opt/ros/kinetic/setup.bash" >> ~/.bashrc
source ~/.bashrc
```

---
<font color="yellowgreen">**QiitaLink**</font>
<font color="black">**Designed by RENOX**</font>
Flutterを環境構築 + 初歩的なDartコードを書いてみた

Angela Yu氏のFlutter開発講座を受講開始しました。

https://www.udemy.com/course/flutter-bootcamp-with-dart/

Python・Kivyを使った開発だとビルドがうまくいかずムカついてしまったので、（笑）マルチプラットフォームでちゃんとしたオンライン講座があるフレームワークを使いたいと考えました。日常生活を便利するアプリをいろいろ作ってみたいなと思ってます。

## Flutterについて

https://flutter.dev

FlutterはGoogleが開発した、**マルチプラットフォームで開発**ができるアプリ開発用フレームワークです。開発言語には、こちらもGoogleが独自開発した**Dart**という言語を使います。
Flutterを用いれば、ネイティブクオリティーのiOS・Androidアプリを手早く制作することができます。Flutterを使ってアプリ開発をしている企業にはGoogle、アリババ、ハミルトンミュージカル等々の大企業が挙げられます。

Flutterを使う利点の一つが、**マルチプラットフォーム**であることです。Flutterは1つのDartコードからiOS・Androidアプリ、そしてWebアプリケーションをデプロイすることができます。
もう一つの利点が、**UIツールキットを使ってレスポンシブ対応**ができることです。レスポンシブ対応とは、Web開発で用いられるページレイアウトを様々な画面幅に適応させる手法です。UIツールキットには、レスポンシブ対応が可能な様々なレイアウト・デザイン用の部品が含まれています。

## Flutter開発に必要なもの

Flutterにおける開発は、**ウィジェットをレゴブロックの様に組み合わせていく**という要領で行われます。これらのウィジェットは、ツリー構造で積み重なる形となります。（ウィジェットツリー）

Fultterの開発には、ハードに関してはWindowsかMac・Linux、ソフトに関してはAndroid StudioかVSCodeが必要です。私はAndroid Studioを使用しています。またGitをDLする必要があります。Flutterは、SDKとしてAndroid Studioに導入する形で使います。

#### 必要なもの一覧

- Git：https://git-scm.com/download/win
- Android Studio:https://developer.android.com/studio
- Dart SDK: https://dart.dev/get-dart/archive
- Flutter SDK：https://docs.flutter.dev/get-started/install/windows

Flutterのコードの実行には付属のエミュレーターが使える他、Android・iOS携帯の実機をPCに接続してデバッグに使うことができます。

Android StudioでFlutterを使うには、Android StudioにFlutter・DartのプラグインをDLする他、Flutter SDKを環境変数に通して機能を使えるようにする必要があります。特に、プロジェクトの作成がうまく行かない場合はコマンドプロンプトで`flutter doctor`を実行すれば必要な作業が明白になります。
![スクリーンショット 2023-01-13 201547.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/54eeadb5-9dc8-8c5f-1cdf-08682c7cea90.png)


## Dartコードを書いてみた

早速初歩的なDartコードを書いて実行してみました。Textウィジェットを画面中央に表示するコードです。

```dart
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: Center(child: Text("Hello World"))));
```

丸カッコの終端にコンマを入れ、`右クリック→"Reformat code with Dart format"`を押せば・改行・インデントを含んだレイアウトに自動でリフォームしてくれます。

```dart
import 'package:flutter/material.dart';
void main() {
  runApp(
    MaterialApp(
      home: Center(
        child: Text("Hello World"),
      ),
    ),
  );
}
```

![スクリーンショット 2023-01-13 095231.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/7ebbb94f-a0dc-5068-0751-e8bd4113bc14.png)

次に、アプリの基礎となるスカフォールド(Scaffold)ウィジェットを作ります。スカフォールドウィジェットでは、上・下のバーに加え左右のナビゲーション、右下のトグルボタン等々がセットになっています。

https://api.flutter.dev/flutter/material/Scaffold-class.html

まずは、上のバー + ボディーに画像を表示するアプリとして見ました。

```dart
import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.blueGrey,
        appBar: AppBar(
          title: const Text('I am Rich'),
          backgroundColor: Colors.blueGrey[900]
        ),
        body:Center(
          child: const Image(
            image:AssetImage("images/diamond-6687408_640.png"),
          ),
        ),
      ),
    ),
  );
}
```

![スクリーンショット 2023-01-13 212601.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/c078e2f7-1fa5-9b32-43a0-99f914836f5d.png)

次回はこうしたアプリの構造を踏まえたうえで、実用的なアプリの開発を目指します。頑張りますね！
【React】useStateとuseReducerはどのように使い分ければいいのか

# この記事について
初学者がReactを学習し初めて気づいた点や、学んだ点を発信しています。

<br>


# useStateとuseReducerはどのように使い分ければいいのか
useReducerとuseStateの使い分けについて学習したため、記録に残します。

## useStateについて
状態の更新の仕方は利用側に託します。つまり使用する場合は、使用する側が更新の仕方を新たに定義してあげる必要があります。

## useReducerについて
状態の更新と、状態の仕方も含めて状態側で管理をします。つまり使用する場合は、更新の**方法**を指定するだけで、更新の**仕方**を指定する必要は無くなります。

<br>

:::note info
今回分かったこと！
**複雑なアプリケーションを複数人で開発する場合では、予期せぬエラーを防ぐためuseReducerを使用することが適している。**
:::