OmniAICreator/Qiita-1.07M huggingface dataset:
sbtでpublishするときのまとめ

sbtを使ってmaven repositoryにアップロード(publish)するときの、build.sbtに設定する方法をまとめます。

# 今北産業

- 必要なプロジェクトに `publishTo` を設定する。
- 必要なプロジェクトに `publish / skip := false` を設定する。
- 必要ないプロジェクトに `publish / skip := true` を設定する。

# ケースまとめ

## rootがライブラリの場合

`publishTo`を設定します。認証などが不要なら、基本はこの設定だけでアップロードできます。

```build.sbt
publishTo := Some("maven repositoryへのパス")
```

実際にアップロードする場合は`sbt publish`を実行します。

```console
sbt publish
```

## サブプロジェクトの1つがライブラリの場合

例えばWebアプリとAPIクライアントをまとめているプロジェクトを想定します。`root`は`aggregate`とし、**`root`を含む**全てのプロジェクトに対して、アップロードが必要ならば`publish / skip := true`を追加します(root忘れがち)。

```build.sbt
lazy val commonSettings = Seq(
  publish / skip := true,
  ...
)

lazy val publishSettings = Seq(
  publish / skip := false,
  publishTo := Some("maven repositoryへのパス")
)

lazy val root = (project in file("."))
  .settings(commonSettings)
  .aggregate(apiClient, webApp)

lazy val apiClient = (project in file("apiClient"))
  .settings(commonSettings)
  .settings(publishSettings)
  ...

lazy val webApp = (project in file("webApp"))
  .settings(commonSettings)
  ...
```

`commonSettings`でスキップするようにして、後で`publishSettings`でスキップしないようにするのがわかりやすいかなーと思います。sbtのsettingsは宣言的ではなく、書いた通りに実行されるので、`commonSettings`と`publishSettings`を逆にしちゃうと意図通りに動かなくなるので注意です。

## サブプロジェクトの複数がライブラリの場合

WebアプリとAPIクライアントがあって、それらが共通して利用するModelsプロジェクトがある想定です。APIクライアントがModelsプロジェクトに依存するので、Modelsプロジェクトもアップロードできなくてはいけません。

```build.sbt
lazy val commonSettings = Seq(
  publish / skip := true,
  ...
)

lazy val publishSettings = Seq(
  publish / skip := false,
  publishTo := Some("maven repositoryへのパス")
)

lazy val root = (project in file("."))
  .settings(commonSettings)
  .aggregate(models, apiClient, webApp)

lazy val models = (project in file("models"))
  .settings(commonSettings)
  .settings(publishSettings)

lazy val apiClient = (project in file("apiClient"))
  .dependsOn(models)
  .settings(commonSettings)
  .settings(publishSettings)
  ...

lazy val webApp = (project in file("webApp"))
  .dependsOn(models)
  .settings(commonSettings)
  ...
```

注意として、`aggregate`には`models`も含める必要があります。これを含めないと`sbt publish`で`apiClient`しかアップロードされません。しかし、`apiClient`はアップロードされていない`models`に依存するため、これを利用するクライアントは依存関係が解決できなくなります。

# 参考

https://www.scala-sbt.org/1.x/docs/Publishing.html

https://github.com/sbt/sbt/issues/3136
Python基本文法2(while文 編)

# 概要
Python初心者です。自分の備忘録用２です。
前回の[Python基本文法1(リスト、辞書、for文 編)](https://qiita.com/iwhg0211/items/973365ed1fe7e707126b)の続きです。
どなたかの助けになれば幸いです。

# 勉強したサイト
[Progate](https://prog-8.com/dashboard)

# while文
```ターミナル
x = 1
while x <= 100:
 print(x)
 x += 1
# ↑Xがtrue（今回はXが100より多くなるまで）の間、下２行の処理を繰り返します。
```

```ターミナルの結果
1
2
3
...
100
```

##### 注意！

```ターミナル
x = 1
while x <= 100:
 print(x)

# ↑Xが更新されないように書くと...
```
```ターミナルの結果
1
1
1
1
1
1
.
.
.

```
と、永遠に処理を繰り返します。これは異常な負荷がかかるので、確実に条件がfalseになるようにしましょう！
また、

```ターミナル
x = 1
while x <= 100:
 print(x)
X += 1
# ↑printの下のx += 1がprintのbインデントに含まれていないと...
```
```ターミナルの結果
1
1
1
1
1
1
.
.
.
```
これも永遠に処理を繰り返します!注意！

#### break文
繰り返し処理の際、途中で処理を終わらせるためのコマンド
```ターミナル
numbers = [1,2,3,4,5,6,7,8,9]
for number in numbers:
    print(number)
    if number == 3:
        break
# ↑もしnumberが３の時、処理を強制終了する
```
```ターミナルの例.
1
2
3
```

#### continue文
```ターミナル.
numbers = [1,2,3,4,5,6,7,8,9]
for number in numbers:
    if number % 2 == 1: ←取り出したnumberが２で割り切れる（偶数）の場合
        continue
    print(number)
```
```ターミナルの例.
1
3
5
7
9
```
Salesforce DevTools – Saleforce.com開発者向け強力なChrome拡張機能

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)


+ [Salesforce DevTools – Saleforce.com開発者向け強力なChrome拡張機能](https://www.xgeek.net/ja/salesforce/tesforce-for-google-chrome/)

+ リストビュー設計書自動生成(Released at v3.7.0)
+ オブジェクトレイアウト設計書自動生成 (Released at v3.5.0)
+ 特定項目の一括チェックオン/チェックオフ(Released at v3.4.0)
+ カスタム項目一括編集 (Released at v3.3.0)
+ Apex Debug Log Viewer (Released at v3.2.0)
+ Lightningで使えるようになりました! (Released at v3.0.0)
+ QueryエディタとCSV出力機能 (Released at v2.8.0)
+ ERDs自動生成 (Released at v2.7.0)
+ All Check (Released at v2.6.0)
【Amazon Connect】初心者がLambdaとの連携でひっかかったこと

みなさんこんにちは！
早いものでそろそろ社会人一年目になろうとしている新卒エンジニアです。

現在の部署に配属されてはじめに行ったのがAmazon ConnectとLambdaの連携だったのですが当初は思ったようにいかないことが多く、
近い未来で自分が後輩に教える立場になったときに過去の自分がどこで躓いていたかを記録したいと思い今回この記事を作成することにしました。

使い慣れている方にとっては当たり前の内容ばかりになるとは思いますが、これからLambdaを触ってみたい方、同じような躓きをしている方の参考になれば幸いです。
 
ちなみに、Lambdaを初めて触った時点での私のスペックを簡単に紹介します。
- AWS自体入社後の新人研修で初めて触ったレベルの初心者
- Amazon Connectは研修で一度簡単なコールセンターを作成した経験あり
- Python歴は独学で3年程度、主に機械学習などの目的で使用していた
- Python3エンジニア認定基礎試験取得済（別記事に合格体験記があります）

上記の理由から今回Lambdaの記述にはある程度使い慣れているPythonを使用することにしました。
ここから私が実際にAmazon ConnectとLambdaの連携で躓いた点について書いていきます。

# ①コンタクトフローの情報を受け取りたい
はじめに実装したかったLambda関数がコンタクトIDと顧客の電話番号をS3にcsvで保存するというものだったのですが、これらの情報の取得方法がわかりませんでした。

Lambdaがeventで受け取るデータはjsonデータで、以下のようになっています。

```json:event
{
  "Details": {
    "ContactData": {
      "Attributes": {},
      "Channel": "VOICE",
      "ContactId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
      "CustomerEndpoint": {
        "Address": "+xxxxxxxxxx",
        "Type": "TELEPHONE_NUMBER"
      },
      "CustomerId": "",
      "Description": "",
      "InitialContactId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
      "InitiationMethod": "INBOUND",
      "InstanceARN": "arn:aws:connect:ap-northeast-1:xxxxxxxxxxxx:instance/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "LanguageCode": "ja-JP",
      "MediaStreams": {
        "Customer": {
          "Audio": ""
        }
      },
      "Name": "",
      "PreviousContactId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "Queue": "",
      "References": {},
      "SystemEndpoint": {
        "Address": "+xxxxxxxxxx",
        "Type": "TELEPHONE_NUMBER"
      }
    },
    "Parameters": {
    }
  },
  "Name": "ContactFlowEvent"
}
```

上記を参考に、LambdaでコンタクトID、顧客の電話番号を取得したい場合以下のように記述します。

```python:Lambda1
def lambda_handler(event, context):
    contactid = event['Details']['ContactData']['ContactId']
    customer_phone_num = event['Details']['ContactData']['CustomerEndpoint']['Address']
...
```

# ②returnでエラーになる
下記は私がはじめに作成したLambdaのreturn箇所です。
```python:Lambda2-1
...
    return 200
```
このままではエラーになります。
ドキュメントを確認すると、以下のように記述されています。

>関数から返される出力は、英数字、ダッシュ、アンダースコアのみが含まれる値を持つ、キーと値のペアのフラットオブジェクトである必要があります。

下記のように修正することで解決することができました！

```python:Lambda2-2
...
    return {"statuscode": 200}
```

# ③作成した関数を呼び出したい
無事Lambda関数の作成が完了したら、あとはフローで呼び出すだけです。
早速「Lambda関数を呼び出す」ブロックを配置し関数を選択しようとしたのですが、作成した関数が表示されませんでした。

Amazon ConnectのフローでLambda関数を呼び出したい場合、事前にそのLambdaを紐づけておく必要があります。

【手順】
1.Amazon Connectコンソールから対象の**インスタンスエイリアス**を選択する
![エイリアス選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728375/28654edf-4a1c-069f-fc8f-5d0a68d7ed2a.png)
※実際の画面では赤枠内にインスタンス名が表示されています

2.左側ナビゲーションメニューから**問い合わせフロー**を選択する


3.AWS Lambdaセクションで**Lambda関数**ドロップダウンボックスから対象のLambdaを選択
![関数選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728375/321b27ae-1144-2cca-91be-9b8b5ca8b691.png)

4.**Add Lambda Function**ボタンを押す

# 最後に
過去の自分がわからなかったところを振り返ったことで、初心にかえることができた気がします。
ここまでお読みくださりありがとうございました！

# 参考

https://docs.aws.amazon.com/ja_jp/connect/latest/adminguide/connect-lambda-functions.html
【Amazon Lex】トリガーとなる質問なしでインテントを呼び出す

# やりたいこと
* Amazon Connectの問い合わせフローでAmazon Lexを呼び出し、名前を質問する
* 質問自体はAmazon Connectのプロンプトで再生する
* 初めから聞く内容が決まっているため、Lex上で「ご用件はなんですか？」「予約をしたいです」というような最初の質問を必要としない
![会話例_トリミング.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728375/45e4464d-9d29-262b-df13-f6e8ba99906e.jpeg)
# ①Amazon Lex
インテント名は**CheckName**に設定しました。

#### スロット
![01_スロット.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728375/3d34b528-c309-3ae1-30f0-0708c9a04fbb.jpeg)
今回このプロンプトは再生されませんが必須項目のため仮の文章を入力しています。

#### 応答を閉じる
![03_応答を閉じる.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728375/e6763d9f-6c91-6bcc-04b8-362513a6920f.jpeg)
取得した情報を再生します。

#### サンプル発話
![02_サンプル発話.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728375/a33dc5c3-2e2f-b1bc-b781-515c150e78d4.jpeg)
**<font color="Red">ここがポイントです</font>**
{Name}でスロット名をインテント呼び出しのトリガーとして指定します。

以上の設定で構築し、Lex上でテストを行うとこのようになります。
![05_テスト.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728375/2e4e7525-f569-be3d-48b2-edc54efd6268.jpeg)

# ②Amazon Connect
#### インスタンスにLexを追加
![06_lex追加.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728375/9bb820c4-f821-21ce-faa1-b3dc800251aa.jpeg)
#### 問い合わせフロー
**顧客の入力を取得する**ブロックの設定
![078_顧客の情報を取得する.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728375/9f752db3-ac94-3dff-e304-05340ebe54eb.jpeg)

以上で想定通りの動きを実装できました！
現状認識率があまり良くないのが難点です。

# 参考
https://docs.aws.amazon.com/ja_jp/lex/latest/dg/gs2-create-bot-configure-intent.html

https://dev.classmethod.jp/articles/amazon-lex-with-amazon-connect/
Three.js(R3F)でカメラレイヤーの切り替え


# 初めに

最近もっぱらWEBGLをやってます。（結構たのしい）

今回はカメラレイヤーの表示非表示の切り替えがどの程度パフォーマンスに影響するか可視化しました。

# 実行結果
![layer0.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493888/123c1ceb-8742-fa56-220f-6f80e5c1a2d6.gif)

# React Three Fiberで記述

## ソースコード

```react
import { OrbitControls } from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber"
import { Perf } from "r3f-perf";
import { useEffect } from "react";
import { Vector3 } from "three";

// テスト用初期値
const boxNum = 1000;    // 表示するBoxの最大数
const layerLength = 10; // レイヤーの数 (1 ~ 10)
let viewLayer = 1;      // 初期レイヤー

export const CameraLayerControlComponent = () => {

    const { camera, gl } = useThree();

    /**
     * レイヤーを変更
     */
    const changeLayer = () => {
        viewLayer++;
        if (viewLayer > layerLength){// 設定レイヤー数を超えたら
            viewLayer = 0;
            camera.layers.disableAll();
            camera.layers.enable(viewLayer);
        }
        camera.layers.enable(viewLayer);
    }

    /**
     * ランダムな色を取得
     * @returns 
     */
    const getRandomColor = () => {
        const letters = '0123456789ABCDEF';
        let color = '#';
        for (let i = 0; i < 6; i++) {
            color += letters[Math.floor(Math.random() * 16)];
        }
        return color;
    }

    /**
     * 任意の範囲でPositionを取得
     * @param min 
     * @param max 
     * @returns 
     */
    const randomVec3 = (min: number, max: number) => {
        const x = Math.floor(Math.random() * (max - min + 1)) + min;
        const y = Math.floor(Math.random() * (max - min + 1)) + min;
        const z = Math.floor(Math.random() * (max - min + 1)) + min;
        return new Vector3(x, y, z);
    }

    useEffect(() => {
        // 最初はカメラレイヤーを１にセットする
        viewLayer = 1;
        // 常に表示するBOXはレイヤー０として設定
        camera.layers.enable(0);
    }, [])

    useFrame((_state, delta) => {
        const position = camera.position.clone();
        // カメラの位置によってLayerをOn/OFF
    })

    
    return (
        <>
            <mesh onClick={() => changeLayer()} layers={0}>
                <boxBufferGeometry args={[5, 5, 5]}/>
                <meshStandardMaterial color={0xff0000}/>
            </mesh>

            {[...Array(boxNum)].map((_, idx) => {
                const color = getRandomColor();
                const position = randomVec3(-50, 50);
                const layerNumber = Math.ceil(((idx + 1) / (boxNum / layerLength)));
                return (
                    <mesh position={position} layers={layerNumber}>
                        <sphereBufferGeometry/>
                        <meshStandardMaterial color={color}/>
                    </mesh>
                )
            })}
            
            <OrbitControls/>
            <Perf />
        </>
    )
}
```

## まとめと感想

CPUやGPUの負荷が比例して上がっているので、
カメラのレイヤー切り替えはパフォーマンス向上にいい手段だと感じました。

カメラの描画位置によって、
表示するレイヤー層を表示非表示を切り替えれる機構があれば、
ReactThreeFiberの性能を向上させるのではないでしょうか。

次は、水平方向にグリッドを引いて、
レイヤー番号をつけてカメラ位置からの近いものを表示することで
どれほどのパフォーマンスが向上するか見てみたいです。

おわり。
TypescriptでPromise.allを使用したループ処理

Typescriptでは、非同期処理を簡単に扱うことができます。
特に、複数の非同期処理を並列実行する場合には、Promise.allを使用することが推奨されます。

今回は、猫の数を数える例を用いて、Promise.allを使用したループ処理について説明します。

## 例：猫の数を数える処理
まず、猫の数を数える処理を非同期処理として実装します。以下の例では、1秒間待ってから、猫の数を返す非同期処理を定義しています。


```typescript
function countCats(): Promise<number> {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(3);
    }, 1000);
  });
}
```
次に、任意の数のPromiseオブジェクトを生成する関数を定義します。

```typescript
function createPromises(): Promise<number>[] {
  const promises: Promise<number>[] = [];
  for (let i = 0; i < 5; i++) {
    promises.push(countCats());
  }
  return promises;
}
```

最後に、Promise.allを使用して、生成した複数のPromiseオブジェクトを並列実行します。

```typescript
Promise.all(createPromises()).then((results) => {
  let total = 0;
  for (const result of results) {
    total += result;
  }
  console.log(`合計猫の数: ${total}匹`);
});
```
この例では、5つのPromiseオブジェクトを生成して、Promise.allを使用して並列実行しています。
すべてのPromiseオブジェクトが完了したら、then関数が実行されます。then関数では、結果を加算して合計猫の数を出力しています。
[Blender]必要無くなったマテリアルを削除する

# 概要
使われていないマテリアルは名前の頭に「0」が表示されています。
![スクリーンショット 2023-02-09 7.31.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/b4c50868-853b-4188-32a9-c2871448bc36.png)

こういうマテリアルを削除する手順を共有します。
# 本文
わかりやすくするためにまず作業場所を確保します。
画面上部のタブをどれでもいいので一つ決めて右クリック（今回はLayoutにしました）
![スクリーンショット 2023-02-09 7.36.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/642dc5a1-00b9-c39b-a7f2-f70949fcba9d.png)
メニューからDuplicate
![スクリーンショット 2023-02-09 7.35.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/51296db1-4e63-ceeb-2ccb-75eefc2666b9.png)
左上EditorTypeからOutliner
![スクリーンショット 2023-02-09 7.39.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/548ce88e-0cb8-0f5c-701b-402e6189fe20.png)
その右隣のDisplayModeからOrphan Data
![スクリーンショット 2023-02-09 7.40.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/25dd9bef-32e2-ff4b-b76e-f30a7d532eda.png)
そうすると使用されていないMaterialだけが表示されます。後は右クリックでメニューを表示してDeleteを選び削除します
![スクリーンショット 2023-02-09 7.43.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/40291c41-ea87-f082-48a1-f7f15be95f63.png)
# 最後に
最初の手順で確保した作業場所はもう必要ないので閉じておきます。
（右クリックしてDelete）
![スクリーンショット 2023-02-09 7.49.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/84de5ccf-5dc8-ea8a-1eb5-18daa702955d.png)
USE　EFFECTについて

# useeffectの引数には、何を入れればよいですか？

useEffectの引数は、関数（エフェクト関数）を渡す必要があります。また、オプションとして、第2引数に依存関係の配列を渡すこともできます。

# エフェクト関数の例を書いて下さい。

エフェクト関数の例：

useEffect(() => {
  // リクエストを送信してデータを取得する
  fetch('/some/endpoint')
    .then(res => res.json())
    .then(data => {
      // データを処理する
    });
}, [dependency1, dependency2]);

# エフェクト関数にreturnはいりますか？

はい、エフェクト関数にはreturnを書くことができます。return値は、エフェクト関数が完了したときに実行されるクリーンアップ関数を指定するために使用されます。

# 例を書いて下さい

useEffect(() => {
  // リクエストを送信してデータを取得する
  const fetchData = async () => {
    const res = await fetch('/some/endpoint');
    const data = await res.json();
    // データを処理する
  };
  fetchData();

  return () => {
    // クリーンアップ処理を行う
  };
}, [dependency1, dependency2]);

# クリーンアップ関数とは何ですか？

クリーンアップ関数とは、特定のエフェクト関数が実行した後に実行される関数のことです。これは、一般的に副作用を解除し、必要なデータを削除するなどの関数を指します。これは、エフェクト関数内で行われた変更をクリーンに保つために必要な処理を行います。

# 分かり易く説明してください

クリーンアップ関数とは、特定のエフェクト関数が実行した後に実行される関数のことです。これは、エフェクト関数内で行われた変更をクリーンに保つために必要な処理を行うもので、例えば、イベントリスナーを解除したり、取得したデータを削除したりするなどの処理を行います。
とっても重要なテーブルインデックス(INDEX)とは

未経験からエンジニアになりたい人は、プログラミングから始める人が多いと思いますが、
エンジニアの仕事は、プログラミングだけではありません。そして、プログラミングだけでは、エンジニアになれません。同時にプログラミングが苦手でも、システム構成や開発の流れを理解するとエンジニアに近づきます！
今回はテーブルのインデックス(INDEX)について更に詳しく調べてみましょう！
![インスタスライド_202301225.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/b7083695-50cc-2fc4-aeb8-422a25d0b84d.gif)


# INDEXとは
処理効率を図るために検索用のインデックスを作成する事ができる

実世界で、書類をバインダーにまとめ、索引ラベルを付けるのと同じ！

→　検索の高速化のために作る

・検索頻度の高い項目にインデックスを作成する

・インデックスは、テーブルとは別の場所にインデックスのデータのみ保有する

・検索速度は速くなるがインデックスの張りすぎは、　更新速度の低下をまねく

・ツリーインデックスや、クラスターインデックス等がある

# INDEXを張るコツ
Where句で検索する時は、INDEXが使えるか？
INDEXがないなら作る必要があるか
必ず検討すること

INDEXを作る事をIndexを張ると言います

# INDEX事例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/59f3b976-4591-6616-bab2-3bac2a529425.png)

# まとめ
ー検索の高速化のためにIndexを張る

ーIndexの貼りすぎはNG

ーwhereで検索する時はIndexを検討する

ーIndexを作る事をIndexを張ると言う

# 最後に
未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
5G 産業連携(vertical domains)の仕様書を読む　TS 22.104

5Gのユースケースの銀の弾丸は、3GPPのStage1(要求条件)にあるのでは？
と思いたち、
TS 22.104　cyber-physical control applications in vertical domains　Stage 1 Rel-16
を読んでみました。

// 状況　とりあえず、仕様書から絵だけ切り貼り。

# サマリ
ページ数は55ページ

# 参考文献
[1]3GPP TS 22.104 V16.5.0 (2020-07)

# 詳細

## 5 Performance requirements 
分散された自動化アプリの間の通信を、5Gでやる。
CSIF：Communication Service Interface
// CSと言われると Circuid Switch（回線交換）が頭をよぎります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/fbc954be-f29b-2eec-e0c3-8cf2ecc0ac55.png)
図は[1]より引用

？？？理解できず。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/0b2341cf-3b8e-daf1-f6e3-cb74905eb930.png)
図は[1]より引用


## 5.2	Periodic deterministic communication

・Motion Cntrol：転送間隔が500μ秒～2m sec・・・　
　//想定の10^-3くらいのオーダーだった。
・Mobile robot：転送間隔10msec　100端末
　//ロボサッカーとかこんな感じになりそう。
・工作機械制御（組み立て・穴あけ）：転送間隔 1～50msec
・建設機械（クレーン・ポンプ）：転送間隔 12msec
・プロセス自動化：転送間隔 10msec
　？？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/044d4442-6634-5789-0bc3-6191d4528598.png)
図は[1]より引用

## 5.3	Aperiodic deterministic communication
あとよみ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/4cb7360e-dd7f-4079-1b56-44eb80389a47.png)
図は[1]より引用

## 5.4	Non-deterministic communication
あとよみ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/7366e228-915f-3771-f3f7-6a9bb7821d85.png)
図は[1]より引用

## 5.5	Mixed traffic
あとよみ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/ce05dc38-2158-3097-684b-52ce8b5f181b.png)
図は[1]より引用

続く
pythonの連想配列で存在しないキーを取得したい。

例えば、リスト１、リスト２の２つが存在していて、リスト１に存在しないリスト２の要素を
リスト１に追加した新たなリストを作りたい。
ハッシュマップを使って高速に探索する。
    list1 =["a","b","c"]
    list2=["a","c","d"]
    hashmap = {}
    list3= []

    # リストにある要素を連想配列に追加
    for i in list2:
        hashmap[i] = i

    # 連想配列にない要素を追加
    #補足　get()は第2引数を持たせることでkeyがない場合のreturnを指定できる。
    for i in list1:
        if hashmap.get(i) is None: list3.append(i)


    #コメントより
    # 連想配列にない要素を追加
    for item in list1:
        if item not in hashmap: list3.append(i)
Eclipse jarファイルのエクスポート


## jarファイルの作成
①Eclipseのパッケージエクスプローラの対象プロジェクト名上で右クリックし、「エクスポート」を選択
②「エクスポート」ウィンドウが表示されるので、「Java > 実行可能JARファイル」を選択し、「次へ」ボタンを押下
③「実行可能JARファイル エクスポート」ウィンドウで「起動構成」にmain()メソッドのクラスを指定する
④同ウィンドウで、「エクスポート先」を指定する

## jarファイルの実行方法
「java -jar FILE_NAME.jar」
「start FILE_NAME.jar」

参考： https://java.keicode.com/lang/how-to-compile-jar-with-eclipse.php
2023/2/9主にITとかセキュリティの記事

「ESXiArgs」対策で製品の更新やOpenSLPの無効化を呼びかけ - VMware
https://www.security-next.com/143465

契約者情報の不正持ち出し、約2.9万件と判明 - JSB
https://www.security-next.com/143479

メタバース活用におけるセキュリティを考えるオンラインイベント - JSSECら
https://www.security-next.com/143477

ジェイ・クリエイション、不正アクセスにより個人情報含むデータ暗号化被害(2/7)
https://cybersecurity-jp.com/news/78226

Microsoft 365のデータ消失は「自己責任」？　保護ポリシーの確認を(2/7)
https://kn.itmedia.co.jp/kn/articles/2302/07/news019.html

代わり映えしない10大脅威から、筆者が読み解いた“悪い兆候”(2/7)
https://news.yahoo.co.jp/articles/f027300b5faf60fac5f6097620a436f2afe60981?source=rss

経産省ら、クレカ会社などにフィッシング対策強化を要請(2/7)
https://www.zaikei.co.jp/article/20230207/708722.html

ラック、サイバー救急センターに関する新たな事業方針を発表(2/7)
https://securityinsight.jp/news/13-inbrief/5313-230207-1

サイバー保険、世界初の大災害債　投資家リスク引き受け(2/7)
https://www.nikkei.com/article/DGXZQOUB279NN0X20C23A1000000/

悪質な広告「マルバタイジング」や「アドウェア」による被害をどう防ぐ？(2/7)
https://ascii.jp/elem/000/004/123/4123609/?rss

裕隆カーシェアも、1.6万人の顧客情報流出リスク（トップニュース）／台湾(2/7)
https://www.ys-consulting.com.tw/news/107278.html

英議員「TikTokアプリを削除せよ」中国監視を警告(2/7)
https://www.epochtimes.jp/2023/02/135618.html

サイバー戦でのウクライナの「教訓」台湾有事に生きるか(2/7)
https://news.yahoo.co.jp/articles/6610af3f6dc5af479eba46f4dbf00f42cc9970df?source=rss

アバランチ上DEX「Trader Joe」、レイヤーゼロ導入でJOEをクロスチェーン転送可能に(2/7)
https://www.neweconomy.jp/posts/294284

自称ビットコイン開発者クレイグ・ライトの25億ドル訴訟が裁判に(2/6)
https://www.neweconomy.jp/posts/293962

英中銀、デジタル通貨の発行検討　20年代後半にも(2/7)
https://www.nikkei.com/article/DGXZQOGR06BWH0W3A200C2000000/

Microsoft OneNote悪用したフィッシング増加、ウイルス対策ソフトで検出できず(2/7)
https://news.mynavi.jp/techplus/article/20230207-2584262/

マイクロソフト、古い「Office」の稼働状況を把握するパッチの詳細を説明(2/7)
https://japan.zdnet.com/article/35199658/

社会のデータ流通を安全に。帝国データバンクと富士通のeシール普及への挑戦(2/7)
https://www.fujitsu.com/jp/microsite/fujitsutransformationnews/2023-02-07/01/

DX推進を実感できている企業は24.7％　データ活用とのセットが得策か──企業IT動向調査2023(2/7)
https://enterprisezine.jp/news/detail/17325

AI の時代を迎えるにあたって: 責任ある AI で未来の発展へ(2/7)
https://news.microsoft.com/ja-jp/2023/02/07/230207-responsible-ai-chatgpt-artificial-intelligence/

身代金を払う企業がまさかの減少、収入減で焦るランサムウエア攻撃者が立てた新戦略(2/8)
https://xtech.nikkei.com/atcl/nxt/column/18/00676/013100126/

富士通、Web3プラットフォーム「Fujitsu Web3 Acceleration Platform」を無償提供(2/7)
https://xtech.nikkei.com/atcl/nxt/news/18/14611/

「パスワードは流出している」が当たり前、管理方法を見直して不正ログインを防ぐ(2/8)
https://xtech.nikkei.com/atcl/nxt/column/18/02353/020700005/

iPhoneを物理デバイス認証でフィッシングから防御、iOS 16.3の「セキュリティキー」(2/8)
https://xtech.nikkei.com/atcl/nxt/column/18/00088/00133/

オンプレミスのシステムも組み合わせて使う、「ハイブリッドクラウド」とは(2/8)
https://xtech.nikkei.com/atcl/nxt/column/18/01842/011900029/

DX推進でのコミュニケーション　相手ありきで留意する5つの要点(2/8)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/010500334/020600002/

社員1人ひとりの変革を支援する「ADKARモデル」の活用法(2/8)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/111100323/020600004/
【Laravel】通常の実行で正常に動作する処理がコマンド実行ではエラーになる原因がAuthファサードだった！

通常の実行(ボタンを押すと発火する処理等)では、上手くいくのに、ターミナルでのコマンド実行（`php artisan batch:Test`）や、自動実行（`php artisan schedule:run`）で実行した場合にエラーになりました。

原因はauthファサードだったので、備忘録を兼ねて記事にしました。

## 考察
authファサードはログインした状態のユーザーが実行した場合に使えるメソッドです。

今回、私が実行したコマンド処理がcronで自動実行する処理だったため、ログインしていない状態で実行していました。

そのため、authファサードを実行しても空が返ってきたようです。

開発時にログインした状態でボタン発火を行い検証していたため、同じ処理でもコマンド時に上手くいかなかったようです。

ボタン発火の処理であれば、laravelの`dd`機能が使えて楽に開発できるのですが、こういった点に目を落とすため注意が必要ですね。

次に検証の際に実行した処理を記載します。

## 実行処理

```ruby:TestCommand.php
class TestCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'batch:Test';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'テスト';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        Log::debug(Auth::id());
        Log::debug(auth()->id());
        return 0;
    }
}
```
## コマンド
```ruby:ターミナル
php artisan batch:Test
```


## ログ
空で出力される
```ruby:laravel.log
[2023-02-09 03:44:39] local.DEBUG:   
[2023-02-09 03:44:39] local.DEBUG:   
```

## 環境
Windows 10
PHP 7.4.29
Laravel Framework 8.83.15
canmatrixを含むasammdf のExe化

# asammdf を Exe化すると警告が表示される
[asammdf GUIをExe化する](https://shibaura-it.tokyo/it-solution/asammdf-gui-exe/) をみると簡単にexe化できそうにみえるが、
Python-3.8.10、asammdf-7.3.2の場合、試すとこんな警告が出る。

```
arxml is not supported
csv is not supported
dbc is not supported
dbf is not supported
json is not supported
ldf is not supported
kcd is not supported
fibex is not supported
sym is not supported
xls is not supported
xlsx is not supported
yaml is not supported
scapy is not supported
wireshark is not supported
odx is not supported
```

```Lib\site-packages\asammdf\gui\asammdfgui.py```に
```python
import csv
```
と追記しても出続ける。```import arxml```とかもエラー出るし。

# 警告が出る理由
```canmatrix-0.9.5``` が 悪さをしている。
```canmatrix.formats.csv```等を動的にimportしているが、pyinstaller で検出できず。
そもそも```csv```ではなく、```canmatrix.formats.csv```。。。

```python
import canmatrix.formats.csv
import canmatrix.formats.arxml
import canmatrix.formats.dbc
import canmatrix.formats.dbf
import canmatrix.formats.json
import canmatrix.formats.ldf
import canmatrix.formats.kcd
import canmatrix.formats.fibex
import canmatrix.formats.sym
import canmatrix.formats.xls
import canmatrix.formats.xlsx
import canmatrix.formats.yaml
import canmatrix.formats.scapy
import canmatrix.formats.wireshark
import canmatrix.formats.odx
```
を ```Lib\site-packages\asammdf\gui\asammdfgui.py``` に追記してExe化

```
Scripts\pyinstaller.exe Lib\site-packages\asammdf\gui\asammdfgui.py -w
```

無事にできたっぽい。```--onefile```を付けると、1ファイルになるが、起動時重い。。。
[備忘録] Optunaの探索結果をUMAPで可視化する

ハイパパラメータが3つ以上存在する場合，探索結果の可視化はなかなか難しいです．
今回はUMAPを利用して探索結果の可視化を行います．

```python
import matplotlib.pyplot as plt

import numpy as np

import optuna

import umap


DIM = 6
SEED = 42
N_SAMPLES = 1000
N_GRID = 50
LB, UB = -5, 5


def func(X: np.ndarray) -> np.ndarray:
    return np.sum(X ** 2, axis=-1)


def objective(trial: optuna.Trial) -> float:
    X = np.asarray([trial.suggest_float(f"x{d}", LB, UB) for d in range(DIM)])
    return func(X)


def get_mapper():
    rng = np.random.RandomState(SEED)
    S = rng.random((N_SAMPLES, DIM)) * (UB - LB) + LB
    mapper = umap.UMAP(random_state=SEED).fit(S)

    S_trans = mapper.transform(S)
    x_bound = np.min(S_trans[:, 0]), np.max(S_trans[:, 0])
    y_bound = np.min(S_trans[:, 1]), np.max(S_trans[:, 1])
    return mapper, x_bound, y_bound


def plot_contour(fig, ax, mapper, x_bound, y_bound):
    X, Y = np.meshgrid(np.linspace(x_bound, N_GRID), np.linspace(y_bound, N_GRID))
    S_grid = np.stack([X.flatten(), Y.flatten()], axis=-1)
    F = func(mapper.inverse_transform(S_grid))

    level = np.linspace(0, 25 * DIM, N_GRID)
    cb = ax.contourf(X, Y, F.reshape(X.shape), level)
    fig.colorbar(cb)


study = optuna.create_study()
study.optimize(objective, n_trials=100)

mapper, x_bound, y_bound = get_mapper()
X = np.asarray([[t.params[f"x{d}"] for d in range(DIM)] for t in study.trials])
X_trans = mapper.transform(X)

fig, ax = plt.subplots()
plot_contour(fig, ax, mapper, x_bound, y_bound)
ax.scatter(X_trans[:, 0], X_trans[:, 1], color="red", s=1)
plt.show()

```
障害対応は寝て、食べるが大事

「 **障害対応** 」 

エンジニアができるだけ見たくない単語ですね。
でも人間が作っているシステムである以上おそらく避けては通れない道...

実は直近で障害対応を経験し、正直すごくしんどい思いをしました。
今回はその教訓を記事に起こしたいと思います。

# 障害&起こったこと

2月某日クライアントから障害報告が来ました。
幸い既に障害原因箇所が今後は動かないコードの部分だったのでシステム自体の改修はありませんでした。

ですが、障害報告として対象データの洗い出しを行う必要がありました。
結構対象データの件数もあったのですが、粛々と対象しないといけないです。
一通り調査し、報告したところ **トラブル発生** ...

調査結果に不備が見つかってしまいました。。。。
障害が起きている時点でクライアントは結構噴火寸前。
もちろん厳しいお言葉をいただきました。。。。

その後も続く調査&報告....そして厳しいお言葉の数々。
今まで障害対応は何度かやってきましたが、
まーうまくいかない。。。

終わってみて気づきました。やっちゃいけなかったことの数々...
みなさんしっかり見てくださいね。
結構あるあるだと思います。。。。


# やっちゃいけないことその1：「人としての生活を崩壊させる」

本当に気をつけないといけないことですね。
というか障害対応あるあるな気がする。。。。

そんな私も↓のようになってました。

* 睡眠時間ほぼなし、昼夜問わず障害データと向き合い続ける
* ご飯なんかほぼ食べない（1日でコップ1杯の水&リポD&ハッピーターン数枚）
* ずっと部屋に篭りっきり

おかげさまでイライラするし(お腹空きすぎ)、頭は痛い(睡眠不足)
そして何よりパフォーマンスが明らかに下がってるんですよね。
思考が巡らないというかなんというか。

やばい状況だからこそ冷静でいないといけないのに
睡眠・食事をちゃんと摂らないと本当に冷静になれないです。
そしてめっちゃポンコツになります。
なので障害が起きたらまずやることはご飯を食べて寝る。
絶対やってほしい。

もちろんそうもいってられない状況もあるので一概にやるってことはできないと思います。
ですが、長期戦になればなるほどやらないといけないことだと今回本当に思いました。

# やっちゃいけないことその2：「調査を内部で完結させる」

これはクライアントとの関係次第なのかな。。。
今回の場合は本音でぶつかればちゃんと一緒にやってくれるすごいいいクライアント様でした。

ですが、「障害 = 開発している私たちの瑕疵」という意識が拭えなかったため
調査も確認も全部こちら側のみで、データのみをお渡しするということをしていました。

まあ、何事もなければ内部のみでやって正式な結果を渡すでいいと思うんです。
でも今回は「調査結果不足」ということになってしまいました。
こうなってくると「調査したのはそちら側だけだから不足しているのはそちらが全て悪い」って感じになってくるんです。

なのでこういう調査とか報告は必ずクライアントを巻き込んだ方がいいなと思いました。
クライアントを巻き込んで調査すると、お互いに調査しあって不足してたとしても、
「お互い様だよね」って思ってもらえるので正直あんまり詰められないです。
そして何といっても「一緒に障害を乗り越えた」という気持ちがあるので
気持ち的にこちらが楽です（笑）

# やっちゃいけないことその3：「クライアントに調査データがわかりづらい報告」

今回これも厳しいお言葉の引き金だったじゃないかなと思ってます。。。。

まず次の2つの表を見てもらいたいです。

## 悪い例
| 障害対象 | 調査結果 | 
|-----------|------------|
| -       |         | 
| ○       | xxxのため障害対象データ | 

## いい例

<table>
<tr>
<th>障害対象</th>
<th>調査結果</th>
<th>調査データ1</th>
<th>調査データ2</th>
<th>調査データ3</th>
</tr>
<tr>
<td>-</td>
<td></td>
<td>xxxxx</td>
<td>yyyyy</td>
<td>zzzzz</td>
</tr>
<tr>
<td>○</td>
<td>調査データ3がnullのため障害対象データ</td>
<td>xxxxx</td>
<td color=red>NULL</td>
<td><b><font color=red>NULL</b></td>
</tr>
</table>

みなさんどうでしょう。。。
気をつけるポイントとしては

* 調査結果の根拠となるデータが一緒にあるか
* 調査理由が根拠となるデータを元にした理由となっているか
* 調査結果となる表が見やすいか（色をつけてあげたり、太字にしたり....)

基本的に調査結果を見るクライアントはDBのデータを見れないということの方が多いと思います。
だからこそ調査の根拠となるデータをこちらから出してあげないと
クライアント的には「何を根拠に....」と正直不安ですよね。。。
しっかりと根拠となるデータをつけてあげてかつわかりやすくしてあげれば
「しっかり調査してくれてるな」
「こういう理由で障害対象データなのね」
と理解していただける。

何よりちゃんとやってる感があるので今後の信頼に繋げていけるかなと思いました。

# 結論

ちょっと長くなっちゃいましたが、今回割と本気で追い込まれました。
でもきっとこういう経験する人は今後もいるはず。

そういう人たちに言いたいことは
「ちゃんと食べて、ちゃんと寝て!!!」
そして障害終わったら自分にご褒美たくさん買ってね！！！

以上！
BardによってGoogle検索は変わるのか？

AIの発達によって、ユーザーの答えを用意できるGoogleのBardというシステムが…

検索結果にも表示されるとか。

本サービスはまだローンチされていないのでなんとも言えないが、AIが答えてしまうならもう検索結果に出てきた各コンテンツが見られなくなるのでは？

…とSEO界隈で話題である。

例えば「アイロンでおすすめのものはなに？」なんてことをGoogleの検索画面で音声検索したりう打ち込んで検索すると

検索結果（サープス）の一番上に

G「アイロンで一番おすすめされているのは●●です。これは●●というメーカーが2022年に出したもので…」

といった具合だ。

これに関する情報もとのソースにリンクは付くみたいだが、正直行って検索流入はかなり減るだろう。

ただ、個人的にどうだろう？

”答えが明確でないもの＝個人の基準によって価値が変わるもの”

に対して、GのBardも一つの参考にはなるだろうけど、AI情報が全て正しいと思われてない昨今においてその程度脅威なのか？

※ただ、そもそも全て鵜呑みにしてしまうユーザーもいるのは分かるが。


わたしは、このAIにおいて一番の魅力は対話できることだと思っていて

G「アイロンで一番おすすめされているのは●●です。これは●●というメーカーが2022年に出したもので…」

↓

ユーザー「じゃあ実際に、どの程度シワが綺麗に取れるの？」

という風にGoogleと対話しながら検索をしていける。そして結果的に「アイロン　おすすめ」なんかでサープスの1枚目を取れなかったサイトたちが活躍できる（日の目を見る）ことになるのではないかな？

と思っている。

つまり、検索される間口や使い方が広がるのでは？と感じる。そして、それによってより多くのWEBサイトが訪問されることになるのでは？と。
CloudflareでCSSやJSがうまく取り込まれないエラー

## サイトのデザインが崩れている

アプリから普段使っている自前のmastodonなので気づかず、
久々にサイトにブラウザからアクセスするとCSSがサイトに適用されてないことを気づきました。
エラーは下記の内容が出ていることに気づきました。

```
Failed to find a valid digest in the 'integrity' attribute for resource 'なんかのアドレス/public-ab941698ac089d1d7d72.chunk.js' with computed SHA-256 integrity 'Hc7ySkRFUKaK478NGlcmpExGk33HiiIixG2obimbNzA='. The resource has been blocked.
```

## 原因
原因はCloudflareなどのCDNを使っているとオプション機能でcssやjsを圧縮してくれるみたいなのですが、
サーバー側の機能ですでに圧縮されていた場合に、
不正なコードが入っていないかチェックする機構が働くとこの現象が起きるみたいです。
下記のところでAuto minifyでjsとcssのチェックを外します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145608/03081aad-ff80-a523-d422-573d2917fc14.png)

最後にキャッシュデータをパージします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145608/db57339d-36ab-342f-0e88-1aa1dcc64b5a.png)

これで正常通りの表示になっているはずです。
構造体の埋め込みを GORM で利用すると便利

## 構造体の埋め込み

```go
type A struct{}

func (A) Execute() { println("A") }

type C struct { A }

func Test(t *testing.T) {
	c := C{}
	c.Execute()
}
```

上記のコードは正しく動作します。
このように、構造体を別の構造体に埋め込むことを Struct Embedding と呼びます。

## GORM での利用

GORM では、構造体からテーブル名を得る際に、構造体の `TableName` メソッドが使われます。
たとえば次のコードを書いたとき、GORM は `a` というテーブル名を得ます。

```go
type A struct{}

func (A) TableName() string { return "a" }
```

Struct Embedding により、以下の `B` 構造体は、外から見ると `TableName` メソッドを持つかのように見えます。

```go
type A struct{}
type B struct{ A }

func (A) TableName() string { return "a" }
```

よって、以下のコードは、`a` テーブルのすべての行を取得することを意味します。

```go
var rows []B
db.Find(&rows)
```

### 具体例 : Window 関数との併用

各生徒のテストの点数が格納されているテーブルがあるとします。
そして、成績の良い順に順位を割り振りたいとします。

テストの点数のテーブルを表す構造体の定義は以下です。

```go
type TestScore struct {
	ID    uint
	Name  string
	Score uint
}

func (TestScore) TableName() string {
	return "test_score"
}
```

このとき、次のように書くことで、順位を含めた結果を得ることができます。

```go
type Result struct {
	TestScore
	Rank uint `gorm:"column:rank_"`
}
var results []Result
db.Select("*, RANK() OVER (ORDER BY score DESC) AS rank_").Find(&results)
```

Struct Embedding を使うことで、Window 関数の結果を受け取れるような構造体を簡単に定義できることがわかります。
flutterをandroidstudioのwindows11環境で動作させるのに苦労した

Flutterを仕事で使う事になったが、
Windows11でFlutterを動作させるのになかなか手こずったのでメモ。
（なんでMacじゃないのとか言わないで...）

Flutterを入れる。
システム環境設定でパスを通して、
コマンドプロンプトでflutter doctorすると、
１．Windowsのバージョンエラー
２．Android toolchainのエラー
３．VisualStudioをダウンロードしていなかったためエラー
４．AndroidStudioのエラー

今、全て問題が解決してしまい思い出し記述。

１．Windowsのバージョンエラー
Windows11のバージョンエラーで参考にしたサイト。
https://lumitec.co.jp/hp/%E3%80%90flutter%E3%80%91windows-version-unable-to-confirm-if-installed-windows-version-is-10-or-greater/

２.Android toolchainのエラー
コマンドプロンプトで
flutter doctor --android-licenses
を入力するも、Javaが古いのじゃないとダメでコマンドが実行出来なかった。
古いJavaを入れてみたけど特に解決せず。
AndroidStudioにもJavaは入っていたので、
そちらを使ってみることに。
AndroidStudioからSetting→Build,Execution、Deployment→Gradleからjdkを確認。
JAVA HOMEもbinもシステム環境変数で同じpathに設定。
Javaをアンドロイドアプリの開発にしか使っていなかったからそうしたけど、
けっこう強引なやり方かも...。
![タイトルなし1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1593052/6f0b885a-400b-affe-e910-783703b3fe3f.png)
JAVAHOMEのパスを編集
![タイトルなし2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1593052/3306bf87-4005-9569-d573-33f779746486.png)
pathも設定。
![タイトルなし3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1593052/843e59de-1ac2-af3a-7ee7-9caa6c04daa5.png)


３．VisualStudioをダウンロードしていなかったためエラー
ダウンロードしただけ。

４．AndroidStudioのエラー
AndroidStudioのエラーは、
jbrフォルダをjreフォルダと間違えて読み込んでしまうFlutterの方の問題。
とりあえずは、
アンドロイドスタジオのフォルダから
jbrフォルダをコピーし、その場に張り付ける→jbrコピーができるので、
jreフォルダの名前を異常が起こらない程度に改変して、
さっきのコピーをjreの名前に変更。
これが一番簡単だった。
![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1593052/e9bd0c09-828d-ac4f-18d5-eea1038e6c9e.png)
AWS初心者がCloud Practitioner(CLF) に４週間で合格した件

## はじめに
今回取った経緯と自分の実力についてお話をした上で、実際やった勉強法の詳細を記載していきたいと思います。

[経緯]
・今年からAWSの開発環境を使ってデータの可視化と基盤構築を担当することとなり、事前勉強
・会社の開発環境が主にAWSであり、社内の流れに置いてきぼりならないため
・合格すれば、[機械学習関連](https://aws.amazon.com/jp/certification/certified-machine-learning-specialty/)の上級資格が半額で受験可能なため、今後のキャリアを見据えて、手始めに一番易しい資格からスタート

[自分の実力]
・データサイエンティスト社会人3年目　学生時代に計量経済学をメインで勉強
・文系学部出身のため、クラウドの知識おろかプログラミングも社会人になって本格的にやりだした
・AWSの知識はSagemakerを使ったことある程度

## 準備期間
・約４週間(平日1~3時間、休日最低4時間)
→2022年12月末〜2023年1月23日　途中コロナに罹患し、２週間程度受験日を遅らせる...

## 学習教材
①[一夜漬けAWS認定クラウドプラクティショナー直前対策テキスト[第2版]](https://www.shuwasystem.co.jp/book/9784798067155.html)
→簡素に内容がまとまっており、導入としては最高であった。勉強開始１週間程度で１周しました。巻末の問題がほとんど解けず、もっと広い知識の習得が必要と判断し、②の教材に着手。

②[これだけでOK! AWS認定クラウドプラクティショナー試験突破講座（豊富な試験問題290問付き)](https://www.udemy.com/course/ok-aws-e/)
→①だけでは不十分と思い、購入。年末年始を活用し、動画を見たが、正直頭には入らなかったです。しかし、テキストに関しては非常にわかりやすく、体系的にまとまっていました。（実務でも役立ちそう）

③[この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集（8回分520問）](https://www.udemy.com/course/aws-4260/)
→この問題集が一番使えた。基礎と本番レベルの問題計５セットを９割程度取れるまで繰り返し実施（大体５周ぐらい）。試験前日まで繰り返し解き、①や②のテキストと照らし合わせながら間違えた問題の解説を読み込みました。（あってる問題も軽く解説を読んで、誤解がないか確認はしました。）

## 試験当日と結果について
ピアソンのテストセンターで受けました。１時間以上かかる会場でしたので、前日は近隣のホテルで宿泊し、そこで勉強。
700点が合格ラインで、取った点数は717点。１問20点ぐらいの配点で、あと１問ミスってれば落ちてました....
![スクリーンショット 2023-02-09 0.54.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725527/d948c2a7-2a02-6907-bdca-84ec3254f7de.png)

また分野別でもどれくらいできたか？が確認できるのですが、２つの分野で合格点に達してない様な結果でした...
![スクリーンショット 2023-02-09 1.00.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725527/100c44b0-9d30-5f34-320a-a2fae4321a70.png)
とはいえ、合格できて安心しました......!!
なお、合否は試験終わってすぐPC上に表示、点数は試験終了半日後に、アカウント上で確認が可能でした。
 
## 合格の勝因
昨年統計検定２級に3回目でようやく受かるという苦い経験([記事はこちら](https://qiita.com/wakama-chan/items/efec20b33c185fb19e82)）をし、「落ちたらまた受験料無駄にするのか...!!」という切羽詰まる感覚で受けました。初見の模試で1回も合格点が超えず、不合格体験記も統計検定に比べればネット上に落ちている記事は少なく、「なんで理解できないんだろう..」と自分を追い込みました。そのおかげか、前日は10時間以上勉強ができ、こういった焦りが合格につながったんだと思います。

## 最後に
やはり、文系出身ということもあり、付け焼き刃の情報系の知識での短期合格は難しい面もありました。しかし、ほんの少しAWSで開発を進めただけでも、この資格で勉強したことが生きてきてます。例えば、LambdaやS3のIAMの設定にしても、これまではチーム内のAWSに長けたメンバーに聞いた情報を丸写ししてましたが、今では何も聞かずとも最低限の設定はできるようになりました。結論、業務の傍ら必死こいて勉強した甲斐があったなと思っています。
btrfsのファイル損壊現象に遭遇し解決したので備忘録として残しておきます。

# 結論
btrfsのマウントオプションで圧縮レベルが設定できるからといって使ってはいけない。compress-force=zstd:7でディスク使用量削減は諦めた。

# 結論に至った経緯
ローカルに保存した画像ファイルが何故か読み込み不能で開けなくなる問題に遭遇した。ブラウザではちゃんと表示されているためネット環境が悪くて正常にダウンロードできなかったのか思って何度か
```
curl -o temp.jpg https://*****/***.jpg
```
を実行して保存してみたが開けない。
もしかしてディスクの寿命かなと思って/dev/shm/上に保存して見ると開けたが不思議なことに他のファイルはローカルに正常に保存できる。

特定のファイルのみが何回やっても正常にディスクに保存できないという状態で
バイナリエディタで壊れたファイルを開くとファイルの先端0x20000まで0x00で埋まっていてリブートするとファイルサイズが0になる。
これらの特徴からファイルシステムがぶっ壊れたと思ってググってファイルシステムを調べるコマンドを実行してみたがエラー無し。

ファイルの先端だけ潰れる処理って何なんだろうと考えると何らかの処理をしている途中で処理がコケた場合、出力先にまだ何も出力していない段階なら0x00なのではと考えて圧縮処理を疑ったら正解だった。
fstabからcompress-force=zstd:7を除去すると今までの異常は何だったのかと思えるくらい正しく動作した。
正常に動作するしないの境界選り分ける作業を追加で行った

###### ファイルが壊れる
* compress-force=zstd:7
###### ファイルが壊れない
* compress-force=zstd:3
* compress-force=zstd (圧縮レベルはデフォルトでは3で上と同じ)
* 圧縮オプションなし

このテストの結果、高圧縮設定にすると何故かファイルが壊れることが分かった。
圧縮レベルを変えただけなのにファイルが壊れるって不思議だな。
家庭教師がオンライン授業のためのホワイトボード共有サイトを作ってみた（その2）

## 前提
今回はログインせずにボードを使える機能の実装を行なった。
[前回の記事]("https://qiita.com/esakiryota/items/999a640abda68d49c9ac" "前回の記事")
[ボードミート](https://board-meet.com/ "ボードミート")

## 技術
**バックエンド**
-- 言語
- Python3

-- フレームワーク
- Django 3.0.6


**フロントエンド**
-- 言語
- CSS
- Javascript
- HTML

-- フレームワーク
- jquery
- materiallize.css

**インフラ**
- AWS EC2
- AWS S3 storage
- AWS Route53

## アーキテクチャー

![スクリーンショット 2022-11-01 18.48.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1860891/9ab885ca-2127-3908-bec2-4ce2e87d8942.png)

## アップデート内容
- 家庭教師を授業を始める際に、いちいちログインするのが面倒くさいので、ユーザー登録、ログインをしなくてもホワイトボードを使えるようにした。

- トップページにアクセスした際に、トークンを発行し、そのトークンを元にルームを作成するように修正を行なった。
- ![start1-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1860891/148d0fc8-4a6b-8639-90f6-f183cfe886d5.png)

- そのトークンを保持しておけば、前回使ったホワイトボードも使えるようにした。

- 始め方ページを作成した。


## 使い方
![スクリーンショット 2022-10-29 19.35.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1860891/1fb50f26-d284-79d1-0b4c-f9ba89981478.png)
- 左上のボタンはボードに記述するためのボタン、左下はリロード、退出、ヘルプ（未実装）ボタン、右下は画像貼り付けや全削除、記述したコンテンツを1つ前に戻すボタン、右上はボードをzoomしたり、動かしたりするボタンです。

- ユーザー登録をすると、自分のホワイトボードを使うことができ、他のユーザーと相互フォロー状態になると、他のユーザーのボードも編集できるようになります。

- 全て無料で使うことができますので、ぜひ一度使ってみてほしいです。できれば、アイデアや、感想などがあればコメントや、bm_admin@board-meet.comのメールアドレスに送信していただくと非常にうれしいです！

## これから実装するもの
- 文字のサイズ、色などを変更する機能
- electronでデスクトップアプリケーション化すること

## ボードミートのコード
GitHub: [esakiryota/my-second-blog](https://github.com/esakiryota/my-second-blog)
クラシックマウス　作ってみた　その6 　プログラム方針


# はじめに
* 作成したクラシックマウスの解説。
* 今回はプログラミングの大まかな流れの話です。具体的なスケッチなどは次回以降です。
* 機体写真、動画などは「その1」をご参照。

# プログラム：大まかな方針
初めてのクラシックマウスで、キットを使わずに製作しているので、高度な動きは狙えない。以下の方針で製作しています。
* 完走が目標
    * とにかく完走が目標。時間内を目標としたいが、まずは時間がかかっても良いので完走が目標。
    * 最短経路での走行などは考えない。2回も走るような時間もない。
* できるだけ自分でプログラムする。
    * ライブラリは利用するが、機体の制御、探索などは自分でコードを書く。
    * マイコンもそれほど経験がないので、高度なプログラミングは難しい。割込みは使わない形になっています。
* 壁にぶつからないように
    * 壁にぶつかるとリカバリーが難しいので、なるべく車体が区画の中心になるようにしたい。

# プログラムの流れ
ちゃんとしたフローチャートは書けないのですが、以下のような流れにしています。
 
* ある区画に到着する
* 前方に壁があれば、前後位置を調節する。
* 左、前、右の壁までの距離を測定する。
* 現区画の壁の有無を判定する。さらにもう一つ先の壁も判定する。
* 壁情報をもとに足立法を用いて、ゴールまでのステップ数を更新する。
* 進むべき方向を決定する。優先順位は直進→左折→右折→Uターンの順。
* 左右にターンする場合は、ターン後に前後位置を調整する。
* 車体の向きを（Gyroセンサーで）調整する。
* 次の区画に移動する。
    * 左右の壁までの距離を測る。
    * 左右に壁があり、壁に近いOR壁から遠い場合は、次の区画の中央に向かうように車体の向きを調整する。
    * 左右に壁がない場合は、そのまま。
    * 加速→減速しなから18cm前進する。
    * 移動後に車体の向きを調整する。

# センサー情報
* VL53L0Xは連続計測モードとしていますので、30ms毎に勝手に距離を測定してくれます。距離を計測したい場合はセンサーから計測結果を入手して利用しています。シングル計測を用いる場合に比べて、静止時間が短くなっているように思います。
* 30msの時間が気になりましたが、本機の移動速度はそれほど早くないので、大きな影響はないようです。
* MPU6050も、DMPが連続的に計測を行ってくれるようで、必要な時に情報を取れば、その時点での機体の向きが入手できます。
* Arduinoのコアは一つですが、各センサーがマイコンを持っているので、ある種の並行処理ができている感じでしょうか。どちらのセンサーも安価なのに、小型で相応の性能があって感心します。

# 割込みについて
* 本プログラムでは、作者の不慣れもあって、割込み処理は用いていません。距離センサーが30ms毎に距離を測定しているので、タイマー割込みで車体の制御を行えるような気もするのですが。
* また、DMPも割込み用のピンがあるので、こちらを用いても車体の制御ができるような気がします。
* 次の製作では、ここらへんにも挑戦したいと思っています。

以上
【Git】GitHub pushが終わらない

## 状況
commitしたファイルを
```
~$ git push origin main
```
pushするも、
```
Enumerating objects: 25, done.
Counting objects: 100% (25/25), done.
Delta compression using up to 8 threads
Compressing objects: 100% (25/25), done.
Writing objects: 100% (25/25), 35.28 MiB | 762.00 KiB/s, done.
Total 25 (delta 1), reused 0 (delta 0), pack-reused 0
```
このまま止まってしまいアップロードが完了しない、終わらない

## 試したこと
control+Cでターミナルを閉じて再度pushしてみる

## 対処法
```
~$ git config --global http.postBuffer 157286400
```
上記のファイルのバッファサイズを上げ、再度pushする。
それでも若干時間はかかったものの、少し待ったらpush完了しました！
※追記もご確認ください。Git LFSを利用した対処法もあります。

## 原因
pushするファイルに画像が何枚か含まれておりファイルサイズが大きすぎたのが原因だと考えられます。~~あくまで考察ですが、、、~~

## 追記（2024.8.8）
Gitコミットの容量上限は1ファイル100MB以内のため、ファイルサイズが原因であると考えられます。
以下の記事を参考に、Git LFSを使うことで1GBまでファイルをコミットすることできます。

https://qiita.com/pvicugna11/items/f84cb2527989a3a4c63a


## 参考
[GithubにPushをしたが終わらない時の対処方法](https://qiita.com/Kazu_Project/items/230916db979e89fd90f3)
[Git push したのに完了のメッセージが出ない(他のエラーは出てない)](https://zenn.dev/t_fukuyama/articles/a7078ed624d04e)
[git push hangs after Total line](https://stackoverflow.com/questions/15843937/git-push-hangs-after-total-line/68711337#68711337)
【Mac】Homebrew で postgresql のバージョンを変えたら動かなくなった

## 起きたこと
新しいバージョンをインストールしてから、古いバージョンを起動しようとしたところ、status に`error 256`が出て、うまく動かなくなってしましました。
```zsh
$ brew install postgresql@14

$ brew services list
Name           Status  User  Plist
postgresql@14  stopped      
postgresql@11  error  256
```

アンインストールしても、なぜか存在し続けるという奇妙な現象。
```zsh
$ brew uninstall postgresql@14

$ brew list | grep postgresql
postgresql
postgresql@14
```
🔽 バージョン切り替えや起動方法については、こちらも参考にどうぞ！

https://qiita.com/yuppymam/items/fad4eec0c5b7d6c86517

## 調べたこと
どうやら、最初にインストールしたバージョンの頃と、新しいバージョンでは、データベースの場所が変更になっているようでした。

```zsh
# 旧
/usr/local/var/postgres

# 新
/usr/local/Cellar/postgresql
```

🔽 参考にさせてもらいました

https://blog.n-z.jp/blog/2020-01-08-homebrew-postgresql.html


## やったこと
古い場所のものを削除して、新しくインストールし直すことで error が消えました。
```zsh
$ rm -rf /usr/local/var/postgres*

$ brew reinstall postgresql@11
$ brew reinstall postgresql@14

$ brew services start postgresql@11

$ brew services list
Name           Status  User  Plist     
postgresql@11  started yuppy ~/Library/LaunchAgents/homebrew.mxcl.postgresql@11.plist
postgresql@14  none
```
【Express】express-generatorで作成した雛形でHTTPSサーバーを起動する【Node.js】

## はじめに
Node.jsとかExpressの公式ドキュメントは基本的にhttpサーバーの立ち上げ方しか解説されておらず、httpsサーバーはどうやって立ち上げるんじゃ？と思ったので、それをやります。
## やること
いつもの雛形に
①証明書配置用のディレクトリを作成して秘密鍵と証明書を配置
②bin/wwwを修正してhttpsサーバーを作成
の2点のみ。

## 環境
- Node,js：18.12.0
- npm：9.2.0
- Express：4.18.2
- EJS：3.1.8（別に必要ない）

## 1.雛形を作成
いつものやつ（テンプレートエンジンはejs）。
```
$ npx express-generator --view=ejs <アプリ名>
$ cd <アプリ名>
$ npm install
```
## 2.SSL証明書を配置
証明書配置用のディレクトリを作成し、
```
$ mkdir .ssl
```
秘密鍵と証明書を配置。
※証明書の作成方法は割愛
```
$ ls .ssl
server.crt  server.key
```
## 3.bin/wwwの修正
fsとhttpsのモジュールを追加して、HTTPSサーバーを作成するように修正する。
express-generatorがvarで書いてるから、なんとなくvarで書く。
```javascript:bin/www
#!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('../app');
var debug = require('debug')('sample-socket.io-express-generator:server');
var http = require('http');
var fs = require('fs'); // 追記
var https = require('https'); // 追記
/*----------省略----------*/
/**
 * Create HTTP server.
 */

//var server = http.createServer(app); // コメントアウト

// ここから下追記
/**
 * Create HTTPS server.
 */

var options = {
  key: fs.readFileSync('./ssl/server.key'),
  cert: fs.readFileSync('./ssl/server.crt')
};
var server = https.createServer(options, app);

/*----------省略----------*/
```
## 4.サーバーを起動

```
$ npm start
```
[https://localhost:3000/](https://localhost:3000/)に接続できることを感じる。
めでたし。

## おわりに
Node.jsとかExpress自体での解説記事はたくさんあるに、express-generatorの雛形での解説記事があまりみつからないので備忘録として書いてみました。
（記事が見つからないのは探し方がヘタクソなだけかもしれないが…）
express-generatorの雛形は非常に便利な反面、bin/wwwで起動しているせいでカスタマイズする時に詰まることが多々あるのがイヤですね…。
最近Expressに触れる機会があったので他にもexpress-generatorの雛形に関する記事を書いていきたいです。

## 参考
- [Node.js v18.14.0 - https.createServer([options][, requestListener])](https://nodejs.org/dist/latest-v18.x/docs/api/https.html#httpscreateserveroptions-requestlistener)
ApacheでSSL/TLSを利用する際の主な流れ

●ApacheでSSL/TLSを利用する際の主な流れ

1. 秘密鍵を作成する
例）秘密鍵のファイル名を「server.key」、アルゴリズムをRSA、鍵長を1024bitで作成
openssl genrsa -out server.key 1024

2. サーバ証明書を認証局に作成してもらう為、CSR証明書の署名要求を作成する
例）秘密鍵「server.key」を使用し、CSRをファイル名「server.csr」として作成
openssl req -new -key server.key -out server.csr

3. 認証局にCSRを提出し、その後、中間CA証明書とサーバ証明書が認証局より発行

4. 秘密鍵と中間CA証明書、サーバ証明書をサーバの所定の場所へ設置し、ApacheのSSL/TLS用の設定ファイル「ssl.conf」でそれぞれのファイルを指定する

5. Apacheを再起動する
apachectl stop; apachectl start


※opensslコマンドの-x509オプションは、CSRの代わりに自己署名証明書を作成。

例）秘密鍵「server.key」を使用して、サーバ証明書「server.crt」を作成する
openssl req -new -x509 -key ser
PHP7.4からPHP8系にバージョンアップ

`php -v`すると下記のエラーが出力した。どうやらicu4cの69系がインストールされてないとのことだった。

72系をインストールしているので、69系にダウングレードはしない。

```markdown
~ $ php -v
dyld[8500]: Library not loaded: '/usr/local/opt/icu4c/lib/libicuio.69.dylib'
  Referenced from: '/usr/local/Cellar/php@7.4/7.4.27/bin/php'
  Reason: tried: '/usr/local/opt/icu4c/lib/libicuio.69.dylib' (no such file)
```

`type -a php`でPHPバージョン確認してみる。

```markdown
~ $ type -a php
php is /usr/local/opt/php@7.4/bin/php
```

現在PHPのバージョンが`7.4`であり、セキュリティサポートが終了していたので、これを機に8系にバージョンアップした。

PHP8系をインストール

```markdown
// インストールするバージョン検索
~ $ brew search php8
==> Formulae
php@8.0 　　　 　　　　php@8.1 ✔

// php@8.1をインストール
~ $ brew install php@8.1
```

インストール完了後、パスを通す。

```markdown
$ echo 'export PATH="/usr/local/opt/php@8.1/bin:$PATH"' >> ~/.zshrc 
$ echo 'export PATH="/usr/local/opt/php@8.1/sbin:$PATH"' >> ~/.zshrc
$ source ~/.zshrc
```

 再度、`php-v`を確認したところ、表示されました。

```markdown
~ $ php -v
PHP 8.1.15 (cli) (built: Feb  3 2023 12:46:32) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.15, Copyright (c) Zend Technologies
with Zend OPcache v8.1.15, Copyright (c), by Zend Technologies
```

### 参考：
https://qiita.com/gyu_outputs/items/60b75e1acc98ca03c092
GitHub ActionsのWindowsイメージでbashを使う方法

## 想定読者
- 普段はGitHub Actionsのホステッド ランナーでUbuntuなどLinux系のイメージを利用している
- Windowsイメージを使うのは初めて
- WindowsでもLinuxのコマンドをそのまま使いたい

## GitHub Actionsのホステッドランナーとは
- ワークフローを実行する仮想環境のこと
- `runs-on:` で指定する
- Ubuntu, Windows, Macが指定できる

## 課題
- 異なるホステッドランナーで共通のコマンドを実行する場合、WindowsとUbuntu, Macでデフォルトで実行すると互換性がないため、実行エラーになる
- Windowsイメージでは何も指定しない場合、pwsh(パワーシェル)が使われます
- Linux/macOSイメージでは何も指定しない場合、bashが使われます

## 解決策
- stepのshellでbashを指定することでWindowsイメージでもLinuxのコマンドをそのまま利用できます
- ちなみにWindowsイメージでbashが使えるのはGitは最初から入っているからのようです。

> Windowsでbashシェルを指定すると、Windows用Gitに含まれるbashシェルが使用されます。

```yml
runs-on: windows-latest
    steps:
      - uses: actions/checkout@v3
      - name: messi is 🐐
        shell: bash
        run: |
          messi='🐐'
          echo $messi
```


## 参考
- [jobs.<job_id>.steps[*].shell](https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell)
- [About GitHub-hosted runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners)

## さいごに
もしこの記事が参考になったら、いいねが貰えると更新の励みになります🙇‍♂️
RustでRubyのハッシュを実現する

# RustでRubyのハッシュを実現する
Rust初心者が、Rubyのようなハッシュ形式でデータを扱おうとすると苦戦しました。結論は一番下にある。
## やりたいこと
Rubyのように`変数名.キー`（ここでは`user.name`）という形で値を取得したい。
```
user = { "name": "Shohei", "age": 27 }
user.name // => "Shohei"
```
## 背景
Rustのハッシュマップを使ってもうまくいかない。
### パターン１
ハッシュマップを使ってやってみる。
```rust
fn main() {
    let mut user = HashMap::new();
    user.insert("name", "Shohei");
    println!("{:?}", user["name"]); // => "Shohei"

    let mut user = HashMap::new();
    user.insert("age", 28);
    println!("{:?}", user["age"]); // => 28
}
```
これじゃあ、nameとageが別の変数として扱われる。配列みたいに、データをまとめて保存したい。
### パターン２
ハッシュマップ + タプルを使ってみる。
```rust
use std::collections::HashMap;

fn main() {
    let mut user = (HashMap::new(), HashMap::new());

    user.0.insert("name", "Shohei");
    user.1.insert("age", 28);

    println!("{:?}", user); // (　{"name": "Shohei"}, {"age": 28}　)
    println!("{:?}", user.0["name"]); // "Shohei"
    println!("{:?}", user.1["age"]); // 28
}
```
なんとかデータをまとめることができた。
しかしユーザーネームを取得する時の、user.0[”name”]の0が邪魔。
しかもageを取得する時は1に変えないとダメ。
## 結論
構造体を使えばいい。
```rust
fn main() {
    let user = User{
        name: String::from("Shohei"),
        age: 28,
    };

    println!("{:?}", user); // User { name: "Shohei", age: 28 }
    println!("{:?}", user.name); // "Shohei"
    println!("{:?}", user.age); // 28
}

#[derive(Debug)] // これつけないとuserを出力できない。
struct User {
    name: String,
    age: u8,
}
```
データもまとめられているし、可読性もいい感じ。構造体ってこんなふうに使うんだと、勉強になった。