OmniAICreator/Qiita-1.07M huggingface dataset:
C++関数のエクスポート（dllexport + extern "C" 編）

# 経緯
前は下記記事で関数のエクスポートとインポートについてメモしました。
>[dllexportとdllimportの使い方](https://qiita.com/Pirlo/items/e603efddac6712e0bf8e)

上記記事の内容を用いて、更に関数がどのようにエクスポートされているかを確認したく、色々テストしてみました。

少しレベルアップ感の内容があるので、新しい記事でメモします。

# DUMPBINというツール
visual studioのインストーラに同梱されているEXEファイルです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188794/bb12bab4-4ea7-e588-f0ca-ce924b1b5310.png)
図にあるvisual studioのコマンドプロンプトを起動してから使えます。
EXEやDLLが他のDLLへの依存性などを確認したり、DLL自身の情報を確認したり、色々情報の調査で役に立つツールです。
Googleすれば色々情報があるので詳細な説明を割愛します。

# シンプルな例のDLLのソース
①DLLの外から構造体が渡されると想定
②渡されている構造体の中身を出力
```c++:Hello.h
#pragma once
#include<stdio.h>

#ifdef CPPDLL_EXPORTS
#define DECLSPEC __declspec(dllexport)
#else
#define DECLSPEC __declspec(dllimport)
#endif

typedef struct {
	int id;
	char name[20];
}st_info;

extern "C" {
	DECLSPEC int output(st_info*);
}
```
ここに「extern "C"」を用いて関数を**Cの方式**で出力するよ、ということで、後で説明します。
```c++:Hello.cpp
#include "Hello.h"

int output(st_info* info) {
	printf("id: %d\nname: %s\n", info->id, info->name);
	return 0;
}
```

# DUMPBINでDLLの情報を確認
①Visual StudioのコマンドプロンプトでDLLの場所に移動してDUMPBINを実行
```batch
C:\Users\pirlo\source\repos\CPPDll\Debug>dumpbin /exports CPPDll.dll
```

```batch:実行結果（一部抜粋）
Dump of file CPPDll.dll

File Type: DLL

  Section contains the following exports for CPPDll.dll
.....

    ordinal hint RVA      name

          1    0 000111A4 output = @ILT+415(_output)

  Summary
.....
```
エクスポートされている関数（output）は、以下のように記載されています。
```batch
    ordinal hint RVA      name

          1    0 000111A4 output = @ILT+415(_output)
```
他のEXEやDLLがoutputという関数を使用する時に、一般的に「ordinal」（順番）や「name」（名前）列の値から関数を検索します。
この例では、「1」または「output」が参照されます。

# extern "C"が使用されない場合
エクスポート対象の関数の実名がソースコードだけで確認できませんが、extern "C"を使用しない場合、DUMPBINの結果は以下のようになります。
```batch
    ordinal hint RVA      name

          1    0 0001112C ?output@@YAHPAUst_info@@@Z = @ILT+295(?output@@YAHPAUst_info@@@Z)
```
結局、エクスポートされている関数の名前が、想定の「output」と異なり、「?output@@YAHPAUst_info@@@Z」に変更されました。

何故かというと、C++の仕様です。
C言語では同名の関数の存在はできず、関数名の唯一性がありますが、C++では関数のオーバーロードができるため、同名の関数を区別するためにDLLの作成段階で関数名が勝手に変更されています。
※詳しい情報を割愛します。

確実にソースコードにある関数の名前「output」を使うために、extern "C"を用いて、**コンパイル時にこの関数の名前を変更しないで**、という指示を出します。

# extern "C"が使用されない時に発生する問題
関数名が裏で変更されたので、他のEXEやDLLでこのDLLのソースにある「output」関数を使用しようとしたら、「output」という関数が見つからないよ、というエラーが発生します。

C++のEXEなどでコンパイル時エラーが発生する場合は多いですが、VBやC#などでDllImportで実行時にDLLをインポートしようとしたら「System.EntryPointNotFoundException」という例外が実行時に発生します。

# extern "C"を使用しなくても問題にならない方法
①DLLをC言語としてコンパイル
以下は設定画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188794/53dc71b0-a75e-a229-431a-02f046f448ba.png)
②DEFファイルを使用して関数をエクスポート
下記記事を参考
>[C++関数エクスポート（DEFモジュール定義ファイル編）](https://qiita.com/Pirlo/items/1dce4354827712262531)
Udon# 自分用のメモの公開

# Udonのメモ
自分用メモを公開、引っかかったところでドキュメントにまとまってないものを書く

## Event
全体で実行されるかどうかの扱いに違いがある？ -> ある
対象のEventが発生したらログに出力するようにして、ひとりのプレイヤーが発生させたとき他のプレイヤーでもログが出力されるかどうかで試した。
結果は以下

|Event|結果|
|-|-|
OnPlayerJoined| 全プレイヤーで実行
Interact| インタラクトしたプレイヤーだけ
InputJump| アクションを実行したプレイヤーだけ
OnPickup| アクションを実行したプレイヤーだけ
OnDrop| 実行プレイヤーだけ
OnPlayerRespawn| 実行プレイヤーだけ
OnPlayerLeft| 全プレイヤー
OnPickupUseUp| 実行プレイヤーだけ
OnPickupUseDown| 実行プレイヤーだけ
OnPlayerTriggerEnter| 全プレイヤー

全部は検証してないけど引数でVRCPlayerApiを取るものは全てのプレイヤーで実行されるっぽい。
同期するかどうかやローカルで実行すべきかどうかに影響がある。
OnPlayerTriggerEnterの中でVRCPlayerApi.Immobilizeを呼ぶとエラー起こすのに引っかかった。

## オブジェクトのレイヤー
厳密にはUdonじゃない。
VRCPickUpのコンポーネントを付けるとオブジェクトのレイヤーが変わってOnPlayerTrigger*系に反応しなくなる。

## 同期関連
[VRChatワールドの同期処理まとめ](https://note.com/noritama_vrc/n/nada045c1b053)
ここの項目見るより上のリンク先の方が正しくて分かりやすい、上のEventの項目で書いたローカル実行のみかどうかも参考にするとだいぶやりやすいと思う。
上記の内容も踏まえつつ修正した。

### 実行されている環境の判定
Eventにて書いたとおり`OnPlayerJoined`はjoinしてきたプレイヤーだけでなく全体で実行される。
joinしてきたプレイヤーにだけ特定の処理(例えばjoin時点でのワールドの状態の同期)をしたい場合は、
```C#
// Networking.LocalPlayer.playerIdは現在このコードを実行しているプレイヤー
// playerはjoinしてきたプレイヤー
if (Networking.LocalPlayer.playerId == player.playerId) DoSomething();
```
などで、現在そのコードが実行されている環境を判定する必要がある。

### 全プレイヤーの環境で処理を実行
SendCustomNetworkEventを使えば、全プレイヤーの環境上でメソッドを実行できる。
例えばOpenというメソッドを全プレイヤーに実行させたいのなら以下のようになる。
```C#
SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.All, nameof(Open));
```
メソッドに引数を渡して実行することはできない。
また、後からjoinしたプレイヤーに現在の状態が同期されたりはしない。
例えば、ドアを開ける処理をしたあとにjoinすると、その人は開ける処理を実行しないので閉まったままに見えるみたいなことが起こる。

当然だけど全てのユーザーにはローカルの自分自身も含むので、Openを実行してからSendCustomNetworkEventで全プレイヤーでOpenを呼ぶと自分だけ二重に実行されるので注意。

### 変数同期
変数を同期したいときは`[UdonSynced]`を付ければいい。
```C#
[UdonSynced] private bool _isExecuted = false;
```
こうすると変更は自動的に全ての環境で同期される、ただし同期のタイミングが微妙っぽい？
普通のワールドでスイッチを押したらドアが開くとかそのぐらいなら問題なかった。

変数が同期されたときに実行したいならOnDeserializationが使える？
まだ使ったことがないので調べる:TODO
-> FieldChangeCallbackを使った方がいい

### 同期モード
Sync ModeをManualにしてRequestSerializationを使うとすぐに`[UdonSynced]`を指定した変数の値を同期できる。
Transformが変化しないと同期されないみたいな話もあるのでなぜか値が同期されないときなどに指定してみるといいかもしれない。Sync MethodがManualじゃなくても動作する？

Sync MethodがManualだとObject Syncが付けられないため、位置を同期する場合は必然的にContinuousを使わないといけない。
それか自前で位置同期を実装する必要がある。


## VRCPlayerApi
VRCPlayerApi.Immobilizeをインスタンス化されたオブジェクトが示すプレイヤー以外で実行するとエラーが起きる?
一部の処理はVRCPlayerApiが示すプレイヤーの環境で実行しないとエラーを起こすらしい。
例えばBさんの実行環境で、Aさんの情報を持つ`VRCPlayerAPi A`に対し`A.Immobilize()`を実行すると、Bさんの実行環境だけ例外を出す。

当然といえば当然だけど、Udonだと例外の確認がしにくくて気付きにくかった。
Bの環境だとAがnullになっているわけでもなく、その点についてのドキュメントも特にみつからなかった。
Unityだと普通の実装なのだろうか？
`VRCPlayerApi`のメソッドについても要調査:TODO

### Playerの判定
VRCApiPlayer.playerIdで比較すべき。
インスタンス同士の比較だと正しく判定できないこともあるらしいのと、処理が重い。
IDの比較なら処理が軽いし正しく判定できないことはまずない。

## Udonがアタッチされたコンポーネントの取得
this.gameObjectでアクセスできる。
特定のコンポーネントが欲しいときは
```C#
Animator anim = (Animator)this.gameObject.GetComponent(typeof(Animator));
```
のようにすることでコンポーネントに対応したクラス名で取得ができる。
子のコンポーネントをサーチしたり取得することもできる、この辺のメソッドとかクラスの情報はUnityの公式ドキュメントから得られる。

## オブジェクトの移動など
基本的にアニメーションを作ってAnimation Contorollerでパラメータを変えた方がいい?
なんでかというとUdonで工夫なく動かすと一瞬で移動したり回転するので動いてる感がない、アニメーションを編集する方がコンパイルとか要らないなどの理由から。
続：PostgreSQLをデータごとDockerコンテナ化する

かなり昔にPostgreSQLコンテナをデータごとイメージ化してテストなどで使い回す方法を考えましたが、PostgreSQL公式イメージの Dockerfile を改変して、自分でビルドする必要があり、（最初の1回だけとはいえ）とても手間でした。PostgreSQLのバージョンが古くなるとdocker buildできなくなったり。

https://qiita.com/oohira/items/3252c639dc3ed9a428c9

よくよく考えてみると、PostgreSQLのデータ保存先である `PGDATA` 環境変数に `VOLUME` 指定されたディレクトリ (`/var/lib/postgresql/data`) が指定されているからコンテナ外に永続化されてしまうわけで、

```:Dockerfile
 ...
 ENV PGDATA /var/lib/postgresql/data
 RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 777 "$PGDATA" # this 777 will be replaced by 700 at runtime (allows semi-arbitrary "--user" values)
 VOLUME /var/lib/postgresql/data
```

`PGDATA` にコンテナ内の別ディレクトリを指定してやれば一緒にイメージ化されるのでは、ということに気付きました。

## 解決策（改）

1. `PGDATA` をコンテナ内の適当なディレクトリに変更してPostgreSQL公式イメージからDBを起動

    ```shell
    $ docker run -d --rm -p 5432:5432 --name temp-db \
        -e POSTGRES_PASSWORD=postgres \
        -e PGDATA=/tmp \
        postgres:14.3-alpine
    ```
1. DBにデータを投入する
    * マイグレーションツールで自動構築するなり、SQLを1つずつ実行して手動構築するなりして、DBを望みの状態にする

1. 新しいDockerイメージとしてDBの状態を保存する

    ```shell
    $ docker commit temp-db my-awesome-db:1.0
    $ docker images my-awesome-db
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    my-awesome-db       1.0                 55f54dadb483        5 seconds ago       257MB
    ```

1. イメージ作成用の実行中コンテナを停止する

    ```shell
    $ docker stop temp-db
    ```

1. 作成したDockerイメージから爆速でDBを起動する（必要になるたび）

    ```shell
    $ docker run -d --rm -p 5432:5432 --name=awesome-db my-awesome-db:1.0
    ```

## まとめ

DBのデータ保存先を `VOLUME` 指定されているディレクトリからあえて変えることで、データごと丸っと Docker イメージ化する方法を紹介しました。

これであの社内プロジェクトの任意の過去バージョンのアプリ＆DB起動も爆速のはず！
Rubyでスレッドセーフでないコードを実行するとどうなる？


マルチスレッドでプログラムを実行するとメモリ空間は同じものを使う。では、Rubyにおいて複数スレッドを立てて同じリソースに同時にアクセスするとどうなるのか？

## IOを伴わない場合

Rubyでスレッドの生成は[Thread](https://ruby-doc.org/core-2.5.0/Thread.html#method-c-current)クラスを使う。
以下のコードを実行してみる。
1000個スレッドを立ててそれぞれのスレッドから変数countを書き換える。

```ruby
count = 0
threads = []

# 1000スレッドが同時に変数countにアクセスするとどうなるか？
1000.times do
  threads << Thread.new do
    count +=1
  end
end

threads.each(&:join)
puts count
```

結果は、スレッドセーフではないコードなのに、何度実行しても正常にインクリメントされ結果は`1000`になる。

これは、Ruby（ここではMRIに限る）ではGiant VM lock (GVL)(別名 Global Interpreter Lock(GIL))が実装されているためいくつスレッドを立てようと複数のスレッドが同時に実行されることはないため。

## IOを伴う場合

前の例ではGVLによる排他制御が効いたが、IOを伴う場合はこのロックが解放されるので注意が必要。
> IO 関連のブロックする可能性があるシステムコールを行う場合には GVL を解放します。その場合にはスレッドは同時に実行され得ます。https://docs.ruby-lang.org/ja/latest/class/Thread.html

インクリメントの前に標準出力処理を入れて試してみる。

```ruby
count = 0
threads = []
flag = true

1000.times do
  threads << Thread.new do
    if flag 
      puts 'hoge' #　インクリメントの前に標準出力をはさむ
      count +=1
      flag = false
    end
  end
end

threads.each(&:join)
puts count
```

結果は`1000`だったり`1`だったり`999`だったり、毎回異なる。

IOを伴う処理で、スレッド間で共通のリソース（メモリ・ファイルなど）にアクセスする場合にはスレッド間の競合に注意する必要がある。
なお競合を回避するためには[Mutex](https://docs.ruby-lang.org/ja/2.0.0/class/Mutex.html)クラスが用意されている。

## 参考
* [Rubyでスレッドセーフでないことを簡単に確認したい](https://moyomot.hatenablog.com/entry/2014/05/04/232538)
* [Untangling Ruby Threads](https://thoughtbot.com/blog/untangling-ruby-threads)
【#4  エンジニア転職学習】Linuxファイル操作関連の補足知識

# はじめに
富山県に住んでいるChikaといいます。
毎日投稿を目標に、バックエンドエンジニア転職に向けた学習内容をアウトプットします。

昨日からLinux基礎ということでカーソルキー等を使用せずにカーソル移動、削除等の操作を練習中です。
本日の記事は、**Google検索ですぐ出てくる基本コマンド等を列挙しても面白くないので、
自分なりに「なるほど」と思ったファイル操作周りの補足内容を投稿**したいと思います。

バックエンドエンジニアになるまでの学習内容は昨日投稿した以下の記事を基にしています。


https://qiita.com/Chika110/items/ef54dddd565a0193ef44

# 本日の学習内容
* Linuxファイルとディレクトリ基礎情報
* **Linux　pwd, cd, ls, mkdir, touch, rm/rmdir, cat, less, cp, mvコマンド　←Topic!!**

# Linux基本コマンド（移動,削除,履歴）
昨日に続きLinux基礎ということでファイル/ディレクトリ関連のコマンドについて補足情報等をまとめていきます。

* 引数をつけないcdはホームディレクトリに移動
* 引数を取るオプションの間スペースは省略可（-w 30 = -w30）
* touchは本来ファイルのタイムスタンプを更新するためのコマンド（だから既存ファイルの内容を上書きしたりしない？）
* 先頭が.で始まるファイルは隠しファイルになる
* cp、mvは同一名のファイルが既に存在する場合、確認をせずに上書きしてしまうので対策として-iオプションを利用する

使用している書籍はこちら↓

https://www.amazon.co.jp/%E6%96%B0%E3%81%97%E3%81%84Linux%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E4%B8%89%E5%AE%85-%E8%8B%B1%E6%98%8E-ebook/dp/B072K1NH76/ref=sr_1_1?adgrpid=113196705062&gclid=Cj0KCQjwzLCVBhD3ARIsAPKYTcR4WAb_4QVrwuBM_1mIPMFsQ6kNDJ-o4yIofVSAI7_eHpWCeva8kKwaAstgEALw_wcB&hvadid=489559881279&hvdev=c&hvlocphy=1009363&hvnetw=g&hvqmt=e&hvrand=10125867468998217428&hvtargid=kwd-1152146940662&hydadcr=21814_10996132&jp-ad-ap=0&keywords=%E6%96%B0%E3%81%97%E3%81%84+linux+%E3%81%AE+%E6%95%99%E7%A7%91%E6%9B%B8&qid=1655473534&sr=8-1




# おわりに
最後までお読みいただきありがとうございました。
明日も引き続きLinuxの基本を進めていこうと思います。
アドバイス・応援コメント等いただけますと幸いです。
SpriteAtlas の GetSprite( string ) の戻り値

Unity には SpriteAtlas という大変に便利なモノがある。

そして、ワタクシの従事しているプロジェクトは 2Dアートが沢山ある都合もあり、このSpriteAtlasを多用しているのだけど、SpriteAtlasにはいくつか奇妙な仕様がある。
その代表的なものが **アトラスに含まれているスプライトの名前だけをリストで取得する方法がない** ということだ。

``` C#
List<string> GetSpriteNameList()
```
みたいなメソッドがあれば、サクっとリストだけを取り出せるのだけど、これがない。
だから Sprite [] を返す、GetSprites()で処理するか、それとも最初からわかっている名前で **GetSprite( string name )** でスプライトを取得することになる。
で、GetSpriteを使っていたコードがあったのだけど、ミスでなかったときの対策をしておこうとマニュアルを見に行ったらである…

https://docs.unity3d.com/ja/2018.4/ScriptReference/U2D.SpriteAtlas.GetSprite.html

なーんと、どこにもエラー、すなわちスプライトがなかった時の値を書いていない。
まあ **null** だろうと思うが、テストするまではわからないので、しょうがないからテストしてみた。

**スプライトがないときの戻り値は null**

マニュアルが更新されるまでの（フィードバックはした）つなぎとしてメモ代わりに残しておく。
.gitignoreでフォルダの構造のみを保持したい場合のより良い書き方

例えばWebサイトのバックエンドでアップロードされたファイルを`/storage/`フォルダ内に入れているとする。その場合、Gitではアップロードされた`/storage/`内の各ファイルは無視したいが、`/storage/`フォルダ自体は残しておきたいということがよくある。しかしGitで管理できるのはファイルだけなので、ファイルが一つも入っていないフォルダをGitで表現することはできない。そのために`.gitkeep`というダミーの空ファイルを作成してGitで管理することでフォルダを保持するということが頻繁に行われている。

ここではそのような場面でこれまでよく解説されている`.gitignore`の書き方とは異なる、より柔軟で単純な書き方を発見したので解説する。

# 結論
1. 保持したいフォルダ構造を作成。ここでは`/storage/`フォルダ以下のフォルダ構造をgitで保持したいとする。
1. 各末端のフォルダに空のファイル`.gitkeep`を作成。
1. `.gitignore`に以下を書く。

```:.gitignore
/storage/**
!/storage/**/
!/storage/**/.gitkeep
```

以上。
これで`/storage/`内の各`.gitkeep`は追跡され、それ以外のファイルは無視される。

`/storage/`内のフォルダ構造は任意の構造にできる。例えば以下のような複雑な構造でも問題ない。

```:フォルダ構造
/
└ storage/
  ├ img/
  │ ├ user_icon/
  │ │ ├ file
  │ │ └ .gitkeep
  │ ├ post/
  │ │ ├ file
  │ │ └ .gitkeep
  │ └ file
  ├ pdf/
  │ ├ file
  │ └ .gitkeep
  └ file
```

この場合でも各`file`は全て無視され、かつ各`.gitkeep`は全て追跡対象になる。

この方法でのポイントは`.gitignore`の記述が`/storage/`内の保持したいフォルダ構造に依存しないことである。後で`/storage/`内にサブフォルダが追加されても、サブフォルダの中にさらにサブフォルダができても`.gitignore`はたった3行のまま、編集する必要がない。

よってこの`.gitignore`の書き方は、特にフォルダ構造が複雑になる可能性がある場合に、保守性も可読性も高いと言える。

# 参考: 従来の方法

よく解説されている方法で書いた上記の場合の`.gitignore`は以下である。

```:.gitignore
/storage/*
!/storage/img/
/storage/img/*
!/storage/img/user_icon/
/storage/img/user_icon/*
!/storage/img/user_icon/.gitkeep
!/storage/img/post/
/storage/img/post/*
!/storage/img/post/.gitkeep
!/storage/pdf/
/storage/pdf/*
!/storage/pdf/.gitkeep
```

とても長いしフォルダ構造を変えた場合`.gitignore`も変更しなければならない。

なんでこんなに長くなってしまうのかは各所で解説されてるので説明しないが、とにかくこうやって全てのサブフォルダの名前を`.gitignore`の中に書く必要がある方法しか出てこなかった（私が調べた限り）。
# 実行環境情報

UbuntuとmacOS両方で挙動を確認した。

## Ubuntu
```console
$ git --version
git version 2.17.1
$ head -n2 /etc/os-release
NAME="Ubuntu"
VERSION="18.04.4 LTS (Bionic Beaver)"
```

## macOS
```console
$ git --version
git version 2.30.1 (Apple Git-130)
$ sw_vers
ProductName:	macOS
ProductVersion:	11.4
BuildVersion:	20F71
```
6.10 (難) 十分統計量3，推定量の評価3

## 方針

(2)について．順序統計量が関係するので，X_(1),...,X_(n)の同時分布を導出し，UやTに変数変換する．
Tの分布を求めるときに確率密度関数を出したくなってしまうが，Tの構成要素である確率変数らは定義域が違うためうまくいかない．そこで積率母関数によって分布を求める．

## 答案

![6. 2周目-21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/1966751b-5fe3-b4a9-dddd-97ed02238606.jpeg)
![6. 2周目-22.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/a86470f5-285d-3cd1-cb65-9970dbcdcf35.jpeg)
![6. 2周目-23.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/c10e9dec-c76f-3bc9-82be-ef6dd5adaf66.jpeg)
![6. 2周目-24.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/95303f53-9cc7-f3b2-a058-98261489f670.jpeg)
![6. 2周目-25.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/c29f5013-84b8-54a2-a98d-41e87b1bfc0f.jpeg)

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
Pythonを用いて母比率の信頼区間を求める 〜ナンパの成功確率〜

# はじめに
Pythonを用いて、母比率の信頼区間を求めます。

# 設定
R君は通算1000回のナンパ経験があり、そのうち230回成功しているとします。
その場合のナンパ成功の母比率を求めます。

# 統計学の知識
- 母比率の区間推定に関する知識
[21-1. 母比率の信頼区間の求め方1 | 統計学の時間 | 統計WEB](https://bellcurve.jp/statistics/course/9122.html)


# scipyを使う場合
## コード
```python:main.py
"""ナンパの成功確率を推定する"""
import math
from typing import Dict

from scipy.stats import binomtest


if __name__ == "__main__":
    # ナンパ回数
    num_of_hitting_on = 1000
    # ナンパの成功回数
    num_of_success = 230

    result = binomtest(num_of_success, num_of_hitting_on)
    low_population_ration = math.floor(result.proportion_ci().low * 100)
    high_population_ration = math.floor(result.proportion_ci().high * 100)
    print("ナンパの成功確率は{}％以上{}％未満です。".format(low_population_ration, high_population_ration))

```

## 結果
```
ナンパの成功確率は20％以上25％未満です。
```

# scipyを使わない場合
## コード 
```python:main.py
"""ナンパの成功確率を推定する"""
import math
from typing import Dict

def estimate_populaton_proportion(sample_proportion: float, trial_num: int) -> Dict[int, int]:
    """標本比率と試行回数から母比率を推定する。

    Args:
        sample_proportion (float): 標本比率
        trial_num (int): 試行回数

    Returns:
        dict: 信頼区間95%にて、最大・最小の母比率を%で返す。
    """
    low_population_proportion = math.floor((sample_proportion - \
                                1.96 * math.sqrt(sample_proportion * (1 - sample_proportion) / trial_num)) * 100)
    high_population_proportion = math.floor((sample_proportion + \
                                1.96 * math.sqrt(sample_proportion * (1 - sample_proportion) / trial_num)) * 100)
    population_ratio = {"low": low_population_proportion, "high": high_population_proportion}
    return population_ratio


if __name__ == "__main__":
    # ナンパ回数
    num_of_hitting_on = 1000
    # ナンパの成功回数
    num_of_success = 230
    # ナンパの成功確率（母比率）
    success_proportion_of_hitting_on = num_of_success / num_of_hitting_on

    hitting_on_population_ration = estimate_populaton_proportion(sample_proportion=success_proportion_of_hitting_on, trial_num=num_of_hitting_on)
    print("ナンパの成功確率は{}％以上{}％未満です。".format(hitting_on_population_ration["low"], hitting_on_population_ration["high"]))
```
## 結果
```
ナンパの成功確率は20％以上25％未満です。
```
# 考察
1000回ものナンパ経験のあるR君ですが、それでも推定の結果に5%も幅が出てしまいました。R君にはもっとナンパを頑張ってもらいたいものです。

# おわりに
３本目の記事になりました。コメントなど頂けますと幸いです。
ご覧いただき、ありがとうございました！
1OS授業解説: C言語入門

# はじめに
この記事は, 同じ学科の1年生向けに書かれたものです.
掲載されているコードなどは, 2022年度の授業スライドに基づいています.

※3年生になった筆者が, 記事を順に修正しております.
※4年生になりました.

# リンク集
OS1年 第5・6回

https://qiita.com/tusoscocoa/private/22f98a345857c8b8160b

OS1年 第7・8回

https://qiita.com/tusoscocoa/private/94c7acee6b75c48c4c31

OS1年 第9・10回

https://qiita.com/tusoscocoa/private/bb6ae725cbbe3e4d48bb

OS1年 第11・12回(前編)

https://qiita.com/tusoscocoa/private/85f022d3e10e1d25f9e4

OS1年 第11・12回(後編)

https://qiita.com/tusoscocoa/private/c51e7ea7ca756e56fe99

OS1年 第13・14 / 15・16回

https://qiita.com/tusoscocoa/private/607939f1980d5abea423

OS1年 第17・18回

https://qiita.com/tusoscocoa/private/0f8711c0f2f8b487e468

OS1年 第19・20回

https://qiita.com/tusoscocoa/private/4cc581e289d2970973b4

OS1年 第21・22回

https://qiita.com/tusoscocoa/private/4161cca2771f297f9ca6

OS1年 第23・24回(行列編)

https://qiita.com/tusoscocoa/private/5eda4de6eedb333c6f12

OS1年 第23・24回（配列・バブルソート編）

https://qiita.com/tusoscocoa/private/ed4d230ab316e0187026

OS1年　前期末前の総集編

https://qiita.com/tusoscocoa/private/e5281f97647612a79e4d
ngrxインストール時にFix the upstream dependency conflict, or retry...エラー

# 環境
Angular13 ngrx13

# エラーメッセージ
Fix the upstream dependency conflict, or retry
this command with --force, or --legacy-peer-deps
to accept an incorrect (and potentially broken) dependency resolution.

# 解決法
まずは下記のコマンド
```
npm config set legacy-peer-deps true
```

その後、ngrxの公式に準拠した下記コマンド実行
```
ng add @ngrx/store@latest --minimal false
```
Oracleでコミットしてしまう前のデータを参照したい

OracleにはフラッシュバッククエリというUNDOの領域があります。
それがあるおかげで、Oracleでは間違ってINSERT、DELETE、UPDATEをしたときに更新前の情報をさかのぼることができます。

その機能について今回は記載していこうと思います。

ただ、**この機能自体は「使えたらラッキー」程度に考えておいた方がいいと思います**（経験談）。

## どんな機能か？
トランザクションを利用したSQLを発行する場合、UNDO領域にその情報を保存します。
それを利用して、過去のデータをさかのぼってみることができる機能です。

イメージとしては、Oracleで行っている一時バックアップのような感覚です。

## どんな時に利用するのか？
・バッチで更新されたDBの更新前の状況をみたい…など。
・DELETEしてCOMMITしたが、消すデータを間違えていた、など。

### 本当ならこんな機能を使うことになる前に…
フラッシュバッククエリも保存期間があるため、ログ情報やCOMMITする前にデータのバックアップをとるなど
使わなくてもいいような運用にしておくことが大事です。

## どんな構文で使うのか
以下のようなSQLで使用できます。
```
-- 30分前を見たい場合
select * from hoge
as of timestamp (systimestamp - interval '30' minute ) 列別名;
WHERE 列別名.検索条件
```

intervalの指定は下記のとおりです。
|  指定する単語  |  意味  |
| ---- | ---- |
|  minute  |  分  |
|  hour  |  時間  |
|  day  |  日  |

また、日付を指定して実行することも可能です。
```
-- 2022/06/18　21：00時点のデータを見たい場合
select * from hoge
as of timestamp to_timestamp('2022-06-18 21:00:00', 'yyyy-mm-dd hh:mi:ss') 列別名;
WHERE 列別名.検索条件
```

## どこまでの期間をさかのぼることができるか？
テーブル内にあるデータ量によります。
また、他のSQL処理でトランザクションを利用した場合、UNDOの情報が上書きされてしまうこともあります。

したがって、確実にこの期間までさかのぼれる…というのは言えないかと思われます。
個人的には1日経ったらほぼ不可能、半日経っていても厳しめのイメージです。

### もしさかのぼれない時はどんなエラーが出るのか？
以下のようなエラーが出ます。
```
ORA-01555: スナップショットが古すぎます: ロールバック・セグメント番号 xxx、名前"yyy"が小さすぎます
```

## TRUNCATEした場合はできないのか？
**できません。あきらめましょう。**
Chromiumとブラウザチェック

## Chromiumとは
Chromiumはオープンソースのwebブラウザです。
日本のブラウザシェア50%以上のChromeは、Chromiumに機能追加する形で作成されています。

- プロジェクトのサイト
  - https://www.chromium.org/chromium-projects/
- ソースコード
  - https://chromium.googlesource.com/chromium/src

2022年6月現在Chromeに次いでシェアが高いのはSafari、Microsoft Edge、Firefoxですが、Microsoft EdgeもChromiumをベースに作成されています。
(シェアの高いブラウザはhttps://gs.statcounter.com/browser-market-share/all/japan/ で確認できます。)

## ブラウザチェックについて
すべてのブラウザを網羅して検証することは困難なため、シェアが高いブラウザをサポートブラウザとして指定しそのブラウザで動作確認するのが一般的かと思います。
また、基本的にブラウザは自動でバージョンがアップデートされるため、Weblioでは最新バージョンを[推奨環境としています](https://help.weblio.jp/ejje/wordbook/w_faq/w_f_service/h0040)。

## Chromiumがベースになっているブラウザであれば、ブラウザごとの動作確認は不要？
細かい差異は生じるため、万全を期すにはブラウザチェックは必要になります。
https://developer.mozilla.org/ja/ や https://caniuse.com/ などのサイトでブラウザ間の互換性を確認するのが良いでしょう。

ブラウザの種類やバージョン以外にも、デバイスやOSの違いによって固有の差異が発生する場合もあります。
効率よく確認するために、自動化ツールやサービスを使うのも良いでしょう。
ブラウザ　Braveのすゝめ

Braveに関する他の記事で余り目にしなかった事や個人的に気づいた点をささっと書きます。
※Braveの仮想通貨の機能 「Brave rewards」は一切試しておりません。
※Qiitaで書く内容では無いかもしれませんが、少しでも気になる方がおられましたら幸いです。

この記事を一言で言うと、
### Braveを使い、ここ2年くらい広告を見ていない。場所を問わずオフラインでyoutubeを見ている。
と言う事です。

## この記事が参考になる方
- よくYouTubeを視聴し、毎回広告をスキップする事にストレスを感じているがYouTubeプレミアムにお金を払いたくは無い方
- 毎月の動画視聴量を減らすか、毎月のデータ通信量とその通信費を減らすかお悩み中の方
---


## 拡張機能


Chromeをお使いの方が大半の中、Braveを使うにあたり気になるのが拡張機能。

:::note info
Chromeの拡張機能も引き継げます。(※全て使えるかは不明)
:::

![9DC5E2F8-2B18-44D8-9A2E-E9D02F90A44D.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2705418/417bbade-036a-33d4-3f54-10e7974283e7.jpeg)
(↑Onetabも使えている)

## Cookie
また、Cookie関連の記事がありますが、

:::note info
毎回パスワードを入力してログインして楽天などのサイトに入っているのかと言われると、そんなバカなことはない。
:::

と、なっております。

## Youtube



私は2年前にChromeからBraveに乗り換え、Youtubeもアプリからではなく、ブラウザから観ております。

Braveではデフォルトで広告が表示されない。
つまり５秒間待って広告をスキップする必要もない。
度々現れるバナーによって字幕やテロップが見えなくてイラッとする事も、そのバナーの小さい [x] を押して消す必要もない。
広告が無い分高速。

ということが、YouTubeプレミアムに入って月額料金を支払わずとも可能です。


:::note info
BraveのPlaylistに動画を入れると、オフラインで動画視聴可能。YouTubeプレミアム入会する動機が薄まる。
:::



Playlistは　神アプリ[kingbox](https://kingbox.jp/news/termination.html)の代わりになる機能かもしれません。
[トルミル](https://tolmil.com/)で動画視聴するほうがBraveのPlaylistより快適かとは思いますが、トルミルで動画を保存する際に広告動画を観る必要があります。
スマホのデータ使用量を抑えたい方はトルミルと使い分けると快適なのではないでしょうか。
(因みにYouTube上で削除された動画もKingboxやトルミルでは引き続き視聴できますが、BraveのPlaylistで視聴できるかどうかは確認できておりません。)

(Playlistへの追加はリロードボタンの横の紫色を押すだけ↓）
![795FC6BA-B64D-47EB-B9F9-D42B2033C817_1_201_a.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2705418/8c249fee-cbf9-c373-0c89-57b896517c57.jpeg)

:::note warn
ただ、Playlistは不安定。リストに追加したはずが再生できない事もある。
:::

:::note warn
PlaylistはのiPhoneとiPadの、iOS13以上で動作します。つまりPCでは使えない。
:::

## Braveにないもの
- リーダーモード・読書モード機能　(現時点で)
- Webキャプチャ機能　　　　　　　(現時点で)
- カンペキなUI/UX 　　　　　　　　(現時点で)
- 広告収入を得るインフルエンサーの方々などからの推薦 (これからも)

:::note warn
表示崩れが起こることがあります。
:::
Linux(Ubuntu)でのeduroamへの接続 芝浦工業大学編

## Linux(Ubuntu)でのeduroamへの接続 芝浦工業大学編
芝浦工業大学でのeduroam接続設定がなかったので備忘録的に。
Windows等でも同じように設定することで、eduroamを導入している他大学のWi-Fiに接続できるようになります。

|        設定項目名| 設定                | 
| -------------- | -------------------------------------- | 
| セキュリティ| WPA&WPA2 Enterprise     | 
| 認証 | 保護付きEAP(PEAP)            | 
| CA証明書       | なし             | 
| PEAPバージョン | 自動 (おそらく1？)         | 
| 内部認証       | MSCHAPv2            | 
| ユーザー名     | 学番(小文字)@eduroam.shibaura-it.ac.jp | 
| パスワード     | AMIで設定したeduroamのパスワード       | 

![hVT-7Zrxa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449776/550fe01c-2054-7f8a-9298-12cf9975f1dd.png)

### ポイント
ユーザー名の後ろに```@eduroam.shibaura-it.ac.jp```を付けることによって認証サーバーと正常に通信できるようになります。
WindowsやiOS、Androidなどでもユーザー名を同じように設定することで、他大学のeduroamへも自動接続してくれるようになります。
edroamは教育機関での相互利用可能なWi-Fi通信サービスで、国際的な基盤であり日本でも多くの大学が取り入れているため、導入しておくといいことがあるかもしれません。
ArduinoUNOと温度センサーMCP9701で温度をシリアル出力2(map文,使用)


x MCP9701-E/TO 販売コード 103199

x ADC値から電圧の変換は、親切な人(@fujitanozomu)がいたので改造して使用

目的
安価に温度を測る。

秋月で売っている安いやつ

1℃　→　19.5mV　ステップ

0℃　→　400mV　センター

0V → -20.512820512820512820512820512821℃
0.4V → 0℃
3.3V →　148.71794871794871794871794871794‬℃
5V　→　235.89743589743589743589743589744℃

数学的　計算式 sは、ADC値　Vは、電圧 tは、温度

```

v = s * (5.0/1024.0)
t = v * (1.0 / 0.0195)  - (0.4 * (1.0 / 0.0195)) )


```
その2

```

v = s * (5.0/1024.0);

t = (v - 0.4) * (1.0 / 0.0195) 

```


![o_con542.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/b7543dd0-4478-a0c4-1ab8-3e3d904976fd.jpeg)




![o_con541.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/f6a4eb10-431d-7ddf-2ec6-c4d00a34cd45.jpeg)



デバッグ時


![o_con540.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/5faf65f6-5ab8-a49a-0882-219675fcb721.jpeg)




```c++


//SER_MCP9701_MAP_UNO_1

#include <Arduino.h>

//初期化処理
void setup()
{

  Serial.begin(9600);

} //setup

//メインループ
void loop()
{

  //センサーの値を読み込む
  int s = analogRead(A0); // UNO

  //s = 82;   //debug
  //s = 1024; //debug
  //Serial.print("Debug Voltage[");
  //Serial.print( ( (unsigned int)0b100111 * (unsigned int)s + (s >> 4 ) ) >> 3);
  //Serial.println("]");

  //センサーのADC値を温度に変換
  int t = map(s, 0, 1024, -205, 2359);

  //温度の小数点以上の表示
  Serial.print(t / 10);

  //小数点の表示
  Serial.print('.');

  //温度の小数点以下の表示
  Serial.println(t % 10);

  //1秒の待ち
  delay(1000);

} //loop



```

3.3系の変換

```

  //センサーのADC値を温度に変換
  int t = map(s, 0, 1024, -205, 1487);

```



標準C言語で温度を求める式(浮動小数点)


```c++




#include <stdio.h>
int main(void){


float s = 0;
float v = 0;

for(int ii=1020;ii<1025;ii++){



printf("%d=",ii);

s = ii;
v = s * (5.0/1024.0);

printf("[%f]",v);
printf("(%f)\r\n",v * (1.0 / 0.0195)  - (0.4 * (1.0 / 0.0195)) );

}//for
    
}



```
Dynamics365  get OptionSet　label  

Hi ,

You can use FormattedValues to retrieve the label try with below code .

string optionSetText= entity.FormattedValues["FieldName"];
In addition also try to call below method and pass required parameter , you will get the label using metadata.

        private string GetOptionsSetTextForValue(IOrganizationService service, string entityName, string attributeName, int selectedValue)
        {

            RetrieveAttributeRequest retrieveAttributeRequest = new
            RetrieveAttributeRequest
            {
                EntityLogicalName = entityName,
                LogicalName = attributeName,
                RetrieveAsIfPublished = true
            };
            // Execute the request.
            RetrieveAttributeResponse retrieveAttributeResponse = (RetrieveAttributeResponse)service.Execute(retrieveAttributeRequest);
            // Access the retrieved attribute.
            Microsoft.Xrm.Sdk.Metadata.PicklistAttributeMetadata retrievedPicklistAttributeMetadata = (Microsoft.Xrm.Sdk.Metadata.PicklistAttributeMetadata)
            retrieveAttributeResponse.AttributeMetadata;// Get the current options list for the retrieved attribute.
            OptionMetadata[] optionList = retrievedPicklistAttributeMetadata.OptionSet.Options.ToArray();
            string selectedOptionLabel = null;
            foreach (OptionMetadata oMD in optionList)
            {
                if (oMD.Value == selectedValue)
                {
                    selectedOptionLabel = oMD.Label.LocalizedLabels[0].Label.ToString();
                    break;
                }
            }
            return selectedOptionLabel;
        }
venvのpython仮想環境をgitで共有する


# ポイント
* venv環境の共有は`requirments.txt`を使う
    * これでライブラリの共有ができる
    * 各自構築したvenv環境内で共有されたライブラリをpipする
* `curl -o .gitignore`でインストールしてきたファイルの名前を指定する
    * 名前を指定せずにインストールするとgitが`.gitignore`ファイルを認識してくれない
        * `.gitignore`というファイル名でないと、gitが認識してくれない


```terminal: terminal
mkdir test
cd test
mkdir a.git
cd a.git
git init --bare
cd ..
git clone a.git
cd a
curl -o .gitignore https://raw.githubusercontent.com/github/gitignore/main/Global/VirtualEnv.gitignore

python3 -m venv .venv
source .venv/bin/activate
pip install pip-autoremove matplotlib
pip freeze > requirements.txt
deactivate
git add -A 
git commit -m "initial commit"
git push

cd ..
mkdir b
cd b
git clone ../a.git
cd a

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
deactivate
cd ../../../

```


# 参考サイト
1. https://akogare-se.hatenablog.com/entry/2019/01/02/220330
2. https://www.lisz-works.com/entry/git-venv
【Express】ESM方式でimportするときにルーターを使う方法

# なぜESM方式を使ってるのか
ESM Moduleを使おうとしてpackage.jsonに`"type": "module"`とやっているとrequireが使えないので

# やり方
まずは普通にimportでやる
```javascript:index.js
import hoge from "./hoge.js";

app.use("/hoge", hoge);
```

お次に`hoge.js`を書いていく
```javascript:hoge.js
import express from "express";
var router = express.Router(); //ルーターを生成

router.get("/puyo", function(req, res){
//なんかの処理
})

export default router;
```


完成
Kotlin 今どきよくある JSON リクエストからのパース

 
数年で一気に変わってます、JSONの取り扱い処理。

Gson も Moshi も不要です。

```kotlin
@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
  val contentType = "application/json".toMediaType()
  val json = Json { 
    ignoreUnknownKeys = true
    isLenient = true
  } // *
  return Retrofit.Builder()
    .client(okHttpClient)
    .baseUrl(BASE_URL)
    .addConverterFactory(json.asConverterFactory(contentType))
    .build()
}
```


Kotlin 内蔵の serialization を使うのが良いでしょう。

[👉 Kotlin 今どきよくある JSON リクエストからのパース](https://android.benigumo.com/20220618/kotlin-json-retrofit/)
JavaのSocketでプロキシを使う

# はじめに
今時のプロキシはConnectすると生データがそのまま通せるので、普通のSocketでもプロキシが使える。

# プロキシサーバの設定
とりあえず普通に指定する場合、Proxyのコンストラクタでアドレスを指定すれば良い。

```java
Proxy px = null;
try {
    InetSocketAddress px_addr = new InetSocketAddress("プロキシサーバのアドレス", 3128);
    px = new Proxy(Proxy.Type.HTTP, px_addr);
}
catch (Exception e) {
    // エラー処理
}
```

# Socket生成
SocketのコンストラクタでProxyが指定できるようになっている。作ったら普通にconnectすれば良い。

```java
Socket sock = null;
try {
    sock = new Socket(px);
    InetSocketAddress con_addr = new InetSocketAddress("接続したいサーバのアドレス", ポート番号);
    sock.connect(con_addr);
}
catch (Exception e) {
    // エラー処理
}
```

# SSLSocketで使いたい場合
SSLSocketFactory の createSocket で元になるSocketが指定できる。なので、上で生成したSocketを使って以下のようにすれば良い。

```java
SSLSocket ssl_sock = null;
try {
    SSLContext ctx = SSLContext.getDefault();
    SSLSocketFactory factory = ctx.getSocketFactory();
    // 最後の false は　autoClose
    ssl_sock = (SSLSocket)factory.createSocket(con_sock, "接続したいサーバのアドレス", ポート番号, false);
    // やらなくてもいいはずだけど、一応
    ssl_sock.startHandshake();
}
catch (Exception e) {
    // エラー処理
}
```

# 認証が必要なプロキシ
java.net.Authenticator を使うと認証の処理をしてくれる。まずは Authenticator を継承したクラスが必要。
一番簡単なのはこんな感じ。
ユーザ名・パスワードを外から入れられるようにすれば使える。

```java
class TestAuthenticator extends Authenticator
{
    @Override
    protected PasswordAuthentication getPasswordAuthentication()
    {
        return new PasswordAuthentication("ユーザ名", "パスワード".toCharArray());
    }
}
```

この Authenticator を使うように設定するには、Authenticator.setDefault() しておく。
プログラムの最初にこんなのを入れる感じ。

```java
Authenticator.setDefault(new TestAuthenticator());
```

また、Java標準設定だと、httpでBasic認証してくれない。プロキシサーバがBasic認証の場合に対応するなら、最初に以下のコードを入れておく。
禁止する認証方式を空に設定している。

```java
System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
```

# OSに設定されているプロキシサーバの取得
ProxySelector.getDefault() を使う。
Java標準設定ではOFFになっているので、まずは以下のようにしてONに設定する。

```java
System.setProperty("java.net.useSystemProxies", "true");
```

そうすると ProxySelector.getDefault() で、OS設定の ProxySelector が取得できる。
そこから Proxy の取得までは以下のようになる。複数取得できるが、大抵は1つだと思うので、最初のものを使っている。
OSの設定を取るだけなら、ローカルアドレスとかでなければ大体どこでも同じプロキシサーバを使うので、アクセスしたいURLも適当で大丈夫。

```java
Proxy px = null;
try {
    ProxySelector ps = ProxySelector.getDefault();
    List<Proxy> px_list = ps.select(new URI("アクセスしたいURL"));
    if (!px_list.isEmpty()) {
        px = px_list.get(0);
    }
}
catch (Exception e) {
    // エラー処理
}
```
CmdStanPyがColab上でも動いてほしい

# やったこと

- 参考文献1.を参考に`GoogleColaboratory`上で`CmdStanPy`の動作確認をしました。

- やった結果のノートブックを以下のリポジトリにアップロードしました。

  - https://github.com/yaminabeworks/cmdstanpy_colab_test/blob/main/stan2cmdstanpy.ipynb

# なぜやったか

- `PyStan`と同じように、`CmdStanPy`も`GoogleColaboratory`上で動くとよいと感じたため。

  - 本記事のテスト結果から、手元に環境がなくても`Stan`ファイルを作って`GoogleColaboratory`上で試せるはずです。

# 参考文献

1.は、`CmdStanPy`環境を`Docker`で構築しているサイトで大変参考になりました。ありがとうございました。

2.は、自分の書いたマジックコマンドの`writefile`を利用した記事となっています。

1. https://qiita.com/amber_kshz/items/172e88e5feda1e7e3133

2. https://qiita.com/yaminabeworks/items/d63620e36aae50eaa290

# 次にやりたいこと

インターネットには`rstan`で書かれた素晴らしい記事が多いので、`PyStan`や`CmdStanPy`に移植した結果をまとめていきたいです。
6.9 (標準) 推定量の評価2 不偏性

## 方針

不偏推定量の定義は6.4参照


## 答案

![6. 2周目-19.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/8b120ad4-4467-d54d-8cfe-06feee4b3240.jpeg)
![6. 2周目-20.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/d724cda2-1e0e-c297-2868-cc6352314f73.jpeg)


## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
「今日のお買得品は何？」にお答えするVoiceflowを作成しました

## 「声かけ」の習慣が無くなった、と大先輩が仰りました
こんにちは、近畿の地場スーパーに勤めて10年、来るべきデジタル時代に向けて、少しスキルを磨きたい、と日々努力を続けているものです。今回はとある会話から「[Voiceflow](https://www.voiceflow.com/)」作成に至る経緯と、結果を書き連ねていきます。

今年1年かけて社内研修会に参加しておりまして、お題は「2030年に生き残る企業になる為に」という、壮大且つ雲をつかむようなお話なのですが、参加メンバーも多種多様な面々で、私のチームには大ベテランの先輩店長がいらっしゃいます。テーマがテーマなので、どうしても議論が「DX」「デジタル化」に進みがちですが、大先輩は<strong>「こんな時代だからこそ人と人のふれあい」</strong>を仰ります。
「具体的には？」と質問したところ、真っ先に「お客さまと従業員のコミュニケーションが無くなった、コロナ過では『声かけ』すらも自粛、昔は『声かけ』が接客の基本の「キ」と徹底されていたのに。」と。
<strong>「『今日は何が安いの？』『今日のおススメはこちらですね』」とチラシ片手にお客さまと交わしていた会話も、デジタルチラシ化がどんどん進んで、それすら無くなった、本当にそれで良いのかね・・・」</strong>
確か、全てを「コロナ過」で済ます訳にはいきませんが、「接客」の習慣が無くなりつつあるのは、私のような本社勤務の人間にも聞こえてくる課題です。求人しても「接客」を嫌がってか、人も集まらず、応対する従業員の数も減っていく現状。大先輩の為に、「人を集めてきます！」とも言えず、ここは一つ、<strong>「デジタル」を使って、せめて、「接客」っぽいものを作成していこう</strong>と思います。


## Voiceflowとは
[Voiceflow](https://www.voiceflow.com/)とはノンコーディングで、Amazon AlexaやGoogle Assistant用の音声アプリを作成できるサービスです。[Voiceflow](https://www.voiceflow.com/)は直接的なインターフェースなので、会話的なプログラムを作成する際にもってこいです。

https://hikari-sedori.com/voiceflow/

今回は店頭に設置したツールに話掛ける事で、<strong>「今日のお買得品」を答えてくれる「デジタル丁稚」</strong>をイメージして作成しようと思います。

## 案ずるより産むが易し、早速作っていきましょう！！

### 今回使用するツール

[Voiceflow](https://www.voiceflow.com/)　今回はこれのみです。

### ログイン

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2668078/fb853505-402d-7fcd-8ff5-6e0d1e6175f2.png)

[Voiceflow](https://www.voiceflow.com/)を使用するにはログインが必要です。が、Googleアカウントがあれば、簡単にログイン出来て、アカウント作成も不要ですので、今回は私のGoogleアカウントでログインします。

### 基本画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2668078/c804a8d4-61c9-e0f0-7481-63b6dfcc7f7e.png)
左側にずらりと並んでいるのが「ノード(機能の固まり)」です。この「ノード」を右側の何もない「パレット」にどんどん配置して「フロー(flow：流れ)」を作成していきます。

今回はフローのスタートを「Alexa」に設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2668078/050719b5-f0e3-019a-0123-c04cb6eebfd6.png)

では、まずはVoiceflowの第1声、「本日のお買得品」を設定し、コネクタで繋ぎます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2668078/d5836a78-df4a-e0d7-1cbc-5243f274def9.png)

今回はテストモデルとして<strong>「野菜」「果実」「鮮魚」「干物」「牛肉」「豚肉」「鶏肉」「フライ」「寿司」「弁当」<strong>を準備し,それぞれの「お買得品」を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2668078/d9e9e645-998f-c7e0-04fd-08e4d2710174.png)
右上の「再生ボタン」をクリックすると、話掛けてきますので、設定した「野菜」等を答えると、それぞれの「お買得品」を教えてくれる、という簡単な仕組みです。

## 完成品
https://twitter.com/KohyoTamashiro/status/1538107482052390912

非常にシンプルですが、簡単に音声認識出来るフローが完成しました！！店頭には「お探しですか？」に対する「答え方(野菜etc)」を記したペーパーを貼っておいて、利用して頂くイメージです。

## 最後に
今回も「シンプル」且つ「お手軽に」作成する事を目標に、モデルを作成しました。が、この「[Voiceflow](https://www.voiceflow.com/)」、なかなかに奥が深い、と実感しました。極めていくと、<strong>人間代わりになんでも答えてくれる「デジタルサービスカウンター」</strong>にまで発展するのでは？と思っています。これは勉強のし甲斐があるというもの。なかなか楽しい勉強が出来ました。

本日も最後までご一読頂き、ありがとうございます。これからも色々なツールにチャレンジしますので、宜しくお願い致します。
confluenceでよく使うショートカットキー一覧

confluenceはよくメモに使います。
人に、技術情報や運用ルールなどの共有をするために、自分でもよく書くし、他の人にもすぐに共有できて楽なのが利点です。

ということで、毎日触るアトラシアンのconfluenceのショートカットキー一覧。
ちなみに、現状macで作業することが多いので、macでの一覧を記載します。
自分がショートカット多用するので、ついでにピン留めしときます。

# 編集してない時のショートカットキー
| キー | 意味 |
| -- | -- |
|[|サイドバーを閉じる・開く|

# 編集中のショートカットキー
| キー | 意味 |
| -- | -- |
| e | 編集 |
|cmd + s|保存（反映）|
|cmd + 0|段落文字|
|cmd + 1|見出し１|
|shift + cmd + b | 箇条書き|
|shift + cmd + n|番号付き箇条書き|
|cmd + 8|引用符|
|cmd + u | 下線|
|cmd + b | 太文字|
|//|カレンダー|
|shift + {|マクロの呼び出しショートカット|
|cmd + k|リンクの挿入|
|cmd + m|画像の挿入|
|alt + ↑|上に行追加|
|alt + ↓|下に行追加|

# Markダウンの呼び出し
| キー | 意味 |
| -- | -- |
| ``` | コード |
| ---- | 水平線 |

# 何気に便利なマクロ呼び出し
マクロ呼び出しはとっても便利。shift + { でマクロのウィンドウを呼び出さずに直接入力できる。検索ワードは下記。
| キー | 意味 |
| -- | -- |
| toc | 目次 |
| jira | jiraチケット |
| child | 子ページ表示 |
| include | ページを含める |
| warning | 警告 |
| info | 情報 |
| note | 注意 |
| tip | ヒント |
| panel | パネル |
| 展開 | 展開 |
JavaScriptの学習ログ

# 学習教材
udemyで[「ウェブ開発入門完全攻略コース - HTML/CSS/JavaScript. プログラミングをはじめて学び創れる人へ！」](https://www.udemy.com/course/web-application-development/)を学習。
ウェブ開発全般の基本的な知識が習得できるコースで合計24.5時間もある。
今回はその中でもJavaScriptについて学習した。
[<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2674841/6e448b63-dace-5900-335b-dfbb64d52531.png
">](https://www.udemy.com/course/web-application-development/)

# 学習範囲
## JavaScript入門
JavaScriptの演算や条件分岐、繰り返し処理・配列を理解した。
## JavaScriptのDOM操作
JavaScriptの演習を通じて学習した。
ここはやや難しく感じたので、理解度はあまり高くなかった。
## JavaScriptイベントとイベントハンドラ
イベントを利用して学習した。
使いこなせれば、便利な機能だと感じた。

# 学習を終えて
JavaScriptの基本的な内容を学習したが、浅い学習範囲だった。
ポートフォリオ作成の際は、より深く学習していきたいと感じた。
Solid.js の使い方 (TypeScript)

こちらを参考にしました。
[Solid を試す](https://www.solidjs.com/guides/getting-started)
[SolidJSに入門してみた](https://dev.classmethod.jp/articles/solidjs-tutorial/)

プロジェクトの作成と起動

```bash
npx degit solidjs/templates/ts ts01
cd ts01
npm i
npm run dev
```

プログラムの改造

```tsx:src/App.tsx
import type { Component } from 'solid-js';

import { SampleCounter } from './SampleCounter';

const App: Component = () => {
  return (
    <SampleCounter />
  );
};

export default App;
```

次のプログラムは新規に作成

```tsx:src/SampleCounter.tsx
import type { Component } from 'solid-js';

import { SampleCounter } from './SampleCounter';

const App: Component = () => {
  return (
    <SampleCounter />
  );
};

export default App;
```

ブラウザーで、http://localhost:3000/　にアクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/537c164a-e7e1-0668-42a0-93e21f5c86b2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/5abd1613-6c37-dc6d-c3f2-5f3da553d216.png)
Nuxt.js・Vuetify・Contentfulで作ったサイトのページスピードを改善するためにやったこと

過去にNuxt.js・Vuetify・Contentful・Netlifyで作ったサイトがあり、ページスピードを改善する為にやったことをまとめます。
使用したライブラリ等もご紹介しています。

## ページスピード（表示速度）の改善前
ページスピード改善前の数値は下記の通り。
[Google PageSpeed Insights](https://pagespeed.web.dev/)で測定しています。

![before1sp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/109c7314-ffc3-f5ad-71a1-6b84e3afcb74.png)

![before1pc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/ce46e9cd-c141-04ee-fb95-64c46f9b145c.png)

![before1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/4355b4d0-1b92-e5d9-9a36-88a9267ae912.png)
特にモバイルが悪いので改善したいところです。

## Webフォントを周りを見直す
Vuetifyのデフォルトのフォント設定をやめて`@nuxtjs/google-fonts`・`@mdi/js`を使用することにしました。

### @nuxtjs/google-fontを導入
[@nuxtjs/google-fonts](https://github.com/nuxt-community/google-fonts-module)には、GoogleFontsをダウンロードして利用できるオプションがあるので導入することにしました。

```
npm install --save-dev @nuxtjs/google-fonts
# OR 
yarn add --dev @nuxtjs/google-fonts 
```

```js:nuxt.config.js
export default {
  buildModules: [
    '@nuxtjs/google-fonts'
  ],
  vuetify: {
    defaultAssets: {
      font: false,
    }
  },
  googleFonts: {
    families: {
      Roboto: [100, 400, 500, 700],
      download: true,
      inject: true
    }
  },
}
```
Vuetifyのデフォルトのフォント設定をfalseにして、`@nuxtjs/google-font`でフォントの設定をしています。
`@nuxtjs/google-font`については、下記の記事でも解説しています。

https://qiita.com/TK-C/items/4a50d0dba3fa7a084eb1


### @mdi/jsを導入
マテリアルデザインアイコンを`@mdi/font`から`@mdi/js`に変更して、必要なアイコンのみを利用するようにしました。

```
npm install @mdi/js
# OR
yarn add @mdi/js
```

```js:nuxt.config.js
export default {
  vuetify: {
    defaultAssets: {
      font: false,
      icons: 'mdiSvg'
    }
  }
}
```
```vue
<template>
  <v-icon>{{ mdiEmail }}</v-icon>
</template>

<script lang="ts">
import Vue from 'vue'
import { mdiEmail } from '@mdi/js'

export default Vue.extend({
  data() {
    return {
      mdiEmail
    }
  }
})
</script>
```
上記のように、マテリアルデザインアイコンを必要に応じてimportする形です。

https://www.npmjs.com/package/@mdi/js

## 画像の最適化
画像の最適化については[@nuxt/image](https://github.com/nuxt/image)を使っておこないました。

### @nuxt/imageの導入
```
npm install -D @nuxt/image
# OR
yarn add --dev @nuxt/image
```

```nuxt.config.js
export default {
  modules: [
    '@nuxt/image',
  ]
}
```

```vue
<template>
  <nuxt-img
    src="/photo.jpg"
    width="400"
    height="200"
    loading="lazy"
    :alt="image"
  />
</template>
```
`@nuxt/image`については、下記の記事でも解説しています。

https://qiita.com/TK-C/items/b0337483f44cb928308d


## ページスピード（表示速度）の改善結果

![nuxt-after-sp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/f43e6c83-e9e6-6a53-e540-cc79de67802b.png)
![nuxt-after-pc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/f63c1383-c4f1-18cc-bbec-f3f0874fdde4.png)

まだまだMedium（黄色）ですが、改善前と比べたら結構良くなったかと思います。
画像の最適化をした時にかなり変化がありました。

CLS(Cumulative Layout Shift)がまだ悪い状態です。VuetifyのCSSが重いようでGridのレイアウトが崩れてしまうのが原因かなと思います。
ゆくゆくはCLSの改善もしていきたいところです。
スーパーブロック とは

## 勉強前イメージ

linuxのなにかのある区画のこと指してる？

## 調査

### スーパーブロック とは

ファイルシステムの論理パーティションを管理するためのメタデータです。
要するに、ファイルシステムのタイプや作成日、レイアウトや空き領域の情報などが含まれている重要なデータです。。

Linuxはそもそも一つのファイルシステムだけではなく、
いろいろな種類のファイルシステムを扱うことが出来ます。
そのため、ファイルシステムの種別ごとに管理するデータが必要になります。

ファイルシステムの作成時にいくつかの必ず管理しないといけないデータ用のブロックは確保しておいて
それをブロックグループとしてまとめて管理を行います。
その中の一つにスーパーブロックが含まれており
他にもグループ内の情報や [inode](https://qiita.com/miyuki_samitani/items/376efd3e6d400054fb31) テーブルなどあります。
また、ブロックグループはシステムの破損に備えて複製も含まれています。

## 勉強後イメージ

ファイルシステムの重要なデータを置いてあるとこって感じかな？
これって複製もあるって言ってるけど同じところに複製あったら一緒に壊れない？
実は違う区画だったりするのかな・・・
今度調べてみよう

## 参考

- [10. ファイルシステム](https://linuxjf.osdn.jp/JFdocs/The-Linux-Kernel-10.html)
- [仮想ファイルシステムのありがたみを知ろう ＝ ファイルシステム種別とスーパーブロックについて ＝](https://monoist.itmedia.co.jp/mn/articles/1009/01/news108_2.html)
時系列データ解析でよく使うsliding windowをつくってみた。

# はじめに

配列を一定幅で切り出して分割する、いわゆるsliding windowは時系列データなどを扱うときに何かと便利です。[ピリオドグラム](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.periodogram.html#scipy.signal.periodogram)や[ウェルチのパワースペクトル](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.welch.html#scipy.signal.welch)、[短時間フーリエ変換](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.stft.html)などよく使われているのですが、see alsoに分割するときに用いる関数が載っていない。

ということで調べてそれっぽい引数で作ってみることにしました。といっても[`numpy.lib.stride_tricks.sliding_window_view`](https://numpy.org/devdocs/reference/generated/numpy.lib.stride_tricks.sliding_window_view.html)を用いれば苦労なく完成ですね。つまりは備忘録です。


# コード
```python
from numpy.lib.stride_tricks import sliding_window_view

def divide_by_sliding_window(a, nperseg=256, noverlap=None):
    if noverlap == None:
        noverlap = nperseg // 2
    nstep = nperseg - noverlap
    return sliding_window_view(a, nperseg)[::nstep]
```

引数は`scipy`の関数に倣いました。
Laravel sail のテスト用DBの設定方法

## 概要
Laravel sail での開発環境で、PHPUnitをテスト用DBで実行するための手順を記載する。
(自分の備忘録用の記事になります)

## 前提

- Docker実行環境が整っていること
- Laravelの実行環境が整っていること
- Mysqlが使用できる環境であること

## 環境
- php 8.1.4
- Laravel 8.83.16
- Mysql 8.0.28

## 手順

1. Laravel, sailをインストールする。
    
    ```bash
    $ composer create-project laravel/laravel:^8.0 sail-test
    $ cd sail-test
    $ composer require laravel/sail --dev
    $ php artisan sail:install
    
     Which services would you like to install? [mysql]:
      [0] mysql
      [1] pgsql
      [2] mariadb
      [3] redis
      [4] memcached
      [5] meilisearch
      [6] minio
      [7] mailhog
      [8] selenium
     > 0,7
    
    Sail scaffolding installed successfully.
    ```
2. aliasを登録します。
    
    ```bash
    alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail'
    ```
    
3. 各コンテナを起動させる。
    
    ```bash
    $ sail up -d
    ```
    
4. sail コマンドでsanctum、breezeをインストールする。
   (Breezeをインストールすると、Breezeに関するDBを使用したテストも用意できるのでBreezeをインストールしてます。）
    
    ```bash
    $ sail composer require laravel/breeze --dev
    $ sail artisan breeze:install
    ```
    
5. .env.testingファイルを作成すること
    ```bash
    $ cp .env.example .env.testing
    ```

6. `.env.testing`ファイルの中身を修正する
    
    ```bash
    DB_CONNECTION=mysql
    DB_HOST=mysql // docker-compose.ymlのmysqlのホスト名にする
    DB_PORT=3306
    DB_DATABASE=testing // test用のテーブルを記載
    DB_USERNAME=sail // 修正箇所
    DB_PASSWORD=password　// 修正箇所
    ```
    
    <details><summary>デフォルトのMysqlのテーブル(sail ユーザでログインした場合)</summary>
        以下のコマンドでmysqlに接続する。
        
        
        mysql -h 127.0.0.1 -u sail -P 3306 -p
        
        mysql> show databases;
        +--------------------+
        | Database           |
        +--------------------+
        | information_schema |
        | laravel            |
        | testing            |
        +--------------------+
        3 rows in set (0.01 sec)
        
     </details>
        
7. testing用のAPP_KEYを生成する。
    
    ```bash
    $ sail artisan key:generate --env=testing
    ```
    
8. 環境変数をクリアする。
    ```bash
    $ sail artisan config:clear
    ```

## 結果
これでテスト用DBを使用して`sail test`を実行できるようになりました! 

    
    $ sail test
    
    <省略>
    
    PASS  Tests\Feature\ExampleTest
      ✓ example
    
      Tests:  17 passed
      Time:   2.51s
AWS CodeStar メモ

## AWS Code Starとは？

* 統合されたI/FでAWS CI/CDサービスチェーンを構築、運用できるAWSサービス

* CodeCommit (リポジトリ）からCodeBuild(ビルド）、CodeDeploy(デプロイ）をCodePipelineでシームレスに繋げることができる。

![codestar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/2053a917-26a4-1294-d3a2-65ad0e46e6ff.png)

## 特徴

* 豊富なプロジェクトテンプレート
  * 選択テンプレートからCI/CD環境が自動で構築される
* プロジェクトダッシュボード
  * リポジトリやパイプライン、開発ツール（IDE）との連携設定を行う
* パイプラインの自動生成
  * Source,Build,Deployがステージとして構築される
* 開発ツールとの連携
  * CLI,Eclipse,VSCode,Cloud9,CodeCommitと連携

## 利点

* **スムーズにAWS開発をスタートできる**
  * アプリケーションコードのコーディング、ビルド、テスト、デプロイに使用する開発およびCI/CDサービスチェーン全体を簡単に設定できる。
  * プロジェクト開始時には、Amazon EC2、AWS Lambda、およびAWS Elastic Beanstalkに対応するさまざまな AWS CodeStar テンプレートの中から選ぶことが可能。
  * プロジェクトのソース管理として AWS CodeCommitもしくはGitHub の使用を選択できる。
  * AWS Cloud9、Microsoft Visual Studio、Eclipse などのオプションを使用してソースコードを編集することもできる。
* **ソフトウェアデリバリーを 1 箇所で管理できる**
  * AWS CodeStar のプロジェクトダッシュボードにより、1 箇所からアプリケーションアクティビティを監視し、コードのコミット、ビルド、テスト、デプロイなどのソフトウェア開発プロセスの全段階にわたって進行状況を追跡できる。
  * サードパーティーの問題追跡およびプロジェクト管理ツールAtlassian JIRA Softwareが統合されているため、JIRA の問題を AWS CodeStar のダッシュボードで直接管理できる。
* **チーム全体でセキュアに作業できる**
  * プロジェクトの所有者、コントリビューター、ビューワーのアクセスを管理し、サービスごとに独自のポリシーを手動で設定する必要がない。
  * AWS IAMのベストプラクティスに準拠するロールベースのポリシーが組み込まれているため、開発チームのプロジェクトへのアクセス権を設定するプロセスを簡略化できる。
* **さまざまなプロジェクトテンプレートを利用できる**
  * プロジェクトテンプレートには、Java、JavaScript、PHP、Ruby、C#、Python などのプログラミング言語でプロジェクトを開始するためのコードが用意され、ウェブサイト、ウェブアプリケーション、ウェブサービス、Alexa スキルなどの様々なアプリケーション開発に利用できる。

## 大まかな設定の流れ

1. プロジェクト作成
   * テンプレート選択
   * プロジェクト名、リポジトリ情報入力
2. チームメンバー追加
   * IAMユーザーから追加、表示名、メールアドレス、ロールを設定
3. プロジェクト編集
   * Code Pipeline,Cloudwatchメトリクス



## 利用料金

* CodeStarでプロビジョニングされたAWSリソース(EC2インスタンス、Lambda実行など)に対してのみ発生。

## 参考情報

* [AWS CodeStar](https://aws.amazon.com/jp/codestar/)
* [20201111 AWS Black Belt Online Seminar AWS CodeStar & AWS CodePipeline](https://www.slideshare.net/AmazonWebServicesJapan/20201111-aws-black-belt-online-seminar-aws-codestar-aws-codepipeline)
暗号化ライブラリTinkをPythonで使ってみる

# Tinkとは
Google製の暗号化ライブラリです。GitHubのリポジトリは[こちら](https://github.com/google/tink)。
JavaやC++など、いくつかの言語に対応していますが、今回はPythonを使ってみました。

# Tinkのインストール
Pythonの場合、`pip`を使ってインストールできます。
```
pip3 install tink
```

# サンプルコード
暗号化と復号化を行う、簡単なサンプルコードを作成してみました。
```python
#!/usr/bin/env python

import tink
from tink import aead

plaintext = b'your data...'
associated_data = b'context'

# 1.機能の初期化処理。目的の機能をregisterメソッドで有効化します。
aead.register()

# 2.鍵のテンプレートを使って、キーセットを生成
key_template = aead.aead_key_templates.AES256_GCM
keyset_handle = tink.new_keyset_handle(key_template)

# 3.プリミティブの生成。このプリミティブのI/Fを介して、暗号化操作を実行します。
aead_primitive = keyset_handle.primitive(aead.Aead)

# 4.暗号化操作。引数はバイト型で指定します。
ciphertext = aead_primitive.encrypt(plaintext, associated_data)
print(ciphertext)

# 5. 復号化操作
plain = aead_primitive.decrypt(ciphertext, associated_data)
print(plain)
```
log出力させる最短ルート

1．lombokインストーラーダウンロード

2．sts（eclipse）をインストーラーと同じディレクトリへ？

3．sts（eclipse）を指定して、lombokインストール
（versionの関係でビルドエラーの可能性あり）

4．pom.xmlに以下を追加

<dependency>
		 <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
        </dependency>

5．maven→プロジェクトの更新

6．classに@slf4jつける

7．log.info() 等が使えるようになる。
vscodeでテストする（fsharp)

ちょっとはまったのでメモ

# Sumary

2022.06.18(sat)現在、標準のvscodeにてfsharpのコードをテストできるが、テスト項目をモジュールで区切れない

## 結論

namespace を指定してモジュールで区切る

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149269/3efaad45-5b55-f4c4-6758-463f71f8deda.png)


# 現場からは以上です