OmniAICreator/Qiita-1.07M huggingface dataset:
Node.js から MongoDB Atlas の基本操作を行う

## ■ はじめに

Node.jsからMongoDB Atlasの基本操作ができるようになることが目標です。

※MongoDB Atlasは MongoDB社が提供しているクラウド上のMongoDB環境です。\
※MongoDB Atlasを利用するには利用登録が必要ですが、このドキュメントでは解説しません。

## ■ 環境

MongoDB Atlas version 5.0.8

Node.js v16.15.0

mongodb（ドライバ） 4.6.0

## ■ 目標

- クラウド上のMongoDBに接続できるようになる
- MongoDBからデータを取得できるようになる
- MongoDBにデータを追加できるようになる
- MongoDBのデータを変更できるようになる
- MongoDBからデータを削除できるようになる


## ■ 準備
` npm install mongodb `

## ■ 接続

```js
const { MongoClient, ServerApiVersion, MongoCursorInUseError } = require('mongodb')

// 接続文字列（MongoDBのサイトで調べることができる）
const uri = 'mongodb+srv://...'

async function main() {
    const client = new MongoClient(uri,
        { useNewUrlParser: true, useUnifiedTopology: true, verApi: ServerApiVersion.v1 })

    try {
        await client.connect()

        // ToDo: 各種DB操作
    }
    catch (err) {
        console.log(err.message)
    }
    finally {
        client.close()
    }
}
```

## ■ データの取得

```js
const query = {}    // 検索条件
const sort = { contents: 1 }    // ソート　1:昇順、-1:降順
const collection = client.db("test").collection("items")
const cursor = collection.find(query).sort(sort)
const documents = await cursor.toArray()
documents.forEach(doc => console.log(doc))
await cursor.close()
```

### 検索条件

```js
// 全件取得
const query = {}

// titleが「今日の天気」と完全一致するアイテムを取得
const query = { title: '今日の天気' }

// テキストの部分一致は正規表現を使う
const query = { title: /今日/ }

// 数値の場合はこう
const query = { id: 123 }
```

### ソートの優先順位

```js
// 複数のソートキーを指定すると、指定順に優先度が決まる
// 1:昇順、-1:降順
const sort = { contents: 1, temp: 1 }
```



## ■ データの追加

```js
const item = {
    title: '今日の天気',
    contents: '今日の天気は晴れのち曇り'
}
const collection = client.db("test").collection("items")
const result = await collection.insertOne(item)
console.log(`追加したドキュメントのIDは${result.insertedId}です`)
```

## ■ データの変更

### １件更新

```js
const filter = {title: '今日の天気'}
const update = {
    $set: {
        contents: '今日は晴天'
    }
}
const collection = client.db("test").collection("items")
// 複数のドキュメントが見つかった場合は最初のドキュメントが更新される
const result = await collection.updateOne(filter, update)
console.log(`${result.modifiedCount}件のドキュメントを更新しました`);
```

### 複数件更新

```js
const filter = {title: '今日の天気'}
const update = {
    $set: {
        contents: '今日は晴天'
    }
}
const collection = client.db("test").collection("items")
const result = await collection.updateMany(filter, update)
console.log(`${result.modifiedCount}件のドキュメントを更新しました`);
```

## ■ データの削除

### １件削除

```js
const query = {title: '今日の天気'}    // 検索条件
const collection = client.db("test").collection("items")
// 複数のドキュメントが見つかった場合は最初のドキュメントが削除される
const result = await collection.deleteOne(query)
console.log(`${result.deletedCount}件、ドキュメントを削除しました`)
```

### 複数件削除
```js
const query = {title: '今日の天気'}    // 検索条件
const collection = client.db("test").collection("items")
const result = await collection.deleteMany(query)
console.log(`${result.deletedCount}件、ドキュメントを削除しました`)
```

## ■ 参考

[本家サイトの使用例](https://www.mongodb.com/docs/drivers/node/current/usage-examples/)
ECSのデプロイ時エラーによるタスク無限再起動を防ぐ

# 概要
ECSにデプロイ時、
- ALBのヘルスチェックが通らない
- タスク自身のヘルスチェックが通らない
- コンテナ内部のエラーによってコンテナが止まってしまう

などの理由でECSがサービス内のタスクを無限に再起動し続けます。
放っておくとNATの通信料などがかかり痛手です。
これはECSサービスの`DeploymentCircuitBreaker`設定をオンにすると防げます。


# 実装
```CFn.yml
  YourService:
    Type: AWS::ECS::Service
    Properties:
      ServiceName: !Ref YourServiceName
      Cluster: !Ref YourClusterArn
      LaunchType: FARGATE
      DeploymentConfiguration:
        DeploymentCircuitBreaker: #ここを設定！
          Enable: true
          Rollback: true
        MaximumPercent: 200
        MinimumHealthyPercent: 75
      DesiredCount: !Ref DesiredCount
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: DISABLED
          SecurityGroups:
            - !Ref YourSecurityGroupId
          Subnets:
            - !Ref YourPrivateSubnet
      TaskDefinition: !Ref YourTaskDefinition
```

# コンソール
![スクリーンショット 2022-06-09 11.59.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572098/3e618ecc-5621-cb08-ebe1-ff894970d4f0.png)


# 参考
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/APIReference/API_DeploymentConfiguration.html

https://d1.awsstatic.com/Developer%20Marketing/jp/developer-zone/ECS-Deployment-Circuit-Breaker-Rollback.pdf
PHPのarray_mergeは配列のindexを振りなおす。連想配列の数字のindexを維持して結合したい際は足し算で結合しよう。

## array_mergeは添字を振りなおす

```php
$left = [
  2 => '2',
  1000 => '1000'
];

$right = [
  5 => '5',
  2000 => '2000'
];

$result = array_merge($left,$right);
 
```

とした場合、この連想配列の`array_merge`の結果は、連想配列が維持されません。

```php
array (
  0 => '2',
  1 => '1000',
  2 => '5',
  3 => '2000',
)  

```

になります。
同様に引っかかった人が多いのか、`array_merge`のドキュメントを読んでみると、このことが念入りに書いてあります。
[***「入力配列の中にある数値添字要素の添字の数値は結果の配列ではゼロから始まる連続した数値に置き換えられます」***](https://www.php.net/manual/ja/function.array-merge.php )。

なんでや! by 犠牲者N号


ちなみにインデックスがString型でも、数字の場合はphpが勝手に数字として解釈してしまい、添字の振り直しが行われます。

```php
$left = [
  '2' => '2',
  '1000' => '1000'
];

$right = [
  '5' => '5',
  '2000' => '2000'
];
```

これはアウトです。

## 足し算での結合の場合は数字の振り直しはない

足し算で結合すれば振り直しは行われないようです。

```php
$left = [
  2 => '2',
  1000 => '1000'
];

$right = [
  5 => '5',
  2000 => '2000'
];

$result = $left + $right;
 
```

この結果は

```php
array (
  2 => '2',
  1000 => '1000',
  5 => '5',
  2000 => '2000',
)  
```

になります。

## 結論

というわけで連想配列の数字のindexを維持して結合したい際は足し算で結合しましょう。
逆にもし、振り直しをしたいユースケースの場合は足し算を使わずに`array_merge`を使うのがよいと思います。

余談ですが、PHP7.4移行は`[...$left,...$right]`のようにスプレッド構文での結合方法が存在しますが、
この場合も連想配列のキーが数字の場合は添字を振りなおします。
なお、連想配列がキーがString型の場合はそもそもスプレッド構文を用いた結合ができません。

知らないと積みポイントなので備忘録化。
kintoneのテーブル内の計算についてのメモ

kintoneのテーブル内の項目を計算する際の注意点など。
全般ではなくてアプリ作成時に困ったことについてなので、かなり偏った内容。

# 計算式について

kintoneの計算式についてのリンク

計算式の設定
https://jp.cybozu.help/k/ja/id/040495.html

kintoneヘルプ。基本はここに書いてあることを正として確認する。

# テーブル内の項目の計算について

テーブルを使った計算
https://jp.cybozu.help/k/ja/id/040510.html

## CONTAINS関数

CONTAINS(フィールドコード, 検索文字列)

>・第1引数には、テーブル内の文字列（1行）、ラジオボタン、ドロップダウン、ルックアップ（コピー元が文字列型の場合）を指定します。
>・第2引数に検索文字列を指定します。

第１引数のフィールドコードは、複数の値をとるもの（つまり、内部的に配列構造を持つもの）は指定できないので注意。

例えばよくやりがち（？）な、チェックボックスを1つの項目だけにしてフラグのように使う場合は、CONTAINS関数でフィールドに指定できないので、チェックがついたら。。。などの判定を入れることはできない。

NG → CONTAINS(チェックボックスフィールド, "OK")
OK → CONTAINS(ドロップダウンフィールド, "OK")
[自分向けメモ]特定の条件の最後のレコードを出すクエリ

# 自分へ
もういい加減覚えてほしい。何度これを開くんですかね。。

# 内容
下記のようなテーブルがあった時、type_idとuser_idごとにまとめた最後(最新)のレコードが欲しい時のクエリ
つまり、idが2,4,5,6のレコードが欲しい時

テーブル名:test_table
|id|user_id|type_id|value|
|:-----------|:------------|:------------|:------------|
|1|1|1|AAA|
|2|1|2|BBB|
|3|2|1|CCC|
|4|2|2|DDD|
|5|1|1|EEE|
|6|2|1|FFF|

```sql
SELECT
    *
FROM test_table
INNER JOIN (
    SELECT 
        MAX(id)
    FROM test_table
    GROUP BY user_id, type_id
) AS max_id ON test_table.id = max_id.id
```
読書：Reactハンズオンラーニング


# はじめに

最近買った本が良かったので紹介します。

https://qiita.com/official-events/8746fa99d4e403fad3d1

今回読んだ本は、「Reactハンズオンラーニング〜Webアプリケーション開発のベストプラクティス」です。

https://www.oreilly.co.jp/books/9784873119380/

本書は、こんなアプリを作ってみましょう。まずは、...というようなハンズオン形式では書かれていません。原著のタイトルを確認してみましたが、「Learning React, 2nd Edition」となっていてハンズオンとは書かれていませんでした。
ハンズオンを期待している人は注意が必要です。

# 内容
ネットの記事やハンズオン的な書籍は、「どうやって書くのか」がメインなので「なぜこう書くのか」が体系的にわかる本書は、良書だと思います。また、ReactやJavaScriptの歴史的変遷にも触れられているため、他の情報を見た時に古いかどうか見分けられるようになります。最初、ネットの情報だけを頼りにしていたのですが、どの情報が古くて今の推奨はどれなのかわからずに時間を無駄にしてしまいました。
掲載されているコードがどれも10から20行程度でパッと見て理解できるものが多く読みやすいと思います。基本的な内容が多いので、一通りさっと読めて、あとはネットの情報を元に何か作れそうな気になります。（<- 今この状態）

# おすすめポイント

フック（Hook）については、この本を読んでやっと理解できました。「6章　ステート管理」、「7章　フック」に書かれています。フック（Hook）についてモヤモヤしている人にはおすすめです。

# まとめ

プログラミングを始めてみようという人には向いていないと思います。
（そもそも、そんな人はオライリーに手は出さないですよね。）
自分のように、他の言語の経験があってreactやってみようという人にはおすすめです。
AWS AuroraにGraviton導入しようとしてクジ運で負ける

2022/06/08 の事。

AWSはここ数年Gravitonプロセッサをプッシュしていますが、同程度のCPU・メモリだとAWS Pricing Calculatorの費用計算上はx86系より確かに安くなるな、ということでAWS東京リージョンのAWS AuroraでGraviton導入してみました。

https://aws.amazon.com/jp/ec2/graviton/

…いや、しようとしました。
以下はRDSイベントからの抜粋：

```plaintext
Insufficient instance capacity for instance type db.r6g.large in 
availability zone ap-northeast-1c; putting database instance into available
```

実際は[インスタンス容量の不足](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/CHAP_Troubleshooting.html#CHAP_Troubleshooting.Capacity)ということで導入できず。
別の機会ではうまく行ったんですけど。AWS東京リージョンの一部アベイラビリティゾーンでGravitonプロセッサの空きが物理的に足りないんだと想像してます。

つまり、今はクジ運が問われるかもしれない状況。

__あくまで一過性かもしれませんが__、いつGravitonプロセッサの空きが補充されるかわかりかねるので、現時点だと常にGravitonプロセッサで動かすような運用シナリオは堅牢じゃないのかもしれないですね。

長めのリードタイム、多めのリトライを心がけてインスタンス導入を始めたり、RDSリザーブドインスタンスでGravitonプロセッサ使うタイプが何台欲しいのか事前指定しておくなどが対策として考えられます。

以下詳細。

- 2022/06/08 時点で、東京リージョン `ap-northeast-1` のアベイラビリティゾーン `apne1-az1` では、RDSのタイプ `db.r6g.large` のインスタンス確保が難しそう。14:00〜17:30で11回試行して2回だけ成功。
- 一方、`apne1-az4`では5回試行してすべて成功。

:::note
一意なアベイラビリティゾーンIDの調べ方：
https://dev.classmethod.jp/articles/use-az-id-for-identify-az-crossing-over-account/
:::

# 雑感
バージニア北部リージョンのCloudWatchメトリクスの名前空間 `AWS/TrustedAdvisor` では自アカウントがサービス毎の制限にどれほど近づきつつあるかがメトリクスから判断できるんですが、ここでは流石にアカウントをまたいだリソース状況（例：アベイラビリティゾーンのGravitonプロセッサの空き）を正確に公開するのは不味いんでしょうかね。

AWS APIやサービスに対するメタ情報を提供する口がもっと増えてくれたらなぁと思います。
Excel VBAでSelenium無しのシンプルなWebスクレイピング。WebDriverも無し。

# やりたいこと
VBAを使って、Web上のテキスト情報を取得してExcelのセルにコピペしたいが、
Seleniumも、WebDriverも使わずに、てっとり早くやりたい。

この記事をさらにシンプルした手法になります。（その分やれることも少ないです）
https://qiita.com/uezo/items/66e20b064ffd5f239b9a

# やったこと
URLを指定すると、その下にURLのHTMLソースをとってくるVBAができました。
画像はサンプルで、Yahooファイナンストヨタの株価ページ
https://finance.yahoo.co.jp/quote/7203.T
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100646/a7289cf9-1062-fef3-459a-17ee812b997e.png)

# VBAコード
コードはたったの40行です。
```vb
Sub ソース取得実行()

    'urlと貼り付け先を取得
    url = "https://finance.yahoo.co.jp/quote/7203.T"
    Set target = Cells(3, 1)
    
    '前回の結果を削除する
    Range(target, Cells(Rows.Count, target.Column).End(xlUp).Offset(1)).Clear
    
    res = ソース取得(url)
    
    'セルに転記する
    'セルの最大文字数を考慮して<span>タグで改行するようにする
    res = Replace(res, "<span", vbLf & "<span")
    '改行で分けて配列化する
    arr = Split(res, vbLf)
    '配列をセル範囲に一気に貼る。セルループするととても遅い。
    target.Resize(UBound(arr) + 1, 1).Value = Application.Transpose(arr)
    
End Sub

Function ソース取得(url)

    'ソースを取得
    With CreateObject("WinHttp.WinHttpRequest.5.1")
        .Open "GET", url
        .Send
        buf = .responseBody
        
        'ソースを日本語に直す(.responseTextだとエラーが出ることがたまにある)
        With CreateObject("ADODB.Stream")
            .Open
            .Type = 1
            .Write buf
            .Position = 0
            .Type = 2
            .Charset = "utf-8"
'            .Charset = "shift_jis" '文字化けするときは"shift_jis"を試す
            ソース取得 = .ReadText
        End With
    End With

End Function
```

# 参考サイト
>バイナリ(ResponseBody)で結果を受け取って、Streamオブジェクトで適当に文字コードを変換してはいかがでしょうか。

https://answers.microsoft.com/ja-jp/msoffice/forum/all/winhttpwinhttprequest51/4a079e8e-3b9c-46b1-83d8-ed51618aeae5

https://www.web-dev-qa-db-ja.com/ja/excel/vbaxmlhttp%E3%81%8A%E3%82%88%E3%81%B3winhttp%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%AE%E9%80%9F%E5%BA%A6/828787223/
【react-fook-form】 Form内でEnterキーを押した際にSubmitをさせない方法

##  Form内でEnterキーを押した際の意図せぬSubmitを防ぐ方法


react-hook-formで作成したForm内でEnterキーを押すと、Submitが走り、勝手に次の未入力のinputにカーソルが移動したり、画面がリロードされます。
バリデーションを設けていない項目などは、入力途中にも関わらず（入力確定状態で）Enterを押すと勝手にリロード処理が走りform内容のpostリクエストがとんでしまう。ブラウザバックすると入力内容全てが消えている。。。
この動きはユーザー側からするとかなりダルい挙動なので、useStateとpreventDefaultでこれを制御してみました。
メモは要点のみでreact-hook-formの細かな設定やinputコンポーネント内のpropsや型の宣言等は割愛してます。

```typescript:UserForm.tsx
import { useContext, useEffect, useState } from 'react';


const UserForm: NextPage<Props> = ({ user }: Props) => {
...            
// ①入力しているか、していないかの状態をこのstateで管理します、デフォはtrue
  const [completeState, setCompleteState] = useState<boolean>(true);
...
  const onSubmit: SubmitHandler<HogeValues> = (input) => {
   // postリクエスト処理実行関数
  };
  return (
// ③Inputにカーソルが入っている時はpreventDefaultでsubmitスルー、カーソルが外れたらreact-hook-formのhandleSubmitが判定されsubmitスタンバイ状態＝下のボタンでpost可能な状態になります。通常のformなら単純にpreventDefaultをセットするだけで良いみたいですが、react-hook-formで作っている場合だとうまくいかず、stateのboolによるreact-hook-form実行or preventDefaultの判定を設けました。
        <form
          onSubmit={
            completeState
              ? handleSubmit(onSubmit) //handleSubmitはreact-hook-formの関数
              : (e) => {
                  e.preventDefault();
                }
          }
        >
// ②Inputに対して「カーソルが入っている時はfalse」「カーソルが外れた時はtrue」という状態をもたせます
          <Title>情報を入力してください</Title>
            <Input
              labelName='姓'
              name='lastName'
              type='text'
              control={control}
              error={errors.lastName?.message}
              onBlur={() => setCompleteState(true)}
              onFocus={() => setCompleteState(false)}
            />
            <Input
              labelName='名'
              name='firstName'
              type='text'
              control={control}
              error={errors.firstName?.message}
              onBlur={() => setCompleteState(true)}
              onFocus={() => setCompleteState(false)}
            />
          <Button>確定</Button>
        </form>
  );
};
export default UserForm;
..
```
【EBS】ボリュームの拡張

## EBSのストレージが不足

```shell-session
$ df -hT
Filesystem     Type      Size  Used Avail Use% Mounted on
devtmpfs       devtmpfs  967M     0  967M   0% /dev
tmpfs          tmpfs     978M     0  978M   0% /dev/shm
tmpfs          tmpfs     978M  632K  977M   1% /run
tmpfs          tmpfs     978M     0  978M   0% /sys/fs/cgroup
/dev/nvme0n1p1 xfs       8.0G  7.2G  836M  90% /
tmpfs          tmpfs     196M     0  196M   0% /run/user/1000
tmpfs          tmpfs     196M     0  196M   0% /run/user/0
```

上記のように、ストレージが90%使っており、ストレージを前もって拡張しておく必要がありました。

## EBS自体の拡張はAWSコンソールからできるが…
EBS自体のボリューム拡張はAWSコンソールからいくらか時間はかかりますがダウンタイム無しで可能です。ただそれだけでは実際に使っているファイルシステムには適用されないので、Linuxコマンドでファイルシステムの拡張をします。今回はAmazon Linux2での作業内容です

## ファイルシステムを拡張する

#### パーティションを確認する
```shell-session
lsblk
NAME          MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1       259:0    0  10G  0 disk
├─nvme0n1p1   259:1    0   8G  0 part /
└─nvme0n1p128 259:2    0   1M  0 part
```

nvme0n1の part１を拡張する必要があるとわかる。nvme0n1p1というのはnvme0n1のpart(?)1という意味

#### パーティションを拡張する
引数にはnvme0n1のpart1という意味合いで `/dev/nvme0n1 1` となる。
```
 sudo growpart /dev/nvme0n1 1
CHANGED: partition=1 start=4096 old: size=16773087 end=16777183 new: size=20967391 end=20971487
```

#### 拡張されているのがわかる
```
lsblk
NAME          MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1       259:0    0  10G  0 disk
├─nvme0n1p1   259:1    0  10G  0 part /
└─nvme0n1p128 259:2    0   1M  0 part
```


#### 各ボリュームでファイルシステムを拡張

```
df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        967M     0  967M   0% /dev
tmpfs           978M     0  978M   0% /dev/shm
tmpfs           978M  632K  977M   1% /run
tmpfs           978M     0  978M   0% /sys/fs/cgroup
/dev/nvme0n1p1  8.0G  7.2G  836M  90% /
tmpfs           196M     0  196M   0% /run/user/1000
tmpfs           196M     0  196M   0% /run/user/0
```

`/dev/nvme0n1p1` のmouted onの `/` を拡張する
今回はファイルシステムがxfsだったので以下のコマンド

```
$ sudo xfs_growfs -d /
meta-data=/dev/nvme0n1p1         isize=512    agcount=4, agsize=524159 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1 spinodes=0
data     =                       bsize=4096   blocks=2096635, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal               bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 2096635 to 2620923
```

## 結果
72%となり無事ストレージが拡張された

```
df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        967M     0  967M   0% /dev
tmpfs           978M     0  978M   0% /dev/shm
tmpfs           978M  632K  977M   1% /run
tmpfs           978M     0  978M   0% /sys/fs/cgroup
/dev/nvme0n1p1   10G  7.2G  2.9G  72% /
tmpfs           196M     0  196M   0% /run/user/1000
tmpfs           196M     0  196M   0% /run/user/0
```
iOS16の新機能のRoomPlanを実機で動かしてみた

このツイートを見て早速実機に入れて試してみました。

https://twitter.com/takesenit/status/1533964445810302976

## ドキュメント

https://developer.apple.com/documentation/roomplan

> デバイスのカメラを使用して物理的環境をスキャンするように人々をインタラクティブにガイドすることにより、部屋の3Dモデルを作成します。

> RoomPlanを使用して、室内の3Dモデルを作成します。フレームワークは、デバイスのセンサー、トレーニング済みのMLモデル、およびRealityKitのレンダリング機能を使用して、室内の物理的な環境をキャプチャします。たとえば、フレームワークはデバイスのカメラフィードとLiDARの読み取り値を検査し、壁、窓、開口部、ドアを識別します。RoomPlanは、部屋の機能、家具、電化製品（暖炉、ベッド、冷蔵庫など）も認識し、その情報をアプリに提供します。

## サンプルコード

サンプルコードは以下にあります。

https://developer.apple.com/documentation/roomplan/create_a_3d_model_of_an_interior_room_by_guiding_the_user_through_an_ar_experience

## 実機に入れるまでの流れ

- [iOSを16にアップデート](https://mobilelaby.com/blog-entry-how-to-install-the-ios-16-beta.html)
- [Xcode14](https://developer.apple.com/download/all/?q=Xcode)をインストール
- [サンプルコードをダウンロード](https://developer.apple.com/documentation/roomplan/create_a_3d_model_of_an_interior_room_by_guiding_the_user_through_an_ar_experience)してビルドする

## 使ってみた感じ

- 階段は認識しなかったので"部屋"に特化したAPI
- スキャンしながらモデルが生成されるので、既存のLiDARアプリより直感的
- スキャンしながらモデルが生成されるので、モデルを即エクスポートできて最高
  - 以前似たようなことをしたときはデータ出力〜変換で2日かかった

https://qiita.com/kitanote/items/90aa90bb07fa0912a02d

## 開発したアプリ

10/24にRoomPlanを使ったアプリをストアに公開しました。
よろしければ使ってみてください。

https://lp-measure.remodela.jp/
sshuttleとdnsmasqを組み合わせて，内部ネットワークに透過的にアクセスする

## 接続先ネットワークの諸元

接続先ネットワークの諸元を以下のように仮定する．

* 内部ネットワークのIPアドレス: 198.51.100.0/24
* 内部ネットワーク向けDNSサーバ: 198.51.100.3, 198.51.100.4
* 内部ネットワークのドメイン: internal.example.jp
* 外部ネットワークから内部ネットワークへのSSH踏台サーバ: ssh.example.jp

## SSH-VPNの設定

最初に，SSH踏台サーバに接続できることを確認する．公開鍵・秘密鍵の設定については，本稿では解説しない．

```sh
$ ssh ssh.example.jp
```

次に，`sshuttle`を直接実行してSSH-VPNを構成できることを確認する．

```sh
$ sshuttle --remote=ssh.example.jp 198.51.100.0/24 --ns-hosts 198.51.100.2,198.51.100.3
```

このコマンド実行時に，`sudo`コマンドのパスワードプロンプトが出現する場合には，sudoers の設定が必要である．

```sh
$ sshuttle --sudoers
```

というコマンドを実行して，`/etc/sudoers.d/sshuttle.auto`ファイルを生成する．

`sshuttle`により予定通りのルーティングが実現されているかどうかは，iptables の内容を見ると確認できる．

```sh
$ sudo iptables-save | grep sshuttle
:sshuttle-23400 - [0:0]
-A PREROUTING -j sshuttle-23400
-A OUTPUT -j sshuttle-23400
-A sshuttle-23400 -m ttl --ttl-eq 63 -j RETURN
-A sshuttle-23400 -d 198.51.100.3/32 -p udp -m udp --dport 53 -j REDIRECT --to-ports 23399
-A sshuttle-23400 -d 198.51.100.4/32 -p udp -m udp --dport 53 -j REDIRECT --to-ports 23399
-A sshuttle-23400 -m addrtype --dst-type LOCAL -j RETURN
-A sshuttle-23400 -d 127.0.0.1/32 -p tcp -j RETURN
-A sshuttle-23400 -d 198.51.100.0/24 -p tcp -j REDIRECT --to-ports 23400
```

最後に，`sshuttle`を`systemd`経由で起動できるよう設定する．まず，以下のような内容のファイルを，`~/.config/systemd/user/sshuttle.service`に用意する．

```conf:~/.config/systemd/user/sshuttle.service
[Unit]
Description=sshuttle
Requires=gpg-agent-ssh.socket
After=gpg-agent-ssh.socket

[Service]
Type=simple
Environment=SSH_AUTH_SOCK=/run/user/%U/gnupg/S.gpg-agent.ssh
ExecStart=/usr/bin/sshuttle --remote=ssh.example.jp 198.51.100.0/24 --ns-hosts 198.51.100.3,198.51.100.4

[Install]
WantedBy=default.target
```

以下のコマンドで，設定ファイルを読み込んでから，`sshuttle`を起動する．

```sh
$ systemctl --user daemon-reload
$ systemctl --user start sshuttle.service
```

## dnsmasqの設定

最初に，従来の`resolv.conf`を`dnsmasq`用にコピーする．

```sh
# cp -p /etc/resolv.conf /etc/dnsmasq.resolv.conf
```

次に，内部ネットワークの名前解決は内部ネットワーク向けDNSサーバに，それ以外の名前解決は通常のサーバに依頼するよう`dnsmasq`を設定する．

```conf:/etc/dnsmasq.conf
# Never forward plain names (without a dot or domain part)
domain-needed

# Never forward addresses in the non-routed address spaces.
bogus-priv

# Change this line if you want dns to get its upstream servers from
# somewhere other that /etc/resolv.conf
resolv-file=/etc/dnsmasq.resolv.conf

server=/internal.example.jp/198.51.100.3
server=/internal.example.jp/198.51.100.4
```

この段階で，`dnsmasq`が正しく動作しているかどうか，外部ネットワークおよび内部ネットワークおよびSSH踏台サーバの名前解決がそれぞれできているかどうかを確認する．

```sh
# 外部ネットワークの名前解決確認
$ host www.google.com localhost
# 内部ネットワークの名前解決確認
$ host some-machine.internal.example.jp localhost
# SSH踏台サーバの名前解決確認
$ host ssh.example.jp localhost
```

筆者の環境では，SSH踏台サーバのホスト名が内部ネットワークのドメイン名と一致してしまっていたため，名前解決ができなくなるトラブルが発生した．この場合は，SSH踏台サーバの名前解決を，内部ネットワーク向けDNSで行わないよう，以下を`/etc/dnsmasq.conf`に追記しておく必要がある．

```conf:/etc/dnsmasq.conf
server=/ssh.example.jp/8.8.8.8
```

なお，8.8.8.8 の部分は，適宜に適切なDNSキャッシュサーバに書き換えること．

正常に動作しているようであれば，`resolv.conf`を変更して，`dnsmasq`を参照するようにする．

```conf:/etc/resolv.conf
nameserver 127.0.0.1
```
lambda から OpenSearch （ ElasticSearch ）にqueryする

# はじめに
定期的にOpenSearchからデータ（ドキュメントの件数）を取得し、cloudwatchのカスタムメトリクスとして設定したかったので、lambdaからOpenSearchのデータ取得することを検討しました。curlの実行事例は多くありますが、lambda（python）はあまりなかったのでメモしておきます。

# lambdaの設定
lambdaがOpenSearchにアクセスできる必要があるため、OpenSearchと同じVPCに配置しておきます。また、セキュリティグループを設定します。

# OpenSearchに対してQueryする
pythonで書きました。専用ライブラリなどはなく、普通にjsonでhttpリクエストします。
query条件に応じて、URLとBodyを設定します。curlでリクエストできていれば、同じ内容でリクエストすればOK。

``` py
import json
import boto3
from urllib import request

def lambda_handler(event, context):
    
    #URLとHeader準備
    url = 'https://{endpoint}:443/{indexName}/{typeName}/_count?pretty'
    headers = {
        'Content-Type': 'application/json',
    }
    
    #query用のbody準備
    data = {
        'query': { 
            'bool': {
                'must' : {
                    'range' : {
                        'xxx_date': {
                            'lte': "2022-05-28T23:59:59.999"
                        }
                    }
                }
            }
        }
    }

    #HTTP request
    res = http_req(url, data, headers)
    
    #countだけ取り出して表示
    xxx_count = res["count"]
    print(xxx_count)
    #Cloudwatch metricsへの出力は省略

    return {
        'statusCode': 200
    }

# 引数のURL、BODY、HeaderでHTTPリクエストし、レスポンスボディをjsonで返す
def http_req(url, data, headers):
    post_req = request.Request(url, json.dumps(data).encode(), headers, method='POST')
    with request.urlopen(post_req) as res:
        body = json.load(res)
        return body

```

# おわりに
lambdaのトリガーは、EventBridgeで定期実行にしました。低頻度であれば、EC2でcronより低コストで済みます。
いろいろ入れたら npm がエラーになる

いつの間にか
npm run watch がエラーになってしまっていました。

:::note alert
> watch
> mix watch

node:internal/modules/cjs/loader:936
  throw err;
  ^

Error: Cannot find module '../package.json'
Require stack:
- /home/vagrant/docker-laravel-apache/backend/node_modules/.bin/mix
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
:::

../package.jspn が無いのが原因なんだそうだけど、どこからの相対パスなんだかわからん。
でqiitaでキーワード検索してみると、結構たくさんありました。
mumucochimu 氏の記事と

https://qiita.com/mumucochimu/items/fe1358fa5ffb5b06fca2

kuroro_ru 氏の記事がとても参考になりました。

https://qiita.com/kuroro_ru/items/d50212a1919308cc1480
Laravelの404エラーページを、bladeの中だけで簡潔にフロントページと管理画面でデザイン変更したい

## シンプルに三項演算子とPHPを使って分岐を作ろう
通常はフロント用のレイアウト用の共通ファイルを、/resources/view/layoutsに入れて使っていればこのように書いているとします。
404エラーは、フロント用のデザインに404エラーを表示しますね。
```php:404.blade.php
@extends('layouts.frontend')
```
フロントと管理画面で、404エラーのデザインを分けたいので、
管理画面用に別途用意した、admin_error.blade.phpを/resources/view/layoutsに入れておきます。

管理画面のURL（/admin）かどうかを
URIの２つめにadminが入っているURLかで
判別して、レイアウト共通ファイルを分岐させてやります。


```php:404.blade.php
@extends((explode("/", $_SERVER['REQUEST_URI'])[1]=='admin'?'layouts.admin_error':'layouts.frontend'))
```

こんな感じで、三項演算子とPHPを使って、bladeの中だけで完結することも可能ですね。
axiosでエラーにもレスポンスを表示させる方法

## 今回の目的
axiosでエラーのときでも、エラーのレスポンスを表示できたら嬉しいですよね！ってことで紹介します。
知っている人も多いかもしれませんが、自分の知識の定着として書きます！

### 今までの自分のエラー表示
```index.js
this.$axios.$post('postするときのURL')
.then((res)=>{
  console.log('RESPONSE',res)
})
.cacth((error)=>{
  console.log('ERROR',error)
})

```

こんな感じで書いていました。
![スクリーンショット 2022-06-09 10.03.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763535/87b9fd15-a9a2-a4c0-364a-2f82829f2317.png)

こんな感じで400なので、フロントのミスということはわかりますが、具体的に何が悪いのか？が分かりにくいですよね。

### 改善したエラー表示
```index.js
this.$axios.$post('postするときのURL')
.then((res)=>{
  console.log('RESPONSE',res)
})
.cacth((error)=>{
  console.log('ERROR',error.response.data
)
})

```
![スクリーンショット 2022-06-09 10.05.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763535/a7b12011-a256-edf5-eb31-dd91f500283c.png)

すると、こんな感じで具体的なメッセージがきて分かりやすく、表示されてどうしたらいいのかが分かりやすくなりました！
これを知った時は、感動しましたww

## 最後に
自分みたいにエラー内容が分かりにくくて、苦しんでいる人が少なくなればと思います。
CircleCIで行末の空白をチェックする

CircleCIで行末の空白をチェックする方法を紹介します。

### 行末の空白のチェックとは？

テキスト形式のファイルにおいて行末に空白があるかどうか検査します。一般的なコーディング規約ではコード、設定ファイル、README.mdなどのテキストファイルで行末の空白があるのはペストプラクティスから外れるとされる傾向があります。

### 行末の空白の例

![スクリーンショット 2022-06-09 9.18.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79373/5473f3a5-18df-755a-bfb4-756937a0c2d2.png)

画像でオレンジ色の部分が行末の空白です。テキストの行末の空白を削除する事を英語では**trailing space**や**traling whitespace**と言います。

### Executor用のDockerイメージの作成

CircleCIで行末の空白をチェックする場合専用のツールを使う方法もありますがパイプラインの先頭に処理を入れたい場合は専用のExecutorを実行した方が処理が速いと思われます。

そこで専用のExecutor用のDockerイメージを作成します。

```dockerfile:Dockerfile
FROM python:3-slim

# Install required packages
RUN apt-get update \
  && mkdir -p /usr/share/man/man1 \
  && apt-get install -y \
    apt ca-certificates curl git locales openssh-client sudo unzip

# Add User
RUN groupadd --gid 3434 circleci \
  && useradd --uid 3434 --gid circleci --shell /bin/bash --create-home circleci \
  && echo 'circleci ALL=NOPASSWD: ALL' >> /etc/sudoers.d/50-circleci \
  && echo 'Defaults    env_keep += "DEBIAN_FRONTEND"' >> /etc/sudoers.d/env_keep

# Copy trailing whitespace bash script to the image
COPY --chown=root:root --chmod=755 trailing-whitespace /usr/local/bin/trailing-whitespace

USER circleci
ENV PATH /home/circleci/.local/bin:/home/circleci/bin:${PATH}

CMD ["/bin/sh"]
```

```bash:trailing-whitespace
#!/usr/bin/env bash

set -e

tw_lines=""  # Lines containing trailing whitespaces.

# TODO (harupy): Check only changed files.
for file in $(git ls-files | sed -e 's/^/.\//')
do
  lines=$(egrep -rnIH " +$" $file | cut -f-2 -d ":")
  if [ ! -z "$lines" ]; then
    tw_lines+=$([[ -z "$tw_lines" ]] && echo "$lines" || echo $'\n'"$lines")
  fi
done

exit_code=0

# If tw_lines is not empty, change the exit code to 1 to fail the CI.
if [ ! -z "$tw_lines" ]; then
  echo -e "\n***** Lines containing trailing whitespace *****\n"
  echo -e "${tw_lines[@]}"
  echo -e "\nFailed.\n"
  exit_code=1
fi

exit $exit_code
```

このDockerfileとシェルスクリプト実行ファイルにより作成したDockerイメージを任意のコンテナレジストリへ登録します。

シェルスクリプトの実行部分は[こちらのリポジトリ](https://github.com/harupy/find-trailing-whitespace)を参考に作成しました。

### CircleCIで実行する

以下のようにコードを書いて実行します。

```yaml:.circlecli/config.yml

---
jobs:
  trailing-whitespace:
    docker:
      - image: ghcr.io/docker-hub-tm/circleci-executors/trailing-whitespace:latest
    resource_class: small
    steps:
      - checkout
      - run:
          name: Execute trailing-whitespace
          command: trailing-whitespace

version: 2.1
workflows:
  version: 2
  build:
    jobs:
      - trailing-whitespace
```

### 参考サイト

#### 処理を書く時に参考にしたコード
* [harupy/find-trailing-whitespace | GitHub](https://github.com/harupy/find-trailing-whitespace)

#### CircleCIで実際に動いているコードのサンプルコード
* [ansible-roles-mamono210/sl | GitHub](https://github.com/ansible-roles-mamono210/sl)

#### CircleCIのExecutor用イメージを作成するサンプルコード
* [docker-hub-tm/circleci-executors_trailing-whitespace](https://github.com/docker-hub-tm/circleci-executors_trailing-whitespace)
【Salesforce】レポートでテキストの数字を並べたい

# 問題

レポートでテキストの数字を並べたい。

テスト1、テスト2、テスト3・・・テスト10、テスト11、テスト12・・・

上記のようなデータの場合、レポートで並べ替えると、下記のような並び順になってしまう。

テスト1
テスト10
テスト11
テスト12
テスト2
テスト3

# 解決策

元々の項目の桁を0埋めで合わせる。

テスト01、テスト02、テスト03・・・テスト10、テスト11、テスト12・・・

「テスト」と「1」を結合する場合は、数式で0埋め対応をする。

```java:数式

IF ( LEN(TEXT(数字項目__c)) == 1 ,
    // 数字項目が1桁だった場合、先頭に0を付与する → [テスト][0][1]となる
    TEXT(テキスト項目__c) + '0' + TEXT(数字項目__c),
    // 数字項目が2桁だった場合、そのまま結合する → [テスト][11]となる
    TEXT(テキスト項目__c) + TEXT(数字項目__c)
) 

// 上記は回数の項目の桁が2桁の場合

```
SenjuでEC2インスタンスを自動で起動・停止する。祝日対応や緊急変更も簡単に。

# はじめに
AWSのEC2インスタンスを夜間や休日は停止しておいて、EC2のインスタンス課金を抑えたいといった場合の、インスタンスの自動起動・停止の方法は
+ Lambdaスクリプトを書いて、EventBridgeから呼び出し
+ AWS提供のInstance Schedulerをデプロイして利用

などいくつか方法があると思います。

しかし、下記のような条件に対応しようとすると、ルールやスクリプトが複雑になったり、変更のタイミングや戻しなど運用が煩雑になってしまいます。
+ 土日だけではなく祝日や特異日も停止しておく
+ 緊急リリースがあるため、急遽今週だけ土日も起動をする

そこで、Senjuのジョブスケジュールを使って、祝日など複雑な条件にも対応し、変更もしやすいEC2インスタンス自動起動・停止の仕組みを作ってみました。

# スクリプト作成
特定のタグが付いているインスタンスを対象に、起動・停止を行います。
今回は Key : ec2-reboot-senju , Value : On としました。

ジョブスケジュールで実行するスクリプトを作成し、Senjuのサーバーに配置します。
スクリプトは、AWS CLIで特定のタグを持つEC2インスタンスの一覧から、インスタンスIDを取得し、インスタンスのstartまたはstopを実行します。

```
aws ec2 describe-instances --filters "Name=tag:ec2-reboot-senju,Values=On" --query "Reservations[*].Instances[].InstanceId"
aws ec2 start-instances --instance-ids i-0123456789abcdefg
aws ec2 stop-instances --instance-ids i-0123456789abcdefg
```

# AWSでの設定
## EC2インスタンスへのタグ付け
起動・停止の対象とするEC2インスタンスへタグを設定します。
![senju06-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2683528/fd5514a1-c7cd-6aed-fbb3-1590f90ebd7c.png)


## EC2インスタンス操作の権限付与
SenjuサーバーからAWS CLIを用いたスクリプトを実行できるようにするために、SenjuサーバーのEC2へIAMロールをアタッチします。

AmazonEC2FullAccessポリシーを持つIAMロールを作成する。
※カスタムポリシーを作成してIAMロールに紐づけることで、より権限を制限することも可能です。
![senju05-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2683528/e54f05f4-5ba1-d0c4-e980-cb4568e36962.png)


EC2インスタンスに、IAMロールをアタッチします。
![senju05-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2683528/66652fec-5574-07bc-73ae-be40299c7451.png)


# Senjuでの設定
## カレンダーの作成(起動・停止の日付の設定)
営業日カレンダーを、会社や組織の営業日・非営業日を1年単位で指定して作成します。
今回は、2022年の日本の祝祭日に加え、6/15、7/13を特異日として非営業日にしています。
![senju02-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2683528/dedc77c0-41d4-6f37-d5e4-340103729705.png)

稼働日カレンダーを、元となる営業日カレンダーとジョブ稼働条件および非稼働条件を指定して作成します。
今回は、営業日はジョブを稼働し、非営業日は非稼働としています。
ただし、月初(毎月1日)は非営業日だったとしてもジョブが稼働する条件としています。
![senju02-0203.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2683528/111d7cfc-1775-45e7-a275-e86c30782788.png)




## ジョブの作成(起動・停止の時刻の設定)
「EC2インスタンス起動ジョブ」と「EC2インスタンス停止ジョブ」の2つのジョブを先行後続をつけずに並列に配置しています。
それぞれのジョブに起動時刻を設定でき、起動は9:00、停止は18:30と設定しています。
![senju03-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2683528/7c2d5a8e-4f12-2c9d-9dd2-73eb87c8f7ca.png)
![senju03-0203.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2683528/8f2ae061-be53-2d38-433a-b8aeb17d3177.png)

作成した営業日カレンダー、ジョブ・ネットを「システム」に登録し、自動サイクルをONにすることで、自動で稼働日に応じてジョブが実行されるようになります。
![senju04-0102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2683528/20eea762-391f-efa9-257d-9d7c9abd3b3d.png)


# まとめ
Senjuのジョブスケジュールを使って、祝祭日や特異日も含めた休日はEC2インスタンスを停止しておき、平日は9:00にインスタンスを起動し、18:30にインスタンスを停止する仕組みができました。

急遽今週だけ土日もインスタンス起動をするといった場合も、Senjuのカレンダーの設定を変更して稼働日とするだけで、ジョブが実行され、9:00にインスタンス起動、18:30にインスタンス停止が行われます。

# mPLAT/Tourのご紹介
「mPLAT/Tour」は、Senjuをクラウド型で提供しているmPLATを、メールアドレスを登録するだけで気軽にトライアル利用できるサービスです。
各種課題ごとに予めサンプル画面と環境設定が用意されているため、初心者でも簡単に、実践的な運用業務をご体験いただけます。
今回ご紹介したような、EC2スケジュール運用ガイドも用意をしており、指定したAWSアカウント上の任意のタグ付けがされたEC2インスタンスの自動での起動・停止をお試しいただけます。

_/_/ 詳しいご説明、お申し込みはコチラ↓_/_/
https://exp.mplattour.cloud/navi/index
【初心者】AndroidStudioでプロジェクトを作ってgithubに紐付けるまで

# この記事は
AndroidStudioで作ったプロジェクトをgithubのリポジトリに紐づけて、pushしたりpullしたりできるようにする方法を記します。

# 前提
sshを使いますので、その設定はすでにできているものとします。
sshナニソレ？な方は「ssh github」で調べてsshの作成と登録を行なってからこの記事を読んでください。


# 本題
では本題に入っていきます。

## githubに新しいリポジトリを作る
これはgithubにログインする→画面右上のアイコンクリック→Repository→NEW
で新しいリポジトリを作成できます。

プロジェクトの名前をテキトーに設定したら、まぁ一旦READMEは無しで`create repository`をクリックしましょう。これでgithub上にリポジトリができました！

`create repository`クリック後に出てきた画面の上らへん？にそのリポジトリのsshが表示されているはずなので、それをコピーしちゃいましょう。後で使います。


## AndroidStudio上で新しくプロジェクトを作成する
AndroidStudioを開く→New Project→アプリの名前(適当でおk), パッケージ名(適当でおk), minSDK(今だと8くらいでいいかな)を入力する→Finish

これでAndroid Studio上で新しいプロジェクトを作成することができました。
次は、早速Android Studioで作ったこの新しいプロジェクトを、さっき作ったgithubのリポジトリに紐づけていきます。紐付けができると、ソースコードをpushしたりpullしたりできるようになります。

## AndroidStudio上のプロジェクトをgithubのリポジトリに紐づける
AndroidStudioのターミナルを開きましょう。
AndroidStudioの一番下にGit, TODO, Problems..とかが書いてあるちっこいバーみたいなのがあって、そこに`Terminal`っていうのがあるはずです。それをクリックするとターミナルが開きます。

ターミナルを開いたら、以下のコマンドを順番に叩いていきましょう
```terminal
git init

git remote add origin [さっきコピーしたssh]

git status

git add .

git commit -m "initial commit"

git push origin master
```

これでgithubのリポジトリに行ってみて、さっき作成したプロジェクトがリポジトリに入っていればおk

## おまけ
`.gitignore`を編集すると、無駄なものをgithubにpushするのを防いでくれます。
今回はこのように設定しました。
```.gitignore
*.iml
.gradle
/local.properties
/.idea
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
*.apk
*.aab
```
JavaScript 有効な日付か判断する方法 isNaN

## Dateオブジェクトに変換して有効かどうか判断する

```js:例
var date = new Date("2000-10-40"); // 40日は存在しない

console.log(isNaN(date.getDate()));
// true
```

**解説**
1. 日付をDateオブジェクトに変換する。
2. getDateメソッドで日付の情報を取得する。
3. getDateメソッドは有効でない日付だとNaNを返す。
4. それを `isNaN` で判断する。( `isNaN()` 関数は引数が `NaN` かどうかを判定します)

※ `yyyyMMdd` の形式の日付は、Dateオブジェクトへの変換がうまくいかず、正しい日付でも有効でない日付と判断されることがあります。形式を変換してから行う必要があります。

**処理速度**
`isNaN(new Date())` のように、Dateオブジェクトを直接isNaNで判定することができますが、getDateを判定させた方が高速になるケースが多いらしいです。

**Invalid Dateで判断すれば良いのではないか？**
有効ではない日付をnew Dateに渡すとInvalid DateというDateオブジェクトが返されます。
`toString()` を使って `Invalid Date` かどうかを判断する方法もあります。
必ず `Invalid Date` の文字列を返す実装の場合はそれでもよいのですが、必ず `Invalid Date` の文字列を返すとは限らない実装の場合は `isNaN()` で判定をしましょう。
　
　

参考にした記事
https://ribbit.konomi.app/blog/javascript-check-date-one-liner/
TypeScriptの「as」の使い方

# `as`の使い方

TypeScriptでは`as`を型アサーションを行うために利用します。
つまり`型情報を強制的に修正する`ときに利用されます。

##### (例)
```typescript
type Info1 = {
  id: number;
}
type Info2 = {
  id: number;
  name: string;
}

function foo(obj: Info1): string {
  // ↓ これはエラーとなる
  // return obj.name;

  // objはInfo1型だが、無理やりInfo2型に修正して利用
  return (obj as Info2).name;
}

```
5.18 (標準) 順序統計量7

## 答案

![5.-29.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/f87a1a28-4867-f457-c615-e0131e056a21.jpeg)

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
[備忘録]Dockerとは？

<h2>概要</h2>
Dockerの勉強をする際に
・Dockerってなんだ？
・仮想マシン（VM）と何が違うの？
・メリット、デメリットは？
となったので、書き留めます。

<h2>Dockerとは</h2>

Dockerとは、コンテナ型の仮想サービスを提供しているパッケージのこと
Dockerを使うことで、ソースコードや構築が面倒な実行環境などを配布したりできる（イメージ化）

<h2>Dockerイメージとは</h2>

Dockerの説明に”Dockerイメージ”という言葉がよく使われますが、なんでしょう？
これは実行環境や実行に必要な変数、メタデータなどを含んだ動作環境テンプレートです。
Dockerイメージを作成する場合、Dockerfileというものが必要となります。

<h2>Dockerfileとは</h2>

Dockerイメージを作成するための設計図のようなもので、どんな構成にしたいかなどをテキストファイルに打ち込み、それを元にDockerイメージを作成することで、処理の一元化が可能になる、というものです。

<h2>Dockerイメージを使用する際に押さえておきたいポイント</h2>

1. ポート設定
　通信に用いるポート番号です。docker runする際に、-pオプションを使ってポートの結び付けを指定します。

2. 永続化すべきディレクトリ
　コンテナ内部のディレクトリのうち、マウントを必要とするディレクトリです。例えば「コンテンツを保存するディレクトリ」「データベースを保存するディレクトリ」などは、docker runする際に、-vオプションでそのディレクトリをマウントし、コンテナが破棄されても消えないようにします。

3. 設定情報
　ほとんどのDockerイメージは、環境変数などを使って各種設定をします。docker runする際に、-eオプションで指定します。

<h2>仮想マシンとの違い</h2>

仮想マシンとDockerの違いは以下です。

仮想マシン：
・OSを仮想化する
・OSの上にアプリケーションなどが乗っかっている
Docker：
・コンテナを仮想化する
・1個のOSをベースに複数のコンテナを用意できる

<h2>Dockerのメリット</h2>
・高速起動ができる
・簡単に環境構築ができる
・1個のコンテナにかかるリソースが少ないため、複数コンテナが起動していても負荷増にならない
・物理サーバーを用意しなくて良い

デメリット
・OS違いの検証ができない
・コンテナを削除するとデータも削除される
・セキュリティリスクが大きい
→１つのOSで稼働しているため


ーーーーーーーーーーーーーーーーーーーーーーーーーーー
<h2>疑問</h2>
・Dockerで本番環境運用すると、あまり良くないときくが、なぜか？

<h2>コンテナに向く/向かないシステム</h2>

<h3>向くシステム</h3>
・システムの変更が活発に行われる
・アップデート等の変更に対応していく必要がある
・バッチ処理のために起動するシステム

<h3>向かないシステム<h3>
・システムの変更がほとんどない
・長期の安定性が求められる
・ライセンス管理、保守サポートが必要

メリット
・開発環境がイメージとして配布できるため、環境構築に時間をかけずに済む
・

デメリット
・セキュリティに懸念がある？
・コンテナのデータ保存に工夫が必要？（どこかのストレージ、ローカルに保存するなど？）

ーーーーーーーーーーーーーーーーーーーーーーーーーーー


Dockerコマンドの早見表

Docker CLIの基本コマンド
DockerのCLIコマンドでよく利用するものをまとめてみました。

・Docker基本情報

docker version：Dockerバージョン情報の表示

docker info：Dockerシステム情報の表示

・コンテナの生成と削除

docker create：コンテナの生成

docker rm：コンテナの削除

・コンテナの実行

docker run：新規コンテナでコマンドを実行

・コンテナの起動・停止

docker start：コンテナの起動

docker stop：実行中のコンテナの停止

docker restart：コンテナの再起動

・コンテナ内プロセスの一時停止と解除

docker pause：コンテナ内プロセスの一時停止

docker unpause：コンテナ内プロセスの停止解除（再開）

・コンテナの操作

docker attach：標準入出力・エラー出力の実行中コンテナへの割当

docker exec：実行中コンテナでのコマンド実行

docker cp：ファイルやフォルダーのコンテナ間、ローカルファイルシステム間でコピー

・コンテナの保全

docker rename：コンテナ名の変更

docker diff：コンテナのファイル・ディレクトリ変更確認

・稼働状況とログ出力

docker ps：コンテナの一覧表示

docker top：コンテナ内実行プロセスの表示

docker stats：コンテナのリソース統計出力

docker logs：コンテナからログの取込み

Docker CLIのイメージ向けコマンド
Docker CLIのコマンドは多岐に渡りますが、Dockerイメージに関係するコマンドは以下の通りです。

・イメージの表示と管理

docker history：イメージの履歴表示

docker image：イメージの管理

docker images：イメージの一覧表示

docker inspect：Dockerイメージ等のオブジェクト詳細情報表示

・イメージの生成（作成）と削除

docker build：Dockerfileからイメージのビルド

docker commit：コンテナの変更情報からイメージを生成

docker rmi：イメージの削除

docker import：Tar形式アーカイブからファイルシステムイメージを生成

・イメージの保全

docker tag：イメージ共有用にタグ付け

docker trust：イメージ上の Docker署名管理

・イメージのロードと保存

docker load：Tar・標準入力からイメージをロード

docker save：イメージを Tarアーカイブとして保存

・リポジトリ運用

docker login：Docker Hub（Dockerレジストリ）にログイン

docker logout：Docker Hub（Dockerレジストリ）からログアウト

docker search：Docker Hubでのイメージ検索

docker pull：レジストリからイメージ・リポジトリのPull（ダウンロード取得）

docker push：リポジトリ・レジストリに対するイメージPush（アップロード登録）

参考文献

・Dockerイメージとコンテナの違いとは？作成の流れ入門

https://and-engineer.com/articles/YaSPjRIAACAAkhMI

https://knowledge.sakura.ad.jp/15253/
バッチ処理でwinscpを使いS3にアップロードする

表題のピンポイントの記事はなかったと記憶していますので、ご紹介します。

## 他の記事やブログ、マニュアルとの違い
1.S3にアップロードして
2.手動ではなくバッチ処理で
3.ダブルクォーテションでwinscpのコマンドを囲っていたものを囲わない書き方に

## 記述

```
file.bat

@echo off
"C:\Program Files\WinSCP\winscp.exe" /console /script="text_file_name.txt" /parameter %date:~0,4% %date:~5,2% %date:~8,2%

REM WinSCPの場所は各自変更してください。
REM dateは年、月、日で分けて引数としてtxtファイルに渡しています。
```

```
text_file_name.txt

option batch on
option confirm off

open s3://アクセスキー:シークレットキー@s3.amazonaws.com/ -hostkey="公開鍵1;公開鍵2"
cd /directory/%1%/%2%/
put C:\hoge\directory\hogefuga%1%%2%%3%.csv
exit

REM %1%などは引数、１は一つ目の意味
REM hostkeyに設定する公開鍵の値はIPv6のような00~ffがコロンで区切られているもので、私の環境では二種類出てきたのでそれをセミコロン区切りで記述しています。
REM 最初にhostkeyを付けずに実行すると証明書を信頼するかどうか聞かれるので、その画面で公開鍵を確認できます。
```
Ansibleの初期設定をシェルスクリプトで自動化してみた

# やったこと
Ansible使うぞ！と思ってもキーを出して実行されるサーバー側にキーを設定してとか、hostsファイルにIPアドレスを記載してとか色々設定がめんどくさい。。。。
そこで、Ansibleの初期設定をシェルスクリプトにして自動化しました！
↓のシェルスクリプトを使えばほんの10数秒でAnisbleが使用できるようになりますので、ぜひご覧くださいませ。

# シェルスクリプトの内容／解説
以下のようにシェルスクリプトを作りました。
```
amazon-linux-extras install -y ansible2
ssh-keygen -N ""
chmod 777 /root/.ssh/id_rsa.pub
ssh -i <秘密鍵> ユーザー名@$1 'sudo chmod 777 /root ; sudo chmod 777 /root/.ssh'
scp -i <秘密鍵> /root/.ssh/id_rsa.pub ユーザー@${1}:/root/.ssh/
ssh -i <秘密鍵> ユーザー名@$1 'sudo chmod 777 /root/.ssh/authorized_keys'
ssh -i <秘密鍵> ユーザー名@$1 ' cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys '
ssh -i <秘密鍵> ユーザー名@$1 'sudo chmod 550 /root ; sudo chmod 550 /root/.ssh ; sudo chmod 550 /root/.ssh/authorized_keys '
if [ `cat /etc/ansible/hosts|grep $1` = "$1" ]
then
echo OK
else
echo $1 >> /etc/ansible/hosts
fi
echo interpreter_python=/usr/bin/python >> /etc/ansible/ansible.cfg
```
流れとしては以下のようになります。

:::note info
ansibleをインストール
↓
権限を開いて実行される側のサーバーのauthorized_keysにid_rsa.pubの中身をコピー
↓
権限を閉じる
↓
if文で実行される側のサーバーのアドレスを/etc/ansible/hostsに記載
※すでに記載されている場合であれば実行されずOKを表示
↓
ansible.cfgに「interpreter_python=/usr/bin/python」を記載
:::

# 最後に
上記のスクリプトを使えば楽に初期設定ができるようになりました。
実行する際も下記コマンドを使えばOK
```
sh (ファイル名).sh IPアドレス
```
これで簡単に初期設定が行えます！
# 【JavaScript関数ドリル】初級編のlast関数の実装アウトプット

## last関数の課題内容

_.last関数を自分で実装する課題。
https://lodash.com/docs/4.17.15#last

「課題内容」/「解説動画」/「解答例」を確認したい場合は、以下リンク先のページを参照。
https://js-drills.com/blog/last/


## 課題に取り組む前の状態

- 解答例を見なくてもできそうだと思った。


## 課題に取り組んだ後の状態

- 同じように書けたのでよかった。

## last関数の実装コード（答えを見る前）
```javascript
function last(array) {
    return array[array.length - 1];
}
```

## last関数の実装コード（答えを見た後）
```javascript
function last(array) {
    return array[array.length - 1];
}
```
Matlabからpowershell スクリプトを実行する


Matlab mファイルから powershell スクリプトを読み出す方法です。

```Matlab
% Execute powershell script
op = "text.txt"
command = ['!powershell -NoProfile -ExecutionPolicy Remotesigned -File .\exec-samplescript.ps1 -File'];

command = [ command ' ' op];
eval(command);

```
FlutterSDK version の更新方法

# エラー概要
こちらのサイトをもとにFlutter＆Firebaseの環境構築の途中で詰まりました。
[Flutter アプリに Firebase を追加する](https://firebase.google.com/docs/flutter/setup?hl=ja&platform=ios)

下記のコマンドに対してエラーが発生しました。
```console:console
$ dart pub global activate flutterfire_cli

Resolving dependencies... (2.7s)
The current Dart SDK version is 2.12.0.

Because every version of flutterfire_cli depends on xml >=5.2.0 which requires SDK version >=2.13.0 <3.0.0,
  flutterfire_cli is forbidden.
So, because pub global activate depends on flutterfire_cli any, version solving failed.
```

・DartのVersion確認。
```console:console
$ dart --version
Dart SDK version: 2.12.0 (stable) (Thu Feb 25 19:50:53 2021 +0100) on "macos_x64"
```

# 解決方法
・コマンド等ではなく、FlutterSDKの差し替えを行うことで解決しました。

①下記サイトへアクセス。(2022年6月時点でのStableリンクです。)
[Get the Flutter SDK](https://docs.flutter.dev/get-started/install/macos#get-sdk)

②zipファイルのダウンロード（Intel, Apple Siliconのどちらかを選択）
![スクリーンショット 2022-06-09 8.33.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/852882/9ae773d5-37ce-1b9b-2261-3444ac4d7781.png)

③Finder上で解凍し、既存のflutterフォルダと差し替える
![スクリーンショット 2022-06-09 8.34.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/852882/89186f1b-8372-e842-079a-44be8a7ec658.png)

# 結果
・再度、DartのVersion確認。
```console:console
$ dart --version
Dart SDK version: 2.17.1 (stable) (Tue May 17 17:58:21 2022 +0000) on "macos_x64"
```

・コマンドの再実行。
```console:console
$ dart pub global activate flutterfire_cli

+ ansi_styles 0.3.2+1s... (1.4s)
+ args 2.3.1
+ async 2.9.0
+ ci 0.1.0
// 以下略
```

・無事に成功しました。
BATファイルからpowershellスクリプトを実行する

bat ファイルから powershell スクリプトを読み出す方法です。

```DOS
# Execute powershell script
powershell -NoProfile -ExecutionPolicy Unrestricted -File exe-samplescript.ps1

```

引数はそのまま 引数を書けば Powershell Scirptの引数として認識されます。

```DOS
powershell -NoProfile -ExecutionPolicy Unrestricted -File exe-samplescript.ps1 -path "c:\test" -output ".\test.txt"

```
【JavaScript関数ドリル】初級編のlastIndexOf関数の実装アウトプット

## lastIndexOf関数の課題内容

_.lastIndexOf関数を自分で実装する課題。
https://lodash.com/docs/4.17.15#lastIndexOf

「課題内容」/「解説動画」/「解答例」を確認したい場合は、以下リンク先のページを参照。
https://js-drills.com/blog/lastIndexOf/


## 課題に取り組む前の状態

- 解答例を見なくてもできそうだと思った。


## 課題に取り組んだ後の状態

- だいたい同じように書けたのでよかった。

## lastIndexOf関数の実装コード（答えを見る前）
```javascript
function lastIndexOf(array, value, fromIndex = array.length - 1) {
    for (let i = fromIndex; i >= 0; i--) {
        if (array[i] === value) {
            return i;
        }
    }
    return -1;
}
```

## lastIndexOf関数の実装コード（答えを見た後）
```javascript
function lastIndexOf(array, value, fromIndex = array.length - 1) {
    for (let i = fromIndex; 0 <= i; i--) {
        if (array[i] === value) {
            return i;
        }
    }
    return -1;
}


```
ModelMapperでRecord->POJOへのマッピングがしたい

現在公式ではサポートされておらず、自前で実装する必要があります。

https://github.com/modelmapper/modelmapper/issues/546

以下2つを行うことで変換ができるようになります。

 - `ValueReader`を自前で実装する
 - `ModelMapper`の`Configuration`に上記で実装した`ValueReader`を追加する

## `ValueReader`を自前で実装する

`org.modelmapper.spi.ValueReader`というインターフェースが用意されているので、
`Record`のフィールドが取得できるように実装します。

以下のソースコードをコピペすれば使えると思います。
やっていることはシンプルで引数の値に応じてリフレクションを使って値を引っこ抜くというコードを書いています。

https://gist.github.com/okaponta/29a0a761db2282e588ebe6715353a560

## `ModelMapper`の`Configuration`に上記で実装した`ValueReader`を追加する

上記で実装したクラスを`RecordValueReader`と名付けたとして、以下のように呼び出しを追加してあげます。

```JavaConfig.java
@Bean
public ModelMapper modelMapper() {
    ModelMapper mapper = new ModelMapper();
    mapper.getConfiguration().addValueReader(new RecordValueReader());
    return mapper;
}
```

これで、以下のように呼び出してあげれば`Record -> POJO`への変換ができます。

```java
Converted converted = modelMapper.map(record, Converted.class);
```

## 結論

`ModelMapper`を使いたいなら、
現時点では`Record`を使わずに`POJO`でやった方が楽ちん。
【JavaScript関数ドリル】初級編のnth関数の実装アウトプット


## nth関数の課題内容

_.nth関数を自分で実装する課題。
https://lodash.com/docs/4.17.15#nth

「課題内容」/「解説動画」/「解答例」を確認したい場合は、以下リンク先のページを参照。
https://js-drills.com/blog/nth/


## 課題に取り組む前の状態

- 解答例を見なくてもできそうだと思った。


## 課題に取り組んだ後の状態

- ちょっと時間がかかった
- １行で済ませる書き方がまだわかっていなかった

## nth関数の実装コード（答えを見る前）
```javascript

function nth(arr, n = 0) {
    
    if (n < 0) {
        return arr[n + arr.length];
    } else {
        return arr[n];
    }
}

```

## nth関数の実装コード（解答例）
```javascript

function nth(array, n = 0) {
  return n >= 0 ? array[n] : array[array.length + n];
}

```
ReactでHot Reloadが出来なかった理由

## 背景
現在、Webアプリ開発をしたくReactを勉強中の身です。

yarn start(npm start)でローカルサーバーを立てた後はファイルを変更すれば自動的に再読み込み(Hot Reload)されるはずなのに一向にされないので原因を調べてた結果、原因と対策が分かりましたので備忘録をつけておこうと思い、書いております。

## 環境
Windows 11
Docker Desktop v4.9.0


## 原因
Dockerの/workspaceフォルダ直下にプロジェクトを作成したのが問題でした。
どうやらworkspace直下だとファイルを監視できないみたいですね。

[takashiuesaka](https://qiita.com/takashiuesaka/items/4012fee49ee0e06db72b "VSCode の Remote Container で React開発環境を構築する")様の記事に書いてありました。ありがとうございます。

## 対策
devcontainer.json内の`workspaceFolder`をhomeディレクトリに変えれば解決されました。
```devcontainer.json
//"workspaceFolder": "/workspace/ui",
"workspaceFolder": "/home"
```
上記を実行したことで、HotReloadされるようになり、ビルド時間もだいぶ短縮されました。

Docker上でReact開発している人で同じような現象が出ている人は参考にしてください。

他の解決策がある人は教えていていただけると嬉しいです。
GoogleAIを使ったアナログデータデジタル化プロジェクト＃１

世の中に沢山あるアナログデータ、特に検査機器のジャーナルプリンタより吐き出される印刷物のデジタル化は医療業務では今後不可欠となると考え、GoogleAIを利用した例として、今回は動物血液検査機器の検査結果プリントアウトをiPhone(iPad)にて撮影データ転送と共にGoogleのテキスト解析AIにて結果データを抽出し、データベース化を図るというものです。
先ずは、カメラにて撮影さらに検査結果部分をトリミング。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/2501fbc8-1fb2-9c07-3b4d-35686ee59bda.png" width="50%"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/c48fa7f1-8335-9206-c961-553e889b320d.png" width="50%">
トリミングされた結果データ画像をサーバへ転送と同時にGoogleAIにて解析。
リクエスト用のJSONを作成、今回はPHPのcURL関数にてレスポンスとして取得したJSONのdescriptionより結果データを取得しする。
取得データサンプル
WBC
RBC
HGB
HCT
MCV
MCH
MCHC
PLT
111
545
13.5
40.9
75.0
24.8
33.0
49.1
次回は、iPhone(iPad)によるトリミング機能付き画像データ転送アプリおよびサーバサイドの解析処理を解説します。
【JavaScript関数ドリル】初級編のslice関数の実装アウトプット

# 【JavaScript関数ドリル】初級編のslice関数の実装アウトプット

## slice関数の課題内容

_.slice関数を自分で実装する課題。
https://lodash.com/docs/4.17.15#slice

「課題内容」/「解説動画」/「解答例」を確認したい場合は、以下リンク先のページを参照。
https://js-drills.com/blog/slice/


## 課題に取り組む前の状態

- 解答例を見なくてもできそうだと思った。


## 課題に取り組んだ後の状態

- だいたい解答例と同じようなコードを書くことができた。

## slice関数の実装コード（答えを見る前）
```javascript
function slice(array, start = 0, end = array.length) {
    const newArray = [];
    
    for (let i = start; i < end; i++) {
        newArray.push(array[i]);
    }

    return newArray;
}

```
【JavaScript関数ドリル】初級編のtail関数の実装アウトプット

## tail関数の課題内容

_.tail関数を自分で実装する課題。
https://lodash.com/docs/4.17.15#tail

「課題内容」/「解説動画」/「解答例」を確認したい場合は、以下リンク先のページを参照。
https://js-drills.com/blog/tail/


## 課題に取り組む前の状態

- 解答例を見なくてもできそうだと思った。


## 課題に取り組んだ後の状態

- だいたい解答例と同じようなコードを書くことができた。

## tail関数の実装コード（答えを見る前）
```javascript
function tail(array) {
    if (!array) {
        return;
    }

    return array.slice(1);
}

console.log(tail([1, 2, 3]));
// => [2, 3]
```

## tail関数の実装コード（答えを見た後）
```javascript
function tail(array) {
    const newArray = [];

    for (let i = 1; i < array.length; i++) {
        newArray.push(array[i]);
    }
    
    return newArray;
}
```