OmniAICreator/Qiita-1.07M huggingface dataset:
Specification of Ethernet Driver, No.430, AUTOSAR R21-11(179) CP

Specification of Ethernet Driver, No.430, 2021-11

https://www.autosar.org/fileadmin/standards/classic/21-11/AUTOSAR_SWS_EthernetDriver.pdf


AUTOSAR R21-11記事一覧はこちら。

AUTOSAR 21-11, 160文書読んだ。2022年5月に半分到達。

https://qiita.com/kaizen_nagoya/items/4043e8414f850ce266a4

AUTOSAR R21-11(0) 仕様ダウンロード一覧。単語帳。参考文献資料作成

https://qiita.com/kaizen_nagoya/items/9b3a1b9b8d1e8d7e288e

# 用語(terms)

|Term|Description|
|:--|:--|
|EC |Ethernet controller
|Eth |Ethernet Driver (AUTOSAR BSW module)
|EthIf| Ethernet Interface (AUTOSAR BSW module)
|EthTrcv| Ethernet Transceiver Driver (AUTOSAR BSW module)
|ISR| Interrupt Service Routine
|MACPHY| Ethernet controller and PHY integrated in one module
|MCG |Module Configuration Generator
|MII| Media Independent Interface (standardized Interface provided by Ethernet controllers to access Ethernet transceivers)
|OA TC06 |OPEN ALLIANCE Technical Committee 6 "10BASE-T1x MACPHY Serial interface"
|OA TC10 [2] |OPEN ALLIANCE Technical Committee 10 "Automotive Ethernet Sleep/Wake-Up"
|PLCA| Physical Layer Collision Avoidance - Media acces
|TCP |Transmission Control Protocol
|UDP |User Datagram Protocol
## 英日単語帳
日本語は仮訳

T.B.D.

# 参考(reference)

[1] Glossary, AUTOSAR_TR_Glossary
https://www.autosar.org/fileadmin/standards/foundation/21-11/AUTOSAR_TR_Glossary.pdf
[2] OPEN Sleep/Wake-up Specification for Automotive Ethernet
http://www.opensig.org/Automotive-Ethernet-Specifications/
[3] General Specification of Basic Software Modules
AUTOSAR_SWS_BSWGeneral
[4] Specification of Ethernet Interface
AUTOSAR_SWS_EthernetInterface
[5] Specification of Ethernet Transceiver Driver
AUTOSAR_SWS_EthernetTransceiverDriver
[6] Specification of Ethernet Switch Driver
AUTOSAR_SWS_EthernetSwitchDriver
[7] General Requirements on SPAL
AUTOSAR_SRS_SPALGeneral
[8] Specification of ECU State Manager
AUTOSAR_SWS_ECUStateManager
[9] Requirements on Ethernet Support in AUTOSAR
AUTOSAR_SRS_Ethernet
[10] Specification of Default Error Tracer
AUTOSAR_SWS_DefaultErrorTracer
[20] IEEE 802.3-2015
[21] IEC 7498-1 The Basic Model, IEC Norm, 1994
[22] IETF RFC 2819
[23] IEEE Standard 802.1AS - 30 of March 2011
http://standards.ieee.org/getieee802/download/802.1AS-2011.pdf
[24] IEEE 802.3cg-2019
[25] OPEN ALLIANCE 10BASE-T1S MACPHY Serial interface (Sep 2020),
http://www.opensig.org/Automotive-Ethernet-Specifications/
darkflowについて調べてみた

前回記事では、Darkflowというオープンソースの物体検出のライブラリを用いました。
理解できない用語があったので、調べたことをまとめてみました。

https://qiita.com/yutaka_m/items/2fb41602312f4855dfcf

# 1.darkflow
darknetをtensorflow環境で動作するようにしたパッケージです。darknetは、YOLOの論文作者が作ったライブラリで手軽にインストールできるが、改造する場合、C言語を理解する必要ががあります。

# 2.YOLOとは
YOLOは「You Only Live Once」の略称で、物体検出をするアルゴリズムの一つです。その中でも、検出と識別を同時に行うことでリアルタイムに近い処理速度を実現しています。しかし、小さい画像処理の検出には向いていないそうです。小さい処理は、SSD(Single Shot MultiBox Detector)の方が向いています。

物体検出のアルゴリズムについては、下記サイトを読むと参考になります。

[物体検出についての歴史まとめ(1)](https://qiita.com/mshinoda88/items/9770ee671ea27f2c81a9)
[物体検出の５つの代表的なアーキテクチャの特徴まとめ](https://ai-kenkyujo.com/ai-architecture/)

# 2.1.GPU使用有無の違い
darkflowでは、GPUが備わっている環境であれば使用できるそうです。GPUの方が断然早く処理できるみたいです。
[【YOLO】GPU使用と非使用でのYOLOの処理速度の違い。](https://sunnyday-travel-aso-6487.ssl-lolipop.jp/programing/python/yolo/gpu-object-detect-time/)

# 2.2.学習済みモデル
[学習済みモデル](https://drive.google.com/drive/folders/0B1tW_VtY7onidEwyQ2FtQVplWEU)とは、物体かどうかを予測するために訓練を行い、学習させたモデルのことを指すそうです。

[機械学習におけるモデルとは？](https://ainow.ai/2021/04/13/254075/#i)

下記は、学習済みモデルの精度、処理速度、書き出し速度の検証をされているサイトです。
[YOLOv3で様々な学習済モデルを検証する](https://www.nakasha.co.jp/future/ai/yolov3_pre-trained_model.html)

# 2.3.認識できるもの
```https://github.com/thtrieu/darkflow.git```のデフォルトで認識できるのは、[coco.name](https://github.com/thtrieu/darkflow/blob/master/cfg/coco.names)にある80のカテゴリを識別できるそうです。

また、自分で好きなものを学習でさせることもできます。

[【Darknet】リアルタイムオブジェクト認識 YOLOをTensorflowで試す](https://qiita.com/tttttt/items/a33bc8297c9a03b38c74)
[オブジェクト検出 YOLO](https://www.renom.jp/ja/notebooks/tutorial/image_processing/yolo/notebook.html)
[Google Colab上でdarknet（YOLO）を使って物体を数える【画像認識】](https://wakuphas.hatenablog.com/entry/2018/09/19/025941)

# 3.終わりに
簡単ですが、まとめてみました。工夫すれば、処理速度を上げたり、新たな学習データを作ることができることが分かったので、機会があれば試してみます。
Step Functions で Athena クエリを（動的に）実行する

## Step FunctionsからAthenaのクエリを実行したい！
ETL処理において、これまでStep FunctionsからAthenaクエリを実行する場合は、Lambdaを呼び出してboto3を利用してクエリを実行していました。
クエリも動的に変わることが多かったので基本これで問題なかったのですが、処理データの増加にしたがい、クエリが15分以上かかることが発生してしまい、Lambdaのタイムアウトエラーに遭遇する問題が発生しました。

## Step Functionから直接Athenaクエリを実行する
https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/connect-athena.html

上記公式サイトから直接クエリを実行できることがわかりました。

以下がその例です
```json
{
  "Comment": "A Hello World example of the Amazon States Language using Pass states",
  "StartAt": "SQL実行",
  "States": {
    "SQL実行": {
      "Type": "Task",
      "Resource": "arn:aws:states:::athena:startQueryExecution.sync",
      "Parameters": {
        "QueryString": "insert into foo select * from hoge",
        "WorkGroup": "primary",
        "ResultConfiguration": {
          "OutputLocation": "s3://example-backet"
        },
        "QueryExecutionContext": { 
          "Database": "db_name" 
       }
      },
      "End": true
    }
  }
}
```

いくつか付け足すと
`arn:aws:states:::athena:startQueryExecution.sync` という指定で最後に`.sync`をつけていると同期実行になります。なくすと非同期になるのでクエリの完了を待たずに次の処理へと移ります。Step Functionsを利用する際は殆どの場合は同期実行なのではないでしょうか。
`Database`を指定していますが、ここはoptionなので指定なしでも、クエリでDBを指定することも可能です。


## 動的にSQLを変えたい
場合によってSQLを修正したいというのは当然発生すると思われます。その場合はSQLを引数で受け取ることが可能です。
自分の場合はLambdaでSQLを生成してそれを引数で渡すというやり方をとりました。

```json
{
  "Comment": "A Hello World example of the Amazon States Language using Pass states",
  "StartAt": "SQL取得",
  "States": {
    "SQL取得": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "OutputPath": "$.Payload",
      "Parameters": {
        "Payload.$": "$",
        "FunctionName": "arn:aws:lambda:ap-northeast-1:1234567890:function:getSQL:$LATEST"
      },
      "Retry": [
        {
          "ErrorEquals": [
            "Lambda.ServiceException",
            "Lambda.AWSLambdaException",
            "Lambda.SdkClientException"
          ],
          "IntervalSeconds": 2,
          "MaxAttempts": 6,
          "BackoffRate": 2
        }
      ],
      "Next": "SQL実行"
    },
    "SQL実行": {
      "Type": "Task",
      "Resource": "arn:aws:states:::athena:startQueryExecution.sync",
      "Parameters": {
        "QueryString.$": "$.sql",
        "WorkGroup": "primary",
        "ResultConfiguration": {
          "OutputLocation": "s3://example-backet"
        },
        "QueryExecutionContext": { 
          "Database": "db_name"
       }
      },
      "End": true
    }
  }
}
```

呼び出しているLambdaは
```python
def lambda_handler(event, context):
    # 動的にSQLを生成する
    sql = f"""
        insert into foo select * from hoge
    """
    return {
        'sql': sql
    }
```

ポイントは`"QueryString.$": "$.sql",`とドルマークをつけて引数を受け取ります。
これでタイムアウトを気にせずクエリを実行できるようになりました。
numpy, list の append の速度の違い


# やること

`numpy` と `python list` の `append` が結構速度が違うと見たので、実際に違いを計測してみる。 

https://numpy.org/doc/stable/reference/generated/numpy.append.html

https://docs.python.org/ja/3/library/stdtypes.html#sequence-types-list-tuple-range


# コード

```python
import numpy as np
import time
import matplotlib.pyplot as plt
import pandas as pd

data_nums = np.logspace(1, 5, 5)
# [1.e+01 1.e+02 1.e+03 1.e+04 1.e+05]
data_nums = data_nums.astype("int64")

df = pd.DataFrame(
    index=range(len(data_nums)), columns=["data_num", "python_list", "numpy_ndarray"]
)
df.loc[:, "data_num"] = data_nums

for data_num in data_nums:

    df_index = df.index[df["data_num"] == data_num].to_list()
    print(f"-" * 30)
    print(f"data_num : {data_num}")
    print(f"-" * 30)

    # =========================================
    # using python list append
    # =========================================
    start_time_python_list = time.perf_counter()

    data_python_list = np.empty(0)
    data_python_list_ = data_python_list.tolist()  #  numpy ndarray -> python list
    for i in range(data_num):  # append data
        data_python_list_.append(i)
    data_python_list_np = np.asarray(data_python_list_)
    # python list -> numpy ndarray
    # print(data_python_list_np)

    end_time_python_list = time.perf_counter()
    elapsed_time_python_list = end_time_python_list - start_time_python_list
    print(f"python_list : {elapsed_time_python_list} [sec]")
    df.at[df.index[df_index[0]], "python_list"] = elapsed_time_python_list

    # =========================================
    # using numpy ndarray append
    # =========================================
    start_time_numpy = time.perf_counter()

    data_numpy_append_ = np.empty(0)
    for i in range(data_num):  # append data
        data_numpy_append_ = np.append(data_numpy_append_, i)
    # print(data_numpy_append_)

    end_time_numpy = time.perf_counter()
    elapsed_time_numpy = end_time_numpy - start_time_numpy
    print(f"numpy_ndarray : {elapsed_time_numpy} [sec]")
    df.at[df.index[df_index[0]], "numpy_ndarray"] = elapsed_time_numpy

    print(f"")

print(df)
a = df.to_numpy()

# グラフ描画用
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.set_xscale("log")
ax.set_xlabel("data num")
ax.set_ylabel("elapsed time[s]")
ax.plot(a[:, 0], a[:, 1], label="python_list")
ax.scatter(a[:, 0], a[:, 1])
ax.plot(a[:, 0], a[:, 2], label="numpy_ndarray")
ax.scatter(a[:, 0], a[:, 2])
ax.legend()
plt.show()
```

# 結果

| 配列の要素数（data_num）| python_list [sec] | numpy_ndarray [sec] |
|:-:|:-:|:-:|
| 10  |  0.000019|  0.000081|
| 100  | 0.000221|  0.000634|
| 1000  | 0.00026| 0.007898|
| 10000  |  0.001955| 0.071762|
| 100000  | 0.018196| 2.05108|

![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189684/3c84451c-c01e-3051-b229-b6f8cdc790a5.png)


#### `append` は `python list` の方が速い。
`numpy ndarray` は固定長で宣言されており、`python list` は可変長配列であることが理由らしい。
【Flutter】共通化したAlertDialogに「OK」の場合に実行する処理を渡す方法

# はじめに
Flutterの`AlertDialog`を共通のwidgetとして、複数の所で使いたいと言う場合はよくあるかと思います。

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

そんな時、**「キャンセル」は閉じる、「OK」なら任意の処理を発動する**と言う実装はどうやったらいいのだろう？と思い調べてみました！

何かしらの情報を表示させるだけの`AlertDialog`なら簡単にできるんですけど、、、

# 共通化したAlertDialogにFunctionを渡す
## 共通化したAlertDialog

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

class ConfirmationDialog extends StatelessWidget {
  const ConfirmationDialog({
    Key? key,
    required this.action,
  }) : super(key: key);

  final Function? action;

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: Text(
        'AlertDialog Title',
        style: Theme.of(context).textTheme.headline6,
      ),
      content: Text('AlertDialog description',
          style: Theme.of(context).textTheme.bodyText1),
      actions: <Widget>[
        TextButton(
          onPressed: () => Navigator.pop(context, 'Cancel'),
          child: const Text('Cancel'),
        ),
        TextButton(
          onPressed: () {
            Navigator.pop(context, 'OK');
            print('送信だ！！！');
            action!(); // 渡された処理を実行
          },
          child: const Text('OK'),
        ),
      ],
    );
  }
}
```


## 使用例

```dart
void postTheme(String uid) async {
        String res = await FireStoreMethods()
            .postTheme(_titleController.text, _descriptionController.text, uid);
  }

// 省略

 final UserProvider userProvider = Provider.of<UserProvider>(context);

// 省略

 TextButton(
                  child: Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: !_isLoading
                        ? const Text('投稿')
                        : const CircularProgressIndicator(color: primaryColor),
                  ),
                  onPressed: () => showDialog(
                    context: context,
                    builder: (context) => ConfirmationDialog(
                      action: () {
                        postTheme(userProvider.getUser.uid); // 引数に値をもたすことも可能！
                      },
                    ),
                  ),
                  style: TextButton.styleFrom(
                    backgroundColor: secondaryColor,
                    shape: const StadiumBorder(),
                  ),
                ),
```

これで色々な処理を「OK」の場合に実行することができるようになりました！:relieved:


# よくあるエラー

```console
This expression has a type of 'void' so its value can't be used. Try checking to see if you're using the correct API; there might be a function or call that returns void you didn't expect. Also check type parameters and variables which might also be void
```

👇これだとダメです！

```dart
 onPressed: () => showDialog(
                    context: context,
                    builder: (context) => ConfirmationDialog(
                      action: postTheme(userProvider.getUser.uid),
                    ),
                  ),
```

actionは`Function`なので、`() {}`の形にしてあげないといけません。
下からスライドして出てくる感じのモーダル

## DEMO
codepen
https://codepen.io/kkosuke/pen/vYdWMjm

## イメージ
開く前 | 開いたあと
-- | --
![before](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106666/1ceeff82-fa81-df10-7d7f-445b1e5cc82e.png)|![after](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106666/8ced609b-c65b-7b69-280d-fa502dcbf206.png)



## 気にしたこと
- css でanimation
- 閉じたり開いたり
- 開いた時に裏側のスクロールを抑える
- fixed内のscrollをすると、スクロールが出来なくなるバグ(?)にも対応
- iPhoneのアドレスバーのスキマにも配慮


## 参考
https://simplesimples.com/web/markup/javascript/ios-safari-bugfix-smooth-scroll/
https://stackoverflow.com/questions/69589924/ios-15-minimized-address-bar-issue-with-fixed-position-full-screen-content
AWSの料金の話をするときに食い物やモノに例えると話がスムーズである現象

## これはなんですか
AWSの料金を試算して話すときの規模感の共有についての知見
基準として人間の主観時間である１ヶ月を単位とする。

## なんでその例えが必要なの？
あと、アメリカドルとか日本円変動するし、１ヶ月っていっても２８日から３１日まであって定かではないから、もやっとしたイメージで良い。
そういいうとき本書にあるたとえで話すとよい。

この話をしないと怒られることが多々あるので、関係者各位で情報をイメエジとして共有するのに最も有効な手段がこれであると行き着いた。

もうちょっと精緻に共有したい人は、具体的な店名や前提を付け足すとよいでしょう。

## もやっとグレード
| グレード名 | 金額 | 説明 |
|:-----------|------------:|:------------:|
| お賽銭       | $1, ¥100未満        | １００万回呼ばれないlambdaとか、小数点下５桁目くらいから料金が発生している類のものとか         |
| アイスクリーム     | ＄1~$3, ¥100~¥500      | 安めのストレージなど       |
| ラーメン     | ＄4~$10, ¥500~¥1000      |       |
| ステーキ     | ＄8~$20, ¥1000~¥2500      |       |
| 焼肉（食べ放題、グレード低）     | ＄20~$30, ¥2,500~¥3,500      | まじめなドメイン買うとこのくらいかな      |
| 焼肉（食べ放題、グレード中）, 飲み会１回分     | ＄30~$40, ¥3,500~¥4,800      | 踏み台とか安めのEC2      |
| 焼肉（食べ放題、グレード高い）     | ＄40~$60, ¥5,000~¥7,000      | ECSコンテナ１個または冗長構成の運用      |
| 飲み放題の焼肉（食べ放題ではない、グレード高い）     | ＄60~$80, ¥7,000~¥10,000      | 実用レベルのRDBの費用      |
| ちょっと洒落たレストランでコース料理     | ＄80~$150, ¥10,000~¥20,000      |       |
| ご祝儀, キャバクラ(*1)     | ＄150~$300, ¥20,000-¥35,000      |       |
| 自動車税, ソー○     | ¥35,000-¥60,000      | 割としっかりくんだ開発環境、サーバレスを活用しコストカリカリした本番環境      |
| 車（7年落ちの軽トラ）が買える     | ~¥150,000      | ユーザ数万人レベルの小規模なサービスの提供      |
| 原付（新車）が買える     | ¥150,000~¥200,000      | このあたりが中規模なSaaSの運用費用      |
| このゾーンはめったに買い物しないし金額そのものがもやっとしたインパクトを持つので実際の価格を万円単位で伝えると良い     | ¥200,000~      |       |

(*1) キャバクラやホストクラブとRDSは構成次第で青天井だから価格的には同じに見える。この辺は前提条件をきちんとアライメントした上で共有してください。この意見に共感できるひとはフォローはいらないのでLGTM押してください。

## 具体例
### ミニマムなRDB
「焼き肉食べ放題くらいです、飲み放題はつけていません」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570665/6450dca9-db10-73a0-df58-73ecd3263110.png)

## 終わりに
AWSなどのCloudのコスト感は持っておいたほうがよい、そのため、どれをどれだけ運用すると何が食べられる、買えるというので覚えておくと、数字をすぐ忘れる人でも多少の物価や為替レートの変動に対応できるようになるのでラッキーというお話でした。

この先はかすれていて読めない。
無駄な名前を増やすな！概念を増やすな！ KONAMI e-amusument pass にチャージする PASERI ってなんだよ

# e-amusement pass

ゲームセンターの「ゲームカード」で e-amusement pass というものがある。
KONAMIが発行しているものだが、これを使うと自分のゲームの成績が記録できるのだ。

なおかつ、ここに電子マネーをチャージすることが出来る。その名も PASERI だ。
ここで「は？」と思った人はいるだろうか。

KONAMIのゲームカードにチャージする電子マネーの名前がPASERIって。
まったく一貫性がない。

- e-amusement pass という名前からKONAMIを連想できない。
- PASERI という名前から e-amusement pass も KONAMI も電子マネーも連想できない。

# チャージ

このPASERIをチャージするには、ゲームセンターの端末を使い

- e-amusement passカードに対して
- 現金で
- PASERI をチャージする

という仕組み。

e-amusement passをまず購入して

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89618/d1433fea-2bbe-4a9d-7ead-5cc89aced9ea.png)

次にそのe-amusement pass を持って PASERI チャージ機に向かう必要がある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89618/cd72ff04-03a0-f417-788d-9b4c0ad5f2c8.png)

最初にチャージ端末を見つけたときは、本当にどういうことなのか分からなかった。
まさか電子マネーのチャージのために、複数の登場人物が出てくると思わないだろう。

# ではどういう名前にすればよいか？

- KONAMIゲームカード
- KONAMIゲームセンターマネー

以上でよろしくお願いいたします。

# 余談だが

この PASERI のチャージにさえ e-amusement pass のパスワード入力が必要なのだった。

え、銀行ATMでの入金でさえパスワード不要でしょ？
被害者が得だけするようなアクションに、セキュリティなんてまず要らないのである。

開発者はセキュリティというものがまるで分かっておらず、セキュリティ対利便性のトレードオフを間違った方向に倒してしまっている気がした。

あとね、ゲームを1回プレイするたびにパスワード入力が必要なの。あほか。
SOFA framework備忘録 (2) データ構造

今回はシミュレーション扱うにあたっての基本的な事項について

# 構造
### データ構造
- Root Node
    - Animation Loop
        - Object1
            - `計算機(Solver)`
            - 自由度(Degree of Freedom)
            - 外力(Force Field)
            - 質量(Mass)
        - Object2
            - `計算機(Solver)`
            - 自由度(Degree of Freedom)
            - 力(Force Field)
            - 質量(Mass)
        - Object3
        - Object4
        -  

シミュレーションのシーンは __親ノード__ で構成され、すべての __子ノード__ はこの親ノードの下に格納されます。
例えば`RootNode`の下に`Object1`が定義されており、`Object1`に関連するコンポーネントは基本的にこの子ノードで構成されます。

シーン内のコンポーネントは互いに独立したモジュール構造になっているので、DOFやSolverなどのそれぞれのコンポーネントを変更することでシミュレーションを書き換えることができます。
### マッピング
- Root Node
    - Animation Loop
        - Object1
            - `計算機(Solver)`
            - 自由度(Degree of Freedom)
            - 外力(Force Field)
            - 質量(Mass)
            - Visual
                - Mecanical model
                - Visual  model
        - 
一つのオブジェクトのノードの中に複数のモデルを実装することができ、物理計算を行うためのメッシュと見た目の良いビジュアルモデルを導入できます。

__Animationloop__ は物理演算における衝突と物理反応の演算に関して物理的制約の管理や衝突の検出などをトリガーとして物理演算のステップを管理し各イベントが処理されます。基本的にはDefoultAnimationLoopが自動的に生成されます。

参考
https://www.youtube.com/watch?v=KHTAgD1oG8Y
「package.js」についてメモ書き

# 「package.js」について

package.jsonの中身を直接いじるものなのかと思っており、jsonのバージョンを変更して`npm install`コマンドを叩いていた。
しかし、依存関係エラーが出てなかなか解消できなくて、余計な時間を食ってしまった。

[npm公式](https://www.npmjs.com/)に行っていちいち確認して、パッケージを入れ直していたが、色々調べたら`npm-check-updates`という一括更新コマンドがあった。

そのため、以下の更新コマンドを利用する。

## npm-check-updates
まず、`npm-check-updates`が入っていない場合は、インストールする必要がある。

```shell
npm install -g npm-check-updates
```

以下のコマンドで更新

```shell
npm-check-updates -u
```

その結果、 `package.json`の中身が更新されている。
AWS WAFで日本以外からのアクセスをブロックする

こんな感じに


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/4a17d18c-05ae-4386-828c-683ca0e89864.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/2184291c-ca05-7af1-06ae-2829671214ad.png)
【脱駆け出しエンジニア】binding.pryについて

# 概要
本記事ではrailsでデバッグする際に使用するbinding.prybについてです。
会社でお恥ずかしい思いをしましたので記事として残しておきます。

# 経緯
先日、会社でこのようなやりとりがありました。

私） 「センパイ、エラーが出てるんですけど何が原因でどこでエラーが出てるかわからないっす」
先輩エンジニア）「とりあえずbinding.pry使いなよ。」
私） 「バ、バ、バインデングぷらい,,,,はにゃ？」
先輩エンジニア）「,,,え？?binding.pry知らないの？？？それはもうif分知らないでjs書いてるのと一緒だよww(ジョーク)」

# binding.pryとは
railsで処理を一時的にストップさせるデバックツールの一つです。
エラーの発生箇所に```binding.pry```と記載することで処理を一時停止させることができます。
binding.pryはただ処理を止めるだけでなく、オブジェクトの参照や変更したり、その後の処理を一行ずつ実行することができます。
binding.pryは.rbファイルだけでなく、.erbファイルでも使用することができます。
```exit```でbinding.pryを止めることができます。

# 参考記事
https://qiita.com/STHEXA/items/1de2411cb3987066c9b9
https://tech.smarthr.jp/entry/2021/11/08/143649
https://pikawaka.com/rails/pry
https://asapoon.com/ruby/rails/2936/binding-pry/
Pythonで一様乱数の配列を生成するときの速度比較

# やること


**一様乱数の配列を生成するための時間を比較する**

一様分布とは。

https://ja.wikipedia.org/wiki/%E4%B8%80%E6%A7%98%E5%88%86%E5%B8%83#:~:text=%E4%B8%80%E6%A7%98%E5%88%86%E5%B8%83%EF%BC%88%E3%81%84%E3%81%A1%E3%82%88%E3%81%86,%E8%B7%9D%E9%9B%A2%E3%81%AE%E5%88%86%E5%B8%83%E3%82%92%E6%8C%87%E3%81%99%E3%80%82


# 一様乱数を生成するために使用したライブラリ


- ```numpy.random.uniform```

https://numpy.org/doc/stable/reference/random/generated/numpy.random.uniform.html


- ```numpy.random.default_rng``` (Numpy version1.17以降で推奨されているようです)

https://numpy.org/doc/stable/reference/random/generator.html


- ```scipy.stats.uniform```

https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.uniform.html

他に、```random.uniform```もありますが、要素数を指定できないように見えたため、今回は除外します。

https://docs.python.org/ja/3/library/random.html#random.uniform

# コード

### ```numpy.random.uniform```

```python
import numpy as np
import time

array1d_size = 1_000_000 # 要素数

start_time = time.perf_counter()
np_uniform = np.random.uniform(0, 1, array1d_size)
end_time = time.perf_counter()
elapsed_time = end_time - start_time

print(f"numpy.random.uniform : {elapsed_time}[sec]")
# numpy.random.uniform : 0.008119800128042698[sec]
```

### ```numpy.random.default_rng```

```python
import numpy as np
import time

rng = np.random.default_rng()

array1d_size = 1_000_000  # 要素数

start_time = time.perf_counter()
rng_uniform = rng.uniform(0, 1, array1d_size)
end_time = time.perf_counter()
elapsed_time = end_time - start_time

print(f"numpy.random.default_rng : {elapsed_time}[sec]")
# numpy.random.uniform : 0.004869400057941675[sec]
```

### ```scipy.stats.uniform```

```python
from scipy.stats import uniform
import time

array1d_size = 1_000_000  # 要素数

start_time = time.perf_counter()
scipy_uniform = uniform.rvs(size=array1d_size)
end_time = time.perf_counter()
elapsed_time = end_time - start_time

print(f"scipy.stats.uniform : {elapsed_time}[sec]")
# scipy.stats.uniform : 0.012748599983751774[sec]
```


# 結果

| ライブラリ | 計算時間 |
|:-:|:-:|
| ```numpy.random.uniform```  | 0.008119800128042698[sec]  |
| ```numpy.random.default_rng```  | 0.004869400057941675[sec]  |
| ```scipy.stats.uniform```  | 0.012748599983751774[sec]  |

条件：配列の要素数 1,000,000
試行回数：1回（本当は何回もやるのが必要だと思いますが...）

### ```numpy.random.default_rng``` を使うのが最も速い。
Access データ型の通貨型と数値型の違い

>数値を保存するフィールドはどのデータ型にすればいいの？
数値型と通貨型は、「¥」記号の有無の違いだけでなく、数値を扱う仕組みが異なります。数値型は2進数、通貨型は10進数で数値を扱います。

>2進数では数値の小数部分に誤差が生じる可能性があるので、正確な計算が必要になるデータは通貨型に設定します。通貨型の精度は、小数点の左側が15けた、右側が4けたになります。

>それ以外の数値は数値型にして、整数・実数など入力するデータの種類に応じて［フィールドサイズ］プロパティを設定します。整数は長整数型、実数は倍精度浮動小数点型にするのが一般的です。

引用元：

https://dekiru.net/article/14891/#:~:text=%E6%95%B0%E5%80%A4%E5%9E%8B%E3%81%A8%E9%80%9A%E8%B2%A8%E5%9E%8B%E3%81%AF%E3%80%81%E3%80%8C%C2%A5%E3%80%8D%E8%A8%98%E5%8F%B7%E3%81%AE,4%E3%81%91%E3%81%9F%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82
Alpine.js「どけ、livewire。切り替えは俺がやる」

livewireで開発をしていて
要素の表示,非表示を切り替える処理を書いたりしてると思います。

その場合、リクエストが返ってくるまでの少しのラグが気になったりする場合があります。

ミニマムな動的部分はalpine.jsを添えてサクサク動かしましょう

# Alpine.jsとは
現代版jQuery的な立ち位置にいるJavascriptフレームワークです。
詳しく紹介している記事を添付します。

https://qiita.com/kohashi/items/ae8b1186567ec34b2a75

# 比較
要素の表示非表示する切替処理を
livewireとAlpine,js両方用意します

## コード

```php:PHP
class Sample0523 extends Component
{
    public $isShow;

    public function render()
    {
        return view('livewire.sample0523');
    }
}
```


```html:Blade
<div>
    <div x-data="{isShow:false}" class="pt-3">
        <button type="button" class="btn btn-primary mb-3" @click="isShow= !isShow" wire:click="$toggle('isShow')">
            表示切替
        </button>
        <p x-show="isShow">Alpine.js表示</p>
        @if($isShow)
            <p>Livewire表示</p>
        @endif
    </div>
</div>
```

## 解説
| コード                   | 解説                                                 | 
| ------------------------ | ---------------------------------------------------- | 
| <span>@</span>click="isShow= !isShow" | alpine.jsクリックイベント、``x-on:click=``とも書ける | 
| x-data="{isShow:false}"  | alpine.js変数宣言                                    | 
| x-show="isShow"          | isShowがtrue時に要素を表示                           | 



ボタンをクリックして見てみましょう

![ダウンロード.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282328/2050667f-d541-f5c4-f70a-d25524e3628c.gif)

# おわり
jsを使った方が爆速なのは当然と言えば当然なのですが、alpine.jsはcdnで読み込んですぐ使えて
表記も簡潔なので使いやすいです。

livewireとalpine.jsは作者が同じなので連携がしやすいように色々と処理が用意されています

https://laravel-livewire.com/docs/2.x/alpine-js

連携処理の紹介も書いていこうと思います。
Databricksワークスペースにユーザーを追加する

[こちら](https://qiita.com/taka_yayoi/items/3262ea8529ad96b920ce#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AE%E8%BF%BD%E5%8A%A0)で説明されているユーザーの追加手順をウォークスルーした内容です。

> [Databricksクイックスタートガイド](https://qiita.com/taka_yayoi/items/125231c126a602693610)のコンテンツです。

:::note info
**注意**
- こちらで説明している手順は[シングルサインオン](https://docs.databricks.com/administration-guide/users-groups/single-sign-on/index.html)が有効化されているケースでは当てはまりません。
- GUIは日本語を想定しています。GUIを日本語に変更する手順に関しては[こちら](https://qiita.com/taka_yayoi/items/ff4127e0d632f5e02603)を参照してください。
:::

# Databricks管理者の作業

1. Databricksワークスペースに管理者としてログインします。
1. サイドメニューの**設定 > 管理コンソール**を選択します。
1. **Users**タブが選択されていることを確認します。
1. **+ ユーザーを追加**ボタンをクリックします。
![Screen Shot 2022-05-26 at 17.51.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/4c744e1b-a166-272f-fa9e-cb08e8efb9b5.png)
1. **Email**に招待したいユーザーのメールアドレスを入力し、**Send invite**をクリックします。
![Screen Shot 2022-05-26 at 17.51.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/d6406895-1a14-c64b-d86c-254112cb5373.png)
1. 招待メールが送信された旨のメッセージが表示されるので**OK**をクリックします。他のユーザーを招待するにはステップ4からの操作を繰り返します。
![Screen Shot 2022-05-26 at 17.52.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/32841c5b-719d-17a6-96b7-54140924f58d.png)

:::note
**注意**
招待するユーザーが以下の作業を完了してDatabricksにログインすると一般ユーザーとして登録されます。管理者権限を付与するには、管理コンソール上で管理者の手でAdmin権限を付与する必要があります。ただし、Admin権限は非常に強い権限ですので、注意して付与するようにしてください。
![Screen Shot 2022-05-26 at 18.10.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/d19ad005-ab43-4ff1-a30f-ac6efb1f1887.png)
:::

# Databricksユーザーの作業

:::note
**注意**
上の操作から5分以内に確認メールが届かない場合には、迷惑メールに分類されていないか確認してください。
:::

1. Databricksからの確認メール(メールタイトル: **管理者の名前 has invited you to collaborate using Databricks**)を開きます。招待者の名前とメールアドレスを確認の上、メールに記載されているURLをクリックします。
![Screen Shot 2022-05-26 at 17.59.07.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/abf24735-9c41-0bed-6573-8e50f936821d.jpeg)
1. Databricksワークスペースに遷移します。ここで、**First and last name**に自分の名前、**Password**と**Confirm password**にパスワードを入力し、**Sign Up**ボタンをクリックします。

:::note
**注意**
パスワードは最低8文字を指定してください。
:::

これで、Databricksワークスペースにログインできました！
![Screen Shot 2022-05-26 at 18.00.04.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/11b32425-39ab-4abb-5ec0-4606390023e3.jpeg)

ログイン後の最初の操作手順に関してはこちらを参照ください。

https://qiita.com/taka_yayoi/items/d8355c0c8363b3c6658a

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
scipy.stats: 幾何平均と調和平均 gmean, hmean


# 1.　幾何平均 `gmean`

`gmean(a, axis=0, dtype=None, weights=None)`


```python
from scipy.stats import gmean
x = [1.2, 3.1, 4.6, 2.2, 5.7]
gmean(x)
```




    2.9263054868319522



`gmean` 関数を使わずに計算すると以下のようになる。


```python
import numpy as np
np.exp(np.mean(np.log(x)))
```




    2.9263054868319522




```python
np.prod(x)**(1/len(x)) # 非推奨
```




    2.9263054868319527




```python
以下のようなテストデータ（平均値=50，標準偏差=10)で幾何平均を求めてみる。
```


```python
from scipy.stats import norm
z = norm.rvs(loc=50, scale=10, size=200)
import matplotlib.pyplot as plt
plt.hist(z, bins=30);
```


    
![output_6_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611739/b0c52e08-f0b8-2647-8a20-a8bf9af4fa2d.png)
    
サンプルサイズ 200 で，教科書的な定義式通りの `np.prod(z)**(1/len(z))` は途中でオーバーフローしてしまい `inf` を返す。


```python
gmean(z), np.exp(np.mean(np.log(z))), np.prod(z)**(1/len(z)), np.prod(z)
```




    (49.19589704885539, 49.19589704885539, inf, inf)



# 2.　調和平均 `hmean`

`hmean(a, axis=0, dtype=None)`


```python
from scipy.stats import hmean
x = [1.2, 3.1, 4.6, 2.2, 5.7]
hmean(x)
```




    2.4958950838709315



`hmean` 関数を使わずに計算すると以下のようになる。


```python
1/np.mean(1/np.array(x))
```




    2.4958950838709315




```python
`np.array` を使ったのは，`x` がリストのとき `1/x` はエラーになるので，numpy.ndarray に変換するためである。

どうせ `numpy` を使うなら，逆数を返す `np.reciprocal` を使えば，統一性がある。
```


```python
np.reciprocal(np.mean(np.reciprocal(x)))
```




    2.4958950838709315
[Opensearch]Aliasを便利につけるRakeタスクを作りたい

どうも、「[病院なび](https://byoinnavi.jp/)」の開発チームメンバー甘利です。
毎日ワクワクしながら、業務に携わっています。前回に引き続きAWS Opensearch の導入について書いていこうと思います。
今回はOpensearchのAliasについて書こうと思います。

# 概要
前回の「[自社サービス「病院なび」へ AWS Opensearch を導入したい](https://qiita.com/namarin/items/533e4297f05d23f198b3)」　の続きになります。
前回はIndexを作るRakeタスクを作りましたが今回はそのIndexにAliasを付与するRakeタスクを作っていきたいと思います。

# なぜAliasを利用するのか
Aliasがなぜ必要かを説明するために、Opensearchをどのように利用するかについて説明します。
現在、ざっくりと以下みたいな構成を考えています。SQLのを永続化のために利用し、検索用のDBとしてOpensearchを利用します。
![graph1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265224/8f8ae614-9f38-bcdd-bc84-a5ade316b100.png)
上記の図ではアプリケーションサーバーから直接Indexを指定していますが、
Alias利用すると、アプリケーションサーバーからIndexに直接接続せず、Aliasを介してIndexにアクセスできるようになります。
![hoge2.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265224/83dba4ea-866e-95e4-9866-176197f312fd.png)
このAliasをうまく使って運用方法を考えたいと思っています。

# 運用時のIndexのマッピング（ドキュメントの構造）変更について
運用時におけるIndexの定義の変更を以下のようにする予定です。
![hoge3.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265224/93ced47c-425f-57b0-9d24-ab8e42315ea1.png)
1. Opensearchindex が稼働している状態で、SQL　Databaseから新しい　Opensearchindex'を作成する。
1. Aliasを Opensearchindex　から　Opensearchindex'に張り替える。

このようにする理由として、Opensearchではマッピングを変更してもデータ自体の変更はそのデータが次に更新されたタイミングになるためです。データが全て更新されている状態にするには結局一度アクセス（更新）する必要があります。
そうなると、一つのインデックスを更新しながら使うよりも永続化DBであるSQLデータベースから、都度INDEXを作り直し、Aliasの変更によって差し替えた方が色々とリスクが少なくなると考えました。（なんか他にいい方法があればご教示いただければと思います）

# 用意するタスク
オペレーションとしては Alias　を　Opensearchindex　から　Opensearchindex'　へ張り替えるタスクだけで事足りるのですが、必ず張り替えともかぎらず、個々に追加、削除も行うケースが考えられますので以下の3つを用意しました。
```
rake db:open_search:add_alias[alias,index]                                               # エーリアスの設定
rake db:open_search:change_alias[alias,index,index_dest]                                 # エーリアスの付け替え
rake db:open_search:remove_alias[alias,index]                                            # エーリアスの削除
```

# まとめ
今回は運用を考慮してAliasの操作タスクを作っていきました。
今後はどのようにデータをコピーしていくか、といったところをを記事にしていければと思います。

少しでも面白いと思っていただけたら　LGTM お願いします
また、続きが気になるようでしたらフォローいただけると幸いです。
WebSphere Libertyランタイムの製品版を入手する

IBMからライセンスを購入いただき，製品版のWebSphere Libertyを導入し，使用する際に必要なファイルをダウンロードする手順となります。Libertyを使用するには，JDKとWebSphere Libertyの導入が必要です。必要に応じて，IBM HTTP ServerとWebサーバープラグインも導入します。

IBMのソフトウェア製品を利用するには，通常は契約者のサイトのダウンロードページから導入メディア（GM・出荷時の最初のバージョン）をダウンロードして製品を導入し，その後サポートサイトから最新のFixpackをダウンロードして適用してから利用します。ですがWebSphere Libertyの場合，サポートサイトからダウンロードできるFixpackは，GMバージョンが導入されていなくても，直接，導入することが可能です。サポートサイトからダウンロードしたファイルだけで導入作業をおこなうことができるのです。

サポートサイトからのファイルのダウンロードには，契約時に登録したIBM IDが必要です。

# JDKをダウンロードする

WebSphere Libertyでは，以下のJava SDKが利用できます。それぞれ，リンク先から利用するプラットフォームに応じたアーカイブファイルをダウンロードし，展開して導入してください。

- [IBM SDK Java Technology Edition Version 8.0](https://www.ibm.com/support/pages/ibm-sdk-java-technology-edition-version-80-websphere-liberty-using-archives)
- [IBM Semeru Runtimes](https://developer.ibm.com/languages/java/semeru-runtimes/downloads/)
- [Eclipse Temurin](https://adoptium.net/temurin/releases/)

Java 8を利用する場合は，IBM SDK Java Technology Edition（いわゆるIBM Java）がサポート期間がほかよりも長いためお薦めです。Java 11以降を利用する場合はSemeruかTemurinを使用してください。

これ以外のJava SE仕様に準拠したJava SDKを使用することもできますが，その場合，Java実行環境の障害などについては，IBMからのサポートは受けられません。

# Libertyをダウンロードする

IBMサポートサイトの，[Recommended updates for WebSphere Application Server](https://www.ibm.com/support/pages/recommended-updates-websphere-application-server)のページへアクセスし，「WebSphere Liberty - Continuous Delivery」にリストされたバージョンの中から，使用するバージョンをクリックして個別ページに移動します。末尾が3の倍数（3/6/9/12）で，なるべく新しいものがお薦めです。

たとえば，「22.0.0.3」をクリックすると[WebSphere Application Server Liberty 22.0.0.3](https://www.ibm.com/support/pages/node/6560398)の個別バージョンのページに移動します。ここから，適切なアーカイブパッケージを選択してダウンロードします。どれが適切か不明な場合には，利用可能な全てのFeatureを含んだ以下のファイルをダウンロードしてください。

- WAS NDエディションを契約いただいている場合は
wlp-nd-all-22.0.0.3.jar
- WAS(Base)エディションを契約いただいている場合は
wlp-base-all-22.0.0.3.jar
- WAS Liberty Coreエディションを契約いただいている場合は
wlp-core-all-22.0.0.3.jar

ZIPファイルはunzipコマンドなどで展開します。JARファイルは，Javaコマンドを使用して，`java -jar アーカイブ名.jar`のように実行して展開します。

また，こちらのページからは，[無償で使用できる開発者版](https://www.ibm.com/support/pages/websphere-liberty-developers)を実働環境でも使用できる製品版に変換するLicense upgrade archivesをダウンロードすることもできます。ライセンスを適用する手順は[こちら](https://www.ibm.com/docs/ja/was-liberty/base?topic=archives-applying-license-liberty-installations)を参照してください。

# IBM HTTP ServerとWebサーバープラグインをダウンロードする

上記のLibertyの個別バージョンのダウンロードページに「IBM HTTP Server and Web Server Plug-ins」という項目があります。こちらに，公開時の最新バージョンのIHSのダウンロードページへのリンクがあります。[V9.0.5.11 archive packages](https://www.ibm.com/support/pages/node/6561051#IHSArchive)のようなリンクをクリックし，ダウンロードページに移動します。各プラットフォームに対応したアーカイブファイルを選択してダウンロードします。

ダウンロードしたZIPファイルを展開して導入します。
【JavaScript】現在の日付時刻をyy-mm-dd-hh-mm の形で返す関数

備忘録

# 現在の日付時刻をyymmddhhmm の形で返す関数
```formatDate.js
 function formatDate(dt) {
    const y = ('00'+dt.getFullYear()).slice(-2);
    const m = ('00' + (dt.getMonth()+1)).slice(-2);
    const d = ('00' + dt.getDate()).slice(-2);
    const h = ('00' + dt.getHours()).slice(-2);
    const mm = ('00' + dt.getMinutes()).slice(-2);
    return (y + m + d +  h  + mm);
  }
```

```result.js
> formatDate(new Date());
'2205261737'
```

slice(-2) は、文字列の右から数えて2文字目までを抜き出すので、`getFullYear()`で`2022`と取得し`22`を出力している

# ハイフンをつける場合(yy-mm-dd-hh-mm)

```formatDate.js
 function formatDate(dt) {
    const y = ('00'+dt.getFullYear()).slice(-2);
    const m = ('00' + (dt.getMonth()+1)).slice(-2);
    const d = ('00' + dt.getDate()).slice(-2);
    const h = ('00' + dt.getHours()).slice(-2);
    const mm = ('00' + dt.getMinutes()).slice(-2);
    return (y + '-' + m + '-' + d + '-' + h  + '-' + mm);
  }
```

```result.js
> formatDate(new Date());
'22-05-26-17-37'
```
YAML文法チェッカ（バリデータ）を作成したった

## TL;DR

YAMLの文法チェッカを作成した。これでYAMLファイルの内容のバリデーションができる。
引数でもパイプでも渡せるぞ！

## 紹介

YAMLファイルをコミットする前に最低限の文法チェックぐらいは済ませておきたい、というのは人情だと思う。
「[Ruby のワンライナーで YAML の文法チェック](https://qiita.com/key-amb/items/7c82d08887a81edf4d08)」という記事にいつもお世話になっていたが、ファイルの引数渡しでもパイプライン経由でもチェックできるよう、シェルスクリプトで工夫したものを作った。

肝となる引数とパイプ両方に対応、というのはコードにあるように `if` で判断してパイプで流しております。

次のシェルスクリプトを適当なファイル名で保存して使ってください。（僕は ymlck.sh という名前にして 0755 にして ~/bin/　に置いております）


```bash:ymlck.sh
#!/bin/sh

if [ -p /dev/stdin ]; then
    cat -
else
    cat $@
fi | ruby -r yaml -e 'YAML.load STDIN; puts "OK"'
```

### 使い方

```shell
# パイプ
$ cat somefile.yaml | ymlck.sh

# 引数渡し
$ ymlck.sh somefile.yaml
```

問題ないファイルであれば何も出ません。
問題のあるYAMLファイルの場合、エラーメッセージが出ます。


## もう少し工夫したやつ

出力結果をJSONとして表示させるようなオプション付きのものを、こちらで公開しています。

https://github.com/ping414ms/ymlck
jestでtsconfigのpathsを有効化したい

```ts
const { pathsToModuleNameMapper } = require('ts-jest/utils');
const { compilerOptions } = require('./tsconfig');

module.exports = {
  //...
  moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths , { prefix: '<rootDir>/' } )
};
```

https://github.com/dividab/tsconfig-paths/issues/97#issuecomment-542650519
DB設計で考えること

上司から学んだことのノートです。

# 利用者に操作されるテーブルは〜ed_byをつける
どの利用者が作成・編集したかはログになり、
実際にアプリケーションで利用するケースが多く考えられるため、
利用者操作によって作成・編集・削除されるテーブルに関しては
`created_by` `updated_by` `deleted_by` カラムを設けておくと良い。

# 一般利用者と管理者のテーブルを分ける利点
ユーザーを一つのテーブルで管理すると、権限カラムからのチェックが必要となるが、
一般利用者と管理者を分けることにより分岐が不要となる。

また、一般利用者と管理者はユースケースが違うことが多く、
管理者は管理者に必要なカラム、一般利用者は一般利用者に必要なカラムが出てくることを考慮すると、
分けておいた方が柔軟性がある。

さらに、一般利用者をマーケティング等分析に使用するのであれば
管理者とはデータの性質が違うため、
分けた上で年齢や性別等の情報を持たせておくと、
利用しやすいデータとなる。

# 検索する時のことを考える
正規化はデータベースに柔軟性や保守性をもたらすが、
しすぎると利用時に多重JOINが必要になる。

するとパフォーマンス上よくなかったり、
SQLが煩雑になることによりアプリケーション側の保守性が悪くなったりする。

そのため、検索する時のことを考え、
ユーザが必要とする情報やシステムの根幹となる情報は
なるだけJOIN数を抑えて取得できるテーブル設計が良さそう。

# 状態を持つような情報は独立したテーブルにする
更新が多いと予想される、状態を持つような情報は
リレーションテーブルとして独立させておくと、
過去の状態が履歴として残る。

また基本的に更新が少ないテーブルと分離しておくことで
責務が分かれ、変更に強くなる。
Nuxtでブラウザから直接APIを叩くのはやめましょう

# はじめに
Nuxt案件でAWS構築を任される際、いつも下記エラーが話題になるので、説明資料としてあらかじめQiitaにまとめておきます。

- バックエンドAPIに繋がらない
- 環境変数を取得できない

# 前提
ECSでフロントエンドとバックエンドのそれぞれのサービスをデプロイします。
両方のサービスはプライベートサブネットに配置してあります。
![スクリーンショット 2022-05-26 17.09.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572098/66df64ac-b1a7-dc26-8fe2-c4d308d3b6a9.png)

# NuxtからバックエンドAPIに繋がらない
Nuxtからaxiosを使ってAPIを呼ぶときは、ブラウザから直接APIを叩くことはできません。
Nuxtサーバーを経由してバックエンドのAPIを呼ぶ必要があります。
そのため、proxyの設定をしましょう。
下記`process.env.BASE_URL`がバックエンドAPIのエンドポイントです。

```nuxt.config.js
export default {
    ...
    // Axios module configuration: https://go.nuxtjs.dev/config-axios
    axios: {
        proxy: true,
    },

    proxy: {
        '/api/': {
            target: process.env.BASE_URL,
        },
    },
    ... 
}
```
https://axios.nuxtjs.org/options/#proxy

# 環境変数が取得できない
ECSで設定できる環境変数は、Nuxtサーバーが動いている環境（例えばEC2やFargate）における環境変数です。
つまり、クライアント（ブラウザ）における環境変数ではありません。
そのため、上記proxy設定がされていないと、ECS設定した環境変数をNuxtが読み込むことはできません。

# 最後に
クライアントから直接APIを叩くのはやめましょうと言いましたが、API経由で画像などダウンロードするとNATの通信料がかかってしまうので、S3などはクライアントから直接アクセスしてもらった方がいいです。
SOFAframework備忘録　Softrobotpluginを使うための事前準備

SOFA flameworkのSoftrobot pluginのチュートリアルでいろいろ一緒にビルドされたパッケージが配布されてるのでこれを始めるための環境設定について記す
https://project.inria.fr/softrobot/

# 必要なもの

- 本体
    - SOFA framework
- プラグイン
    - Sofrrobot plugin
        - ソフトロボットの制御に関するあれこれを楽にしてくれる
    - STLIB(SOFA template library)
        - SOFAを使うにあたってよく書くテンプレ文を省略するためのライブラリ
    - SOFApython3
        - SOFAで.pyが使えるようになるplugin
        STLIBを使う場合必要になる

-----
自前で設定の必要のある項目
- python3.8
(python3.7-3.9なら大丈夫そうだけど公式が3.8を推奨)
- numpy scipy
- 環境変数周り

# 手順
### 1 pythonの準備
python3.8を入手しインストール
ターミナルでnumpy scipyをインストール
```
pip install numpy
pip install scipy
```

### 2 SoftRobotプラグインビルド済みSOFAの入手
ビルドされたものをダウンロード
https://project.inria.fr/softrobot/install-get-started-2/download/

解凍してrunSOFAを実行してみる
Edit→pluginManager
STLIBとSofaPython3が認識されているか確認

確認できれば4へ

### 3 SOFAPython3：環境変数の設定
runSOFA実行時のターミナルでSOFApython3が認識できていない場合以下のリンク先に従ってシステム環境変数を設定する
https://sofapython3.readthedocs.io/en/latest/menu/SofaPlugin.html#within-a-python3-interpreter

Windowsの場合
|変数名|値|
|:--|:--|
|SOFA_ROOT|SOFAのインストールディレクトリ|
|PYTHON_ROOT| pythonのインストールディレクトリ|
|PYTHONPATH|%SOFA_ROOT%\plugins\SofaPython3\lib\python3\site-packages|
|Path|;%PYTHON_ROOT%;%PYTHON_ROOT%\DLLs;%PYTHON_ROOT%\Lib;%SOFA_ROOT%\bin;|

SOFAを再起動するとSOFAPython3が認識されて.pyが読み込めるようになる

### 4 動作確認
SOFAでSoftrobotpluginのチュートリアル`~\SOFA\plugins\SoftRobots\docs\sofapython3\tutorials\FirstSteps\firststeps-tuto.py`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1680015/018efb07-b440-3f18-6f38-caea8b514af2.png)
Try the scene in Sofa をクリックするとコードが読み込まれる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1680015/18d3cf91-85aa-caef-849d-e7b73b4e40ae.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1680015/b57a9e30-6fa9-b5ec-01b8-004d65c89ff8.png)
Animateで落下するCubeを楽しめる

### 5 STLIB：VSの設定
editerでコードを開くとSTLIBが連携されてないのでVSが警告を吐く
面倒ならFile　→　ユーザー設定　→　設定
検索窓にExtra paths
Auto Completeの項目以下を追加
`\SOFA\plugins\STLIB\lib\python3\site-packages`

これでSTLIBをVSで呼び出せるようになる

以上

チュートリアルにたどり着くまでが一番長いのだ
チュートリアルを楽しもう！
https://www.youtube.com/watch?v=91G-knmgnxM&t
Shopifyで簡単にGoogle Fonts（フォント）や日本語フォントを導入する方法【備忘録】

## はじめに
今回の記事は、ShopifyでGoogleフォントや日本語フォントを導入した際の備忘録です。

いくつかの方法を調査して、今回の要件に合致する方法を発見したので、その備忘録としてこちらの記事を書いています。

それでは、ShopifyでGoogleフォントや日本語フォントを導入する方法について解説していきます。

## Shopifyでフォントを変更する方法
Shopifyはデフォルトである程度フォント変更を行うことができます。ただし、Googleフォントや日本語フォントには残念ながら対応していません。

Shopifyの管理画面から「オンラインストア＞テーマ＞カスタマイズ」に移動します。その後にテーマー設定をクリックすると、Shopifyのデフォルト機能としてフォントを変更することができます。

## ShopifyでGoogleフォントを導入するアプリ
ShopifyでGoogle Fontsを導入する方法を探していたところ、Fonifyというアプリを発見しました。

早速こちらのアプリを導入してみましたが、こちらは海外製のアプリであるため管理画面等があまり分かりやすく無いです。

事前の知識もいくつか必要なので、使用するのが難しいと感じました。

また、Googleフォント以外の日本語フォント（ヒラギノ等）を導入することはできないので、こちらのアプリは見送りました。

さらに調査を進めたところ、日本製のShopifyアプリを発見しました。

**らくらく日本語フォント設定｜リテリア Font Picker**というアプリです。

https://apps.shopify.com/font-picker-1?locale=ja

こちらのアプリを使用すると、Googleフォントだけでなく、日本語フォントを簡単にShopifyストアに導入することができました。

価格は4.9ドルになっているので、割りとお手頃価格です。

アプリの管理画面というよりは、ストアのカスタマイズ画面のセクション設定からフォントのカスタマイズを行うことができます。

実際にストアの見た目を確認しながらフォントを変更することができるため、イメージに合致した日本語フォントはGoogleフォントを簡単にShopifyストアに導入することができます。

以下、アプリのリストからいくつかの画像を引用させながら、簡単に機能を説明します。

## らくらく日本語フォント設定｜リテリア Font Pickerの簡単な説明
こちらのアプリについてですが、以下の画像が分かりやすいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2672276/e0227b29-ebb0-440c-7e85-fc42a2fac2f9.png)

このように、ノーコードで日本語フォントやGoogleフォントを使用することができます。

また、以下のように、ストアのカスタマイズ画面から簡単に日本語フォントやGoogleフォントを導入することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2672276/c3209cb8-978f-d3b5-5730-c1609c420a60.png)

また、以下の画像の場所にWebフォント読み込み用コードを貼り付けることで、簡単にGoogleフォントを使用することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2672276/14de0ae8-c927-5d24-120d-916d003cc7d1.png)

こちらのアプリを使用すれば、Shopifyストアで簡単にNoto Sans JPなどを導入することができます。

また、プロ向けの設定として、アクセントフォント等も設定することができます。

この設定を使用すると、h1,h2,h3などの各々のタグに別々の日本語フォントやGoogleフォントを当てることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2672276/3fcd150a-c943-5c67-b32a-764c31071c90.png)

また、カスタムWebフォントを実際に使用する場合には、以下のように指定の場所にコードを貼り付ける必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2672276/6157d6bd-c133-3c80-4e4f-d38b34e629ec.png)

また、こちらのアプリはアンインストールすれば負債となるコードが残ることはありません。

とりあえずShopifyストアに導入して動作検証を行うことをおすすめしています。

## 終わりに
ここまでで、ShopifyストアにGoogle Fonts（フォント）や日本語フォントを導入する方法の備忘録は終了です。

以下のURLより、アプリのインストールを行うことができます。

お疲れ様でした。

https://apps.shopify.com/font-picker-1?locale=ja
AL2内のElastic Beanstalk環境でbundle exec rails c (rails console) する方法

# Amazon Linux 1（AL1）

```shell-session
$ eb ssh
```

```shell-session
$ sudo su -
# cd /var/app/current
# bundle exec rails c
```

# Amazon Linux 2（AL2）

```shell-session
$ eb ssh
```

```shell-session
$ sudo su -
# /opt/elasticbeanstalk/bin/get-config environment | jq -r 'to_entries | .[] | "export \(.key)=\"\(.value)\""' > /opt/elasticbeanstalk/support/envvars
# sudo su - webapp
$ source /opt/elasticbeanstalk/support/envvars
$ rbenv shell $(rbenv global)
$ cd /var/app/current
$ bundle exec rails c
```

# ちょっとだけ解説

AL1のEB環境ではアプリケーションのデプロイ時にrootユーザに必要なEB環境変数等が設定された状態で実行されていました。
RubyやBundler等はシステムグローバルに入っているものが使われています。

AL2のEB環境ではwebappユーザが各種初期化スクリプトを経由してRails（Puma）を起動しています。
RubyやBundler等はrbenvによって管理されるようになりました。

webappユーザは様々なサポートスクリプトを経由してPumaを起動しますが、その際にEB環境に設定されている環境変数を取り込んでいます。
その内容が記述されているファイルをAL1と同様に扱うためにrootユーザで`/opt/elasticbeanstalk/support/envvars`へ出力し、`source`によって環境変数へ反映させています。

EB環境は複数のRuby用プラットフォームからバージョンのあったものを選択する必要がありますが、`64bit Amazon Linux 2 v3.4.6 running Ruby 2.7`のように詳細なバージョンまで指定する方法はありません。
そのため、AL1のEB環境では参照されていなかった`.ruby-version`との食い違い[^1]が発生してしまうことがあるのですが、それを回避するために`rbenv shell $(rbenv global)`を実行し、環境変数に`RBENV_VERSION=2.7.6`のようなものを設定することでコマンドラインでのRubyバージョンを指定しています。
[^1]:当然ですが`.ruby-version`の方をプラットフォームと同じバージョンにした方が良いです
TypeScriptで日付文字列(YYYY-MM-DD)の型を作る

# なにがしたいか
`2022-06-01`や`22/06/01`など特定の形式の文字列だけ許容したい。

# やりかた

テンプレートリテラルタイプを使用する。
下記のように特定の形式のみ許容できる型が作れます

```typescript
type Lang = '日本語' | '英語'
type LangTemplate = `母国語は${Lang}です` //   Template literal type

const okLang: LangTemplate = `母国語は日本語です` // ok
const errLang: LangTemplate = `母国語はhogehogeです` // error
```

これを利用します。

まずは年を定義します。

```typescript
type YYYY = `20${0|1|2|3|4|5|6|7|8|9}${0|1|2|3|4|5|6|7|8|9}`
```

これによりyearは2000~2099に制限できました。
1900年代も含めたい場合``19${0|1|2|3|4|5|6|7|8|9}${0|1|2|3|4|5|6|7|8|9}``を追加します。

次に月を定義します。
月は01~12までしかありませんので下記のように定義します。

```typescript
type MM = `0${1|2|3|4|5|6|7|8|9}` | `1${0|1|2}`
```

次に日付です。
日付は01~31です。

```typescript
type DD = `${0}${1|2|3|4|5|6|7|8|9}` | `${1|2}${zeroToNine}` | `3${0|1}`
```

そして、定義したこれらを使用して、`YYYY-MM-DD`の形式の型を作成します

```typescript
type YYYYMMDD = `${YYYY}-${MM}-${DD}`;
```

これで日付文字列だけ許容する型を作成できました。
あとは、`0|1|2|3|4|5|6|7|8|9`や`1|2|3|4|5|6|7|8|9`の共通化できるものなどをまとめたら完成です。


```typescript
type oneToNine = 1|2|3|4|5|6|7|8|9
type zeroToNine = 0|1|2|3|4|5|6|7|8|9
type YYYY = `19${zeroToNine}${zeroToNine}` | `20${zeroToNine}${zeroToNine}`
type MM = `0${oneToNine}` | `1${0|1|2}`
type DD = `${0}${oneToNine}` | `${1|2}${zeroToNine}` | `3${0|1}`
type YYYYMMDD = `${YYYY}-${MM}-${DD}`;
```

---
参考

https://javascript.plainenglish.io/type-safe-date-strings-66b6dc58658a

https://blog.logrocket.com/handing-date-strings-typescript/
scipy.stats: 平均値まわりの第 r 次母積率 moment

# 平均値まわりの r 次母積率

$(x-\mu)^r$ の期待値のことである。$\nu_r'$ で表すことが多い。

離散変数のときは

$\nu_r' = \sum(x-\mu)^r f(x)$

連続変数のときは

$\nu_r' = \displaystyle \int_{-\infty}^{\infty} (x-\mu）^rf(x）dx$

`moment(a, moment=1, axis=0, nan_policy='propagate')`


```python
from scipy.stats import moment
x = [1.2, 3.1, 4.6, 2.2, 5.7]
```

1次（デフォルト），2次，3次，4次の母積率（モーメント）


```python
moment(x), moment(x, 2), moment(x, 3), moment(x, 4)
```




    (0.0, 2.6184, 0.6126720000000052, 11.18588832)




```python
moment(x, [0, 1, 2, 3, 4, 5])
```




    array([ 1.        ,  0.        ,  2.6184    ,  0.612672  , 11.18588832,
            4.79398679])



$\nu_2'$ は母分散(ddof=0）である。


```python
x = [1.2, 3.1, 4.6, 2.2, 5.7]
moment(x, 2), np.var(x)

```




    (2.6184, 2.6184)



## 利用例

尖度 $g_2$ は 以下のように定義される。

$g_2 = m_4\ /\ m_2^2 - 3$


```python
from scipy.stats import kurtosis
x = [1.2, 3.1, 4.6, 2.2, 5.7]

m4 = moment(x, 4)
m2 = moment(x, 2)
g2 = m4 / m2**2 - 3 # kurtosis(x)
g2, kurtosis(x)
```




    (-1.3684571122281206, -1.3684571122281206)



歪度 $g_1$ は以下のように定義される。

$g_1 = m_3\ /\ m_2^{3/2}$


```python
from scipy.stats import skew
x = [1.2, 3.1, 4.6, 2.2, 5.7]

m3 = moment(x, 3)
m2 = moment(x, 2)
g1 = m3 / m2**(3/2) # skew(x)
g1, skew(x)
```




    (0.14460191499270095, 0.14460191499270095)
手っ取り早くカレントディレクトリのWARをローカルで動かしたい

# そんなあなたのためのワンライナー
```powershell
docker run --rm -d --name app -v "$(pwd):/config/dropins" -p 80:9080 -p 443:9443 websphere-liberty:full-java17-openj9
```

# ブラウザで確認
例えばhoge.warだったら以下。
```
http://localhost/hoge/
```

# ログの確認
```powershell
docker exec app cat /logs/messages.log
```

勿論tailでもOK
```powershell
docker exec app tail -f /logs/messages.log
```

# 終了する時
```powershell
docker stop app
```
or
```powershell
docker exec app server stop
```

どっちにしてもコンテナ消えます。
どっちでもいいですかね。

初回にLibertyのイメージさえ引いておけば、軽いし早いしマウントしなくても **docker cp app.war app:/config/dropins/** でデプロイ出来てお手軽なんで最近はよく使ってます。
scipy.stats: 記述統計 describe

# 記述統計 `describe`

サンプルサイズ，最小値，最大値，平均値，分散，歪度，尖度を求める。

`describe(a, axis=0, ddof=1, bias=True, nan_policy='propagate')`


```python
from scipy.stats import describe
x = [1.2, 3.1, 4.6, 2.2, 5.7]
describe(x)
```




    DescribeResult(nobs=5, minmax=(1.2, 5.7), mean=3.3599999999999994, variance=3.2729999999999997, skewness=0.14460191499270095, kurtosis=-1.3684571122281206)



表示される variance は，デフォルトで `ddof=1`， `numpy.var(x, ddof=1)` すなわち，不偏分散である。


```python
np.var(x, ddof=1)
```




    3.2729999999999997



`ddof=0` を指定すれば，不偏でない分散を表示する。


```python
describe(x, ddof=0)
```




    DescribeResult(nobs=5, minmax=(1.2, 5.7), mean=3.3599999999999994, variance=2.6184, skewness=0.14460191499270095, kurtosis=-1.3684571122281206)




```python
np.var(x)
```




    2.6184



表示される skewness，kurtosis は，デフォルトで `bias=True` であり，， `scipy.stats` の `skew(x)`, `kurtosis(x)` で計算されるものである。


```python
from scipy.stats import skew, kurtosis
skew(x), kurtosis(x)
```




    (0.14460191499270095, -1.3684571122281206)



`biase=False` を指定すれば，不偏推定量を表示する。


```python
describe(x, bias=False)
```




    DescribeResult(nobs=5, minmax=(1.2, 5.7), mean=3.3599999999999994, variance=3.2729999999999997, skewness=0.2155598077335502, kurtosis=-1.4738284489124838)




```python
skew(x, bias=False), kurtosis(x, bias=False)
```




    (0.2155598077335502, -1.4738284489124838)



多重代入して，必要なものだけを取り出すこともできる。


```python
n, minmax, mean, variance, skewness, kurtosis = describe(x)
minmax[1]
```




    5.7



2 次元以上の配列の場合には，`axis` で計算軸を指定できる。[^1]

[^1]: scipy.stats の統計関数に共通


```python
A = [[1.0, 2.0, 3.0],
     [4.0, 5.0, 6.0]]
```

`axis=0` で各列に対して集計される。


```python
describe(A, axis=0)
```




    DescribeResult(nobs=2, minmax=(array([1., 2., 3.]), array([4., 5., 6.])), mean=array([2.5, 3.5, 4.5]), variance=array([4.5, 4.5, 4.5]), skewness=array([0., 0., 0.]), kurtosis=array([-2., -2., -2.]))



`axis=1` で各行に対して集計される。


```python
describe(A, axis=1)
```




    DescribeResult(nobs=3, minmax=(array([1., 4.]), array([3., 6.])), mean=array([2., 5.]), variance=array([1., 1.]), skewness=array([0., 0.]), kurtosis=array([-1.5, -1.5]))



NaN 具体的には `np.nan` を含む場合には統計量はすべて `nan` になる。


```python
x = [1.2, 3.1, 4.6, 2.2, 5.7, np.nan]
describe(x)
```




    DescribeResult(nobs=6, minmax=(nan, nan), mean=nan, variance=nan, skewness=nan, kurtosis=nan)



NaN を除いて統計量を求めるためには，事前に NaN を除くか，`nan_policy='omit'` を指定する。


```python
y = np.array(x)[~np.isnan(x)]
describe(y)
```




    DescribeResult(nobs=5, minmax=(1.2, 5.7), mean=3.3599999999999994, variance=3.2729999999999997, skewness=0.14460191499270095, kurtosis=-1.3684571122281206)




```python
describe(x, nan_policy='omit')
```




    DescribeResult(nobs=5, minmax=(masked_array(data=1.2,
                 mask=False,
           fill_value=1e+20), masked_array(data=5.7,
                 mask=False,
           fill_value=1e+20)), mean=3.3599999999999994, variance=3.2729999999999997, skewness=masked_array(data=0.14460191,
                 mask=False,
           fill_value=1e+20), kurtosis=-1.3684571122281206)