OmniAICreator/Qiita-1.07M huggingface dataset:
C#でカノジョをつくる（19日目）

お疲れ様です。たなしょです。
今日はカノジョのフォームのデザイン部分や返答する部分を作成していきます。
今日でカノジョが完成する予定です。
## パターンマッチングした場合の返答
Responder(返答部分)は以前のプロトタイプモデルで作成したのとほぼほぼ変わらないのですが、
パターンマッチングした場合のReponderがないので追加しました。

```c#
foreach (ParseItem parseItem in Cdictionary.Pattern)
{
    string mtc = parseItem.Match(input);
    if (String.IsNullOrEmpty(mtc) == false)
    {
        string resp = parseItem.Choice(mood);
        if (resp != null)
            return resp.Replace("%match%", mtc);
    }
}
```
パターンがマッチングした場合Choice()を実行する。Choice()がnullなら%match%が存在するかチェックしています。
## 感情モデルをクラス化する。
感情の起伏をクラス化してフォームに反映できるようにしていきます。

1.ランダムで返答を返す分岐でPatternResponderが追加しています。

```c#
public string Dialogue(string input)
{
    _emotion.Update(input);
    Random rnd = new();
    int num = rnd.Next();
    if (num < 6)
        _responder = _res_pattern;
    else if(num < 9)
        _responder = _res_random;
    else
        _responder = _res_repeat;
    return _responder.Response(
        input,
        _emotion.Mood);
}
```
2.ボタンを押して表情を変わるようにif文で調整してます。

```c#
int em = _chan.Emotion.Mood;
if ((-5 <= em) && (em <= 5))
{
    this.pictureBox1.Image = Properties.Resources.normal;
}
else if (-10 <= em & em < -5)
{
    this.pictureBox1.Image = Properties.Resources.what;
}
else if (-15 <= em & em < -10)
{
    this.pictureBox1.Image = Properties.Resources.angry;
}
else if (5 <= em & em <= 15)
{
    this.pictureBox1.Image = Properties.Resources.smile;
}
label2.Text = Convert.ToString(_chan.Emotion.Mood);
```

## ちょっとここで
いざ実行してみてもエラーになってしまいました。
デバッグしてみるとCdictionary.csのpattern.txtを読み込んでパターン分割するところでエラーが起きていました。

```c#
string[] carveLine = rep_line.Split(new char[] { '\t' });
    _patternList.Add(
        new ParseItem(
        carveLine[0],
        carveLine[1])
    );
```
pattern.txtで空白だったのがよくなかったのかと思い下記のようにpattern.txtを変更しました。

```
こん(ちは|にちは)$\tこんにちは|やほー|ハーイ|どうもー|まああなた？
おはよう|おはよー|オハヨウ\tおはよ！|まだ眠い…|さっき寝たばかりなんだー
こんばん(は|わ)\tこんばんわ|わんばんこ|今何時？
```
実行してまたエラーが出てしまったのでパラメータをよくて見ると

```
こん(ちは|にちは)$\\tこんにちは|やほー|ハーイ|どうもー|まああなた？
```
上記のようにwindows特有の\tが\\\tになる事象が発生していたので置換する処理を分割処理の前に付けました。

```c#
string rep_line = line.Replace("\\t", "\t");
```

## カノジョができた
メリークリスマスと入力すると「メリークリスマス」と言ってくれるカノジョが僕にもできました🎉
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268048/0a354fc7-8f18-dd68-d272-be19648b03df.png)

## 最後に
感情の起伏があるカノジョができたので、
次はちょっとAIぽく言葉を学習するカノジョを作っていければなと思います。
pythonにおける翻訳

この記事では、Pythonの翻訳機能について記載します。

### GNU gettext

Djangoの多言語機能を使うためには、GNU gettextパッケージが必要。
gettextパッケージは、Pythonだけではなく、他の言語等でも使用されている。

```
gettext モジュールは、 Python のモジュールやアプリケーションの国際化 (I18N, I-nternationalizatio-N) および地域化 (L10N, L-ocalizatio-N) サービスを提供します。 このモジュールは GNU gettext メッセージカタログの API と、より高水準で Python ファイルに適しているクラス形式の API の両方をサポートしてます。
`https://docs.python.org/ja/3/library/gettext.html#module-gettext`
```

このパッケージには、標準で翻訳に使えるメソッドが豊富にある。
以下の公式ドキュメントに、以下のように各メソッドについての詳細が記載されている。

```
gettext.gettext(message)
現在のグローバルドメイン、言語、およびロケールディレクトリに基づいて、 message の地域化された訳文を返します。 通常、この関数はローカルな名前空間にある _() という別名を持ちます (下の例を参照してください)。
`https://docs.python.org/ja/3.7/library/gettext.html`
```

### po、mo、potファイルについて. 

翻訳を行うにあたって、以下のファイルを使用する必要がある。

.potファイル
poの元になるファイル(テキストファイル)
.poファイル
potファイルに翻訳文を記入したファイル
 .moファイル
poファイルからgettextにより作成されたバイナリファイル。

- poファイル

```
msgid "this is a string"
msgstr "これは文字です"
```

`msgid`に翻訳文の元。
`msgstr`に翻訳後の文。

gettextなどで、.poから.moを作成する。

- 作業手順

1. gettextのインストール
2. 設定変更
settings.pyに設定を追加する。

```
LANGUAGE_CODE = 'ja'

LOCALE_PATHS = (
    os.path.join(BASE_DIR, 'locale'),
)

```

3.ローケルファイル作成
workspaceにおいては、以下にファイルがある。

```
workspace
- locale
 - en
  - LC_MESSAGES
   - django.mo
   - django.po
 - ja
  - LC_MESSAGES
   - django.mo
   - django.po
```

4.ローケルファイルの編集とコンパイル
.poファイルに追加したい翻訳を追加などする。
そして、以下のコマンドを実行する。

```
docker-compose run server python manage.py compilemessages -l ja
docker-compose run server python manage.py compilemessages -l en
```
ページネーションにkaminariを使う

ページネーションとは、検索結果を表示するページや記事がたくさん投稿されている場合など、ボリュームの多いWebページを複数のページに分割し、各ページへのリンクを並べることで見やすくすることです。


# 1. kaminariをbundle install
以下のコードをGemfileに記入して`bundle install`

```Gemfile.
gem 'kaminari'
```


# 2. コントローラでの設定

kaminariをインストールすることによって`.page(params[:page]).per(5)`が使用できるようになります。1ページあたり何件表示するかは`.per(5)`の値を変更してください。

```posts_controller.rb
@posts = Post.all.page(params[:page]).per(5)
```

# 3. viewページへ挿入
各リンクへのリストを表示したいところに以下のコードを挿入します

```posts/index.htmnl.erb
<%= paginate @posts %>
```



# 4. デザインを整える

以降の操作は必須ではありませんがcssを使用してページネーションのデザインを整えていきます。

```:terminal
rails g kaminari:views default
```

とするとviewフォルダにkaminariに関連するファイルがいくつかダウンロードされます。
自分で`kaminari.scss`のファイルを作って以下のコードを挿入。

```kaminari.scss
.pagination {
  text-align: center;

  .page {
  margin-right: 10px;
  width: 5%;
  padding-left: 10px;
  }

  .next , .last {
  padding-left: 10px;
  }
}
```

`ja.yml`ファイルも少しいじる。

```config/locals/ja.yml
ja:
  views:
    pagination:
      first: "&laquo; 最初"
      last: "最後 &raquo;"
      previous: "&lsaquo; 前"
      next: "次 &rsaquo;"
      truncate: "..."
```


これで出来上がり！！↓

![スクリーンショット 2021-12-19 23.51.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293293/b06aa99d-fa2a-ebc2-0b77-c7c063517d94.png)


# 5. 参考
[【Rails】 kaminariの使い方を理解してページネーションを実装しよう](https://pikawaka.com/rails/kaminari)
[TypeScript] プロパティ名を型として扱う

https://qiita.com/advent-calendar/2021/first-try

# はじめに
この記事は「初めてのアドベントカレンダー Advent Calendar 2021
」12/19の投稿記事です。


# やりたいこと
チェックボックスの状態を管理する関数の引数に、設定したプロパティのみ受け取るよう型をつけたい。

# 現状

```tsx
const [optionModal, setOptionModal] = useState({
  hoge: false,
  foo: false,
  bar: false,
});

const onChangeOptionItem = key => {
  setOptionModal({
    ...optionModal,
    [key]: !optionModal[key],
  });
};

```

これだと引数```key```がanyになってしまいTSのメリットが薄れてしまう

# 解決策

オブジェクトのキーをユニオン型にして返す```keyof```を使用する。

```tsx
type optionState = {
  hoge: boolean;
  foo: boolean;
  bar: boolean;
};

type optionStateKey = keyof optionState

const [optionModal, setOptionModal] = useState({
  hoge: false,
  foo: false,
  bar: false,
});

const onChangeOptionItem = (key:optionStateKey) => {
  setOptionModal({
    ...optionModal,
    [key]: !optionModal[key],
  });
};

// no error
onChangeOptionItem("bar")

// 型 '"barrr"' の引数を型 'keyof optionState' のパラメーターに割り当てることはできません。ts(2345)
onChangeOptionItem("barrr")
```

keyofで型をつけておけばコンパイル前に注意され修正できるようになりました。

最後まで読んでくださって、ありがとうございます。



# 参考記事
https://typescriptbook.jp/tips/generates-type-from-object-key
kubernetes immutable fieldsを探す

immutableなfieldを解明するため、我々調査隊はkubernetesの奥地へと向かった…

kubernetesのimmutableなfieldをコードを読んで地道に探します

# バージョン

kubernetes 1.23.1

# 使いそうなやつ

使いそう、は個人的な感覚です

- apps
    - Daemonset.spec.selector
    - Deployment.spec.selector
    - ReplicaSet.spec.selector
    - Statefulset.spec
        - replicas template updateStrategy persistentVolumeClaimRetentionPolicy minReadySeconds __以外__
- batch
    - Job.spec.completions
    - Job.spec.selector
    - Job.spec.completionMode
    - Job.spec.template
- core
    - PersistentVolume.spec.volumeMode
    - PersistentVolume.spec.nodeAffinity
    - PersistentVolumeClaim.spec.volumeMode
    - PersistentVolumeClaim.metadata.annotations."volume.beta.kubernetes.io/storage-class"
    - Secret.type
    - Service.spec.healthCheckNodePort
    - ExpandPersistentVolumesが無効の場合
        - PersistentVolumeClaim.spec
- discovery.k8s.io
    - EndpointSlice.addressType
- networking.k8s.io
    - IngressClass.spec.controller
- scheduling.k8s.io
    - PriorityClass.preemptionPolicy

# 使わなそうなやつ

使わなそう、は個人的な感覚です

- apps
    - ControllerRevisions.data
- core
    - Event.involvedObject
    - Event.reason
    - Event.message
    - Event.source
    - Event.firstTimestamp
    - Event.lastTimestamp
    - Event.count
    - Event.type
    - Event.eventTime
    - Event.action
    - Event.related
    - Event.reportingController
    - Event.reportingInstance
    - ResourceQuota.spec.scopes
- apiextensions.k8s.io
    - CustomResourceDefinition.spec.scope
    - CustomResourceDefinition.spec.names.kind
    - CustomResourceDefinition.spec.group
    - CustomResourceDefinition.spec.names.plural
- storage.k8s.io
    - StorageClass.volumeBindingMode
    - CSIDriver.spec.attachedRequired
    - CSIDriver.spec.fsGroupPolicy
    - CSIDriver.spec.podInfoOnMount
    - CSIDriver.spec.volumeLifecycleModes
    - VolumeAttachment.spec
    - CSINode.spec.drivers
    - CSIStorageCapacity.nodeTopology
    - CSIStorageCapacity.storageClassName
    - StorageClass.parameters
    - StorageClass.provisioner
    - StorageClass.reclaimPolicy
- node.k8s.io
    - RuntimeClass.handler

# なんでまた
statefulsetのrevisionHistoryLimitが変えられないとか言われてカッとなってやった
教養としてのコンピュータサイエンス講義を読んでみた



<h1>コンピュータサイエンスとは？</h1>

コンピュータ・サイエンスとは、コンピュータを使って、工学、理学、数学を扱う学問らしいです。

皆さんの身近な画像と音楽について、あまり知られていないのでは？ということがあったので共有させていただきます！




<h2>アナログ/デジタル変換</h2>

<h3>画像をデジタル形式に変換するやり方</h3>


<h4>アナログカメラの場合</h4>
撮影しようとしている物体から届く光を化学物質に覆われたプラスチックフィルムの感光領域にあてることによって画像を生み出す。
それぞれの領域で異なる色の異なる量の光を受け取る。色は着色染料の量の違いとして表現される。



>感光領域
https://astamuse.com/ja/keyword/11290161


<h4>デジタルカメラの場合</h4>
レンズは赤、緑、青のフィルターの後ろにある、小さな感光装置が置かれた長方形の領域に画像を集める。
各感光装置は、その上に当たる光の量に比例した電荷量を記憶し、数値に変換される。
その光強度を表す結果の数値が並べられたものが、画像のデジタル表現になる。
感光装置がより小さく、より多く、電荷がより正確に測定される場合には、デジタル化された画像は、元の物体をより正確に捉えている。

>電荷量
https://juken-philo.com/denkatohanani/



<h3>デジタル音楽</h3>

デジタル音楽は社会、経済、法的に大きな影響を及ぼしました。

レコードやオーディオカセットテープとは異なり、デジタル音楽は自由自在に任意の家庭用コンピュータ上で何度でも完全にコピーするとこができる。
インターネット経由で誤りなく、無料で送信できてしまうので、音楽業界はとても大打撃を食らっているようです。


<h3>音とは?</h3>
音源は、振動やその他の急速な動きによって、空気圧を生み、耳はその圧力の変化を脳が音として解釈できる神経アクティビティに変換する。
この仕組みを使って、録音したり、再生することができます。

その波形データを測定し、数値の列を対応する電圧または電流のパターンに変換し、スピーカーまたはイヤフォンを駆動して音に戻す機器を用いて、再生できる。




<h2>最後に</h2>
知っている内容だったでしょうか？
音も画像も数値が元になっていることに驚きました。
この本には他にもコンピュータの基本的なことが学べることがたくさん記されているので
ITについて勉強し始めた人や興味がある人におすすめです！





<h4>書籍</h4>
>教養としてのコンピュータサイエンス講義
https://www.amazon.co.jp/%E6%95%99%E9%A4%8A%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%83%BC%E3%82%B5%E3%82%A4%E3%82%A8%E3%83%B3%E3%82%B9%E8%AC%9B%E7%BE%A9-%E4%BB%8A%E3%81%93%E3%81%9D%E7%9F%A5%E3%81%A3%E3%81%A6%E3%81%8A%E3%81%8F%E3%81%B9%E3%81%8D%E3%80%8C%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E4%B8%96%E7%95%8C%E3%80%8D%E3%81%AE%E5%9F%BA%E7%A4%8E%E7%9F%A5%E8%AD%98-%E3%83%96%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%BB%E3%82%AB%E3%83%BC%E3%83%8B%E3%83%8F%E3%83%B3/dp/4822288730
【Rails】Gemfileのgemバージョン指定

####初めに
Gemfileにgemを記入する際に、バージョン指定の書き方がいまいち理解できていなかったので、まとめてみました。

####gem記入方
```
gem ライブラリ名 ,バージョン
```

####バージョン指定

◆``1.0.0`` 
バージョンを固定。

◆``>= 1.0.0``
1.0.0以上のバージョンが必要。

◆``>= 1.0.0, < 2.0.0``
1.0.0以上、2.0.0未満のバージョンが必要。

◆``~> 1.0.0``
1.0.0以上で利用可能で、1.0.9などは問題なく、1.1にバージョンが上がると利用不可になる。

◆バージョン指定無しの場合は、常に最新版をインストール。

####参考記事
[【Rails】Gemfileのバージョン指定の書き方](https://blog.yuhiisk.com/archive/2017/04/24/specify-the-version-of-gemfile.html)
【論文読み】Stock price prediction using BERT and GAN

## はじめに

こんにちは。論文を1人で読んだ結果の紹介記事です。  
今回紹介するのは、2021年の「Stock price prediction using BERT and GAN」という論文です。  

- タイトル：Stock price prediction using BERT and GAN  
- 出典：Priyank Sonkiya, Vikas Bajpai, Anukriti Bansal; Statistical Finance, 2021  
- URL：https://arxiv.org/abs/2107.09055  



## 概要
生成器(GRU)と識別機(CNN)で構成されたGANの構成で、データセットの一部としてFinBERTを使った金融市場の感情分析結果を使用することで、従来のモデルよりも株価予測の予測誤差(RMSE)が小さくなった。


## 技術的特徴
- ニュースと見出しをFinBERTに入力し、感情分析結果を使用した。  
- バックテストでは、前の３日間のデータで次の４日目の価格を予測した。  
- 提案手法のGANでは、画像ではなく一次元配列のデータを生成した。
- GANの損失関数はKL-JSダイバージェンスに基づいていて、学習ステップではクロス・エントロピーを用いて、2つの分布（実際のデータ分布と生成されたデータ分布）を区別する。このクロス・エントロピーを最小化することで、KL-JSダイバージェンスを最小化し、実際のデータに類似した分布を得る。


## 想定される適用例
- 論文の説明変数に含まれる株価や商品価格の予測


## 参考
- [BERTとGANを使った株価予測](https://ai-scholar.tech/articles/gan/stockprice_bertandgan)  
- [Stock price prediction using BERT and GAN](https://arxiv.org/abs/2107.09055)
WSL2 Ubuntu再起動時にPathを通しておく

#問題
WSL2で動いているUbuntu 20.04 LTSについて、
Ubuntuのウィンドウを閉じると、起動時に通しておいたPathが消えてしまう。

#解決策
ホームディレクトリにある`.bashrc`に以下のように書き加える。

```:.bashrc
export PATH={フルパス}:$PATH
```

`.bashrc`とは起動時に読み込まれる設定ファイルである
参考：[「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word13649.html)
Alibaba Cloudハードウェアセキュリティモジュールについて

# ハードウェアセキュリティモジュールとは
Hardware Security Module(HSM)とは、暗号化や暗号鍵の管理などをデバイス側が備えたものです。
主に国際規格のFIPS/CommonCriteria/JCMVPなどの認定を取得しているデバイスを指します。
規格のレベルなどによって保証されるセキュリティ水準は異なります。
AzureではDedicated HSM、AWSではCloudHSMというサービス名で提供されています。

# Data Encryption Serviceとは
Data Encryption Serviceとは、Alibaba Cloudが提供しているクラウドホスト型HSMサービスです。

# 概要
Data Encryption Serviceの機能や特徴、価格などについて説明します。

## 機能
Data Encryption Serviceが提供する機能として、次の7つが挙げられます。

* キーのライフサイクルの管理
* 複数のキータイプをサポート
* データの暗号化と復号化に対称鍵と非対称鍵をサポート
* 複数のダイジェストアルゴリズムとハッシュベースのメッセージ認証コード(HMAC)のサポート
* 非対称鍵の署名と検証をサポート
* 安全なランダムデータの生成
* HSMクラスター

## 対応している汎用HSM
対応しているアルゴリズムタイプとその内容はこちらです。
基本的なデータ暗号化のアルゴリズムに対応しているように思います。

| アルゴリズムタイプ | 説明 |
|:-:|:-:|
| 対称アルゴリズム  | DES/3DES/AES(128,192,256)など  |
| 非対称アルゴリズム  | RSA(1024～4096), ECCなど  |
| ダイジェストアルゴリズム | SHA1, SHA256, SHA384, SHA512など |

## 特徴
Alibaba CloudのData Encryption Serviceの大きな特徴は5つあります。

**1.安全なキーストレージ** 
HSMを直接使用して暗号化キーを保護します。
(ハードウェアとファームウェアは、FIPS140-2レベル3の認定を受けたものです。)

**2.安全な鍵管理**
HSMインスタンスの可用性の確保のため、HSMのみ管理し、キーは管理しません。

**3.利用しやすさ** 
HSMインスタンスは、VPCにデプロイされます。
このインスタンスは、指定したプライベートIPアドレスを使用して管理・呼び出しを行います。

**4.自動スケーリング** 
状況に応じてHSMインスタンス数を動的に調整し、負荷分散を実装することが可能です。

**5.サービスの有効期限**
HSMインスタンスの有効期限が切れた場合、HSMインスタンスは7日間保持されます。
その間にインスタンスを更新されれば、引き続き使用することが可能です。

# 価格
料金は、月額または年額のサブスクリプション課金方式となっています。
現在サービスが提供されているのは、シンガポール、マレーシア、香港リージョンのみとなっています。
別リージョンで使用する場合は問い合わせが必要です。
HSMユニットごとに金額が設定されています。

2021/12/19現在の価格(**価格は変更になる場合があるので、必ず公式サイトでご確認ください。**)

| リージョン | Unit Price of HSM(USD/Month) | Unit Price of HSM(USD/Year) |
|:-:|:-:|:-:|
| Singapore(Singapore)  | 1,300 | 14,300 |
| Malaysia(Kuala Lumpur)  | 1,300 | 14,300 |
| China(Hong Kong)  | 1,500 | 16,500 |


# まとめ
HSMを利用するとこで、WebサーバーのSSL及びTLS処理のオフロードや、CAの秘密鍵の保護、TDEの実行、クラウド内の機密データの暗号化などに対応しています。
今後日本リージョンでサービスが展開されるといいなと思います。


# 参考資料

* [IT用語辞典](https://e-words.jp/w/HSM.html)
* [Azure Dedicated HSM](https://azure.microsoft.com/ja-jp/services/azure-dedicated-hsm)
* [AWS CloudHSM](https://aws.amazon.com/jp/cloudhsm/)
* [Alibaba Cloud Data Encryption Service](https://www.alibabacloud.com/product/cloudhsm)
[Android Kotlin]インタースティシャル広告のcloseイベント検知

### 実装


```MainActivity.kt
val adRequest = AdRequest.Builder().build()
InterstitialAd.load(context, interstitial_id), adRequest, object : InterstitialAdLoadCallback() {
    override fun onAdLoaded(interstitialAd: InterstitialAd) {
        interstitialAd.fullScreenContentCallback = object : FullScreenContentCallback() {
            override fun onAdDismissedFullScreenContent() {
                super.onAdDismissedFullScreenContent()
                // ここに閉じたあとの処理を記述する
            }
        }
        interstitialAd.show(activity)
    }
})
```
React Class ComponentでuseMediaQuery（hook）を使う

##課題

現在、ReactでMaterial-UIを利用しているが、コンポーネントは基本的に全部Class Componentを利用している。
一つのコンポーネントで画面のサイズによって、FullScreenか否かを設定しようとしている。
下記のMUIのドキュメントにあるDiagramの例をそのまま利用したいですが、MUIの例は全部Function Componentでできている。
画面のサイズによって、異なるモードの値を設定しないといけないが、これはuseMediaQuery というHookを利用している。

https://mui.com/components/dialogs/#responsive-full-screen


##解決策

https://stackoverflow.com/questions/59672212/how-to-use-usemediaquery-in-class-component

基本的に上記で解決策が記載されているが、日本語でまとめてみる。

```withMediaQuery.js
import React from 'react'
import useMediaQuery from '@mui/material/useMediaQuery';

const withMediaQuery = (queries = []) => Component => props => {
  const mediaProps = {}
  queries.forEach(q => {
    mediaProps[q[0]] = useMediaQuery(q[1])
    console.log(q)
  })
  console.log(mediaProps)
  return <Component {...mediaProps} {...props} />
}

export default withMediaQuery;
```

まず、Hookを利用したいClass Componentの別ファイルとしてwithMediaQueryというコンポーネントを作る。
このwithMediaQueryというコンポーネント経由で指定のClass Component（以下ではMainというComponent）でuseMediaQueryで取得できる値を利用できるようにする。

```Main.js
// まず、先程定義したwithMediaQueryをインポートする
import withMediaQuery from '../Lib/withMediaQuery';

class Main extends React.Component {
   render() {
     // propsとして利用可能。
     console.log(this.props.isMobile)
     return (
       <div> 
       <Dialog fullScreen ={this.props.isMobile}
                                    open={this.state.open}
                                    onClose={this.handleClose}
                                    aria-labelledby="responsive-dialog-title">
                            <DialogTitle id="responsive-dialog-title">
                                    {"Full Image"}
                            </DialogTitle>
                            <DialogActions>
                            <Button autoFocus onClick={this.handleClose}>
                                Close
                            </Button>
                            </DialogActions>
                            </Dialog>
       </div>
     )
   }
}

// 下記のように、MainコンポーネントをExportするときに、withMediaQueryを利用して、prop値として取得した値をこのClass Componentで利用することが可能になる。
export default withRouter(withMediaQuery([['isMobile', theme => theme.breakpoints.down('md'), {
    defaultMatches: true
  }]])(Main));

```

以上です。
phpのビルトインサーバー

php -S localhost:8080 sample.php

などと記述してしまうと、フォルダ全体のファイルは普通には参照されなくなっちゃうのね〜。

php -S localhost:8080

こうやったら、localhost:8080/sample.php　なんてアクセスすればフォルダ全体のファイルを普通に参照できるみたい。
《初心者です》HTML CSS 記述　自動補完についてのメモ

VSCode使用時
Emmet 自動補完ツールの使い方 個人memo
知らなくても書けるが知ってたら便利だそう。


"! + tabキー"

```HTML
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
</body>
</html>
```


#例: idのついたdivタグを作る
" # + container + tabキー"
" #container + tabキー"

```HTML
<div id="container"></div>
```


#例: classのついたdivタグを作る
" . + cls + tabキー" 
" .cls + tabキー" 

```HTML
<div id="container"></div>
```


#例: span要素にclass
"span + . + cls + tab キー" 
"span.cls + tab キー" 

```HTML
<span class="cls"></span>
```

#例: divタグの中にspan要素配置
"# + container + > + . + cls + tabキー"
"#container>.cls + tabキー"
 
```HTML
<div id="container">
  <div class="cls"></div>
</div>
```


#例: divタグの中にspan要素配置
"# + container + > + . + cls + tabキー"
"#container>.cls + tabキー"

```HTML
<div id="container">
  <div class="cls"></div>
</div>
```

#例: 複数個のdivが含まれたcontainer作成
"# + container + > + . + cls + * + 個数 + tabキー"
"#container>.cls*5 + tabキー"

```HTML
<div id="container">
  <div class="cls"></div>
  <div class="cls"></div>
  <div class="cls"></div>
  <div class="cls"></div>
  <div class="cls"></div>
</div>
```


#例: 上記clsに数字をつける
"# + container + > + . + cls + - + $ + * + 個数 + tabキー"

```HTML
"#container>.cls-$*5 + tabキー"
<div id="container">
  <div class="cls-1"></div>
  <div class="cls-2"></div>
  <div class="cls-3"></div>
  <div class="cls-4"></div>
  <div class="cls-5"></div>
</div>


"#container>.cls-$$*5 + tabキー"
<div id="container">
  <div class="cls-01"></div>
  <div class="cls-02"></div>
  <div class="cls-03"></div>
  <div class="cls-04"></div>
  <div class="cls-05"></div>
</div>
```
化石がマイナスからKaggleを始めてみる

**前提**

アンモナイトはながらくWFで社畜として働いてきたが、ある日、アジャイルに目覚め、
自分が「化石エンジニア」、つまり「エンジニアレベル＝Lv3」くらいになってると気づく。
たぶん、いま太古の海中にいる。せめて肺呼吸ができるようになりたい。
人類へ進化するため、Pythonを使ってKaggleに挑戦することにした。

**1：Kaggleとは**
実は、自分の技術力の低さに驚愕し、最近、週末はPythonを少し触っていた。
Pythonの使い方を調べてて、「Kaggle」があると知った。
Kaggleは誰かが出したお題の解法を考えるサイト。
コンペティション形式でお題が出され、優れた解法は採用され、「賞金」をゲットできる。（超浅い理解）
面白そうなことができて、勉強もできて、賞金も出る？！
やるしかない。（3秒の結論）

**2：マイナスからのスタート**

アンモナイトのスペック：
　・数学レベル：「移動する点P」で考えるのが面倒くさくなり、その時点で永眠
　・技術レベル：Pythonを少々
　・Kaggleの知識：オモシロ＆賞金しか知らない
　・統計や機械学習の知識：ゼロ

よく「ゼロから始める～」があるが、そもそも数学も技術も統計も思考もないアンモナイトの現在地は「陸上」ではなく、「海面下（海抜ゼロよりもさらに下）」である。
つまり、「ゼロから始めるKaggle」ではなく、
「思考するのが面倒くさい化石がマイナスから始める」Kaggleだ。　

これは自分だけではどうにもならないと判断、
密林で『PythonではじめるKaggleスタートブック』を購入した。
（https://www.amazon.co.jp/dp/4065190061）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1668633/8bf977e0-1ca3-3f49-f505-3f1dd271e4b4.png)
冒頭の「本書の対象読者」で挙げられた中に「Kaggleに興味はあるが、どこから手をつけて良いか困っている方」があった。
うん、アンモナイトは対象読者だな。間違いない。
この本通りにやれば、Kaggle参加→技術力のレベルUp可能では？

**3：環境準備**
『PythonではじめるKaggleスタートブック』は初心者・アンモナイトには良書だった。
ちゃんと「Kaggleとは」が詳しく説明されている（メダルとか称号とか）。
サンプルコードも記載されている。
Kaggle以外のコンペサイトも記載があった。

必要なもの：
　・GitHub　（→後でDocker選択時にいる？ らしいと判明）
　・Docker（PythonのKaggle向け分析環境）　（→後で「選択肢の一つ」と判明）

早くも知らない単語が出てきた。GitHubはなんとかなりそうだけど、
Dockerってなに？（←化石の問いはこのレベルから始まる）
Google先生に教えてもらう。
「Dockerは、コンテナ仮想化を用いてアプリケーションを開発・配置・実行するためのオープンプラットフォームである。
  Dockerはコンテナ仮想化を用いたOSレベルの仮想化によりアプリケーションを開発・実行環境から隔離し、
  アプリケーションの素早い提供を可能にする。」（By Wikipedia）
プラットフォームってのはわかるけど、コンテナってなに？（←化石の問い）

再びGoogle先生に教えてもらう。
「コンピュータプログラミングにおいて、コンテナとはオブジェクトの集まりを表現するデータ構造、抽象データ型またはクラスの総称である。
  コレクションとも言う。コンテナには複数の種類があり、それぞれ独自の方法でオブジェクトを組織的に格納する。」（By Wikipedia）
コレクションのことか。

でもさっき、Dockerの説明で「OSレベルの仮想化」って出てたけど、
「コンテナはOSレベル仮想化を省くから動きやすくなる」んでしょ？
なんか矛盾があるような…。Dockerの上にコンテナがある？　うん、わからない。
やってみるしかない。（3秒の結論）

**4：環境構築**

GitHubとDockerとKaggleがないことには始まらない（らしい）のでアカウントを作る。
GitHubのアカウントを作る。アカウントネームの名づけで失敗する。もう変更できない。
Kaggleのアカウントを作る。アカウントネームの名づけで失敗する。もう変更できない。
Kaggleのアカウントネームについてはちゃんと『PythonではじめるKaggleスタートブック』に注意書きがある。
よい子のみんなはこの本のアドバイス通りに作れば問題ない。
Dockerはまだ本に出てこないので、あとでいいのかな。

**5：すでに始まっていた**

ここで想定外の事態が2つ発生。
　1：Kaggleのサイトは全文英語表記→どっかで変えられる？
　2：気づいたら、最初のチュートリアルコンペ「タイタニック号-災害からの機械学習」（適当な英訳）に参加済
どうやって参加したんだ？　どこを間違えたのかわからない。
とりあえず過去のことはもうどうしようもないので（例：アカウントネーム）、本の説明を読む。
サイトのページのタブと本のタブの説明が一致してない。
「タイタニック号～」はチュートリアルだからか？
それともレイアウトが変わった？
わからないので、次へ進む。

**6：Notebookを作る**
Dockerってどうやって入れんの？ 本に出てこないけど、と疑問を感じつつ、本の通りにNotebookタブを探し、Notebookタブがないことを発見する。
「Codeタブじゃね？」と安易にクリック。
すぐにNotebook画面に切り替わる。すでに言語はPythonが選択されている。
話が早いからまぁいいかと思いつつも、Dockerって……という疑問は残る。

**7：NotebookとDocker**
本を読み進んだら、謎が解けた。
Notebookはもうクラウドに構築済・すぐに使用できる環境。
Dockerは自PCで自分で環境構築の際に、使用する。
こんなん知ってる人からしたら猛烈なツッコミが来ると思うが、
なにせこちとら古代生物である。マジです。マジでやってます。（すでに3時間が経過）

**8：今後の予感**
こんな感じで『PythonではじめるKaggleスタートブック』の第一章が終わる。
今後、「タイタニック号-災害からの機械学習」（適当な英訳）に挑戦する予定。
そしていま気づく。
「もしかして、Notebook使用するなら、GitHubいらないのでは……？」
だってGitHubとの連携について、全く触れられてないよ……？



ここまで長文にお付き合いいただき、ありがとうございました！
ロングスリーパーのエンジニアが生き残る方法

# はじめに
- この記事は、[LIGHTz advent calendar](https://qiita.com/advent-calendar/2021/lightz)の17日目の記事です。
- ポエムです（プログラミング関係ない）
- ショートスリーパーになる方法を書いた記事ではありません。寝ようや。

# ロングスリーパーとは 
一般的にヒト（成人）の最適な睡眠時間は1日6-8時間程度と言われていますが、個人差が大きいです。
この記事では、先天的に1日8時間以上の睡眠を必要とする人を「ロングスリーパー」と定義します。

# 筆者について
- 1日8-10時間睡眠
- 平日は22 or 23時就寝-翌8時起床。休日は翌9時まで寝ている。
- 8時間睡眠でギリギリ
- 7時間睡眠ではぼんやり、6時間睡眠では起きているのがやっと。それ以下は死

# 気づいたきっかけ
学生時代は無限に寝ていました。
学校から帰ってとりあえず寝て、親が夕飯作ったら食べて風呂入って寝る。

社会人になってから**忘れ物が多い、会議中に眠くなる、仕事でケアレスミスが多い**ことに悩まされるようになりました。

眠気はガム、コーヒー、ミンティア、エスタロンモカ、眠眠打破、各種ドリンク…色々試しましたがダメでした。

その後、通勤片道1時間半の職場→通勤片道10分の職場に転職し、
ミスが多い、眠いのは「ただの睡眠不足」が原因だと気づきました。

1日7～8時間寝ているけど頭がすっきりしなくて悩んでいるあなた。
もしかしたら私と同じロングスリーパーかもしれません。

# ロングスリーパーが生き残る方法
残念ながら「健康を維持しつつ睡眠時間を短縮する」方法は現時点では確立していません。
特にロングスリーパーは無理して睡眠時間を短くしないほうがよいというのが持論です。
（身体より先にメンタルにきます）
以下に睡眠時間を確保しつつ、社会生活を送る方法をご紹介します。


## 0.睡眠外来に行く
昼間あまりにも眠い人は、睡眠時無呼吸症候群やナルコレプシー、突発性過眠症の可能性もあるので、睡眠外来に行きましょう。
私は専門クリニックに行き、睡眠日誌を付けたり睡眠時脳波を測定したりした結果、ただの長時間睡眠者と診断されました。

## 1.通勤時間は短く
片道30分以内。できれば15分以内。
私は家族の勤務地に合わせて、徒歩通勤ができるエリアに転職しました。

## 2.お酒は飲まない
睡眠の質が悪くなるため、できるだけアルコールは摂らないようにしています。

## 3.カフェインはほどほどに
カフェインの過剰摂取は睡眠の質悪化を招きます。
私はコーヒーは「1日2杯まで」「14時まで」としています。
お酒と同じで個人差が大きいので、自分のベストな摂取量とタイミングを実験してみてください。

## 4.寝具にこだわる
1日の1/3どころか半分は寝ているので、寝具は良いものを使いましょう。
1年に1回は布団を丸洗いに出して清潔を保つようにしましょう。

おすすめグッズは以下

### 除湿シート
睡眠時間が長い→布団に湿気がたまる→カビの原因に！
布団の下に除湿シートを敷き、定期的に干しています。
西川リビングの「からっと寝」がおすすめ。繰り返し使えます。
フローリング＋からっと寝＋マットレス直置きでもカビません。

### マットレス
長時間寝ると普通の人より綿がへたりやすくなるため、厚めの布団・マットレスがおすすめです。
私は天然ウール100%の高密凹凸マットレスを使ってます（ふるさと納税の返礼品でもろた）
https://www.furusato-tax.jp/product/detail/19202/4509095

## 5.長時間睡眠に理解ある人をパートナーにする
一番大事。
同じロングスリーパーと結婚する必要はありませんが、

- 寝室別でOKな人（私は結婚当初から寝室別）
- 先に寝ても怒らない人

だと助かります。
朝ごはん作ってくれる人だとさらにいいですね！（その分、夕飯作りなどで家事参加しましょう）

## 6.長時間&不定期勤務の仕事は避ける
終電まで勤務→翌朝通常勤務とか続くとキツいです。
一時的にならなんとかなりますが。普段は遅くとも、20時には退社したいですね……。

シフト制の場合、勤務間インターバルが最低11時間以上確保されている案件を選びましょう。

# ロングスリーパーのメリット/デメリットってあるの？

[メリット]
- たくさん夢がみられる（私は1日2-3本立て）
- お金を使う暇がない（寝てる）ので、貯金できる
- 記憶の定着が良い（気がする）


[デメリット]
- 稼働時間が人より少ない
- ライフスタイルに制限がかかる（長時間勤務や通勤ができない）

…1日あたりの稼働時間が短いぶん、長生きして人生の元を取ろうと思います。


# ロングスリーパーにそもそもエンジニアって仕事向いてるの？
たまに聞かれますが、私はIT業界以外で働いたことがないのでわからないですね…

# おわりに
この記事が眠くて悩んでいる方のお役に立てれば幸いです。
ここまでお読みいただき、ありがとうございました。
【Git】サブモジュール化を使用したプロジェクト管理

## はじめに
フロントエンドとバックエンドで
gitリポジトリを分けたサブモジュール管理を行なったのでその備忘録

## 環境
macOS

## 前提条件
・GitHubへ登録済
・ステージング追加　コミットの概要を理解している

## ゴール
![スクリーンショット 2021-12-19 22.09.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1986536/f7b40461-ef40-72d4-f5a3-ec66e90248c2.png)

※青文字の`front@290b86d`がサブモジュールで親リポジトリとは別で管理しています。

## ディレクトリ構成図
sample $

```
├── sample
  ├── sample.txt
  └── front
      　　└── front.txt
```

## ディレクトリ/ファイルの作成
```
documents $ mkdir sample

documents $ cd sample

sample $ touch sample.txt

sample $ mkdir front

sample $ cd front

front $ touch front.txt
```
※txtファイルは空でOKです

## リモートリポジトリの作成
GitHub上に【sample】、【sample_front】のリモートリポジトリを作成する
![スクリーンショット 2021-12-19 22.26.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1986536/407f7aa9-f42f-9087-604e-bd5852ea64ed.png)
※この画面が出ればOKです

## gitmodulesファイル作成
```
sample $ touch .gitmodules
```
```:.gitmodules
[submodule "front"]
	path = front
	url = ( サブモジュール化するリポジトリのURL)
```

## gitHubへPush
```:front側
front $ git init 

front $ git add -A

front $ git commit -m"サブモジュールTRY"

front $ git branch -M main

front $ git remote add origin (frontのリモートリポジトリのURL)

front $ git push -u origin main
```

```sample側
sample $ git init 

sample $ git add -A

sample $ git commit -m"サブモジュールTRY"

sample $ git branch -M main

sample $ git remote add origin (sampleのリモートリポジトリのURL)

sample $ git push -u origin main
```

## gitHub確認
sampleのリモートリポジトリを確認
![スクリーンショット 2021-12-19 22.09.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1986536/ece6f930-5cef-c35f-9a57-6917815033c6.png)
【青文字】をクリックしてfront側のリモートリポジトリへ遷移するか確認してください
macOS に Python の環境を構築する

# はじめに

macOS に Python の環境を構築した履歴を残しておく。

# pyenv をインストールする
brew はインストール済みの前提である。

pyenv をインストールして、バージョンが異なる複数の Python を切り替えて利用できるようにする。

```zsh
$ which brew
/usr/local/bin/brew
$ which python
/usr/bin/python
$ brew install pyenv
🍺  /usr/local/Cellar/readline/8.1.1: 48 files, 1.6MB
==> Installing pyenv
$ which pyenv
/usr/local/bin/pyenv
$ pyenv -v
pyenv 2.2.2
```

次に pyenv の設定をする。

```zsh
$ ls -la ~/.zshrc
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
$ echo 'eval "$(pyenv init --path)"' >> ~/.zshrc
$ echo 'eval "$(pyenv init -)"' >> ~/.zshrc
$ tail ~/.zshrc
  FPATH=$(brew --prefix)/share/zsh-completions:$FPATH

  autoload -Uz compinit
  compinit
fi

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv init -)"
$ source ~/.zshrc
$ echo $PATH
/Users/yourname/.pyenv/shims:/Users/yourname/.pyenv/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
```
# Python をインストールする

```zsh
$ pyenv install --list | grep 3.9
  3.9.0
  3.9-dev
  3.9.1
  3.9.2
  3.9.4
  3.9.5
  3.9.6
  3.9.7
  3.9.8
  3.9.9
  miniconda-3.9.1
  miniconda3-3.9.1
  miniconda3-3.9-4.9.2
  miniconda3-3.9-4.10.3
```

今回は 3.9.x 系の最新版である 3.9.9 をインストールする。

```zsh
$ pyenv install 3.9.9
python-build: use openssl@1.1 from homebrew
python-build: use readline from homebrew
Downloading Python-3.9.9.tar.xz...
-> https://www.python.org/ftp/python/3.9.9/Python-3.9.9.tar.xz
Installing Python-3.9.9...
python-build: use readline from homebrew
python-build: use zlib from xcode sdk
Installed Python-3.9.9 to /Users/yourname/.pyenv/versions/3.9.9
```

使用する Python のバージョンを切り替えてみる。

```zsh
$ pyenv versions
* system (set by /Users/yourname/.pyenv/version)
  3.9.9
$ python --version
Python 2.7.16
$ pyenv global 3.9.9
$ python --version
Python 3.9.9
```

もし、pyenv で指定したバージョンに Python が切り替わらない場合は、

```zsh
$ source ~/.zshrc
```

を実行して、`eval "$(pyenv init -)"` が実行されるようにする。
Javaでベンチマーク(性能測定) JUnit5編

[Javaのカレンダー | Advent Calendar 2021](https://qiita.com/advent-calendar/2021/java)の3日目の記事です

# 概要

Javaの単体テストのベンチマーク(性能測定)を簡単に取りたいときに使える方法
golang の `go test -bench` のようにサクッとメソッドの性能を確認したいときに利用します

## 参考

- [openjdk/jmh： https：//openjdk.java.net/projects/code-tools/jmh/](https://github.com/openjdk/jmh)
- [Javaによるマイクロベンチマーク| Baeldung](https://www.baeldung.com/java-microbenchmark-harness)
- [jmh](https://qiita.com/tags/jmh)

# やり方

## pom.xml

dependencies に以下を追加

```
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>1.33</version>
</dependency>
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>1.33</version>
    <scope>provided</scope>
</dependency>
```

## 測定コード

ポイント

- @Test で JMH の Runner を初期化します
    - 初期化で設定するのはデフォルト値だと余分な forks と warmup iterations のみを変更
- 測定したいテストメソッドに @Benchmark をつける

```java
public class BenchmarkTest {

    // Junit の Test アノテーションで Runner を設定する
    @Test
    void benchMark() throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(BenchmarkTest.class.getSimpleName())
                .forks(1) // 1回実行
                .warmupIterations(1) // 1回繰り返し
                .build();
        new Runner(opt).run();
    }

    // 測定したいテストに Benchmark アノテーションをつける
    @Benchmark
    public void test() throws InterruptedException {
        match(new Date().toString());
    }

    // テスト対象のメソッド(中身は適当)
    static boolean match(String str) {
        final var pattern = Pattern.compile(".*1*2");
        return pattern.matcher(str).find();
    }
}
```

#### 実行結果

```
Benchmark            Mode  Cnt        Score        Error  Units
BenchmarkTest.test  thrpt    5  4242841.831 ± 189193.259  ops/s
```

### 応用

試してはいませんが、以下は考慮ポイントです

- 個別に設定を変えたい場合は、Runner の設定値をいじるのではなく、アノテーション(@BenchmarkMode, @Fork, @State)でベンチマークテストごとに設定を変える
- ものによってはテストモードを Mode.AverageTime (平均時間)にしたほうがわかりやすいかもしれない
    - ただし、測定対象のメソッドが速すぎると、平均時間が目視で確認できなくなるので注意
- コンパイルの最適化で速くなるケースがあるので、コンパイラの気持ちになって書く
Vue3+Firebase　error解決の備忘録（Uncaught TypeError: firebase_compat_app__WEBPACK_IMPORTED_MODULE_0__.default.auth is not a function）

#初めに

こんにちは。

このerrorに2時間格闘し勝ったので備忘録です。

version
``node.js 14.18.1``
``vue 3.0.0``
``Firebase 9.6.1``

#error文

```console.log
Uncaught TypeError: firebase_compat_app__WEBPACK_IMPORTED_MODULE_0__.default.auth is not a function
```

#事象

Vue3とFirebase databaseの接続を試み、ローカルのビルド時に発生したエラー文。
画面真っ白になって上記のエラーがconsole上に出現。

問題箇所はここでした。

```javascript:firebase/config.js
// 【原因】ここから
import firebase from "firebase/app"; 
import "firebase/firestore"; 
import "firebase/auth";
import "firebase/storage";
// 【原因】ここまで

const firebaseConfig = {
    apiKey: ***************************,
    authDomain: ***************************,
    databaseURL: ***************************,
    projectId: ***************************,
    storageBucket: ***************************,
    messagingSenderId: ***************************,
    appId: ***************************,
};

// init firebase
firebase.initializeApp(firebaseConfig); // バックエンドのfirebaseを初期化する

// init firestore service
const projectFirestore = firebase.firestore(); // firebaseのサービスも初期化する
const projectAuth = firebase.auth();
const projectStorage = firebase.storage();

const timestamp = firebase.firestore.FieldValue.serverTimestamp; //firebaseのtimestamp

export { projectFirestore, projectAuth, projectStorage, timestamp };

```

#解決方法

インポートのパスが違うようです。
公式にも乗ってなかったし何なん。

``compat``

解決後、

```javascript:firebase/config.js

// compatのパスをかませるだけ
import firebase from "firebase/compat/app";
import "firebase/compat/firestore";
import "firebase/compat/auth";
import "firebase/compat/storage";

const firebaseConfig = {
    apiKey: ***************************,
    authDomain: ***************************,
    databaseURL: ***************************,
    projectId: ***************************,
    storageBucket: ***************************,
    messagingSenderId: ***************************,
    appId: ***************************,
};

// init firebase
firebase.initializeApp(firebaseConfig); // バックエンドのfirebaseを初期化する

// init firestore service
const projectFirestore = firebase.firestore(); // firebaseのサービスも初期化する
const projectAuth = firebase.auth();
const projectStorage = firebase.storage();

const timestamp = firebase.firestore.FieldValue.serverTimestamp; //firebaseのtimestamp

export { projectFirestore, projectAuth, projectStorage, timestamp };

```

#最後に
どこに書いてあんねん・・・

#参考
https://devsakaso.com/firebase-basics/


https://stackoverflow.com/questions/48592656/firebase-auth-is-not-a-function
【VSCode】Djangoで仮想環境を構築する手順

#はじめに
こんばんは、吉田プログラマーです。
実は今まで仮想環境を構築しないで開発をしていたのですが、流石にそれはちょっとまずいのでは？と思い始めた今日この頃です(実際は仮想環境の意義を理解してませんでした。。。)。

てなわけで、今回は習得した仮想環境構築方法を残していきます。

#(1) 環境
#### OS
- Windows10

#### エディタ
- Visual Studio Code

#(2) 参考サイト

###[外部サイト]

① [【初めてのPython環境構築】仮想環境の設定とDjango導入まで](https://scuration.hateblo.jp/entry/2020/06/07/220000#%E4%BB%AE%E6%83%B3%E7%92%B0%E5%A2%83%E3%81%A8%E3%81%AF%E3%81%AA%E3%81%9C%E4%BD%9C%E3%82%8B)

② [VSCodeでActivate時に「このシステムではスクリプトの実行が無効になっているため、ファイルｘｘを読み込むことができません」とエラーが表示される時の対処法](https://manumaruscript.com/vscode-activate-error/)

③ [【VSCode】settings.jsonについて理解する](https://amateur-engineer-blog.com/vscode-settingsjson/)

④ [仮想環境](https://www.python.jp/install/windows/venv.html)

###[Qiita]

⑤ [PowerShell のスクリプトが実行できない場合の対処方法](https://qiita.com/Targityen/items/3d2e0b5b0b7b04963750)




#(3) そもそも仮想環境ってなに？

開発を行う際、一時的な実行環境を作りたい場合に構築するようです。例えば以下のような状況で使います。

> 【参考サイト④より抜粋】
>・システム全体で使うPython環境に影響を与えずにモジュールの追加・入れ替えをしたい。
>・異なるバージョンの Python を使いわけたり、同じモジュールの、複数のバージョンを使い分けたい。

開発の前にはもはや必須な作業です。反省します。

#(4) 仮想環境を構築する方法

###①パッケージインストール
まずは仮想環境構築に必要なパッケージをpipでインストールします。

```
$ pip install virtualenv
```
###②仮想環境を作りたいフォルダまで移動する。

【フォルダがない場合は以下コマンドで作成】

``` 
$ mkdir [フォルダ名]
```

【対象フォルダにいない場合は以下コマンドで移動】

```
$ cd [フォルダパス] 
```
###③仮想環境作成

```
$ virtualenv [仮想環境名]
```
※lsコマンド等で作成した仮想環境フォルダがあればＯＫ

###④仮想環境を有効化

```
$  [仮想環境名]\Scripts\activate 
```
※コマンド先頭に(仮想環境名)が表示されていることを確認すること

###⑤仮想環境の終了

```
$ deactivate
```


#(5) コマンド実行時のエラー
仮想環境作成、もしくは有効化で以下のようなエラーが起きた場合、実行ポリシーの設定変更が必要になるようです。


```
用語 'C:\Users\ ~ >' は、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラムの名前として認識さ
れていることを確認し、パスが含まれている場合はそのパスが正しいことを確認してから、再試行してください。 
```

※その対応方法や実行ポリシーについては 『 [参考サイト⑤](https://qiita.com/Targityen/items/3d2e0b5b0b7b04963750)』 にめちゃくちゃ詳しく解説されておりますが、こちらでは必要な手順だけ載せておきます。

###『一時的にコマンド実行を有効化させたい場合』
以下のコマンドを実行するだけ。

```
$ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process 
```

###『常にコマンド実行を有効化させたい場合』

VsCode側の設定を変更する必要があるようです。

①ショートカットコマンド『cmd + ,』、もしくはコマンドパレットから「Preferences: Open Settings」を選択して右上のアイコン『設定(JSON)を開く』でsettings.jsonを開く。

②以下コードを記述し、保存する。

```settings.json
"terminal.integrated.env.windows": {
        "PSExecutionPolicyPreference": "RemoteSigned"
    } 
```

これでエラーが出ることはないはずです。
リストの先頭or末尾を調べる方法

いつも調べて思い出すことが多いので、メモとして残しておこうと思います。

#・リストの先頭かどうか

上記は以下で判断が可能です。

```
recyclerView.canScrollVertically(-1).not()
```

#・リストの末尾かどうか
上記はcanScrollVerticallyの引数を反転させれば判断が可能です。

```
recyclerView.canScrollVertically(1).not()
```

#・onScrolledでの実装
onScrolledで見たいケースが殆どだと思いますが、大体以下のような実装になるかと思います。

```
binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                if (recyclerView.canScrollVertically(-1).not()) {
                    // リストの先頭に来た時の処理
                }
                if (recyclerView.canScrollVertically(1).not()) {
                    // リストの末尾に来た時の処理
                }
            }
        })
```

#さいごに
こういう細かい実装って忘れがちですよね。
細かい実装の検索コストでも数を重ねると馬鹿にできないので、なるべく残していこうと思います。
Amazon SageMakerサービスまとめ　令和3年12月版

この記事は株式会社ナレッジコミュニケーションが運営する [クラウドAI by ナレコム Advent Calendar 2021](https://qiita.com/advent-calendar/2021/knowcom-cloudai) の18日目にあたる記事になります。

2021年11月29日 – 2021年12月3日で開催された「AWS re:Invent2021」では、AutoML（Automated Machine Learning）サービスの「Amazon SageMaker Canvas」など、より一般企業が機械学習、データを活用して、自社の売上や生産性向上が実現できる世界が近づいてきましたね！ただ、SageMakerサービスもかなり多くなっているので令和3年12月時点のサービスをまとめてみます。

# 各SageMakerサービスの位置づけ
令和3年12月時点のAmazon SageMakerのサービス一覧をMLワークフローに合わせて以下図にまとめてみます。
![サービス一覧2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320507/138bd696-c37e-2a6b-0734-3b1a9506593a.png)


# 各SageMakerのサービス概要
## Amazon SageMaker
機械学習を実施するうえで必要なモデル開発、学習、推論をトータルで実施することできるフルマネージド型サービスです。

## Amazon SageMaker Data Wrangler 
AWS の各種サービスからデータをインポートし、リアルタイムでデータの可視化や変換の処理を GUI 上で行えるサービス

## Amazon SageMaker Clarify
各特徴量が予測結果にどのくらい寄与しているか可視化できるなど、機械学習モデルの解釈可能性・公平性というところが視覚的にわかりやすく確認できることができるサービス

## Amazon SageMaker Ground Truth
機械学習でモデルをトレーニングするときの教師データにラベル付けを行うことができるサービス。ラベル付けができるのは、「テキスト分類」、「画像分類」、「物体検出」、「セマンティック・セグメンテーション」、「ユーザー定義のカスタムタスク」

## Amazon SageMaker Ground Truth Plus
ラベルリングアプリケーションを構築したり、ラベル付けのスタッフを自分で管理したりすることなく、高品質のトレーニングデータセットを簡単に作成することができるサービス

## Amazon SageMaker Training Compiler
既存のトレーニング用Pythonの訓練コードを自動でコンパイルして、自然言語処理やコンピュータービジョンタスクのトレーニングや調整に必要な時間を大幅に短縮することができるサービス

## Amazon SageMaker Inference Recommender	
機械学習の推論フェーズで最適な推論パフォーマンスとコストを実現するためにモデルデプロイに最適なMLインスタンスの構成を推奨するサービス

## Amazon SageMaker Serverless Inference
推論のMLモデルをデプロイするインスタンスをサーバレスで構成し、推論リクエストの量に基づき、コンピュート容量のプロビジョニング、スケーリングを自動で行うサービスです。

## Amazon SageMaker Feature Store
インフラを管理することなく、特徴データを安全に保管および取得することができるサービス。特徴データにタグ付けしたりインデックスをつけて検索できたりします。

## Amazon SageMaker Processing
機械学習のためのデータ前処理などをバッチで実行するためのインフラ環境を提供するサービス

## Amazon SageMaker Studio	
機械学習のための統合開発環境（IDE）でNotebookで行う方法よりも簡単に、そして可視化された状態で機械学習が行えるようになるサービスです。

## Amazon SageMaker JumpStart
機械学習の知識がなくとも数クリックでプリセットされている学習済みの機械学習のモデルをデプロイできる。また、時系列予測、金融取引の不正検知などさまざまなジャンルのユースケースに合わせたSageMaker周辺の構成がCloudFormationでデプロイできるサービスです。

## Amazon SageMaker Autopilot
回帰/分類問題に対して、自動で機械学習モデルの準備、トレーニングおよびパラメータ調整を行ってくれるAoutoMLサービスです。

## Amazon SageMaker Debugger
トレーニング中のモデルの問題を自動で検知し、モデル内部を可視化し、問題を調査することができ、トレーニング中の問題を素早く検知し解決することを支援するサービスです。

## Amazon SageMaker Model Monitor	
Amazon SageMakerの機械学習モデルと推論データの品質を監視し、推論時に投入されるデータの質が、モデルを学習した時と変化した場合にアラートを発砲したりするサービスです。

## Amazon SageMaker Edge Manager
スマートカメラ、ロボット、産業用機械などのエッジデバイスにデプロイされたモデルの管理・モニタリングができるサービスです。

## Amazon SageMaker Neo
機械学習モデルをコンパイルし、任意のデバイスで動作させることができる。モデルのコンパイルを行うことで特定のデバイスに最適化を行うことが出来るサービスです。

## Amazon SageMaker Canvas
ノーコードでエンジニアではないビジネスユーザーがコードを記述せずに機械学習モデルを構築できるサービスです。

## Amazon SageMaker Studio Lab
AWSアカウントが不要で無料で機械学習の学習ができるサービス。数クリックで機械学習を学習するインフラの構築ができます。

## Amazon SageMaker Pipelines
エンドツーエンドの機械学習ワークフローを管理するための CI/CD サービスです

# 最後に
令和3年12月時点で20種類ほどのサービスがあり、来年もさらなるアップデートが期待できますね！
個人的にはモデルの監視、管理系のサービスのアップデートがあるとうれしいです。
ご覧いただきありがとうございました！
Raspberry PiのFreeBSDで遊ぶ

#はじめに
遅れてきたサンタさんという絵本があったなと思いながら書いています．

元々は別のPCにFreeBSD13インストールなどを書こうと考えておりましたが，そのPCが動作していないため，昨年のアドベントカレンダーでインストールしたRaspberryPiで少し遊んでみようと思い記事にします．

#環境

利用しているのはいかのとおりです．

| 項目 | 内容 |
|:-----------|:------------|
| PC       | RaspberryPi 2        | 
| OS     | FreeBSD12.2      | 

#V13にアップデート

まず，せっかくなのでupdateしようとすると，いかのように簡単にはできないようでした．
```
root@generic:/home/freebsd # freebsd-update fetch
src component not installed, skipped
Looking up update.FreeBSD.org mirrors... 2 mirrors found.
Fetching public key from update2.freebsd.org... failed.
Fetching public key from update1.freebsd.org... failed.
No mirrors remaining, giving up.

This may be because upgrading from this platform (arm)
or release (12.2-RELEASE) is unsupported by freebsd-update. Only
platforms with Tier 1 support can be upgraded by freebsd-update.
See https://www.freebsd.org/platforms/index.html for more info.

If unsupported, FreeBSD must be upgraded by source.
```

#カメラの利用
RaspberryPiのカメラモジュールを操作してみようと，試してみるもまだうまくとれていません．
もう少しパラメータなど変えて試してみる必要がありそうです．

![test.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174886/185cc33c-5923-a4de-8ecb-921b85f7e2da.jpeg)

#参考URL
今回のカメラの利用は以下のページを参考にしています．
https://wiki.freebsd.org/arm/Raspberry%20Pi
【勉強メモ】ネットワークスペシャリスト編

## ネットワークスペシャリストの取得に向けた勉強メモ
### アウトプットの一環として調べたことなどを記録していきたいと思います！ ※随時更新

まずは、大枠から！

#### 1. プロトコル
     データの送信形式や送信順序など、データを送信するために決められたルール(規約)のこと。

##### 【OSI基本参照モデルとTCP/IPプロトコルスタック】

|OSI参照モデル|TCP/IPプロトコルスタック||
|-|-|-|
|アプリケーション層<br/>プレゼンテーション層<br/>セッション層|アプリケーション層|アプリケーション固有の通信規約|
|トランスポート層|トランスポート層|プロセスを識別し、正しいプロセスにパケットを送信する。|
|ネットワーク層|ネットワーク層|最終的な宛先を探索し、パケットを中継する。|
|データリンク層<br/>物理層|データリンク層|LAN内でデータフレームを伝送する。|

##### データリンク層
      有線若しくは無線で接続されている隣接したノードと通信を行う層。

##### ネットワーク層
      エンド2エンドの通信を行う層。IPパケットを宛先まで届けることが役割。

##### トランスポート層
      ホスト間で行われる通信上の個々のプロセスを識別し、プロセス間のデータ転送を実現させる層。

##### アプリケーション層
      トランスポート層のさらに上位に位置し、DNSやHTTPなどのアプリケーションプロトコルが提供する機能についてその仕様や通信手段などを定めている層。

#### 2.ネットワークの構成要素とその関連技術

##### 回線

##### 接続機器

##### 仮想化技術

1. VLAN  
   物理的な構成にとらわれずに、L2スイッチ上に構築された仮想LANのこと
   仮想LANのことはVLANグループと呼ばれ、VIDにより一意に識別される。
   構成方法は、大きく<b>ポートベースVLAN</b>と<b>タグVLAN</b>の2つである。

2. VID (1~4094)
   複数の顧客システムをつなげたNWを共通基盤として用いる場合には、VIDの上限値を超えることや
   VIDが重複する可能性などがある。
　     

##### WAN

##### ネットワークにおけるセキュリティ課題

##### その他課題

#### 3.主なサーバー機器

##### DHCPサーバー

##### DNSサーバー

##### Webサーバー

##### メールサーバー

##### FTPサーバー

##### プロキシサーバー

##### NTPサーバー

#### 4.その他
##### 学習の際に参考にした書籍＆サイト
    
   1. <a href="https://www.jitec.ipa.go.jp/1_04hanni_sukiru/_index_mondai.html">IPAの公式サイト</a>
   2. <a href="https://www.nw-siken.com/nwkakomon.php">過去門道場</a>
   3. <a href="https://bookstore.tac-school.co.jp/book/detail/009571/">2022年度版 ALL IN ONE パーフェクトマスター ネットワークスペシャリスト</a>
   4. <a href="https://www.ohmsha.co.jp/book/9784274224478/">マスタリングTCP/IP　入門編（第6版）</a>
   5. <a href="https://books.rakuten.co.jp/rb/16510421/">図解入門TCP/IP: 仕組み・動作が見てわかる</a>
   6. <a href="https://www.sbcr.jp/product/4797380484/">ルーティング＆スイッチング標準ハンドブック</a>
【LWC】選択リスト値を動的に取得する

#はじめに
LWCでSalesforceの選択リスト項目を表示させるには、標準のlightning-input-fieldが使用できます。しかしdata-tableの中などで選択リストを実装するにはinput-fieldは使用できません。
comboboxという選択リストを実装するコンポーネントがあるのですが、これは下記のように選択リスト値をこちらで指定する必要があります。そのため選択リスト値が増えた場合コードの修正をする必要があります。
今回はdata-table内でコードの修正をしなくて済むように選択リスト値を動的に取得する方法について調べてみました。

```javascript
options = [
    { label: 'New', value: 'new' },
    { label: 'In Progress', value: 'inProgress' },
    { label: 'Finished', value: 'finished' },
  ];
```

#オブジェクトのレコードタイプを取得
まずレコードタイプのIDを取得します。
LWCには選択リスト値を取得するための標準ライブラリとして[getPickListValues](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reference_wire_adapters_picklist_values)と[getPickListValuesByRecordType](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reference_wire_adapters_picklist_values_record)があるのですがどちらもレコードタイプIDを指定する必要があります。

```javascript
@wire(getObjectInfo, { objectApiName: ACCOUNT})
opportunityInfo({data, error}) {
    if(data) {
        const rtis = data.recordTypeInfos;
        //console.log(Object.keys(rtis).find(rti => rtis[rti].name === 'マスタ'));
        this.recordType = Object.keys(rtis).find(rti => rtis[rti].name === 'マスタ');
    } else if(error) {
        console.log('error');
    } 
}
```
この例ではマスタレコードタイプのIDを取得してます。getObjectInfoで取得できるrecordTypeInfosにはdeveloperNameは入ってないためnameで取得する必要があります。デフォルトのレコードタイプの場合もう少し簡単に取得できるのですが今回は割愛します。
#選択リスト値を取得
先ほど取得したレコードタイプIDを使用して選択リスト値を取得します。

```javascript
 @wire(getPicklistValuesByRecordType, { recordTypeId: '$recordType', objectApiName: ACCOUNT})
  ratingValues({data, error}){
      if(data) {
        this.picklistValue = data.picklistFieldValues.Rating.values;
        for(let i = 0; i < this.picklistValue.length; i++) {
            this.options.push({label: this.picklistValue[i].label, value: this.picklistValue[i].value});
        }
        // 選択リスト値取得後にカラムセットを呼び出し
        this.setColumns();
      } else if(error) {
          console.log('error');
      }
  }

// カラムをセット
setColumns() {
    this.columns = [
        { label: 'Name', fieldName: 'Name', editable: true },
        { label: 'Account Number', fieldName: 'AccountNumber', editable: true },
        { label: '顧客番号', fieldName: 'customerNumber__c', type: 'inputtext',
            typeAttributes: {
                placeholder: '', value: { fieldName: 'customerNumber__c' } 
                , context: { fieldName: 'Id' } 
            } 
        },
        {
            label: 'Rating', fieldName: 'Rating', type: 'picklist', typeAttributes: {
                placeholder: 'Choose rating', options: this.options
                , value: { fieldName: 'Rating' } 
                , context: { fieldName: 'Id' } 
            }
        }
    ];
  }
```
これで下記のように動的に値を取得できるためメンテナンス性はあがると思います。
指定できるレコードタイプIDは１つなため、複数のレコードタイプの選択リスト値を表示する場合は別の方法をとる必要があります。
返却されたデータの構造についてはご自身でお試しください。
注意点としてはdata-tableで使用する場合、columnsを選択リスト値取得後に指定する必要があるということです。
SharedPreferencesに保存した値をAndroidStudioで確認する方法



SharedPreferencesに保存した値を確認する際にLogに表示させて確認することもあるかもしれませんが、端末をUSBでパソコンに接続していれば、簡単にAndroidStudioで確認することができます。


## 1AndroidStudioの右下にあるDeviceFileExplorerをクリックします。

わかりやすい様にスクリーンショットを載せておきます。
![スクリーンショット 2021-12-19 21.34.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/c4e02dbe-0d82-5572-399b-9a5923225c17.png)

## 2確認したい端末を選択します。
右側にDeviceFileExplorerのエリアが出てくるので、そこに確認したい端末を選択します。

![スクリーンショット 2021-12-19 21.42.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/0fe4d96c-a8df-3f0f-d8e8-10789853d51c.png)

## 3プリファレンスのファイルを探します。

保存先は下記の様になってます。

```
data/data/［確認したいアプリのパッケージ名］/shared_prefs
```


![スクリーンショット 2021-12-19 21.50.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/c7dbc4d5-252d-cbd4-f098-14cf927b4d73.png)

表示すると、この様に確認できます。

```SaveData.xml
<map>
    <boolean name="boolean" value="false" />
    <string name="string">test</string>
    <float name="float" value="30.3" />
    <int name="int" value="10" />
    <long name="long" value="20" />
</map>
```



ちなみにEncryptedSharedPreferencesで暗号化されているかも確認できます。
__androidxから始まるものは自動で作られるみたいです。
keyはstringでvalueがtestで保存してます。
暗号化されるとkeyがAXXjxdwCaoaPMdRC5fhpzMrs93Hhyqt47DSL
valueがa1X2iEMIkexBOno31xGeo1R8Edv3KJ7k7ez4Of4zjyAsIplZadF0になりました。
暗号化されている事が確認できましたね！


```EncryptedSaveData.xml
<map>
    <string name="__androidx_security_crypto_encrypted_prefs_key_keyset__">12a9016ad2c529a7cc3799d6f2038d876d4d23727912b16e40f734419f07c1d50077659df5a868f6884eda6652099e64cf584b9051e9a5a0613417e7fe66463d41907bb578ce05e08621f1b61f3e39e3599688a8c468c44429983b2f680681b1e90a306031be613db4bda1c1968dcc495fe53603ad526cbf83223f8b54694463fae1a0df3cc170d3c368c8b1343720f1112b85bbc59873adc5a5e3a33e74f7ddd8e0f38f3f1cab717255598d1a4408dc8b8faf07123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e4165735369764b6579100118dc8b8faf072001</string>
    <string name="AXXjxdwCaoaPMdRC5fhpzMrs93Hhyqt47DSL">AUpVTUb/a1X2iEMIkexBOno31xGeo1R8Edv3KJ7k7ez4Of4zjyAsIplZadF0</string>
    <string name="__androidx_security_crypto_encrypted_prefs_value_keyset__">128801338210002ad6d6092a98e9a6a37bdb3bf403884c50463b1221048386f78ee4f12f08f85e4a9d6ebe902d2bcda4faf78f27b2d3f75e924c0ce82b29187340392aaf9eb061453ac379c5ea2adc9cd605aa50b4c4f0f67fb3c0add31bc723b32251820903a5dc7f2a5230f5659e21c7a7e879e52f98b9f73060141c6ab973058c9bde76064de436cc621a4408c69ad5d204123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e41657347636d4b6579100118c69ad5d2042001</string>
</map>

```
DBへのテストデータの作成について 

テストデータを作成する方法は、以下４つくらいが考えられるでしょう
---
- GUI操作によっての作成
- API利用しての作成
- DB操作での作成
- API + DB操作での作成(上記2,3の組み合わせだが、一応一つの種類と列挙する)

### それぞれの特徴

#### GUI操作によっての作成
実際にシステムのGUI画面を操作して、テストデータを作成する手法
メリット：

1. 一番直感的で、簡単且つシンプル
1. 本当の利用プロセスと同じなので、本番利用と同じ正しさでデータが作れる

デメリット

1. テストデータの作成効率が低い
    - 一回(一連)のGUI操作で、一つ(１セット)のデータしか作れない
    - GUI操作自体が時間かかる

1. ツール化し難い
    - GUI操作でデータを作成しようとすることは、GUI自体への自動化テストケース作成することに相当するので、コストと効率とともに テストデータ作成のいい選択とはいい難い
1. 安定性が低い
    - データ作成する部分のGUI処理の安定性に依存するため、関連ページの微調整でもテストデータ作成の失敗につながる
 
1. 余計な依存関係が生じる
    例： [ログイン機能]をテストテスト対象とする場合：
    そのテストデータの[ログインユーザー]をGUIで作成するために、[登録機能]が問題なく動くことが前提となってしまう
    
以上によって、GUI操作でテストデータ作成することは、止む得ないケースじゃなければ、あんまりいい方法とは言えない

#### API利用しての作成
必要なAPI群を直接コールして、テストデータの作成する手法

メリット：

1. テストデータの作成効率が高い(時間のかかるGUI操作がスキップされたため)
1. ツール化しやすい(APIをラッピングして関数化することは、GUIの方より格段に楽)
1. データ作成する機能の(GUIではなく)APIを依存するので、GUIを依存するより安定性が高い

デメリット：

1. API利用だけで作れないデータがある
1. ケースのよっては、複数のAPIの順次利用や、API間のデータ受け渡しなどが必要になり、複雑な操作が必要な場面が存在する


#### DB操作での作成
直接DBへのCRUD操作によってのテストデータ作成する手法
メリット：

1. 柔軟性が高い
1. この中で、データ作成のスピードが一番高い

デメリット：

1. データ作成用sqlスクリプトの準備・作成コストが高い
1. 整合性の担保が難しい。複数テーブル・操作が必要なうちに、どれか漏れたとしても、すぐに気づかないままのケースがある
1. データ作成の該当する業務ロジックが変えれば、データ作成用sqlスクリプトもそれに合わせてメンテしないといけない


#### API + DB操作での作成
APIの利用とDB直接操作と組み合わせてのデータ作成手法
例： アルバムを作成するAPI `createAlbum` があるんですが、その アルバムの メイン言語を設定する処理が別の複雑なAPIにあるとして、指定したメイン言語のアルバムを作成することが目的の場合:
 `createAlbum`(API利用) + `アルバムのメイン言語を更新するsql文`(DB操作) がいい選択肢かもしれない

#### 纏め
- [GUI操作によっての作成]はシンプルで事前準備も要らず、特に手動テストには向いているでしょう
- [API + DB操作での作成]は、API利用法のメンテしやすいなどのメリットを利用しながら、DB操作法の柔軟性を取り入れたことで、特に自動テストでは一般的に利用していいでしょう


 **この記事は <<[如何准备测试数据？](http://gk.link/a/10WJ8) >> の読書メモ***


また、弊社は現在バックエンドエンドエンジニアを募集しておりますので、**音楽好きな、データ/BizDev領域にも興味がある**という方は是非ご連絡いただければと思います！

https://www.wantedly.com/projects/772400