OmniAICreator/Qiita-1.07M huggingface dataset:
VSCodeでタブが突然無限増殖し始めた時の対処法



# 記事概要
VSCode使用中にタブが突然増殖し続ける現象が起き、とりあえずは対処できたのでその時の方法を書きます。

# 目次
[1.環境](#1-環境)
[2.起きた症状](#2-起きた症状)
[3.試してダメだった方法](#3-試してダメだった方法)
[4.対処方法](#4-対処方法)
[5.増殖させずにkeybindings.jsonを開く方法](#5-増殖させずにkeybindings.jsonを開く方法)
[6.おわりに](#6-おわりに)


# 1. 環境
Windows10
VSCode 1.56.0

# 2. 起きた症状
VSCodeのkeybindings.jsonファイルをいじろうとコマンドパレットから開いたところ、そのJSONファイルのタブが増殖し始めて止まらなくなった。(左下の歯車アイコンから「キーボードショートカット」を選択し、その画面の右上メニューからJSONファイルを開く場合でも同じ現象が起きた)
1000個くらいまで増殖したら止まったが、色々メニューを触ったりしているとまた増殖を始める。
増殖中は、メニューなどを開こうとしてもすぐに閉じてしまう。

こんな感じで増殖する↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259893/6a4ba6c9-9b12-8225-daac-00641cfa75ee.png)


# 3. 試してダメだった方法
とりあえず全部閉じようと思い、右上の・・・アイコンから「すべて閉じる」を押しても、ファイルの変更を保存するか、という旨のポップアップが増殖したすべてのタブについて現れ、一括選択のオプションもなかったので、増殖したタブすべてにそれを適用するとなると膨大な時間がかかってしまうからさすがにしんどい。

アンインストールしてから再インストールしても、本体以外(インストールした拡張機能など)は残るようなので、意味はなかった。
ちなみにVSCodeをしっかりアンインストールしたいなら、各設定ファイルやキャッシュが保存されているディレクトリも削除しないとダメらしい。
(再インストールして起動したら、アンインストール前に開いてるタブまでしっかり保存されてた)

# 4. 対処方法
C:\Users\(ユーザー名)\AppData\Roaming\Code\Backupsにあるフォルダを削除する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259893/c2ab4cf5-3c63-46e0-01f8-1aa64c62699b.png)

そうすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259893/274563c3-97c4-e905-ac30-1457a0ef1cef.png)

増殖したタブがこのような内容に変わり、増殖も止まる。
この状態で右上の・・・アイコンから「すべて閉じる」を押すと、ファイルの変更を保存するか、という旨のポップアップも出ずにすべて一括でタブを閉じることができる。

# 5. 増殖させずにkeybindings.jsonを開く方法
症状の項で書いた方法と同じ方法でkeybindings.jsonを開こうとしたらまた同じ現象が起きるので、
keybindings.jsonを開きたい場合、VSCode内からではなくファイルエクスプローラーから直接開くと増殖させずに開くことができました。

keybindings.jsonの場所↓　一応macとlinuxも載せときます
| OS | 場所 |
|:-:|:-:|
|  Windows  | C:\Users\(ユーザー名)\AppData\Roaming\Code\User  |
| Mac  | $HOME/Library/Application Support/Code/User  |
| Linux  | $HOME/.config/Code/User   |
Matplotlibで可変数ラインのリアルタイムグラフを描写する

#たくさんのセンサー出力値リアルタイムグラフ化したい
例えば、ジャイロのX,Y,Z　加速度計のX,Y,Z　などを同時表示したいと思い
matplotlibをいじっていたのですが、決められたライン数のみしか表示するサンプルしか見つからず、試行錯誤しながら可変数ラインを表示できるリアルタイムグラフ表示を自分で作ってみました。

###使用環境
windows , winpython, numpy, matplotlib

###実行結果
![graph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506495/d6213b36-7b2c-db39-57a7-0ecf823f54ec.png)
Sin, Cos, Tan計算結果をグラフ表示とは別のスレッドで入力しています。
実際に動作させれば、リアルタイムに動作します
サンプルでは3ラインだけですが、理論的に無限にグラフを増やせるはずです。

###苦労したこと
Pythonのタプルをちゃんと理解していなかったので、とても時間がかかった。
(今でもちゃんと理解できていないかもしれませんが...)

###ソースコード


```python:Variable_graph.py
import numpy as np
import tkinter as tk
import tkinter.ttk as ttk
import math

from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure
import matplotlib.animation as animation

class GraphFrame(ttk.Frame):
    def __init__(self, master, graph_num):
        #Graph view
        fig = Figure()
        canvas = FigureCanvasTkAgg(fig, master=master)
        self.x = np.arange(0, 10, 0.1)
        self.y_datas = []
        for y in range(graph_num):
            print(y)
            self.y_datas.append( np.zeros(100) )
        l = np.arange(0, 10, 0.01)
        plt = fig.add_subplot(111)
        plt.set_ylim([-2, 2])
        plt.set_position([0.07, 0.05, 0.9, 0.9])
        self.lines = []
        for y in range(graph_num):
            yp, = plt.plot(self.y_datas[y])
            self.lines.append( yp, )

        ani = animation.FuncAnimation(fig, self.animate, l,
                                      interval=20, blit=True,
        )
        canvas.get_tk_widget().pack()

    def animate(self, i):
        count = 0
        for line in self.lines:
            line.set_ydata(self.y_datas[count])
            count+=1
        return self.lines[0:]

    def setValues(self, vals):
        count = 0
        for val in vals:
            self.y_datas[count] = np.append(self.y_datas[count], val)
            self.y_datas[count] = np.delete(self.y_datas[count], 0)
            count+=1

class DataUpdateGraph(ttk.Frame):
    def __init__(self, master):
        self.test_count = 0
        self.graph_num = 3
        #Selectable lines
        self.master = master

        graph_frame = ttk.Frame(master)
        self.gf =GraphFrame(graph_frame, self.graph_num)
        graph_frame.pack(side = 'right', fill = 'x')

        self.update()

    def update(self):
        vals = []
        vals.append( math.sin(math.radians(10*self.test_count)))
        vals.append( math.cos(math.radians(10*self.test_count)))
        vals.append( math.tan(math.radians(10*self.test_count)))                
        self.gf.setValues( vals )
        self.test_count+=1
        self.master.after(100, self.update)

        
if __name__ == "__main__":
    win = tk.Tk()
    gh = DataUpdateGraph(win)
    win.mainloop()
```
Hybridソリューション（オンプレ）

パブリッククラウドとの連携を考慮した、ブライベートクラウドのソリューションの比較

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683282/7582a20e-1b33-07d3-c4aa-9206fdf64738.png)
【TypeScript】TypeScript の Generics


#  Generics 型とは
* 追加の型情報を提供できる型です
* TypeScriptの型安全を高めたコードを書けます
* IDEの自動補完サポートなどが受けられます
    * `Array<string>`
    * `Array<number>`

##型の指定方法

```ts
const names: any[] = []; 
const names: Array<string> = []; // string[]
const names: Array<string | number> = []; // string[]
const names: Array<any> = []; // string[]
```

```ts
//この配列ではstringの操作が可能
const names: Array<string> = []; // string[]
names[0].split(' ');
```

###Promiseコンストラクタ関数で型を指定
* Promise<T>と指定することで、最終的にnumberを返す関数であることを明示的にできる

```ts
const promise: Promise<string> = new Promise((resolve, reject) => {
   setTimeout(() => { //timer設定
     resolve('終わり！');          //stringを返す
   }, 2000);
 });

// Generics型 <string>を使えば、stringメソッドを呼べる
 promise.then(data => {
    data.split(' ');
 });

```

##独自のGenerics関数を作成
* 関数の引数に object型を指定するのみでは、objectの中身のプロパティ情報が得られません
    * `merge(objA: object, objB: object)`
* 型キャストをつかって、型情報を指定することができるが、1個1個指定するのは大変。。
* Generics型を使えば、特定の異なった型の交差型を渡すと伝えることができ、明確に型を指定しなくても、オブジェクトのプロパティ情報を伝えることができます
* つまり、関数の引数から動的に型を設定することができ、柔軟な関数になります！


```ts
//objectとobjectの交差型を返す
function merge(objA: object, objB: object) {
  return Object.assign(objA, objB);
}

console.log( merge( { name: 'Neko' } ,  { age: 3 } ) );

//変数に格納すると、name,ageのプロパティにアクセスできない
const mergedObj = merge( { name: 'Neko' } ,  { age: 3 } );
// console.log(mergedObj.age);  // Property 'age' does not exist on type 'object'.


//対処法1 型キャストを使った場合
const mergedObj = merge( { name: 'Neko' } ,  { age: 3 } ) as {
    name: string ;
    age: number;
};
mergedObj.name ; //OK


//対処法2 Generics関数を使った場合
function merge<T , U>(objA: T, objB: U) { //交差型（T&U）を返すと推論される
  return Object.assign(objA, objB);
}

const mergedObj = merge({ name: 'Neko', hobbies: ['Sports'] }, { age: 3 });
console.log(mergedObj.name); // Neko

//このように指定するのと同じこと（指定する必要はない）
const mergedObj = merge<{ name:string; hobbies :string[] }, {age: number}>(
    { name: 'Neko', hobbies: ['Sports'] }, 
    { age: 3 },
);

// Generics関数では、型を指定する必要がない
function merge<T , U>(objA: {name: string}, objB: U) { //交差型（T&U）を返すと推論される
  return Object.assign(objA, objB);
}

//string以外を渡すとエラーになってしまう
const mergedObj = merge({ name: 'Max', hobbies: ['Sports'] }, { age: 30 }); // Argument of type '{ name: string; hobbies: string[]; }' is not assignable to parameter of type '{ name: string; }'.

```

# Generics型 と Union型の違い
* Generics型：クラス全体で特定の型を固定して受け取ることができます
* Union型：関数が呼ばれたときに、毎回いづれかの型を受け取る時に使う 呼び出す毎に型を変更する柔軟性が必要な場合、Union型を使います


```ts
//Union型を使った場合
class DataStorage{  //ある特定の型のみを受け取りたい

  //private data:  (string | number | boolean)[] = [];  //3つの型がミックスされてしまう書き方
  private data:  string[] | number[] | boolean[] = [];  //いづれかの配列を受け取る

  addItem(item: string | number | boolean ) { //関数が呼ばれた時に、どの型でも受け取ってしまう
    this.data.push(item);
  }

}
```
【Unity】画面回転を禁止して方向を固定する方法

Edit　→　Project Serrings

Player
→　iOSタブ（Androidタブでも可）
→　Resolution and Presentation
→　Default Orientation

※Default Orientationについての解説
Default Orientationは起動時の画面回転方向を決める項目です。iOSまたはAndroidのどちらかにある項目で設定を行えば、もう一つの設定も同一のものが適応されます。

それぞれのパラメーター設定は以下のような意味があります。

Portrait：縦向き
PortraitUpsideDown：縦向きの逆方向
LandscapeLeft：左へ傾けた向き 縦向きから反時計回り
LandscapeRight：右へ傾けた向き 縦向きから時計回り
AutoRotation：使用可能な向きの中で、必要に応じて自動で向きを変更

単純に一方向で固定したい場合は「Portrait」や横方向の「LandscapeLeft（LandscapeRight）」を使って固定すれば目的は達成できると思います。
ARFoundation ステンシル画像とデプス画像を表示する

ステンシル画像とデプス画像を表示する
---

UI→Rawimageを作成する
![0D3EFEF9-27F8-4BEF-A39A-3AE646FAFE4F_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/c675441c-ddd1-55ae-795b-29195af9b69a.jpeg)

Rawimageをもう一つ作成し、名前をImage Stencil、ImageDepthに変更する
![74988517-B15D-4784-9C07-D7A18A3E7A8B_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/3eef3abd-90fa-f9d1-f972-73e2960e045d.jpeg)

Canvasを選択し、UIScaleModeをScaleWithScreenSizeに変更する
![628A0999-2DC0-42EE-BEAC-DB47A17FBE89.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/c9c45ecf-689e-a965-ee63-8958be4c516f.jpeg)

各Rawimageのサイズを変更する
![8D289EB8-0461-4B9F-BD03-1FB86D67C263.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/3d20a710-d9f3-57ba-5d15-ba74ef1d51cc.jpeg)
![79A78030-EACB-4B53-8930-478E1876C0DB.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/9b80b949-7f8f-6451-af53-609c154b163d.jpeg)


DrawHumanStencil.csを作成し、下記を記述する

```C#:DrawHumanStencil
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR.ARFoundation;

public class DrawHumanStencil : MonoBehaviour
{
    [SerializeField]
    private RawImage imageStencil;

    [SerializeField]
    private RawImage imageDepth;

    private AROcclusionManager m_AROcclusionManager;

    void Awake()
    {
        m_AROcclusionManager = GetComponent<AROcclusionManager>();
    }

    void Update()
    {
        // AROcclusionManager から取得したステンシル画像をテクスチャとして描画する
        imageStencil.texture = m_AROcclusionManager.humanStencilTexture;
        // AROcclusionManager から取得したデプス画像をテクスチャとして描画する
        imageDepth.texture = m_AROcclusionManager.humanDepthTexture;
    }
}
```


ARCameraにスクリプトをつけ、Rawimageをアタッチする
![8C8D857A-E1FC-4568-B977-F8DDA76FF769.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/0b0c8bc3-0979-87c9-0b9c-50459272c681.jpeg)
BaseNEncodersのbase=って何を表しているのだろうと考えたらとてもシンプルだった件について

# はじめに
Category Encodingに関して代表的なものを学習していたのですが、どうもライブラリの使い方がわからず調べるのに時間を費やしたのでまとめたいと思います。

ここからのコードはすべて[以下の記事](https://www.takapy.work/entry/2019/12/10/085810)の内容を利用していますので、そちらを簡単に読んでから読み進めていただくと分かりやすいかもしれません。

Category Encodingについてとてもまとまっていますのでお勧めです。


# BaseNEncodersについて

https://www.takapy.work/entry/2019/12/10/085810

こちらの記事のコードを引用しています。
`BaseNはbaseオプションに指定する値によって、One-Hot / Binary / Ordinal Encodingを使い分けることができます。`とあるがどのように指定すればどのエンコーディングが使えるのかよくわからず、今回の記事を書くことになりました。

ちなみに[公式ドキュメント](https://contrib.scikit-learn.org/category_encoders/basen.html)にはこのようにあります。

```
base: int
when the downstream model copes well with nonlinearities (like decision tree), use higher base.

# 翻訳
ダウンストリームモデルが非線形性（デシジョンツリーなど）にうまく対応する場合は、より高いベースを使用します。
```

うーんわからない。
すこし調べるのに時間がかかったので、わからない方のために指定の仕方をまとめます。

# 問題

`base=1`だとOne-Hotエンコーディング

```
# base=1
bne = ce.BaseNEncoder(cols=cate_col, base=1, drop_invariant=True)
bne_df = bne.fit_transform(df[cate_col])
pd.concat([df[cate_col], bne_df], axis=1)
```

![bandicam 2021-05-14 20-06-50-357.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/a9cc9ce7-89b5-0c2e-4abe-3361a7177cf4.jpeg)


`base=5`だとラベルエンコーディング

```
# base=5
bne = ce.BaseNEncoder(cols=cate_col, base=5, drop_invariant=True)
bne_df = bne.fit_transform(df[cate_col])
pd.concat([df[cate_col], bne_df], axis=1)
```

![bandicam 2021-05-14 20-07-11-105.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/47fcf917-d2be-f015-1c07-27a9dd035d92.jpeg)


なぜ1でOne-Hotなのでしょうか。なぜ5でlabel-encodingなのでしょうか。
これにはしっかりと理由があります。
`この数値はエンコーディングの対象にしているカテゴリ数によって変化します。`

# base=の指定の仕方

この`base`という引数が表しているものはズバリ`〇進数`のことでした。
(たしかに言われてみればと思いました)

というわけで、`base=1`を指定すると`1進数`でカテゴリ変数を表すことになるので`One-Hotエンコーディング`となります。

今回はカテゴリが`4つ`あります。

ですので、`base=5 (5進数)`を選択すると`ラベルエンコーディング`になります。(1-4で表現するため)

`base=2`を選択したところ、`Binary`になることが確かめられました。

```
# base=2
bne = ce.BaseNEncoder(cols=cate_col, base=2, drop_invariant=True)
bne_df = bne.fit_transform(df[cate_col])
pd.concat([df[cate_col], bne_df], axis=1)
```

![bandicam 2021-05-14 20-06-57-950.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/20e3dd32-9b1d-0fe1-c036-2fb0f8a49179.jpeg)


# おわりに
Category Encoderはとても便利なライブラリだと感じました。
これから導入していきたいと思います。カテゴリ変数はどの方法を用いるかとても大切なので、どういうときに利用できるのかまで理解する必要がありそうです。

# 参考記事
https://www.takapy.work/entry/2019/12/10/085810

https://contrib.scikit-learn.org/category_encoders/basen.html

https://bias.hateblo.jp/entry/20160209
Visual Studioでnpmを使う方法

マイクロソフトの公式ドキュメントを参考
[参考URL](https://docs.microsoft.com/ja-jp/visualstudio/javascript/npm-package-management?view=vs-2019)

## Node.jsプロジェクトの場合
### 1.「新しいnpmパッケージのインストール」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662954/09b55e38-c5c2-06e9-47c8-9870917f5067.png)

### 2.パッケージを検索し、「パッケージのインストール」をクリック

画像はjQueryをインストールしている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662954/6026edde-fa65-101a-d022-f2d340b0926d.png)


## .Net Coreプロジェクトの場合

### 1.拡張機能タブ > 拡張機能の管理 > 「Package Installer」をインストールする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662954/8a5136a9-c46d-f0b7-ed52-226d72728f64.png)



### 2.「Quick Install Package...」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662954/c64787bf-b528-2f8e-d1fa-872ce8d9b267.png)

結果
node_modulesフォルダができて、中にjQueryができる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662954/ab5205e5-549d-3612-bb51-224caa1f2529.png)

### 3.「wwwroot」フォルダに追加するように変えたい場合は...
* NuGetパッケージより、「BuildBundlerMinifier」をインストールする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662954/1f5e4c14-5b71-887b-0ea3-85b7be2ea4d6.png)

* 「bundleconfig.json」ファイルを新規作成する。

以下のように中身を書き換える

```
[
  {
    "outputFileName": "wwwroot/lib/jquery.js",
    "inputFiles": [
      "node_modules/jQuery/tmp/jquery.js"
    ],
    "minify": {
      "enabled": true,
      "renameLocals": true
    }
  }
]
```

これで、node_modules内のjuery.jsがwwwrootに追加される。


## ちなみに
package.jsonを直接作って、インストールするパッケージを入力して保存すれば、
勝手にインストールしてくれる

```
こんな感じ
{
  "name": "myproject",
  "version": "1.0.0",
  "devDependencies": {
    "jQuery": "^1.7.4",
    "gulp": "4.0.2",
    "@types/jquery": "3.3.33"
  }
}
```
【備忘録】レジ機能付き買い物カートを試してみた

#はじめに
この記事は投稿者本人の備忘録として投稿する。
今回はたまたま近くのスーパーマーケットでトライアルを行なっていたレジ機能付き買い物カートを体験したので使い勝手や現場の様子を残しておく。

#システム概要
今回東芝テック社製のセルフレジカート「ピピッとカート」というシステムを体験した。[リンク](https://www.toshibatec.co.jp/products/pipit.html)
通常の買い物カートにタブレットとスキャナーがついている。
![IMG_6243.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471496/8c9ad892-6ead-eb53-9dbe-a9be70a9afeb.jpeg)
商品のバーコードをスキャナーで読み取ってからカゴに入れる。
![IMG_6245.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471496/4be18d34-d8c0-0601-9de6-6b87da3c789b.jpeg)
読み取った商品の値段と合計値段がタブレット上に表示される。
![IMG_6247.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471496/4a604246-513a-56d0-f1a5-9338c1e6700a.jpeg)
会計は専用セルフレジで実施。
（他のお客様の迷惑にならないように専用セルフレジの写真は撮れませんでした）
流れとしてはレジカート上のタブレットで会計ボタンを押すと、QRコードが表示されるため専用セルフレジのスキャナーで読み取る。するとデータがレジに引き継がれお支払い方法などを入力する。

専用レジは通常のレジ４台分のスペースにセルフレジ（６台分）＆購入レシート確認ゲートがあった。
![IMG_6246.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471496/1a394e17-0bbc-122d-51c0-a1afc13a1665.jpeg)


#トライアル現場の様子
レジカートの説明とセルフレジにそれぞれ２〜３人ずつ説明要員がいた。
それぞれ説明時間は10秒程度でストレスに感じることはなかった。

突然システムが導入されたため多少の混乱はあるだろうが、説明スタッフが多いため大きな混乱はない様に見えた。
レジカートを使うかはお客さんの判断だが、<font color="Red">全体の１〜２割程度</font>が使用している様子だった。使用したくないユーザーももちろんいるため<font color="Red">通常の流れは確保する</font>必要がある。

#所感
性善説に則ったシステムだと感じた。一応最後にレシート上の点数とカゴ内の点数を確認していたが点数が増えると確認が疎かになる様に感じる。ユーザーを信用した場合においてはレジの混雑を改善するシステムとして素晴らしいと感じた。通常レジと専用レジの比率が5:1くらいであったが、システム導入期であるためどちらのレジも通常より混雑している様子だった。システムスタッフが多くいたためなんとか成り立っていたが、<font color="Red">スタッフなしではかなりの混乱を招いてしまうという</font>印象を持った。

#大事なこと

- 全体の１〜２割程度が試しにシステムを利用していた。
- 8〜9割は普段通りの買い物をしていた。
- スタッフ不足は混乱を招く恐れがある（今回は見える範囲で５〜６人であった）
enum swift

#■enum

基本的な定義の仕方

``` swift
//定義の仕方
enum BloodType {
  case a
  case b
  case o
  case ab
}
```

基本的な使い方
switch文を使う。
if文でも出来るがswitchの方がいい
switchなら定義する時enumの全てのcaseが入っていなければエラーになるので。
抜けていれば教えてくれる。

``` swift
let type = BloodType.a

switch type {
 case .a:
 print("血液型A型")
 case .b:
 print("血液型b型")
 default:
 print("血液型それ以外")
}
```

#■値を持たせることもできる。型を指定できる。文字型,整数,浮動小数のみ

``` swift
enum Color: Int {
 case red = 0
 case blue = 1
 case green = 2
}

//省略してかける。
//インクリメントで値が代入される。
enum Color2: Int {
 case red = 5, blue,green
}

//定義の方法
let color1 = Color.red
let color2: Color = .green
//rawValueで値を指定してアクセスできるがoptinalになる。
let color3 = Color.init(rawValue: 2)

//rawValueで値にアクセスできる。
print("\(color1),\(color1.rawValue)")
//結果: red 0
print("\(color2),\(color2.rawValue)")
//結果 blue 1
print("\(color3),\(color3?.rawValue)")
//結果  Optional(__lldb_expr_2.Color.green),Optional(2)

```

#■enumパラメーターを持たせれる。

``` swift
enum Country { 
 case japan(String,Int)
 case america(String,Int)
 case antarctic(Int)
}

let country1 = Country.japan("日本語",300)
let country2 = Country.america("英語", 500)
let country3 = Country.antarctic(0)

switch country1 {
 case .japan(let lang, let num):
 print("日本:\(lang),\(num)人")
 case .america(let lang, let num):
 print("アメリカ : \(lang, \(num))")
 case .antarctic(let num):
 print("南極 : \(num)人")
}
//結果　日本: 日本語, 300人
```


#■caseだけでなく変数や関数も入れる事ができる。

``` swift
enum Test: Int {
 case one = 1, two, three
 
 var aaa: Int {
  return self.rawValue * 10
  }
 
 func bbb()-> String {
 switch self {
 case .one: return "Oneは1"
 case .two: return "Twoは2"
 case .three: return "Threeは3"
  }
 }
}

let testThree =  Test.three
print("\(testThree)") // three
print("\(testThree.aaa)") // 30
print("\(testThree.bbb)") //Threeは3
```
このパターンをよく使うらしい
後は慣れていきます！！
【WYSIWYG】WYSIWYGエディタ

# WYSIWYG（ウィジウィグ）とは
- 「What You See Is What You Get」の略
- 入力画面と出力画面が一致する様に表現する技術

# よく使用されるライブラリ
## Draft.js
[公式サイト](https://draftjs.org/)

### 特徴
- Facebook製
- Reactベースで作られているため、簡単かつ堅牢な仕組みで実装可能
- Twitter、Wantedly等で使用されている

### データの入出力方法
- 入力: JSONで保存可能
- 出力: [draft-js-export-html](https://www.npmjs.com/package/draft-js-export-html?activeTab=dependencies) を使用することで保存データ（JSON）をHTMLへ変換可能

## Quill
[公式サイト](https://quilljs.com/)

### 特徴
- PC・タブレット・スマートフォンに対応
- Slack、salesforce、LinkedIn等で使用されている

### データの入出力方法
- 入力・出力共にJSONを使用可能
NURO光の速度測定（北海道）

待ちに待ったNURO光が我が家にやってきました:tada:
早速NURO光独自の測定ツールで帯域幅を測ってみました。

申込から、宅内工事まで１週間、屋外工事まで１ヶ月。比較的に早い段階で開通できたかと思いました。

＜測定エリア＞
北海道札幌市東区北十九条東

＜住宅タイプ＞
戸建てアパート

＜ONU・ルータ＞
HUAWEI HG8045Q

＜測定結果＞
■5GHz（2021/5/5 夕方）
![速度測定-20210505-16時.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1105575/bd7e4f1c-3a44-75cf-82fe-c4084d43cce0.png)

■5GHz（2021/5/5 夜）
![速度測定-20210505-20時.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1105575/d6f03e80-bcdf-c24e-a4a9-ceae59be3bf7.png)

■有線（2021/5/14 夕方）
![速度測定-20210514-16時.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1105575/49cbe670-7129-3640-7eb6-77870853c9f3.png)

■有線（2021/5/14 夜）
![速度測定-20210514-19時.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1105575/5e4a8a22-de29-b6b7-2577-829cbf10c19b.png)

＜感想＞
無線の5GHz帯では比較的に安定した速度が出てると思います。
有線での接続ではインターフェイスの制限最大値まで速度が出ていて驚きました。さすがだなと感心しました。
[Nuxt.js] クライアントサイドだけで機能するmiddlewareが作りたい

Nuxtをユニバーサルモードで動かしている時に、CSRでだけで働く共通middlewareが欲しい時がありますね。

そんな時、すぐに思いつくのがmiddlewareの処理を `prosess.client` で条件を絞るという方法です。

```typescript:clientOnlyMiddleware.ts
export default function (context:Context) {
  if (process.client) {
    // 認証処理など
  }
}

```

しかし、このmiddlewareはページの初回読込やブラウザリロード時にはSSR側でのみ起動するため、CSR側では呼び出されません。

ユニバーサルモード時のNuxtのライフサイクルはSSRとCSRで２回呼び出されるものと片方だけで呼び出されるものがありますが、それらの中でCSR側でのみ呼び出されるmiddlewareというパターンがありません。

mixinを使ってbeforeCreateやbeforeMountの処理を共通化しても良いのですが、あまり美しいものではありません。

では、どうするのかと言うとプラグインを使います。

```javascript:app/nuxt.config.js
export default {
  mode: 'universal',
  plugins: [
    { src: '@/plugins/initClient', mode: 'client' }
  ]
}
```

プラグインは動作モードの指定ができるため、CSRのみのプラグインを作成します。
このプラグインから、先程のmiddlewareを起動することで、問題であった初回読込やブラウザリロード時にもCSR側から起動することができます。

```typescript:initClient.ts
import clientOnlyMiddleware from '@/middleware/clientOnlyMiddleware'

export default function (context:Context) {
  clientOnlyMiddleware(context)
}
```



pluginと同じように、middlewareでもモード指定ができるように作ってくれてもいいと思うのですけどね。
それなりに要望はあるようですが、本家の回答を見ると意地でも作る気は無いような感じがします。

[参考] https://github.com/nuxt/nuxt.js/issues/2653
コントローラーへ送る値を同じ値を複数指定

 コントローラーへ送る値を同じ値を複数指定
-

選択したユーザーの情報をparamsで扱えるようにパラメーターを送ります。
以下のようにnew.html.erbを編集してください。

```rb:app/views/rooms/new.html.erb
<!-- 中略 -->
<select name="room[user_ids][]">
  <option value="">チャットするユーザーを選択してください</option>
  <% User.where.not(id: current_user.id).each do |user| %>
    <option value=<%= user.id %>><%= user.name %></option>
  <% end %>
</select>
<!-- 中略 -->
```

select要素のname属性にroom[user_ids][]を指定し、option要素のvalue属性にuser.idを指定しました。このように記述することで、これまでとは異なる形でパラメーターが送信されるため、paramsは以下のようになります。

【例】paramsの中身

```rb
# room[user_ids][ ]で送られるパラメーター
{"room" => {"user_ids" => ["選択したユーザーのid"]}}
```

この記述について、name属性のroom[user_ids][]を、room[user_ids]と[]に分けて説明します。

まず、room[user_ids]という記述は、キーに対する値という通常のパラメーターと異なり、値としてさらにハッシュを入れ子にすることを示すものです。

【例】room[user_ids]で送られるparamsの中身

```rb
{"room" => {"user_ids" => "値"}}
```
続いて、末尾についた[]について説明します。この記述は、キーに対する値を配列として格納することを示すものです。これにより、1つのキーに対して、複数の値を受け取ることができるようになります。

【例】room[user_ids][]で送られるparamsの中身

```rb
{"room" => {"user_ids" => ["値"]}}
```

以上の仕組みを利用して、選択したユーザーの情報をコントローラーへ送信する仕組みができました。

しかし、現状の実装のままでは、現在ログインしているユーザーのidを送信することができず、送信したユーザーのみチャットルームに存在していることになってしまいます。

したがって、現在ログイン中のユーザーのidも一緒に、paramsでコントローラーへ送信できるよう実装します。

 パラメーターにログイン中ユーザーのidも含めましょう
以下のようにnew.html.erbを記述してください。

```rb:app/views/rooms/new.html.erb
<!-- 中略 -->
<select name="room[user_ids][]">
  <option value="">チャットするユーザーを選択してください</option>
  <% User.where.not(id: current_user.id).each do |user| %>
    <option value=<%=user.id%>><%= user.name %></option>
  <% end %>
</select>
<input name="room[user_ids][]" type="hidden" value=<%= current_user.id %>>
<!-- 中略 -->
```

この記述で、現在ログイン中のユーザーが持つidをparamsに含めることができます。

```rb:【例】
<input name="room[user_ids][]" type="hidden" value=<%= current_user.id %>>
```

type属性にhiddenを指定することで、画面上には表示されないinput要素を作成できます。そして、先ほどのselect要素と同様、name属性にroom[user_ids][]を指定し、room[user_ids]をキーに対する値を配列で受け取る仕組みです。value属性にはcurrent_user.idを指定しているため、room[user_ids]キーに対して、ログイン中ユーザーのidを配列として格納し、コントローラーへ送信します。

この記述の結果、コントローラーに送られるparamsは以下のようになります。

【例】room[user_ids][]で送られるparamsの中身

```rb
{"room" => {"user_ids" => ["選択したユーザーのid", "現在ログインしているユーザーのid"]}}
```


room[user_ids]に2種類のユーザーidを格納することができました。
Mac初心者の初期環境設定

はじめてMacで開発するので、備忘録

# 環境

- MacBook Air (M1, 2020)
- macOS Big Sur 11.3.1

# シェル
コンピューター名が長いので、短くする

ターミナルで以下を実行

```
% cd /Users/Shared/kay/
% touch .zshrc
```

.zshrcに以下の行を記載

```
PROMPT='%n %c %# '
```

ターミナルで読み込んで設定を反映

```
% source .zshrc
```

macのデフォルトシェルはzshなんですね。
とりあえず、そのまま使ってみる

# homebrewを入れる

おとなしく、公式サイトのインストラクションに従ってインストール
https://brew.sh/index_ja.html

# gitのインストール

```
% brew install git
% git --version   
git version 2.30.1 (Apple Git-130)
```

# 感想
最初にターミナルを起動する方法が一番難しかった
Deviseのデフォルトのメールアドレスバリデーションが弱すぎる件に対処する

Railsでユーザのログイン機能を実装する場合、言わずと知れた __Devise__ を使うといろんな機能がすぐに使えて便利ですよね。デフォルトでは、メールアドレスとパスワードで登録・ログインするようになっていますが、今更ながら不正なメールアドレスが登録されてしまうというバグを生み出してしまいました :innocent:

Deviseにおけるメールアドレスのバリデーションには、

```sh
$ bin/rails g devise:install
```

で生成される `config/initializers/devise.rb` に定義されている正規表現が使われるのですが…

https://github.com/heartcombo/devise/blob/c82e4cf47b02002b2fd7ca31d441cf1043fc634c/lib/generators/templates/devise.rb#L183-L186

> `/\A[^@\s]+@[^@\s]+\z/`

うーん、弱い！

ということで、今回は __email_validator__ というGemを使って、メールアドレスの有効性をある程度きちんと検証できるようにしていきます。

https://github.com/K-and-R/email_validator

# email_validatorをインストール

Gemfileにemail_validatorを追記し、インストールします。

```ruby:Gemfile
gem 'email_validator'
```

```sh
bundle install
```

# Deviseの設定を書き換える

`config/initializers/devise.rb` に定義されている正規表現を、email_validatorが提供している正規表現に書き換えます。

email_validatorも、デフォルト（Loose mode）の正規表現はDeviseと同様に `/\A[^\s]+@[^\s]+\z/` となっているので、Strict modeかRFC modeの正規表現を使うようにしましょう。RFCに準拠すると、メールアドレスでよく使われている文字が使えないことがあるので、今回はStrict modeを使うことにします。

```diff_ruby:config/initializers/devise.rb
- config.email_regexp = /\A[^@\s]+@[^@\s]+\z/
+ config.email_regexp = EmailValidator.regexp(mode: :strict)
```

これで、メールアドレスの有効性をある程度きちんと検証できるようになりました :tada:

# 最後に

今回は、`mode: :strict` と明示的にStrict modeを使うように指定しましたが、Gemfileに

```ruby:Gemfile
gem 'email_validator', require: 'email_validator/strict'
```

のように記述することで、デフォルトをStrict modeにすることもできます。

Railsは便利なGemが多く、盲目的に使うと思わぬバグや脆弱性を仕込んでしまう可能性があります。注意して使いたいですね（自分への戒め :angel:
XCode12でCarthageから取得したRealmを使用する



Xcode12ではcarthage でライブラリの管理をしようとしたとき
```carthage update --platform ios --use-xcframeworks```
で.xcframeworksを取得してくることで可能だがRealmだと上のコマンドを使用しても.frameworkが取得されていて

無理やりだがgitからRealm.xcworkspaceとダウンロードしてきて手動で設定する必要があった

carthageが 0.38.0にバージョンアップしたことで解消されていたので
対応を記載

## carthage version up
```
$ carthage version
0.37.0

$ brew upgrade carthage
...

$ carthage version
0.38.0
```

```
$ carthage update --platform ios --use-xcframeworks
・・・
*** Building scheme "Realm iOS static" in Realm.xcworkspace
*** Building scheme "Realm" in Realm.xcworkspace
*** Building scheme "RealmSwift" in Realm.xcworkspace
```

## xcode

[Frameworks, Libraries, and Embedded Content]
にRealm.xcframeworkとRealmSwift.xcframeworkを設定
※ Embedには「Embed & Sign」を設定する

![スクリーンショット01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442879/17db6e40-8c54-0a10-277e-dd544092ecfe.png)

Run ScriptのInputFilesからframeworkを削除
![スクリーンショット 02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442879/ea5448c6-776a-e091-e5af-8ed90b03c597.png)

で完了

##後書き

すでにアプリ審査ではXcode 12でのビルドが必須になっているため
Realmを使用する際はpodやSwift Package Manager へ移行する方が良いのかもしれないが
carthageを使うことでビルドに時間が掛からなくなるのはやっぱり魅了的なので、
重いものをcarthageで使うのは個人的にはありだとは思う
ブラウザバックで画面遷移してきたことを判定し、処理を動かす

## はじめに
ページの離脱直前に確認ダイアログを出すなど、そのページから遷移しようとすることをトリガーに処理を書く際は[beforeunload](https://developer.mozilla.org/ja/docs/Web/API/Window/beforeunload_event)イベントを使用するメジャーなやり方がありますが、ページの読み込み時( jQueryの$(document).readyが動くタイミング )に**ブラウザバックでこの画面に遷移してきたどうか**を判定して処理したいケースがあり、無事実現できたのでご紹介します。（とてもレアケースだとは思いますが…）


どんなケースで必要だったか気になる方に向けて使用した際の用途にも触れておきます。Bootstrapの[tagsinput](https://bootstrap-tagsinput.github.io/bootstrap-tagsinput/examples/)というプラグインを導入してフォーム画面のinputへの入力がタグ化されるようにしていたため、ブラウザバック時のフォーム復元には別途処理を実装する必要がありました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021040/1748264b-cffc-d696-9c36-585d7d9e7630.png)
復元するための入力値は[sessionStorage](https://developer.mozilla.org/ja/docs/Web/API/Window/sessionStorage)に保存していたので、同一タブでブックマークからフォームを再度開いた際は入力値を復元したくなく、どうしてもブラウザバックで遷移してきたかどうかの情報を取得する必要がありました…。

## 実行環境
 jQuery 3.5.1

## 遷移元の種類を判定する方法


``` Javascript
$(document).ready(function () {
    if (window.performance.navigation.type == 2) {
        //遷移後に動かす処理
    }
});
```

なんと、window.performance.navigation.typeに**どうやって今いるページにたどり着いたのか**を数値として持っています。

実際、Chromeの開発者ツールから実行してみてもこの通り
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021040/7dca6102-fca3-df2a-537c-804f6aa5296c.png)
値を持っていることがわかります。

[PerformanceNavigation.type - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/PerformanceNavigation/type)
Mozillaのドキュメントを見ると、数値の意味は下記の通り設定されているようです。

| 値 | 定数名 | 意味 |
|:-:|:-:|:-:|
| 0 | TYPE_NAVIGATE | リンク、ブックマーク、フォーム送信、スクリプト、またはアドレスバーに URL を入力してページにアクセスしました。 |
| 1 | TYPE_RELOAD | 	このページには、[再読み込み] ボタンをクリックするか、Location.reload() メソッドを介してアクセスしました。 |
| 2 | TYPE_BACK_FORWARD | このページには履歴をたどってアクセスしました。 |
| 255 | TYPE_RESERVED | その他の方法。 |

サンプルコードにはブラウザバックをべた書きで"2"と書きましたが、window.performance.navigation.TYPE_BACK_FORWARDとすることでもこの数値は取れました。

※@yoshi389111 さんからのコメントを受けて補足
TYPE_BACK_ **FORWARD**とある通り、ブラウザバックだけではなく前に進んだ場合も数値が2になります。用途によってはご注意ください。


## 補足
PerformanceNavigation.typeのドキュメントによると、新しいPerformanceNavigationTimingの使用が推奨されています。

>このインターフェイスは Navigation Timing Level 2 仕様では非推奨です。
代わりに PerformanceNavigationTiming インターフェイスを使用してください。

[PerformanceNavigation.type - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/PerformanceNavigation/type)
[PerformanceNavigationTiming - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/PerformanceNavigationTiming)

新しい仕様では、メソッド経由でナビゲーションタイプを取得するようです。
ただし、PerformanceNavigationTimingのドキュメントには「実験的な機能」との記載があり、IEとSafariには完全非対応とのことなので要件に合わせて使い分けるのがよさそうです。

今回は、全ブラウザ対応で安定しているPerformanceNavigation.typeを使用しました。

## 参考リンク

下記質問への回答を参考にさせていただきました。

https://teratail.com/questions/304935?link=qa_related_pc
Notes ドキュメント内のすべてのフィールドを出力する

Sub Initialize
	
	Dim ss As New NotesSession
	Dim db As NotesDatabase
	Dim col As NotesDocumentCollection
	Dim doc As NotesDocument
	
	Dim fileNum As Integer
	Dim PathText As String
	fileNum%                = Freefile()
	PathText                ="c:\temp\ALL_field値_書き出し"+Join(+Split(Join(Split(Cstr(Now()),"/"),"-"),":"),"：")+".csv"
	Open PathText For Output As fileNum%    
	
	
	
	
	Set db=ss.CurrentDatabase	
	Set col = db.UnprocessedDocuments
	Set doc = col.GetFirstDocument()
	''While Not(doc Is Nothing)
	Forall o1 In doc.Items
		Print #fileNum%,o1.name		
	End Forall
	
	''Wend
	Close fileNum
	
End Sub
[Ruby]Fiberとはなんなのさ！

# Fiberとは
Fiberを利用することで複数のプログラム間で実行の中断や再開を相互に行わせることができます。
Fiberを用いると「ある処理を途中まで実行して、その後任意のタイミングで、前回の続きから処理を行う」みたいな処理の流れを扱うことが出来ます！

## 基本的な使い方

### Fiberの作成
生成されたファイバは、`Fiber#resume`メソッドにより実行を開始する必要があります。
ファイバの切り替えは自動的に行われないので、自分で切り替える必要があります。

```ruby
fiber = Fiber.new {
  puts 'Hello, Fiber!'
 
  # 実行されたファイバから親に切り替える
  Fiber.yield

  puts 'Hello, (again)'
}

fiber.resume #=> "Hello, Fiber!"

fiber.resume #=> "Hello, (again)"

fiber.resume #=> FiberError: dead fiber called
```

### 引数と戻り値について


```ruby
fiber = Fiber.new {|first|
  puts 'Hello, Fiber!'
 
  second = Fiber.yield('goodbye')

  puts second

  puts 'Hello, (again)'
}

puts fiber.resume('Hello, Fiber!') #=> "Hello, Fiber!"

puts fiber.resume(Hello, (again)) #=> "goodbye", "Hello, (agein)", "goodbye, (again)"
```

### ジェネレーター
ジェネレーターとは、`部分的な結果だけを計算して返し、続きを次回に計算すること`です。
これにより、実際の計算を最小限で済ませて、大きいデータを少ないリソースで扱うことが出来ます。

```ruby
fiber = Fiber.new {
  a, b = 0, 1

  loop do
    a, b = b, a + b
    
    Fiber.yield(a)
  end
}

10.times.map { fiber.resume } #=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
puts fiber.resume #=> "89"
puts feiber.resume #=> "144"
```

## 標準添付ライブラリを利用してより手軽に！
標準添付ライブラリでは、親子関係のないコルーチンとして扱うことが出来ます。
新たに`Fiber#transfer`使えるようになるメソッドになります。
このメソッドは、ファイバの処理を移した際に、その後自動的に呼び出し元に戻らないということです。

```ruby
require 'fiber'

f1 = Fiber.new {
  puts 'from f1'
}

f2 = Fiber.new {
  f1.transfer

  puts 'from f2'
}

# 生成されてからスタートしていないorブロックが終了していないときにtrue
f1.alive? #=> true

f2.resume #=> "from f1"
```
Excel上のビュー列情報から、View列を生成

Sub Initialize
	
	Const cntViewNm="◆Base01"
	
	Msgbox "「◆Base01 」というビューがあらかじめ、作成されている事が条件です！"
	
	Dim s As New NotesSession
	Dim ws As New NotesUIWorkspace
	Dim col As NotesViewColumn
	Set view = s.CurrentDatabase.GetView(cntViewNm)
	
	'Excel選択
	varFilePath = ws.OpenFileDialog(False, "入力ファイルの選択", "EXCEL ファイル","")
	If Not Isarray( varFilePath ) Then
		Exit Sub
	End If
	If Dir$( Cstr( varFilePath( 0 ) ) ) = "" Then
		Exit Sub
	End If
	
	Set xlapp = CreateObject( "Excel.Application" )
	Set xlbook = xlapp.Workbooks.Open( Cstr( varFilePath( 0 ) ) )
	Set xlsht = xlbook.WorkSheets( 1 )
	
	'<Excel イメージ>
	'1行目…列 タイトル１　参照Field1
	'2行目…列 タイトル２　参照Field2
	'　：
	'　：
	
	i			=0
	Do While (True)
		i		=i+1		
		Label=Cstr(xlsht.Cells( i, 1 ).Value)	
		FldNm=Cstr(xlsht.Cells( i, 2 ).Value)	
		If FldNm="" Then
			Exit Do
		End If
		Set col = view.CreateColumn(,Label,FldNm)
	Loop
	
	
End Sub
Houdiniを日本語で勉強するときに参考にしたサイト

# Houdiniを日本語で勉強するときに参考にしたサイト

プロシージャルモデリングソフトHoudiniを学習するにあたり、参考にしたサイトをまとめます。



# KAYAC engineers' blog

2017年の記事で、情報としてはかなり古いですが、用語説明やインストール手順等が日本語で丁寧に書いてあってわかりやすかったです！

[Houdini超々入門](https://techblog.kayac.com/houdini-super-super-introduction)



# STYLY MAGAZINE

身内が運営しているサイトの宣伝になっちゃうんですが、こちらもインストール手順やウィンドウの説明がわかりやすいです！

[【Houdini】プロシージャルモデリング入門](https://styly.cc/ja/tips/houdini_01_introduction/)



# SideFX

Houdiniの公式チュートリアルはとても充実してます。非常にオススメです。

[Games Quickstart](https://www.sidefx.com/ja/tutorials/games-quickstart/)

動画音声が英語なので、一見とっつきづらいのですが、実は日本語字幕を表示することができます！

字幕は、動画プレイヤー右下の `CC` ボタンを押せば選べます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/15618886-0a78-1026-2bbd-ca1ff4ea532a.png)

特に嬉しいのが、動画に登場するHoudiniのUIが最新のものであることです。

解説のスクショが古いバージョンのUIだったりしないので、とりあえず動画で見たまま真似すれば、チュートリアルを進めることができます。
サーバー用のワイルドカードSSL証明書の更新方法

いざというときに慌てない為の､自分用作業メモ (2021/5/14)

 - Ubuntu 20.04.2 LTS

■Apacheのバージョン確認 
 Apache 2.4.8 以降であることを再確認　(証明書ファイルの作り方が変わる為)

~~~
$ apache2 -v
Server version: Apache/2.4.41 (Ubuntu)
Server built:   2020-08-12T19:46:17
~~~


■サーバー証明書の作成(例：サーバー証明書_new.crt)

サーバー証明書.crt + 中間CA証明書.crt を追記し
→ サーバー証明書_new.crt として保存する。

```サーバー証明書_new.crt
-----BEGIN CERTIFICATE-----

　　サーバー証明書.crt　

-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----

　　中間CA証明書.crt

-----END CERTIFICATE-----
```

■証明書の保存場所について　(自分はcert2フォルダを作成してここに保存)

~~~
$sudo mkdir /etc/ssl/certs2
/usr/local/ssl/certs2/サーバー証明書new.crt
/usr/local/ssl/certs2/秘密鍵ファイル.key
~~~


■証明書の保存場所を設定しているファイル　(念のため記述を再確認)
~~~
　/etc/apache2/sites-available/default-ssl.conf
~~~

■以下、設定の反映＋Apaheの再起動コマンド
~~~
$ sudo apache2ctl configtest
$ sudo service apache2 restart
~~~

■注意事項
秘密鍵などのファイルは、rootユーザーのみでしか参照できないように
 chown root:root および chmod 400 しておくことが推奨だそうです。
Next.js × Auth0でログイン機能を追加する。


#はじめに
Next.js×Auth0を使ってログイン機能を作成します。

[公式のページ](https://auth0.com/docs/quickstart/webapp/nextjs)が一番分かりやすく、簡単だったのでそちらの方法で進めていきます。

##必要なもの
1.[Auth0](https://auth0.com/jp)のアカウント
2.```npm install @auth0/nextjs-auth0```

##1.アカウントを作成する。

アカウントを作成したらDashboardからApplications
![スクリーンショット 2021-05-13 8.37.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1202267/262a04a3-4947-7401-decb-ee7e2ad6b06d.png)

アプリケーションを作成

![スクリーンショット 2021-05-13 8.38.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1202267/31333a85-f50f-3237-7b93-089069566af7.png)

名前を決めて、SPAを選択

ダッシュボードページに移行したら
[Setting](https://manage.auth0.com/dashboard/jp/dev-qz008pyi/applications/3QOVzU60K2R2dTxvaLwSmyg2uMygNP3f/settings)の

![スクリーンショット 2021-05-13 8.49.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1202267/9a1463d3-7e4c-4d7b-ceab-5f76342a8857.png)

**Allowed Callback URL**を```http://localhost:3000/api/auth/callback```
**Logout URL**を```http://localhost:3000```
と設定します。

QuickStartページに移行し、Next.jsと入力します。
![スクリーンショット 2021-05-13 8.44.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1202267/c1b93599-af17-4cc8-3478-fd7983f71803.png)
![スクリーンショット 2021-05-13 8.45.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1202267/8cd1ada7-528a-b07a-fe4b-26ef6532dda2.png)

##2.Next.js

###authインストール
auth0をインストールします。
```npm install @auth0/nextjs-auth0```

###keyを取得
ルートディレクトリの中に***.env.local***ファイルを作成し、以下の内容をコピペします。
![スクリーンショット 2021-05-13 8.55.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1202267/01857309-0414-52ca-5b9f-6ae8942b6747.png)

``page/api``の中に``auth/[...auth0].js``を作成

```[...auth0].js
import { handleAuth } from '@auth0/nextjs-auth0';

export default handleAuth();
```

###UseProviderを設定
``pages/_app.jsx`にuseProviderをimportします。

```_app.jsx
import React from 'react';
import { UserProvider } from '@auth0/nextjs-auth0';

export default function App({ Component, pageProps }) {
  return (
    <UserProvider>
      <Component {...pageProps} />
    </UserProvider>
  );
}
```
###Loginボタン,Logoutボタンを作成

``<a href="/api/auth/login">Login</a>``
``<a href="/api/auth/logout">Logout</a>``

クリックするとログインページに移動します。
![スクリーンショット 2021-05-14 17.33.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1202267/2ae8a515-6882-13f1-9740-d758cf60fd85.png)

#参考にしたページ
https://auth0.com/docs/quickstart/webapp/nextjs

https://zenn.dev/syu/articles/5acfabc49e715e
Xubuntuのターミナルに表示されるディレクトリ名の文字色を簡単に変更する

# 初めに
**lsコマンドなどで表示されるディレクトリ名が見づらい！**
そう思い、いろいろ調べると、「環境変数に...」や「カラーコードを...」など、とても面倒くさい手順を踏むことがわかりました。
そこで「**GUI操作でもっと手軽にできないか**」とターミナルの設定項目を調べていると...発見しました！

本記事は**GUI操作でターミナルの文字配色を変更する手順**を紹介します。

環境は「[低スペックノートPCに Xubuntu21.04 を minimal install して fish を入れたお話](https://qiita.com/RiRyCasals/items/9ea9ad5bc58f5dc5c3fe)」で作成したものになります。
**Ubuntu系のLinuxディストリビューションであれば同様の手順で変更できます。**

## 変更前と変更後
手順に入る前に、参考として変更前と変更後の文字色をのせておきます。

### 変更前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690399/e9a39d61-f850-1d91-0df7-f5a50bbf15ea.png)
私はターミナルの背景を透過に設定することが多いです。
その影響もあり、**暗い青文字が非常に見づらいのです**。

### 変更後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690399/9adaca95-7a91-9879-c99b-450a312e12f0.png)
**明るい青文字に変更しました。**
とても見やすいですね。

# 手順
手順はとても簡単です。

1. terminal の Edit から preference を開く
1. colorタブ を開く
1. palette にある青色を任意のカラーに変更する

### 1.terminalのpreferenceを開く
preferenceは環境設定などの意味があります。
![change-color.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690399/a280b1ca-62ea-1912-074a-91db2aabcbb4.png)

### 2.colorタブを開く
![change-color2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690399/286bdd5d-1963-3331-2196-a6c51319724f.png)

### 3.paletteのカラーを変更する
1枚目の画像が変更前、2枚目の画像が変更後です。
![change-color3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690399/14677877-9081-a650-c7eb-096a74d2b317.png)
少しだけ色を明るくしました。
![change-color4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690399/ec42b7b0-dab1-ffe7-c544-6343c35d0b77.png)
Closeでpreferenceを閉じます。

更新などせずに勝手に切り替わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690399/9adaca95-7a91-9879-c99b-450a312e12f0.png)

# まとめ
GUI操作ができる環境では、terminalのpreferenceから簡単に変更できることがわかりました。
CUI操作になれることは良いことですが、たまにはこうしてGUIで楽をするのもいいですね。
ネットワーク プロトコル

#【ネットワーク プロトコル】

基本情報技術者試験の過去問から抜粋しました。

##ARP（Address Resolution Protocol）

イーサネット環境で、IPアドレスから対応するMACアドレスを取得するプロトコル

※ **MACアドレス**は、PCやルータなどのネットワーク機器に付いている番号

##OSPF（Open Shortest Path First）

TCP/IPネットワークで利用されるルーティングプロトコル
　→ 各ルーターがネットワーク全体のリンクの状態を学習し、その内容に従ってパケットの中継動作を行う。

　問）隣接するルーターとの回線のリンク状態を管理して、経路制御を行うルーティングプロトコルは？
　答）OSPF

##RIP（Routing Information Protocol）

ネットワークに接続されているルーターなど機器間で経路情報を交換して、宛先までに経由する中継機器数によって、動的に最短経路を決定するルーティングプロトコル

##SNMP（Simple Network Management Protocol）

TCP/IPネットワークに接続されたルーター、スイッチ、サーバー、などの機器に対して、ネットワーク経由で監視や制御をするためのプロトコル

サーバーに対して、CPUやメモリやディスクの使用率、プロセスやイベントログなどの監視をおこなう。
ネットワーク機器に対して、各ポート上で送受信されたパケット数、エラーパケット数、ポートの状態、CPUやメモリの使用率などの監視をおこなう。

##おわりに。

初見の用語が毎日のように出てくる。
日々、着実に知識と出来ることを増やしていけるように時間を効率的に使おう。
検索 Suggest サーバーをコンテナ化しました

　こんにちは。弁護士ドットコム SRE 室のテイです。
　当社の検索 Suggest サーバーのコンテナ化をご紹介させていただきます。

# Suggest について
## Suggest とは？
　検索 Suggest とは、検索フォームに検索ワードを入力した際に、その入力に基づいて他の検索ワードをおすすめする仕組みです。

## どのように機能するか
　当社の Suggest サーバーは以下のような機能があります。

1. 検索ログから検索語部分を抽出
1. DB (SQLite or MySQL) にその検索語が何回検索されたかを記録
1. 一定回数（4）以上検索されている検索語を、検索回数が多い順に取り出し、接尾辞配列の索引を作成
1. あるキーワードを含む検索語を出力

# なぜコンテナ化するか
　当社の Suggest サーバーはコンテナ化する前は EC2 インスタンスで動かしていました。
　このインスタンスは DB 更新をするにはスペックが低く処理時間が長くかかるため、担当者のローカル環境である MacBook Pro で手動更新していました。具体的には下の図のような構成になっていました。

- Solr ログ保管用 S3 から、すべての検索ログをローカルにダウンロードします
- ローカルで検索ログから Suggest DB を再作成します
- 最新の DB を Suggest サーバーへ転送します

![suggestコンテナ化前.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260895/cb266f50-6190-9061-e1df-f1042a014ed6.png)
　この不合理な運用のため、たくさんの問題がありました。

- DB の更新があまり行われないので、最近の検索キーワードが出てこない可能性があります。
- 担当者の端末の環境などに依存し、更新処理が属人化していました。
- EC2 インスタンスにはオートスケーリング等の設定がされておらず、障害が発生した場合には復旧時間がかかり、サービス影響が出てしまいます。

　そのため、 Suggest サーバーをコンテナ化し、合わせて DB 更新も自動化しました。

# コンテナ化した後
　当社は AWS のマネジードサービス Fargate を採用しました。コンテナ化した後の構成は下図のようです。
![suggestコンテナ化.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260895/9c21863b-7f5a-c254-c643-acd19b02d941.png)

　詳細について、説明します。

　Code シリーズの CodeBuild を使って Suggest DB を最新化して、Docker イメージをビルドします。
　まずは、前日分の Solr ログと Suggest DB を それぞれの S3 バケットから CodeBuild のインスタンスにコピーします。

``` bash
# 前日の日付
YEAR=`date +%Y -d '1 days ago'`
MONTH=`date +%m -d '1 days ago'`
YESTERDAY=`date +%d -d '1 days ago'`

# S3 から前日分の DB と solr ログを CodeBuild のインスタンスにコピーする
aws s3 cp s3://<db-backup-bucket名>/suggest/<サービス名>.db ./
aws s3 cp s3://<logs-backup-bucket名>/solr/${YEAR}/${MONTH}/<サービス名>-solr.${YEAR}-${MONTH}-${YESTERDAY}.log.gz ./

```

　その後、CodeBuild インスタンスにコピーした Solr ログと Suggest DB を使って、最新の Suggest DB の作成処理を DockerFile で定義し、Docker イメージをビルドします。

``` Dockerfile
# DB コピー
COPY --chown=www-data:www-data <サービス名>.db /var/www/suggest/<サービス名>.db

# 検索ログからDBへ
ARG year
ARG month
ARG yesterday
COPY --chown=www-data:www-data <サービス名>-solr.${year}-${month}-${yesterday}.log.gz /var/www/go/src/suggest/solrlog/
RUN cd /var/www/go/src/suggest/ && \
    suggest log2db サービス名.conf solrlog/<サービス名>-solr.${year}-${month}-${yesterday}.log.gz
```

　イメージをビルドする時に、日付のパラメータを渡します。

``` bash
docker build -t <サービス名>-suggest:latest --build-arg year="${YEAR}" --build-arg month="${MONTH}" --build-arg yesterday="${YESTERDAY}" .
```

　CodeBuild でビルドした Docker イメージを ECR へプッシュし、脆弱性のスキャン結果を Slack へ通知するようにしています。

　その後、CodePipeline を利用して、Fargate にデプロイします。
　Fargate が起動した後、最新化された Suggest DB を S3 へアップロードして、翌日に利用します。

``` bash
aws s3 cp /var/www/suggest/<サービス名>.db s3://<db-backup-bucket名>/suggest/
```

　EventBridge を利用して、 CodePipeline を実行し、 DB の更新を自動化しています。

　また、当社はソースコード管理には GitLab を利用していますが、 CodeBuild 等で使用するものについてはリポジトリを CodeCommit にミラーリングしています。
　Suggest に関する設定変更がありまして、修正したソースを Gitlab のブランチにプッシュしましたら、CodeCommit へ同期して、CodePipeline を動かして、CI / CD の自動化も実現できます。

　以上、当社の Suggest サーバーのコンテナ化を紹介しました。
【ウイングアークカスタマーサクセスサイト（サポートサイト）】で知りたいことを検索するコツ


# 目標
ウイングアークの各種ツールを使って作業中、
「あれー。どうやってやればいいのかな」「エラーでた！困った」
このようなとき、ウイングアークのサポートサイトであるカスタマーサクセスサイトでよりしっかり検索するコツ。

このやり方なら、マニュアルだけでなくナレッジベース（よくある質問等）も一度に検索できます。
[ウイングアークのサポートサイトはこちら](https://cs.wingarc.com/ja)

# 経緯
サポートセンターの方とお話するチャンスを頂きまして。そこで知りました。
[ウイングアークのサポートサイトはこちら](https://cs.wingarc.com/ja)

# 手順
[ウイングアークのサポートサイトはこちら](https://cs.wingarc.com/ja)
↑大事なことなので三回言いました

例えば、<font color="red"><b>オンプレDr.Sum Datalizerの四捨五入</b></font>の設定方法を検索するならば。
#### (1) カスタマーサクセスサイトへ行き「調べる・学ぶ」からお目当てのツールをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278265/3b87819b-cc2d-dce4-e5e6-d855adf10b9a.png)

クラウドの方は「クラウドサービス」のほう、オンプレの方は「製品」のほうを選択。
今回の例はオンプレなのでココ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278265/ed8ca9ad-70a6-48ae-4d23-7c6fad997785.png)

#### (2)出てきた検索ボックスに知りたいことを入力、検索
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278265/f4747ccd-27d0-d400-9287-73a14c0255d3.png)

#### (3)サイト全体を串刺し検索できる！
サポートサイトにはマニュアルだけでなく、ナレッジベースやリリースノートといった役立つ情報がのっています。それを一度の検索でまとめて検索できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278265/bc8c164b-1255-8e5e-5052-8c23be23c1f2.png)


# つぶやき
知ってて得するお得情報です。



以上
vue2 vue3比較（new Vue() vs createApp()）

#はじめに
vue3勉強初めました、自分で気付きましたvue2とvue3の変更点とそれについて調べたものを共有したいと思います。先ずは最初にvue2のnew Vue()とvue3のcreateApp()から解説していきたいと思います。

#入り口から始まる
今回開発のlaravelアプリケーションの構造で例として解説していきます。resources/js/app.jsでこのようなコードが見れると思います。
vue2の場合は：

```
new Vue({
  render: h => h(App)
}).$mount('#app')
```

すべてがvueインスタンスから始まりますが、vue3の場合はこんな風になりました：

```
import { createApp } from 'vue'
import App from './App.vue'
 
createApp(App).mount('#app')
```

なぜvue3がcreateApp()のように修正したか、これでどんなメリットがありますかをちょうど考えちゃいました。

#createAppのメリット
例えば、ものすごく大きなプロジェクトを開発する複数のチームがある場合。チームAにはグローバルコンポーネントShowDialogが含まれるvueAインスタンスが必要であり、チームBにはグローバルコンポーネントshowDialogが必要としないvueBインスタンスが必要であり、 2つのvueインスタンスの機能は完全に独立、相互の分離が求められている場合はどう実現すればよいですか？

vue2の場合は以下のコードが考えられるでしょう。

```
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>

<div id="foo"></div>
<div id="bar"></div>

<script>
  import Vue from "vue";

  Vue.component('show-dialog',{
    template:'<h1>showDialog</h1>'
  })

  const vueA = new Vue({
    template: `<div>
                vueA
                <show-dialog></show-dialog>
                </div>
    `
  })
  vueA.$mount('#foo')

  const vueB = new Vue({
    template: `<div>
                vueB
                <show-dialog></show-dialog>
                </div>
    `
  })
  vueB.$mount('#bar')
</script>
```
new演算子を使用して2つのvueインスタンスAとBを作成しました、グローバルコンポーネントshow-dialogを登録しました。グローバルコンポーネントshow-dialogはインスタンスAの制御されるビュー領域のみ使えると期待していますが、それは実現できない。 なぜなら、vue2のコンポーネントのレジストリシステム設計では、すべてのvueインスタンスが同じコンストラクターオブジェクト（グローバル命令/グローバルコンポーネントなどを含む）を共有しています、インスタンスAとBを完全に分離することはできません。

それに対して、vue3の場合、以下のコードが考えられるでしょう。

```
<script src="https://unpkg.com/vue@next"></script>

<div id="foo"></div>
<div id="bar"></div>

<script>

    Vue.component('show-dialog',{
        template:'<h1>showDialog</h1>'
    })

    const vueA = Vue.createapp({
        template: `<div>
                vueA
                <show-dialog></show-dialog>
                </div>
    `
    })
    vueA.component('show-dialog',{
        template:'<h1>showDialog</h1>'
    })
    vueA.$mount('#foo')

    const vueB = Vue.createapp({
        template: `<div>
                vueB
                </div>
    `
    })
    vueB.$mount('#bar')
</script>
```

上記のように、vue3のcreateAppメソッドを使用してインスタンスを作成すると、作成されたインスタンスAとBは、完全に分離な環境になります。vue3の場合、show-dialogコンポーネントはインスタンスAの中にレジストリできます。それによって、show-dialogコンポーネントはvueAインスタンスがコントロールしたビューの中では完全に利用できますが、vueBインスタンスがコントロールしたビューの中では利用できません（show-dialogコンポーネントを共有したい場合、AとBの中に別々に登録すればいい）。

以上で、別々に動作し、互いに影響を与えず、完全に分離されるインスタンスが作成されています、共有するものを自由に選択することもできます。
【備忘録】sympyによるグラフの図示

最近Pythonのモジュールであるnumpyやscipy, sympy, matplotlibを勉強中。
個人的備忘録として簡易的な関数の微分とグラフ図示を記事として纏める。

今回はガウス積分でよく出てくる
$$y = e ^ {-x^2} $$
これをサンプルとして使う。

```python:python
import sympy as sp
import matplotlib.pyplot as plt

x = sp.symbols('x')
fx = sp.E ** -x ** 2
# f(x)の一階微分
fx_1 = sp.diff(fx, x)

p = sp.plot(fx, fx_1, (x, -3.5, 3), legend=True, show=False)
p[0].label = "$f(x) = e^{-x^2}$"
p[1].label = "$f(x) = -2xe^{-x^2}$"
p[1].line_color = "red"

plt.rcParams['figure.figsize'] = (9, 2.7)
p.show()
```

![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545378/3ef3f2e5-52bf-de48-d300-48207a7c94fe.png)
DevOpsの３原則を支えるWhatとHowを図式化してみた

# はじめに
「The DevOps ハンドブック　理論・原則・実践のすべて」（日経BPマーケティング）を参考、
DevOpsの３つ原則を支える文化（What）と、その手段（How）とのできるよう図式化してみました。
※詳細な内容に関しては、参考資料1.を手に取って頂くことをお勧めします！

# DevOpsの建て付け
![DevOpsの建て付け（横）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52012/7c5da337-c2b5-cb78-88f1-b87ca01fef37.png)

# 参考資料
1. [The DevOps ハンドブック　理論・原則・実践のすべて](https://www.amazon.co.jp/dp/4822285480/ref=cm_sw_em_r_mt_dp_23XWJKMDK4E0Z3RJ2D8F)
aws-cdkでリソースにタグを追加・上書きしたい

cdkを使ってリソース定義しようとしたらメソッドにtagsが用意されてない！でもCloudformationでは対応してるよ〜っていうときにタグを入れる方法
リソース名が気に入らないときの上書きにも使える

## ①Aspects.ofを使う

### ネットワークACLにNameタグをつける例
```stack.py
# vpcの定義は省略
nacl = ec2.NetworkAcl(self, 'id',
    vpc=vpc,
    subnet_selection=ec2.SubnetSelection(
    subnet_type=ec2.SubnetType.PUBLIC
    ),
    network_acl_name='nacl'
    )
core.Aspects.of(nacl).add(core.Tag("Name", 'your-public-nacl'))
```

### サブネットにまとめてNameタグをつける例
```stack.py
vpc = ec2.Vpc(self, 'vpc',
                max_azs=2,
                cidr='10.0.0.0/24',
                subnet_configuration=[ec2.SubnetConfiguration(
                    subnet_type=ec2.SubnetType.PRIVATE,
                    name="Private",
                    cidr_mask=27
                ), ec2.SubnetConfiguration(
                    subnet_type=ec2.SubnetType.ISOLATED,
                    name="Isolated",
                    cidr_mask=27
                ), ec2.SubnetConfiguration(
                    subnet_type=ec2.SubnetType.PUBLIC,
                    name='Public',
                    cidr_mask=27,
                )
                ],
                )
subnets_list = [vpc.public_subnets, vpc.private_subnets, vpc.isolated_subnets]
for subnets in subnets_list:
    for isubnet in subnets:
        core.Aspects.of(isubnet).add(core.Tag("Name", 'your-subnet-name'))
```

## ②apply_aspectを使う (古いversionの人向け)
### ネットワークACLにNameタグをつける例
```stack.py
# vpcの定義は省略
nacl = ec2.NetworkAcl(self, 'id',
    vpc=vpc,
    subnet_selection=ec2.SubnetSelection(
    subnet_type=ec2.SubnetType.PUBLIC
    ),
    network_acl_name='nacl'
    )
nacl.node.apply_aspect(core.Tag("Name", 'your-public-nacl'))
```

### サブネットにまとめてNameタグをつける例
```stack.py
vpc = ec2.Vpc(self, 'vpc',
                max_azs=2,
                cidr='10.0.0.0/24',
                subnet_configuration=[ec2.SubnetConfiguration(
                    subnet_type=ec2.SubnetType.PRIVATE,
                    name="Private",
                    cidr_mask=27
                ), ec2.SubnetConfiguration(
                    subnet_type=ec2.SubnetType.ISOLATED,
                    name="Isolated",
                    cidr_mask=27
                ), ec2.SubnetConfiguration(
                    subnet_type=ec2.SubnetType.PUBLIC,
                    name='Public',
                    cidr_mask=27,
                )
                ],
                )
subnets_list = [vpc.public_subnets, vpc.private_subnets, vpc.isolated_subnets]
for subnets in subnets_list:
    for isubnet in subnets:
        isubnet.node.apply_aspect(core.Tag("Name", "your-subnet-name"))
```