OmniAICreator/Qiita-1.07M huggingface dataset:
[Python]pipであるはずのバージョンのライブラリがインストールできない(Could not find a version)

WindowsでPython環境を構築していたときのこと。
以前構築できていた環境を再現するだけなので問題ないと思っていた、インストールできるはずのライブラリのバージョンが見つからないとエラーがでた。

~~~
＃例
$ pip install tensorflow==1.14.0
ERROR: Could not find a version that satisfies the requirement 
~~~
のような形。


調べた結果単純な間違いがあったため備忘録として以下に実施したことを記す。

### 実施したこと
pipのアップグレード

~~~
$ pip install -U pip
~~~
なにはともあれアップグレードはやってみるべし思ったので実施したが変わらずライブラリは...

~~~
ERROR: Could not find a version that satisfies the requirement 
~~~
と言われてしまう。


さらに調べた結果どうやらインストールしているPythonが怪しいらしい。
というのも確認してみたところインストールしているPythonが32bit版のものをインストールしていた。

ただしくは64bit版をインストールしなければいけないらしい。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440646/4441e6ed-9607-4a17-608e-3a3751d84c19.png)
これはPython.orgでのダウンロードファイル一覧だが、「Windows x86-64 ~~~」を利用しなければいけないところを誤って「Windows x86 ~~~」を利用してPythonをインストールしていたようだ。

pipのアップグレードで解決しない場合は利用しているPythonを一度確認してみると良いかもしれないい。
【Laravel・PHP】preg_match(): Unknown modifier '�' のエラー

## 状況
正規表現を用いて、文字の検索をかけたいのでpreg_matchを使ったところタイトルのエラーが発生。
## コード

```php
$target = '/' . $request->name . '/';
$names = $collection->filter(function($value) use ($target){
   return preg_match($value['name'], $target);
});
```
## 原因
preg_matchの第一引数と第二引数を逆に記述したことによるエラー。
本来は第一引数に正規表現、第二引数に元データを記述しなくてはならない。

```php
return preg_match($target, $value['name']);
```
とっても単純なエラーでした。
【Golang】ポインタ型の int 変数に値をセットする

ここ 1 年で作成・更新された記事を[「"golang" ポインタに値をセットする int」でググって](https://www.google.com/search?q=%22golang%22+%E3%83%9D%E3%82%A4%E3%83%B3%E3%82%BF%E3%81%AB%E5%80%A4%E3%82%92%E3%82%BB%E3%83%83%E3%83%88%E3%81%99%E3%82%8B+int&tbs=qdr:y)も、わかりやすいタイトルがヒットしなかったので、自分のググラビリティとして。

## TL; DR <sub><sup><sub><sup>（今北産業）</sup></sub></sup></sub>

```go:変数の前に*を付ける
func resetToTen(i *int) {
	*i = 10 // <- ここ
}
```
```go:動くサンプル
package main

import "fmt"

func main() {
	i := 100

	resetToTen(&i)

	fmt.Println(i)
}

func resetToTen(i *int) {
	*i = 10
}
// Output: 10
```
- [オンラインで動作をみる](https://go.dev/play/p/vlQgqqLtcMR) @ Go Playground

## 参考文献

- [Go で関数に渡したポインタの値を変更するには](https://qiita.com/m_green14/items/1efe3f887aee082ba4ef) @ Qiita
  - 「`&` や `*` をどうつけたらいいか、よくわからなくなってしまいがち」な人は必読。
貴方の頸椎を守り隊！！～カメラで様子をチラ見中。居眠りも起こしてくれるよ。～ #画像認識 #猫背予防

#姿勢が悪すぎる
在宅勤務が中心になってから、オフィス用の机や椅子で仕事をする事がなくなり、仕事中の姿勢がかなり悪くなり、腰痛やら肩こり首のバキバキ感がレベルアップしています。
「姿勢が悪いよ！」と指摘してくれる人もいなく、ストレートネックへ一直線状態なので、少しでもいい姿勢に戻れるようなツールを作成しました！

その名も

**貴方の頸椎を守り隊**

頸椎を守るついでに、居眠りが始まったら起こしてくれるオプションもセットとなっています。

#守り隊紹介
仕事中に使用する想定のため、非アクティブ画面となるのでデザインはとてもシンプルです。

https://twitter.com/momoiku3/status/1463377988116877312

**★こちらで試せます★**
カメラが認識後、10秒ごとに判定しています。

https://trusting-shaw-9cf17b.netlify.app/

①猫背状態（首が前に出ている）
　→ポコンと音が鳴ります。
②居眠り（下向き）
　→爆発します:boom:
③居眠り（上向き）
　→爆発します:boom:


#仕様
・JavaScript 
・HTML
・Teachable Machine
・ml5.js
・Bootstrap

#Teachable Machineでの設定
カメラ映像を判定する方法として「Teachable Machine」を使用しました。
Webカメラでサンプル画像を撮るだけで、自動でカメラに写っている映像を判定してくれる優れモノです。

**①サンプル画像の作成**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122228/5641e784-8222-d167-6d93-a74798aafff8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122228/8cf8c581-1b99-7590-4c2e-66db7b3bf8d5.png)

**②トレーニング**
トレーニングボタンを押すだけで、自動で学習してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122228/259a1e7d-36f6-b57c-1f7b-bfa5c8228d9f.png)

**③結果確認**
トレーニング結果はすぐに確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122228/e48b02f6-5dd7-59b4-44dd-a867a57fa1fc.png)



#プログラム

<p class="codepen" data-height="300" data-default-tab="html" data-slug-hash="qBXzOay" data-user="ishikawaikumi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ishikawaikumi/pen/qBXzOay">
  姿勢チェック‗公開</a> by IshikawaIkumi (<a href="https://codepen.io/ishikawaikumi">@ishikawaikumi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

###音源の設定
こちらの音源を使用しました。

https://soundeffect-lab.info/

音源はダウンロードして使用する必要があるため、ダウンロード後に個人のGitHubにファイルをアップロードし、使用しました。
＜参考資料＞
①GitHubへファイルをアップロード

https://www.i-ryo.com/entry/2018/11/28/221938

②アップロードしたファイルの使用方法

https://ytyaru.hatenablog.com/entry/2018/08/20/000000


#守り隊の状況
現在の居眠り判定は高い精度になっていますが、猫背判定が服や髪型等で判定がぶれる事があるため、調整が難しい部分となっています。
判定がブレてきたな、と思ったら、その時の服や髪型でパターンを追加したいと思います。

#参考
https://qiita.com/twtjudy1128/items/4c29a98a035a6e8cbcb4
Rails ロールバックの手順

#はじめに
自分の学びのアウトプットのため、こちらの記事を参考にさせていただきながら書きました。
[【Rails】$rails db:rollbackしたい時の間違えない手順](https://qiita.com/s_tatsuki/items/3e1f119c91e21b8f0c33)

#手順
###1.マイグレートのバージョンを確認
```shell:コンソール
$ rails db:version
Current version: 20211119053634
```

###2.ロールバックを実行
```shell:コンソール
#一つ前のバージョンに戻す
$ rails db:rollback
```

```shell:コンソール
#指定したバージョンまでなかったことにする
$ rails db:rollback　STEP=◯◯○◯◯○◯◯○
```

###3.migrateされる前の状態に戻っているか確認
```shell:コンソール
$ rails db:abort_if_pending_migrations
You have 1 pending migrations:
  20211119020307 AddAutoScalingSupportedToWebServers
  20211119053634 AddWebServersComment

```

###4.マイグレーションファイルを修正

###5.migrateを実行
IntersectionObserverについて

覚えたこと

この辺は定型分

```javascript

const io = new IntersectionObserver(function(entries) {
    entries.forEach(entry => {
    })
})


document.querySelectorAll('.item').forEach(item => {
    io.observe(item);
})

```




オプションつけたり、画面に入ったらクラスつけたりするならこんな感じで

```javascript

const options = {
        root: null,
        rootMargin: "-100px 0px 0px 0px",
        threshold:0
}
const io = new IntersectionObserver(function(entries) {
        entries.forEach(entry => {
            if(entry.isIntersecting){
                entry.target.classList.add('inview');
            }else {
                entry.target.classListremove('inview')
            }
        })
}, options);

```




ちょっと関係ないけど
スクロールに合わせてナビにクラス付けるならこんな感じ

```javascript

entries.forEach(entry => {
       if(entry.isIntersecting){
           const id = entry.target.getAttribute('id')
           document.querySelector(`nav li a[href="#${id}"]`).parentElemnt.classList.add('act');
       }
})

```


ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
参考


https://ics.media/entry/190902/
youtubeサーチChrome拡張プラグイン


# 概要
[site]:https://tecoyan.blogspot.com/#btn_cntrl
[youtube]:https://www.youtube.com/watch?v=aUYJZqZOX2s&t=1326s
[store]:https://chrome.google.com/webstore/detail/yy%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%83%97%E3%83%A9%E3%82%B9/edooldmlaabbmllldenkkceddlbbeing?hl=ja



この「[yyプラグインプラス][store]」とは、[youtubeサイト][youtube]の動画検索を利用して最大100件程の動画を独自のリスト形式で取得します。
リスト形式は独自形式のため、専用のプレーヤーで再生します。
そのプレーヤーは[「なつかしの曲(ポータル)」][site]サイトにあります。
プラグインは、[Chromeウェブストア][store]で公開しています。

# プラグインの必要性
通常は、youtube Data APIを使用して動画の検索を行い再生リストを作りますが、この場合だと、一日当たりのクォータ量に制限があり、それをオーバするとAPIを使用できなくなります。その制約を回避するには、直接、[youtube][youtube]へサーチリクエストを送り、動画の検索を行うことになります。
この[拡張プラグイン][store]はこの方法で自動的にほぼ100件の再生リストを作成します。
# 専用プレーヤ
この再生リストで再生するWebサイトが[「なつかしの曲(ポータル)」][site]です。

# サーチの仕方
[「なつかしの曲(ポータル)」][site]サイトで再生リストを作成するには、クェリー入力してサーチボタンをクリックします。

# このプラグインの動作の仕組みについて
Chrome拡張機能の作り方は省略します。ここでは、このプラグインの特長について記述します。
(1)タブの連携について
二つのタブ間で連携して動作します。
一つは[「なつかしの曲(ポータル)」][site]サイトのタブで、もう一つは、[「youtubeサイト」][youtube]のタブです。先に、「なつかしの曲(ポータル)」ページでクエリー入力して、サーチボタンをクリックします。すると、別タブで[「youtube」][youtube]ページが開き、検索が始まります。この時、自動的にスクロールし、検索数が徐々に上がってきます。その状況は、上部のクェリー欄にステータスとして表示されます。約100件に達すると、検索結果が、親タブへ通知され、親ページのリスト覧に今の検索結果が表示されます。
その後にリストの先頭から自動再生が開始されます。
以上の連携動作は拡張プラグインのcontent.jsとbackground.js間で行われます。
# 動作の仕組み詳細
この拡張プラグインは、次の二つのサイトと連携して動作します。「なつかしの曲(ポータル)」サイトと「youtubeサーチ」サイトです。
動作の仕組みを以下の図に示します。
![なつかしの曲(ポータル).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198006/2be88802-3092-985d-d98f-36d0223d6a5c.png)
順序
(1)タブA(なつかしの曲(ポータル))からタブB(youtubeサーチ)へサーチリクエストを送信します。
(2)タブB(Youtubeサーチ)では、リクエストのクェリーを基に検索を開始します。検索はマウスホィールを下げながら約100件まで繰り返します。この繰り返しはスクリプトで自動化しています。100件に達したら独自形式の再生リストを生成します。専用サーバーに保存後、background.jsへリストを送信します。
(3)background.jsからタブA(なつかしの曲(ポータル))のcontent.jsへリスト(検索結果)を送信します。ふたつのcontent.jsはひとつのファイルです。内部で処理を分けています。
(4)content.jsからタブAのリスト要素にリストデータを格納します。
(5)タブAでリストの先頭から動画の情報を取得し、プレーヤーで自動再生します。
以上がこの拡張プラグインの動作の仕組みです。
# あとがき
このプラグインで約100件程の再生リストが10数秒で作れます。
作成したリストは専用のサーバーに保存されます。そのリストをサーバーから取り出して再生することもできます。
再生については[「なつかしの曲(ポータル)」][site]ページに簡単に実行できますので、よろしかったら試してみてください。
【Laravel】多次元配列のデータにキーワード検索をかける方法

## 背景
キーワード検索でcontroller側でDBにアクセスしてデータを取得する処理はよく行われるが
今回は既に出来上がった多次元配列の変数にキーワード検索を行い、View側に返す処理を実行します。
## 処理概要
View側で部署検索フォームに文字を入れた際に部分検索で該当するデータを返すようにします。
## 処理内容
preg_matchとCollectionクラスのfilterメソッドを使用します。
【多次元配列のデータ】

```php
$departments = [
   ['name' => '佐藤', 'department' => '営業部'],
   ['name' => '鈴木', 'department' => '総務部'],
   ['name' => '田中', 'department' => '人事部'],
];
```
処理。検索キーワードは`$request->department`に入ってる事とします。

```php
$collection = collect($departments);
$target = '/' . $request->department . '/';
$filtered = $collection->filter(function($value) use ($target){
    return preg_match($target, $value['department']);
});

return view("***", compact('filtered'));
```
filterなどの無名関数を引数に取るメソッドは、外部から変数を渡す際にuseが必要になります。
例えばView側から`営業`という文字列が送信されてきた場合
`['name' => '佐藤', 'department' => '営業部'],`
のデータを返す処理となります。
Anacondaでjupyter notebookを使っていてgraphvizのPathが通らない時の解決法のメモ

#状況
Anacondaでjupyter notebookを使っていてgraphvizのPathが通らないので、ググりながら全部試したがやっぱりだめ。


#解決方法：下記であっさりできました
まず、pipでインストールしてしまっていたgraphvizおよびpydotplusを削除。
anaconda navigatorから、grapgviz、python-graphviz、pydotplusを入れる。(全部必要だったのかはよくわからない。)

色々、数日間試しましたがこれであっさりいけたので忘れないうちにメモでした。
WASのプロファイル作成（DMからNAまで）

前回からの続
https://qiita.com/XKYUXSOX/items/c15cc1bebe00b85cd2e0

今回の構成
1号機（DM、NA、アプリケーションサーバ、IHS）
2号機（NA、アプリケーションサーバ、IHS）

前提準備
WASのインストールは終わっていること
hosts登録を終わっていこと
yyd01
yyd02

WASのDMプロファイルを作成する。

```
cd /opt/IBM/WebSphere/AppServer/bin
./manageprofiles.sh -create \
 -isDefault \
 -templatePath /opt/IBM/WebSphere/AppServer/profileTemplates/management \
 -serverType DEPLOYMENT_MANAGER \
 -profileName Dmgr01 \
 -profilePath /opt/IBM/WebSphere/AppServer/profiles/Dmgr01 \
 -hostname yyd1 \
 -cellName yyd1Cell01 \
 -nodeName yyd1CellManager01 \
 -enableAdminSecurity true \
 -personalCertValidityPeriod 15 \
 -adminUserName wasadmin \
 -adminPassword wasadmin \
 -validatePorts true

INSTCONFSUCCESS: 成功: プロファイル Dmgr01 が存在します。 このプロファイルに関する詳細については、/opt/IBM/WebSphere/AppServer/profiles/Dmgr01/logs/AboutThisProfile.txt を参照してください。
```
DMの起動

```
/opt/IBM/WebSphere/AppServer/profiles/Dmgr01/bin/startManager.sh
ADMU0116I: ツール情報は次のファイルに記録されています:
           /opt/IBM/WebSphere/AppServer/profiles/Dmgr01/logs/dmgr/startServer.log
ADMU0128I: Dmgr01 プロファイルを使用してツールを開始しています
ADMU3100I: サーバーの構成を読み取ります: dmgr
ADMU3200I: サーバーが起動しました。 開始処理中です。
ADMU3000I: サーバー dmgr は e-business に対してオープンな状態です。プロセス ID は 11126 です。
```

NAのプロファイル作成 1号機

```
 cd /opt/IBM/WebSphere/AppServer/bin
 ./manageprofiles.sh \
>  -create \
>  -templatePath /opt/IBM/WebSphere/AppServer/profileTemplates/managed \
>  -profileName Custom01 \
>  -profilePath /opt/IBM/WebSphere/AppServer/profiles/Custom01 \
>  -hostname yyd1 \
>  -nodeName yyd1Node01 \
>  -dmgrHost yyd1 \
>  -dmgrPort 8879 \
>  -dmgrAdminUserName wasadmin \
>  -dmgrAdminPassword wasadmin \
>  -federateLater false \
>  -validatePorts true
INSTCONFSUCCESS: 成功: プロファイル Custom01 が存在します。 このプロファイルに関する詳細については、/opt/IBM/WebSphere/AppServer/profiles/Custom01/logs/AboutThisProfile.txt を参照してください。
```
※今回、自動でNAを追加（-federateLater false）しているので、NAは追加したタイミングで起動します。

管理コンソールにログインして
システム管理→ノードで追加されていることを確認する。
システム管理→ノードエージェントでノードエージェントが追加されていることを確認する。


NAのプロファイル作成 2号機

```
cd /opt/IBM/WebSphere/AppServer/bin
 ./manageprofiles.sh \
 -create \
 -templatePath /opt/IBM/WebSphere/AppServer/profileTemplates/managed \
 -profileName Custom01 \
 -profilePath /opt/IBM/WebSphere/AppServer/profiles/Custom01 \
 -hostname yyd2 \
 -nodeName yyd2Node01 \
 -dmgrHost yyd1 \
 -dmgrPort 8879 \
 -dmgrAdminUserName wasadmin \
 -dmgrAdminPassword wasadmin \
 -federateLater false \
 -validatePorts true
```

管理コンソールにログインして
システム管理→ノードで追加されていることを確認する。
システム管理→ノードエージェントでノードエージェントが追加されていることを確認する。
DataVerse検索を利用時、優先テーブル指定方法

DataVerse検索（関連性検索）の対象テーブルが多い場合、以下のような優先検索対象テーブルを指定して、該当テーブルの検索結果の先頭に表示可能
■指定なしの場合
![MicrosoftTeams-image (16).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/b1cc2619-15fc-32c4-68c1-29a5642ee5c6.png)

■指定ありの場合
![MicrosoftTeams-image (17).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/275e9f34-8880-279b-d432-acea8d8f257a.png)

DataVerse検索のより詳しい検索方法は以下を参考してください。
https://docs.microsoft.com/ja-jp/powerapps/user/relevance-search
Gtk3アプリGtk.ListStoreを使ってコントロールを更新する

###Gtk3アプリGtk.ListStoreを使ってコントロールを更新する

Gtk.ListStoreを使いコントロールの更新を行います。
不特定の関数を作るのではなく、ListStoreのイベントハンドリングでまとめて更新をするとわかりやすくなります。


<img width="350" alt="Screenshot from 2021-11-24 14-34-48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182324/eef89fab-3164-1477-1da8-e7551b88f93f.png">


```cs
private Gtk.ListStore listStore1 = new Gtk.ListStore (typeof (testModel));

private void on_btn1_clicked(object sender , EventArgs e){

    testModel testModel1 = new testModel();
    testModel1.Name = "タイトル１";
    testModel1.Description = "詳細1";
    listStore1.Clear();
    listStore1.AppendValues (testModel1);
		
}

private void _mkBining()
{
    listStore1.RowChanged += delegate(object o, RowChangedArgs args)
    {
        ListStore testStore = ((ListStore)o);
        TreeIter iter;
        if (testStore.GetIter(out iter, args.Path))
        {
            testModel testModel1 = (testModel)testStore.GetValue(iter, 0);
            Console.WriteLine("testModel1" + testModel1.icon_id  );
            titleEntry.Text = testModel1.Name;
            descriptionEntry.Text = testModel1.Description;
        }
    };
}
```

ListStoreのRowChangedメソッドを使い、ListStoreが更新されたら他のコントロールを更新するようにします。

```cs
listStore1.RowChanged += delegate(object o, RowChangedArgs args)
{
	ListStore testStore = ((ListStore)o);
	TreeIter iter;
	if (testStore.GetIter(out iter, args.Path))
	{
 	   testModel testModel1 = (testModel)testStore.GetValue(iter, 0);
	}
};
```

[Gtk3アプリ RiderとMySqlとDapper](https://qiita.com/iota_11/items/fa0d5ea82abd34fe5f69)に続く
XrmToolBox:Related Records Analyzer

Dynamics365/PowerAppsモデル駆動アプリで、データ削除の場合、依存エラーで削除できない場合の調査は、以下のツールを利用してまとめて確認することが可能です。RelationのCascade設定をまとめて確認する場合も便利。
![MicrosoftTeams-image (15).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/5023193b-3e38-65a3-d193-d83e07b88ca1.png)
Android Studioで Android端末のAPI分布図を確認する方法

Androidアプリをリリースするときに、どのくらいのアプリのバージョンを基準にしたら良いか、悩むことはありませんか？
こちらを確認すると、すぐに状況が分かります！

①Android Studio から [SVD Manager]を押下し画面を起動する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577004/14dfb9bd-420d-b7a9-5a9f-9716fb20511b.png)

②左下の[Create Virtual Device...]を押下する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577004/406db5b8-152c-687c-1a5c-164868bd7944.png)

③適当な端末を選択し、[Next]を押下する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577004/9aa08449-5369-1c2e-f27e-4b2417b57d0e.png)

④画面右側にAPIレベルの詳細が載っていますが、スクロールして[API level distribution chart]というリンクがあるので押下します。すると、分布図の画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577004/d0284762-bc62-5d49-25af-c755bcf6d31e.png)
肥大化したテーブルをSHRINKする

よく忘れるので。
IMP、全テーブルDROP、同じテーブルをIMP・・・
を繰り返していると40MB程度のDMPのはずなのに、表領域が14GB・・・
そんなときに実行するSQL

```sql:動的SQL.sample
--SELECT 'TRUNCATE TABLE ' || table_name || ';' ,table_name FROM USER_ALL_TABLES
--order by table_name

declare
 tname varchar2(512);
 ssql  varchar2(512);
begin
 for rec in (SELECT SEGMENT_NAME, SEGMENT_TYPE, SUM(BYTES)/1024/1024 "MB"
                FROM USER_SEGMENTS
                WHERE SEGMENT_TYPE LIKE '%TABLE%' --テーブルで実施したらINDEXもSHRINKされた
                having SUM(BYTES)/1024/1024 > 5 
                GROUP BY SEGMENT_NAME, SEGMENT_TYPE
                order by 3 desc) loop
    ssql := 'ALTER TABLE ' || rec.SEGMENT_NAME || ' ENABLE ROW MOVEMENT';
    EXECUTE IMMEDIATE ssql;
    ssql := 'ALTER TABLE ' || rec.SEGMENT_NAME || ' SHRINK SPACE CASCADE';
    EXECUTE IMMEDIATE ssql;
    ssql := 'ALTER TABLE ' || rec.SEGMENT_NAME || ' DISABLE ROW MOVEMENT';
    EXECUTE IMMEDIATE ssql;

 end loop;
 

end ;
/
```
Unity アセットの買い方

仕事の一環でUnityのアセットを初めて購入したので、購入するプロセスや手続きを載せます。

#アセットの購入
最初に自分が買いたいアセットを探します。

![AssetStore.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2143773/3e0467dd-ead2-52a8-7029-b9178dd5eb2d.png)

購入するアセットをクリックしてBuy Nowボタンをクリックします。



#個人情報の入力

ボタンをクリックすると個人情報入力の画面が表示されますので順に入力していきます。

![Organization.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2143773/912c9032-2a48-c1cf-ee3a-cfd2b19e2f6f.png)

入力項目は以下です。
・Location(国名)
・First Name (名前)
・Last Name　(苗字)
・Email　(Eメールアドレス)
・Company Name  (会社名)
・Phone  (電話番号)
・Address  (住所)


#支払情報を入力
次に支払方法を入力します。
クレジットカードで支払う方法とPayPalで支払う方法があります。

![Payment.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2143773/fa3409e6-f742-65cc-3628-be392283afb8.png)

クレジットカードの場合は入力項目が以下です。
・クレジット番号
・有効期限
・CVC番号(カードの裏に記入されている3桁の番号
・クレジットカードに入力されている名前

Paypalの場合は入力項目は以下です。
・PayPalに登録されているEメールアドレス

以降はPayPalのサイトにつながるのでそこで必要な項目を入力します。(今回は割愛します)


#購入前の確認事項等
![Pay.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2143773/38b5a58a-2908-ba94-829a-e8ab25456a58.png)

購入前にユーザーライセンスへの同意を確認されるのでチェックを入れます。

ライセンスの種別は以下のようになります。

![ライセンス.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2143773/708c822b-5607-d8d0-f0f6-625cc1c3ff7a.png)

UnityのAsset Storeに無料・有料で配布されているアセットの利用規約はすべてのアセットで同じ利用規約、使用許諾です。

ただし、以下のアセットはそれ以外のライセンスが優先されます。

MITライセンス、BSD 3-Clause, Apacheライセンスを含むアセット。

また、一部のアセットには独自のライセンスがあります。





また、購入時にアセットについての情報や領収書をの送付を希望する場合はチェックを入れます。
チェックを入れると購入したときに登録したメールアドレス宛にメールが届きますので確認してください。



#アセットのインポート
最後に購入したアセットをインポートして使えるようにします。

Unityエディタのメニュー　Window>Package Managerで画面を開きます。

Importボタンをクリックします。


#まとめ
有料のアセットを購入する際の入力する情報について解説しました。

購入してから使えるようにするための方法を解説しました。
Dynamics365/PowerAppsモデル駆動アプリの汎用的なAction設計

Dynamics 365 FieldServiceの多く処理は、以下のmsdyn_FieldServiceSystemAction経由で行っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/0d8a4e58-6a00-c278-4453-239718b80077.png)
引数はすごくシンプルで汎用的に設計されています。構成は以下のようイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/5364951d-2e7b-9e78-0f54-74e1a2b7f592.png)
C#側の実装で、Type引数で処理を分岐しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/298f7e49-afa6-d23f-b0f4-a00035757bc8.png)

CustomWebAPIはActionと似ているため、同じ思想で設計することが出来ます。
Pythonで指数平滑移動平均をやってみた

# 指数平滑移動平均とは？
### 移動平均について
　移動平均とは、一定の期間の値から平均値を計算して表す値です。単純な平均値とは違い、時系列データの前後のいくつかのデータを足して平均をとるため、平均値が移動していくことから移動平均と呼ばれます。

https://ja.wikipedia.org/wiki/%E7%A7%BB%E5%8B%95%E5%B9%B3%E5%9D%87

### 指数平滑移動平均について
　では指数平滑移動平均とは何でしょうか。これは単純な移動平均とは違い、過去の値よりも直近の値になるほど比重を置いて計算された平均値です。過去の値が減少し、直近の値の変動に対する反応が早くなるという特徴があります。

https://www.smbcnikko.co.jp/terms/japan/si/J0628.html


## Pythonでのやり方
```calc.py
import time
import math
import datetime
import csv
import pandas as pd
import numpy as np

def get_yaw(count):
    acc = [0.0,0.0,0.0]
    mag = [0.0,0.0,0.0]
    date,acc[0],acc[1],acc[2],mag[0],mag[1],mag[2] = custum_get(count)
    yaw_list = list()
    
    for i in range(len(acc[0])):
        acc[0][i] = float(acc[0][i])
        acc[1][i] = float(acc[1][i])
        acc[2][i] = float(acc[2][i])
        mag[0][i] = float(mag[0][i])
        mag[1][i] = float(mag[1][i])
        mag[2][i] = float(mag[2][i])
        roll_error, pitch_error = initial_error(acc[0][i],acc[1][i],acc[2][i])
        roll = math.atan2(acc[1][i] , math.sqrt(acc[0][i]**2+acc[2][i]**2))
        pitch = -math.atan2(acc[0][i] , math.sqrt(acc[1][i]**2+acc[2][i]**2))
        numerator = math.cos(roll)*mag[1][i] - math.sin(roll)*mag[2][i]
        denominator = math.cos(pitch)*mag[0][i] + math.sin(pitch)*math.sin(roll)*mag[1][i] + math.sin(pitch)*math.cos(roll)*mag[2][i]
        yaw = math.atan2(numerator,denominator)

        roll = math.degrees(roll) + roll_error
        pitch = math.degrees(pitch) + pitch_error
        yaw = math.degrees(yaw) 
        if yaw < 0:
          yaw = 360 + yaw    
        yaw_list.append(yaw)
    date_list=list()
    for d in date:
      d_s = d.split(' ')
      date_list.append(d_s[1])

    yaw_list = pd.Series(yaw_list)

　　#指数平滑移動平均の計算
    yaw_list_x = yaw_list.ewm(span=10).mean()

    yaw_list = yaw_list_x.values.tolist()
    
    return yaw_list,date_list

if __name__ == '__main__':
  count = 150
  yaw,date = get_yaw(count)
  print(len(yaw))
  print(len(date))
  

```

## 実行結果
今回は地磁気センサから取得したデータからyaw角を計算するプログラムで指数平滑移動平均を用いた

###平滑化前
![平滑化前.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/739846/38037727-9e71-cafc-78ca-1b6a2fa0d163.png)

###平滑化後
![平滑化後.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/739846/3edd7a01-bc17-6cfe-ec59-df353f957ffb.png)

平滑化に必要な部分はここです。
yaw_list_x = yaw_list.ewm(span=10).mean()
pandasのDataFrameおよび、Seriesに定義されているewm関数を使っています。

##参考
この記事を元に平滑化を行いました。
https://analytics-note.xyz/programming/pandas-ewma/
Harmoware-VISの紹介

#Harmoware-VIS とは
Harmoware-VIS は JST OPERA ( 産学共創プラットフォーム共同研究推進プログラム ) の支援を受けて、人間機械協奏技術コンソーシアム ( HMHS: Human Machine Harmonization System ) (http://hmhs.jp) において、主に名古屋大学河口研究室が中心になって開発したものです。

UBER が開発した deck.GL ( https://github.com/visgl/deck.gl ) を利用し、その上に移動体とその付加情報を可視化する機能を 追加しています。

#Harmoware-VIS の仕組み
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625473/019279f4-77a5-a1cb-483c-52b2811fc35d.png width="90%">
UBER の deck.gl は、マップ上で位置を緯度経度で指定し、様々な３Ｄや２Ｄオブジェクトを配置することが可能です。
しかし、配置したオブジェクトをマップ上で移動させる機能はありません。
そこで Harmoware-VIS ではオブジェクトの位置を変化させたデータを、次々に deck.gl で表示させることで、オブジェクトが移動するアニメーションを実現しています。

###移動データの構造
例として下図のような２つの移動体を想定します。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625473/b4c9190e-932a-520b-61e9-ac0c0d0ae760.png width="90%">
ひとつの移動体データは「始点」「終点」「移動経路」で構成されます。
移動体データは複数定義すること可能です。
２点間の位置は、最短距離での移動を想定し、始点からの経過時間を元に計算します。

###移動データファイル

下に２つの移動体の定義例を示します。

```移動データ（json形式）の定義例.
[
{"operation":[ // １つ目の移動体のデータ
{"position":[136.945255, 35.190691, 0], // 経度、緯度、高度を指定（高度省略時はゼロ）
"elapsedtime":1551575400}, // 上記地点の通過時間をUNIX時間で指定
{"position":[136.936864, 35.191591, 0],"elapsedtime":1551575460},
{"position":[136.945255, 35.190691, 0],"elapsedtime":1551575520}]},

{"operation":[ // ２つ目の移動体のデータ
{"position":[136.900947, 35.143257, 0],"elapsedtime":1551577140},
{"position":[136.901769, 35.134622, 0],"elapsedtime":1551577260},
{"position":[136.906622, 35.127823, 0],"elapsedtime":1551577380}]}
]
```

移動データはjson形式で定義します。
operation に始点から順に終点までの移動経路を位置と通過時間で定義します。

#Harmoware-VIS を使ったアプリ作成について
Harmoware-VIS は以下で公開しています。
https://github.com/Harmoware/Harmoware-VIS

上記のgithubレジストリ内のexamplesアプリも参考にしてください。
https://github.com/Harmoware/Harmoware-VIS/tree/develop/1.7x/examples/visualize-sample

その他、Harmoware-VIS を使った、簡単なサンプルを公開しています。

https://github.com/Harmoware/Harmoware-VIS-Demo
https://github.com/Harmoware/Harmoware-VIS-xband
https://github.com/Harmoware/Harmoware-VIS-SUMO-FCD
https://github.com/Harmoware/Harmoware-VIS-Tile3DLayer
https://github.com/Harmoware/Harmoware-VIS-Geojson

Harmoware-VIS は react、redux 及び react-redux を使用しています。

画面更新のトリガーは基本的にルートからの props に含まれる action に定義済みの関数で行います。
アプリのカスタマイズで action に関数を追加することも可能です。

以下に Harmoware-VIS のリファレンスドキュメントを公開しています。
https://harmoware-vis.gitbook.io/harmoware-vis-documents/

**その他の用例などは、Qiita内に記事を随時追加していきます。**
**よろしくお願いします。**

<b>以降の記事へのリンク</b>
「[Harmoware-VIS はじめに](https://qiita.com/ucl_Harmoware_VIS/items/8cad0b3c7737a1996e81)」
「[Harmoware-VIS APIリファレンス](https://qiita.com/ucl_Harmoware_VIS/items/ea97c5e0e112a3d0ecca)」
「[Harmoware-VIS Layersリファレンス](https://qiita.com/ucl_Harmoware_VIS/items/cc65d90488d2f0d66ae1)」
「[Harmoware-VIS Control component リファレンス](https://qiita.com/ucl_Harmoware_VIS/items/7315ccff187ca608c0db)」
「[Harmoware-VIS css リファレンス](https://qiita.com/ucl_Harmoware_VIS/items/9c75210ed07b23e7255b)」
Explore - "Unity URP Tutorial - Orthographic Fog Plane Shader"

https://www.youtube.com/watch?v=1ZsKBZnbAB8

上記の動画で使われてる技術(特に霧のshader graph)を調べていくなりよ~。

# Orthographic Depth

* 使われてるノード一覧
 * Camera
 * Lerp
 * Scene Depth

* 役割
カメラからの距離を取得。

* やってること
"Camera"の手前のクリップ面までの距離(Near Plane)と奥側のクリップ面(Far Plane)までの距離を"Scene Depth"(カメラからオブジェクトまでの距離で0~1で表される)の値を媒介変数として、"Lerp"で線形補完をし、開始を手前の面までの距離、終了を奥の面までの距離としたものを１つ、それを逆にしたものを１つの計２つ作っている。
※動画では調整してPlaneがScene Depthの値として使われないようになっている?のでPlaneの奥に見える最も手前のものまでの距離となっている。

# Reverse Z Check
+ 使われているノード一覧
 + Camera
 + Comparison
 + Branch

* 役割
Depth BufferにReversed Zを使っているか否かで距離の値が変わるのでDepth Bufferの判定をし、使う値を選択。

* やってること
"Camera"の"Z Buffer Sign"(Reverse Zを使っていれば-1そうでなければ1を返す)を"Comparison"を使って確認するために作成。その結果を"Branch"に接続し、もしTrueならFarPlane-NearPlane間での値をそうでなければNearPlane-FarPlane間の値を使うように条件分けをしている。

* 補足
nvidiaの解説より、"ただし、ここで重要な実際の結果は次のとおりです。逆Zマッピングは基本的に魔法です"らしいから深追いしない。ヤクの毛は刈ってはいけない...

https://developer.nvidia.com/content/depth-precision-visualized

# Calculate World Pos from Scene Depth
+ 使われているノード一覧
 + Negate
 + Position
 + Split
 + Vector3
 + Transform
 + Subtract
 + Object

* 役割
カメラからの奥行きは取得できたのでカメラ視点からのX,Yを取得しそれらをworld座標に変換、オブジェクトの座標を弾いてワールド座標で原点にあった場合の座標としている。

* やってること
"Position"を使い、カメラ視点でのメッシュの頂点/フラグメントの位置を取得しそれをSplitでX座標とY座標の位置のみ抽出。また"Negate"(入力値の符号を反転するだけ)を使って上記で得た値を符号反転した値をZとし、"Vector3"を作成。"Transform"を使って先のベクトルをView座標から、World座標に変換。
その後今得た値から、オブジェクト本体のworld座標のベクトルを引く。

# Handle Fog(based on Normal Direction)
+ 使われているノード一覧
 + Transform
 + Normal Vector
 + Normalize
 + Dot Product
 + Negate
 + Saturate

* 役割
内積を使っている理由は(解説されていないのでおそらくになる)内積はベクトルAとBの絶対値の積にcosθをかけたものとなる。またBのAに対する正射影に対してAの絶対値をかけたものになるのでみている角度がPlaneに対して平行になる程、結果は小さくなるし(見る角度が浅くなる程霧が薄くなる)、また絶対値を利用していることから遠いところほど大きな結果になる(遠いところほど霧が濃くなる)この2つを目的としているから?またNegateをしているのは裏側から見た時に霧が見えないようにするためだと思われ。saturateをしているのは単にアルファが0~1なのと、特に補正をかけるとかじゃなく、ある閾値以上の結果は全て1にしても霧のエフェクトとしては十分だからか？

* やっていること
　計算してきた値と、正規化された法線ベクトルのドット積を計算。それを0から1までの値にする。

# 出力部
*使われているノード一覧
 * Color
 * Split
 * Multiply

*役割
ここまでで近いところほどalphaが小さく、遠いところほどalphaが大きいという入力が得られたのでそれを利用してfragemntの最終調整をしているだけ。

* やっていること
 1. "Color"の値を"Fragmentに接続
 1. "Color"のalphaを"Split"で抽出し、上記の計算で得た値と掛け合わせる。そしてその結果を"Fragment"のalphaに接続。

# 感想
わからん。
【Flutter】画面全体に背景色を設定する

## やりたいこと
画面全体に背景色を設定したい。

## 実装
最初にやったのはrootのWidgetにContainerを設定して**color**プロパティに設定しました。
画面に表示するWidgetはContainerの**child**プロパティに設定すれば良いと思いましたが、結果はこうなりました。

``` sample.dart
class ScreenView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Container(
        color: Colors.orange,
        child: Column(
          children: [
            Text('あいうえお'),
          ],
        ),
      ),
    );
  }
}
```

![ezgif.com-gif-maker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263659/d83d19fe-5873-bb73-fec8-f4010b07fa27.png)

これだとchildのWidgetによって親のContainerのサイズが決まってしまうので、画面全体に背景色を設定できません。

Containerにwidthとheightを設定して画面全体の大きさにすれば解決できそうですが、クールではありません。

結論Scaffoldの**backgroundColor**を使えば画面全体に背景色を設定することができました。

``` sample.dart
class ScreenView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.orange, // 背景色設定
      appBar: AppBar(),
      body: Container(
        child: Column(
          children: [
            Text('あいうえお'),
          ],
        ),
      ),
    );
  }
}
```

![ezgif.com-gif-maker (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263659/ef71d4a3-eb2e-37e7-4188-b67f35d0ce06.png)

以上です。
Helmチャートで環境変数を取り扱う工夫

## 環境
Helm 3.7.1



## Helmチャートでよくある悩み
Helmで実際のアプリをデプロイしていると、次のようなことが悩みどころになってくる。

- values.yamlに機密性の高い環境変数（APIキーなど）を直接書き込んでしまっているので、gitやhelmリポジトリに上げると機密情報が漏れてしまう
- デプロイ環境が複数あるときに、いちいち環境変数を書き換えてデプロイするのが面倒

Helmはあくまでもkubernetesのパッケージ管理ツールだからということもあってか、これらの悩みを解決する機能が明確に用意されているわけではない。そのため、ひと工夫が必要になる。

## この記事を読んでできること

- 機密性の高い変数（APIキーなど）をgitなどの管理から除外する
- 環境変数は、
    - 環境毎で共通のものは、values.yamlに書く
    - 環境毎の差分はenv/以下のファイルに分けて記述する

## Helmチャートを書き換えてみる

以下のvalues.yamlを例にとって説明する。

```values.yaml
app:
  port: 3000 #開発環境で3000、本番環境で3010
  someLimit: 100
secret:
  SOME_API_KEY: "apikey-dev" #開発環境で"apikey-dev"、本番環境で"apikey-prod"
```


このvalues.yamlをそのまま使うと、上述のようにデプロイ環境毎に環境変数を書き換えてからデプロイするひと手間がかかる。
Helmチャートをgit管理している場合、これらの値の更新がコミットされてしまうのも面倒になる上、APIキーをgit管理対象に含めてしまう危険性がある。

### values.yamlのテンプレートを作成する

そこでまず、values.yamlのテンプレートを作る。

```values.template.yaml
app:
  port: <port>
  someLimit: <limit>
secret:
  SOME_API_KEY: <apikey>
```


gitではvalues.template.yamlを管理し、values.yamlはgit管理対象から外しておく。

### env/フォルダ内にマニフェストファイルを作成し、デプロイ環境毎の環境変数を書く

さらに、環境毎の値を記述するマニフェストファイルを作成する。
`env`ディレクトリの下に作成すると整理がしやすい。
APIキーを含んでいるので、これらもgit管理対象から外しておく。


```env/develop.yaml
app:
  #開発環境では、portはvalues.yamlのものを使用
secret:
  SOME_API_KEY: "apikey-dev"
```

```env/product.yaml
app:
  port: 3010 #本番だけポートを変える
secret:
  SOME_API_KEY: "apikey-prod"
```

`app.someLimit`は環境毎で共通の値なので、values.yamlにのみ書いておく。
逆に、環境毎に必ず分けておきたい変数は、無効な値を書いておくとよい。

```values.yaml
app:
  port: 3000 #デフォルト値
  someLimit: 100
secret:
  SOME_API_KEY: null #無効な値を設定し、env/xxx.yamlで指定させる
```

簡単にまとめると、

- デフォルト値や、環境毎で共通の値はvalues.yamlに記述する
- 環境毎に固有の値はenv/xxx.yamlに記述する

とすればよい。

## デプロイ時

これらのファイルを用いてHelmチャートをデプロイ・アップデートするときは、以下のように`-f`オプションを利用する。
`-f`オプションで複数のファイルを指定したとき、各yamlファイルに重複した値がある場合にはより右（後）で指定したファイルのものが優先される（[参考](https://helm.sh/ja/docs/intro/using_helm/)）。

```
$ helm install -f values.yaml -f product.yaml fuga-app-prod .
```

例えば、上記のコマンドでは以下のvalues.yamlを使用したのと同等になる。

```values.yaml
app:
  port: 3010
  someLimit: 100
secret:
  SOME_API_KEY: "apikey-prod"
```

__ファイルの指定順を間違えると、誤った環境変数が適用されてしまうので注意。__
例として、上記のコマンドでvalues.yamlより先にenv/product.yamlを書いてしまうと。以下のvalues.yamlを使用したことになってしまう。

```values.yaml
app:
  port: 3000
  someLimit: 100
secret:
  SOME_API_KEY: null
```


## おわりに
Helmはあまり環境変数の取り扱いに便利な機能が無く、苦労したことがこの記事を執筆したきっかけです。
この記事がどなたかの助けになれば幸いです。

## 参考

- [Helm | Helm の使い方](https://helm.sh/ja/docs/intro/using_helm/)
- [helm Chartを書くときに先に知っておきたかった良い8つのこと - Qiita](https://qiita.com/t10471/items/116081e03aa33eec92b6)
- [ミドルウェア〜Webアプリまで全てをHelm化したサービスの運用事例 - Speaker Deck](https://speakerdeck.com/chokkoyamada/midoruuea-webapurimadequan-tewohelmhua-sitasabisufalseyun-yong-shi-li)
B+Treeインデックスとは？

# 高速にデータを検索するには？
高速に欲しいデータを検索するにはどうしたら良いでしょうか？
国語辞典を例にあげます。
「プログラミング」という言葉を調べたい時に、まず何をしますか？国語辞典の索引を見て、「プログラミング」が何ページ目にあるかを調べると思います。
実はデータベースもデータを検索する時に同じことをしています。

# インデックスとは？
データがファイルの何バイト目にあるかを示しているマッピング表のことです。

|ユーザーID|格納先の位置|
|:---:|:---:|
|1|1バイト目|
|2|73バイト目|
|3|156バイト目|
|...|...|
|100|123309013バイト目|
|...|...|

**注**) 実際にはキー値をハッシュ化した**ハッシュインデックス**が使用されている。

# B+Treeとは
インデックスをさらに分割して、木構造化したものです。
頂上が**ルートブロック**、最下層が**リーフブロック**といい、その中間に**ブランチブロック**があります。インデックス検索時にルート→ブランチ→リーフと検索をかけていくことで対象を絞り込んでいきます。
ちなみに、大規模なデータベースではブランチブロックが何層にもなるそうです。

![0E858E07-AE67-42F2-A888-B1AB96A70C35_1_105_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1936748/45d52f4e-32cd-3792-f2cd-199aa8dd80d3.jpeg)
FluffyDisplay が便利だった話


## [FluffyDisplay](https://github.com/tml1024/FluffyDisplay) が便利だったけど少し改造した話

[FluffyDisplay](https://github.com/tml1024/FluffyDisplay) は仮想ディスプレイを作成するツール。
少し改変すればソフトウェア制御で好きな解像度の画面共有を使えるようになります。

便利だったけど使ってる人が少なそうだったので宣伝。

## 結論

mac内蔵ディスプレイだけでは不可能な、メインマシンの解像度と同じ4Kな仮想ディスプレイを作りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28895/cb31a2fa-6fba-122b-b0fe-d3791cee1de4.png)


## 背景

古いmacを画面共有で使ってます。

Profileで分けるにもChrome君がメモリ馬鹿喰いなのと、
趣味用と仕事用でPCを分けておきたいのと、で、余ったPCに仕事をさせようと考えた時。
何枚もモニタを用意して表示させておくのも首が保たないので、画面共有を使うという発想になりました。

これが意外と快適なので、win機もParallelsを使ってたんですが、物理PCでRemoteDesktopを使うようになりました。
M1でwinが動かせないな。っていうので実機を使うように移行していた、
昨今のリモートワーク情勢においてwinを仮想環境として持ち歩かなくても大丈夫になった、という背景もあります。

## 問題

ただメインPCには4kなモニタがあり、そこにリモートmacを全画面で表示させたい。と思うのですが。
クラムシェルにしてるmacには別にモニタを繋がずな状態だと、内臓ディスプレイの解像度に依存した画面しか出力できません。
DisplyaMenu(alt: QuickRes） などを使って内部解像度を上げて共有したとしても、
画面比率を誤魔化すことができず横に黒帯ができてしまいます。


### 一応の解決

環境としてはよくあるUSB-C 2portを HDMI / USB-A / SDカード / USB-C(PD) / USB-C 。。。 etc なハブを使って
そこにHDMIのダミープラグを差し、4K HDMI プラグに出力しているように見せかけていると、4K解像度の画面共有ができるという寸法です。

### 別の問題

しかしながら。ひょんなことで ハブをLAN付きな製品にアップデートしましたところ、
相性問題でしょうか、ダミープラグに出力できませんでした。

### 探す

困ったな。ということで、少し調査してみる。
発想としては Sidecar などの実現方法はどうなってるのかな。
内部的には仮想モニタを作ってそう。みたいな形で、APIを探したりしてました。

そんな調査の折 FluffyDisplay を見つけました。

### 少し違う

対応している解像度がずらっと出るので4Kを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28895/24728ccd-0568-9fc9-09de-137e8044985e.png)

したものの作られたディスプレイはFHD解像度
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28895/4fb9c7a5-09df-af8f-2158-85f851798b69.png)

HiDPIな設定なりが影響してそう？
じゃ、8Kを設定できれば？と思ったけど、6Kまでしか設定がない、


### new on peer も少しだけ違う。

複数PCで FluffyDisplay を起動しておくと別PCのモニタの解像度に合わせて仮想ディスプレイを作成できる。
作成するとその仮想ディスプレイを自動的に画面共有にしてくれる。

これでいいじゃん。と思わなくもないのだけど、
状況としては画面共有下で操作してるのに、作成と同時に画面共有のセッションがスタートする混乱を招いた。
あと、別PCで起動しなくて済むならそれがいいなと。

### 改造

ソースを読ませてもらったら単純にいくつかの解像度&HiDPIな定義などのパターンを用意しているだけ。
cloneして、Xcodeでちょちょっと書き換えて
いまのところ手元で動けばいいので Code Signing は [Sign to Run Locally] でビルド（実際のところよくは理解してない）

```patch
diff --git a/FluffyDisplay/AppDelegate.swift b/FluffyDisplay/AppDelegate.swift
index a15806b..83d746b 100644
--- a/FluffyDisplay/AppDelegate.swift
+++ b/FluffyDisplay/AppDelegate.swift
@@ -43,6 +43,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NetServiceDelegate, NetServi
       Resolution(4096, 2304, 219, true,  "21.5-inch iMac with Retina 4K display"),
       Resolution(3840, 2400, 200, true,  "WQUXGA"),
       Resolution(3840, 2160, 200, true,  "UHD"),
+      Resolution(3840, 2160, 200, false,  "UHD LowDPI"),
       Resolution(3840, 1600, 200, true,  "WQHD+, UW-QHD+"),
       Resolution(3840, 1080, 200, true,  "DFHD"),
       Resolution(3072, 1920, 226, true,  "16-inch MacBook Pro with Retina display"),
```

実行してみたのが最初のスクショ。
上記解像度のPRを投げるかは検討中。


## ここまでの総括

カスタム解像度をUIから設定できるようなのもissueがあったりするので、それがあればローカルビルドもいらなくなるので期待。
UI用意されるならPR要らないなーという感じです。

## 備考

macの画面共有を快適に使うには有線LANが必須だな。と個人的に思ってます。
空のデータフレームにデータを挿入する時にハマった話

# はじめに
Python の pandas.DataFrame の扱いについてちょっとミスをしてしまった事があったので、備忘録として記事に残しておく。

# 空のデータフレームへのデータ挿入
空のデータフレームのA列に 'aaa' というデータを挿入する場合を考える。
以下、A列とB列を持つ空のデータフレームを作成する。

```python
import pandas as pd

test = pd.DataFrame(columns=['A', 'B'])

print(test)
```

```:出力
Empty DataFrame
Columns: [A, B]
Index: []
```

ここへA列に aaa という文字列を挿入してみると…。

```python
test['A'] = 'aaa'

print(test)
```

```:出力
Empty DataFrame
Columns: [A, B]
Index: []
```

エラーは出ないが、結果、データフレームには値が挿入されない。

```
     A    B
0  aaa  NaN
```

となる事を想定していた。以下の処理でデータフレームに値が入っているものだとしてエラーがでたので、この仕様に気が付くことができた。

結果、index の指定が無い状態だとデータの長さが決まっていないので、`test['A'] = 'aaa'`の挿入方法ではデータが挿入されない、という事が分かった。

# 回避方法その１：index を指定した空のデータフレームを作る
そもそもindex を指定してやれば NaN が入ったデータフレームが作成されるので、この問題は起こらない。

```python
test = pd.DataFrame(columns=['A', 'B'], index = [0])

print(test)
```

```:出力
     A    B
0  NaN  NaN
```

この状態で挿入する

```python
test['A'] = 'aaa'

print(test)
```

```:出力
     A    B
0  aaa  NaN
```

これで値が挿入される。

# 回避方法その２：文字列ではなく pandas.Series を挿入する
index の情報を持つ、pandas.Series にしてから挿入してやることでも、これを回避できる。

```python
test = pd.DataFrame(columns=['A', 'B'])

print(test)
```

```:出力
Empty DataFrame
Columns: [A, B]
Index: []
```

'aaa'を挿入する際に pnadas.Series に変換する。

```python
test['A'] = pd.Series('aaa')

print(test)
```

```:出力
     A    B
0  aaa  NaN
```

この方法でもデータを挿入することができた。

# おわりに
少し考えれば簡単な話でも、正しい挙動や仕様を理解してないとミスをしてしまう事を忘れないためにも、記事を残していければと思う。
\#こうしたミスを晒すのは恥ずかしい面もあるが…。
Unityでカメラが近づくとモデルが消えてしまう時の対処法

![スクリーンショット 2021-11-24 13.13.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740384/2567360d-2922-ad5d-ecb1-70d311d19e77.png)
**カメラが近づいた際にモデルが消えてしまう現象が発生している・・・**
モデルを設置する際には表示されるがなぜ近づくと消えてしまうのか。


##解決方法
**「Inspector」から「update whenoffscreen」**にチェックマークをつける。英文の通り「オフスクリーン時に更新 見えない時もその処理を実行」キャラクターが多く出てくるプロジェクトには問題が発生してくる。
そのほかの対処法としては、**「skinnedMeshRenderer」の「Bounds」の「Extent」**ここを調整して大きくすれば表示される場合もある。

![スクリーンショット 2021-11-24 13.22.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740384/c8ce79df-0611-f32c-5efa-f3705bef4ae3.png)

##それでも解決されない場合
・**FileからBuild Settingを選択する**
![スクリーンショット 2021-11-24 13.25.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740384/1d3b77ab-ec9a-6554-66aa-cb3a1ee0bdc1.png)


・**PlatformからWebGLを選択し、Switch Platformを選択する。**
![スクリーンショット 2021-11-24 13.26.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740384/6b6cc66a-ef2a-f88a-eaec-b2868dedebfe.png)

##結果
**Unityで近づいてもモデルが消えて現象が解消されました。✨**
**「Update when Offscreen」や「skinnedMeshRenderer」の「Bounds」の「Extent」**を変更してもモデルが消えてしまう場合は、WebGLのみの対応なのか、どのプラットフォームに対応しているのか確認してみた方が良いのかもしれませんね〜！
大事な記事のストック

https://qiita.com/notakaos/items/91d807f3151694e6c7a8

https://qiita.com/shimauma_Zzzzz/items/5b6a90e908778082b08e

https://qiita.com/shinyashikis@github/items/294766d75c2ac633e22d

https://oshiete.goo.ne.jp/qa/8766867.html
WASのプロファイル削除手順

https://www.ibm.com/docs/ja/was/9.0.5?topic=mpdios-deleting-profiles

ではプロファイル削除手順
削除するプロファイルは、Custom01とDmgr01

１．プロセスが停止していることを確認する
ps -ef | grep server
ps -ef | grep nodeagent
ps -ef | grep dmgr

2.カスタムプロファイルのほうから削除する.

```
/opt/IBM/WebSphere/AppServer/bin/manageprofiles.sh -delete -profileName Custom01
INSTCONFSUCCESS: 成功: プロファイルは存在しません。
```
3.DMのプロファイルも削除します。

```
/opt/IBM/WebSphere/AppServer/bin/manageprofiles.sh -delete -profileName Dmgr01
INSTCONFSUCCESS: 成功: プロファイルは存在しません。
```

4.不要なのでディレクトリごと削除します。
※怖い方は、mvでもしておいてください。

```
cd /opt/IBM/WebSphere/AppServer/profiles
pwd
rm -rf Custom01
ls -ltr
rm -rf Dmgr01
ls -ltr

/opt/IBM/WebSphere/AppServer/bin/manageprofiles.sh -validateAndUpdateRegistry
[]

```

5.最後にきれいにレジストリからプロファイルが削除されているか確認する

```
cd /opt/IBM/WebSphere/AppServer/properties
cat profileRegistry.xml
※プロファイル名がないこと
※直接消すことは推奨されていないが、まぁバックアップ取って直接編集ならいいんではないのでしょうか。
```
Bluetooth5.3の変更点について

Bluetooth5.3の対応チップがそろそろ出てくるようなので、変更点を確認してみました。
元が英語だったので間違って認識してしまってる部分があると思います。ご注意下さい。

## 「4nmプロセス」「Armv9」など最新技術てんこ盛りなスマホ向けSoC「Dimensity 9000」をMediaTekが発表
Bluetooth5.3対応
https://gigazine.net/news/20211122-mediatek-dimensity-9000/ 

## Bluetoothコア仕様バージョン5.3の機能拡張
https://www.bluetooth.com/blog/new-core-specification-v5-3-feature-enhancements/

### 機能追加＆強化
・定期的なアドバタイズメントの強化

    主に受信側の省電力化。
    送信時に識別コードを追加で送ることで、受信時に2回目以降の同じ識別コードの信号をメインCPUへ送る前に破棄。
    ※受信処理の負荷が軽減される？

・暗号化キーサイズ制御

    暗号通信時の暗号キーの長さを指定可能に。
    近年問題になっているBluetoothセキュリティへの対策

・接続サブレーティング

    接続時の省電力モードとハイパワーモードの切り替えが高速に。
    例：Bluetooth補聴器で電話がかかってきたときにハイパワーモードへ高速切り替えができるようになった。

・チャネル分類の機能強化など

    接続時に送信側（例：Bluetoothイヤホン）側からもチャンネルの調整の提案を受信側へ依頼できるようになる。

### 削除
・代替MAC

    プライバシー対策の為の偽装Macアドレス表示の事？

・PHY（AMP）拡張機能

    ２Mモードとか0.5Mモードで距離伸ばすとかの事？
    あんまり使われてなかったから削除しますと書かれています・・・。

用語参考：https://www.silex.jp/blog/wireless/2017/02/bluetooth5-1.html
OpenWhetherAPIの気温予報と東京工科大学付近の気温差

現在の天候や予測履歴を含む各種気象データの無料APIを提供するオンラインサービスとしてOpenWhetherAPIがある. OpenWhetherAPIから予測される各種気象データは気温,湿度,気圧,雲量の4つである. 今回は予測される気温と大学内の気温にどのくらい差があるのかを調査する.

大学内の気温は気温センサモジュール「s5851a」を用いて計測する.

###結果
![気温差.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/739843/df3c0ea5-97c1-892e-1017-b8eda4a2e3e6.png)

実験日は11月11日の9:00〜13:00の間に行った. 結果から平均気温差は5.30℃となり, 大学内の気温の方が天気予報より高くなる傾向があることがわかった. 同様に別日も計測した結果,やはり大学内の気温が方が高く,平均気温差が5.13℃であったため,　OpenWhetherAPIの予測気温と大学内の気温に約5℃の気温差があることがわかった.
NTT 東日本 - IPA 「シン・テレワークシステム」 で「コンピューターを検出できません」エラー

光回線を NURO にしたら、NTT 東日本 - IPA 「シン・テレワークシステム」 がつながらなくなった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/bb27a566-5ad2-9c26-22fe-fb0b8933683e.png)

# 環境

- サーバ側回線 学術系 IPv4 回線
- クライアント側回線 NURO　光 G2T IPv6 回線
- クライアント側 ONU: ZXHN F660A
- OS サーバ/クライアント双方Microsoft Windows 10 Pro 
- NTT 東日本 - IPA 「シン・テレワークシステム」 2021/08/05 公開版 Ver 0.18 (Beta 7 Fix 1) ビルド 9902
- サーバ側:Windows 版フルパッケージを使用し、「シン・テレワークシステム サーバ」を選択して インストール
- クライアント側:Windows 版フルパッケージを使用し、「シン・テレワークシステム クライアント」 を選択してインストール


# 類似事例


「Re: 【Error？報告】Ver 0.18 (Beta 7) ビルド 9901 Client で IPv6 Off のルーターでVPNが接続できませんでした」
https://forum.cyber.ipa.go.jp/viewtopic.php?f=3&t=197&p=588&hilit=ipv6#p588
において、


> リモートデスクトップはコンピュータ "コンピュータ名.secure-v6.cyber.ipa.go.jp" を検出できません。
> "コンピュータ名.secure-v6.cyber.ipa.go.jp" が指定のネットワークに属していないことが考えられます。
> 接続しようとしているコンピュータの名前とドメインを確認してください。

のエラーに対して以下の対応がなされている。

> IPv6 シングルスタック環境対応時に不具合が生じていました。
> IPv6 の DNS 名前解決が有効であるが IPv6 通信ができない環境でクライアントアプリで RDP 接続エラーが発生する問題を修正しました。
> https://telework.cyber.ipa.go.jp/changelog/
> 
> 問題を修正した Beta 7 Fix 1 をリリースしました。
> なお、遠隔で localhost を返す DNS を無理矢理いじったので、無印 Beta 7 でも 2021/08/05 22:00 頃以降はエラーなく接続できるようになる予定です。(ただし、アドレス表示バーがおかしくなります。)

ふむふむ、クライアント側のIPv6 環境の問題かな？

# クライアント側環境の確認

「あなたの IPv6 をテストしましょう。」サイト
https://test-ipv6.com/index.html.ja_JP
において、クライアント側環境のIPv6接続を検証してみたところ、問題が無いようだ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/847af305-40f5-9346-ab80-c06a4ebb2042.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/02c986d5-2208-8cbd-cedf-1702a1baa757.png)

クライアント側 ONU: ZXHN F660A の設定画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/c8e6ffb7-db54-00d8-1c66-63b678a435bb.png)

問題無さそう?

# 「シン・テレワークシステム」中継システム?

そもそも、上記の問題だと現在は  Beta 7 Fix 1  において問題はないはず。

また、そうでなくても以下のように中継システム側で対応しているはずなので問題ないはず。

> なお、遠隔で localhost を返す DNS を無理矢理いじったので、無印 Beta 7 でも 2021/08/05 22:00 頃以降はエラーなく接続できるようになる予定です。(ただし、アドレス表示バーがおかしくなります。)


# localhost の扱い

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/9d4a844a-a0b5-003e-709e-e0f53aab8ac1.png)

クライアントでの localhost は IPv6 のようだ。何か関係があるかな?

# 「シン・テレワークシステム」設定変更


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/b825d58e-3861-9abf-6a0e-0834dde608dd.png)

関連のありそうなこちらをチェックしてみました。

# 動作しました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/e8566da5-1b00-ef17-f836-70e5054b0244.png)


# おまけ

別エラー

突然このエラーが発生するようになった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/4ada8835-986e-c196-7863-b0dad21c0008.png)

Windows Update 途中の時にこれが発生、待っていればエラーは起こらないようになりました。
スマホからGAS起動

## スマホからだと図形ボタンが押せない
ので、GASの発火に困るんですよね。
今回は図形ボタンの代わりを作ります。

## チェックボックスが便利
チェックボックスはスマホからでも押せます。ちょっと小さいですが。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/62bf21dc-8009-967c-3f78-4fb4132b5bf3.png)

## 完成品
こうなります。ボタン押下で緑のゾーンに今日日付を入力するようにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/263e5acc-cb0c-f06b-827a-5da469aa54da.png)

```GASソース.js
function todayButton() {
  // ★スマホからだと、ダイアログが表示できず、以降の処理が進まないためコメントアウト。
  // let msg = Browser.msgBox('確認メッセージ','今日日付を入力しますか？',Browser.Buttons.OK_CANCEL);
  // if (msg != 'ok') return;
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const LAST_ROW = sheet.getRange('A2:A11').getValues().filter(String).length;
  sheet.getRange(LAST_ROW + 2, 1).setValue(new Date());
}

// 編集時に起動する「onEdit」関数
// ★スマホからだと図形ボタンをクリックできないので、イベント発火をチェックボックスにした。
function onEdit() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  // チェックボックスONで起動
  if (sheet.getRange('A13').getValue()) {
    todayButton();
  }
  sheet.getRange('A13').uncheck();
}
```

## 解説
まずはこちら

```onEdit.js
// 編集時に起動する「onEdit」関数
// ★スマホからだと図形ボタンをクリックできないので、イベント発火をチェックボックスにした。
function onEdit() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  // チェックボックスONで起動
  if (sheet.getRange('A13').getValue()) {
    todayButton();
  }
  sheet.getRange('A13').uncheck();
}
```
onEditという名前の関数にすると、`スプレッドシートが編集された時`に呼び出されます。
またif文にて、チェックボックスがTrueの時のみ処理を実行するようにしています。
そして処理終了でチェックボックスをFalseにします。

これにより、`ボタンが押されたときのみ処理を実行`し、`ボタンでない部分の編集では何もしない`
さらに、`ボタン押下後は再度ボタンが押せる`ようにしてあります。

つぎはこちら。

```処理.js
function todayButton() {
  // ★スマホからだと、ダイアログが表示できず、以降の処理が進まないためコメントアウト。
  // let msg = Browser.msgBox('確認メッセージ','今日日付を入力しますか？',Browser.Buttons.OK_CANCEL);
  // if (msg != 'ok') return;
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const LAST_ROW = sheet.getRange('A2:A11').getValues().filter(String).length;
  sheet.getRange(LAST_ROW + 2, 1).setValue(new Date());
}
```

ダイアログ表示の部分も、図形ボタンと同様にスマホに対応してません。
PC版の時は有効なのでお試しあれ。

```.js
const LAST_ROW = sheet.getRange('A2:A11').getValues().filter(String).length;
```
↑このソースによって、A列の緑の部分のうち、
`「上から入力していくんだけど、次は何行目に入力すんの？」`って行数を取得したい。
ようは空白セルまで何行あるかを取得。
んで

```.js
sheet.getRange(LAST_ROW + 2, 1).setValue(new Date());
```
これで、現在日付を入力する。
まぁここの処理部分は好きな処理にすればよくて
スマホからGASボタンを押すにはonEdit関数をうまく使おう！というお話。
wsadminで設定し、設定できたことを確認する(Library編)


いつものノード情報とサーバ情報の定義ファイル

```jvminfo.txt
yyd1Node01,server1
yyd1Node01,server2
yyd2Node01,server1
```

ライブラリ登録用定義ファイルをノード名_サーバ名で用意する。
クラスタ名で使用するのであればサーバの部分は不要になりますね。
1番目がライブラリの名前
2番目がクラスパス情報

```yyd1Node01_server1.lib
wsadmin,"/opt/opp;/etc/view;/workshop"
```

今回色々考えた結果、ライブラリ用ファイルを準備しました。
※修正版は別に作らないといけませんね。。。
※これは新規登録のみ使用できるスクリプトになっています。

```Library_set.py
import csv

with open('jvminfo.txt') as f:
    csvreader = csv.reader(f)
    for row in csvreader:
      nodename=row[0]
      servername=row[1]
      id=AdminConfig.getid('/Node:'+nodename+'/Server:'+servername+'/')

      with open(nodename+'_'+servername+'.lib') as f2:
          csvreader2 = csv.reader(f2)
          for row2 in csvreader2:
            L_name=row2[0]
            print L_name
            L_libpath=row2[1]
            print L_libpath
            AdminConfig.create('Library', id, '[[name '+L_name+'] [classPath '+L_libpath+']]')

AdminConfig.save()
```

```Library_get.py
import csv

with open('jvminfo.txt') as f:
    csvreader = csv.reader(f)
    for row in csvreader:
      nodename=row[0]
      servername=row[1]
      id=AdminConfig.getid('/Node:'+nodename+'/Server:'+servername+'/')
      ProcessID = AdminConfig.list('Library',id)
      print nodename + servername
      print AdminConfig.showAttribute(ProcessID,'name')
      print AdminConfig.showAttribute(ProcessID,'classPath')

```
【Django】メールログイン用Userモデルをサクッと定義する

備忘録です。

Djangoはデフォルトだと`username`と`password`での認証となっているため、`email`と`password`で認証できるようにユーザーモデルをサクッと実装してみる。

# 1. accountsアプリを作成

まずは認証用のアプリ（**accounts**）を作成して、settings.pyに登録する。ここまでは、至って普通。

```console
python manage.py startapp accounts
```

```python
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'accounts',
]
```

# 2. カスタムユーザーとカスタムマネージャーの作成

ここからが本番。**accounts**のmodels.pyに定義していく。

`django.contrib.auth.models.AbstractBaseUser`を継承したカスタムユーザーのクラスを作成し、必要なフィールド情報を記入する。このとき、`PermissionsMixin`も一緒に継承する（☆1）。
パスワードのフィールドは`AbstractBaseUser`に存在しているので定義する必要はない。`PermissionsMixin`にスーパーユーザーかどうかを識別する`is_superuser`というフィールドが入っているので、定義する必要はない。

`USERNAME_FIELD = 'email'`とすることで、**メールアドレスでこのテーブルのレコードを一意に識別することができる**、つまり**<font color="Tomato">メールアドレスでのログインが可能となる</font>**（☆2）。


カスタムマネージャー（`UserManager`）は、`django.contrib.auth.models.BaseUserManager`を継承して作成し、`create_user`と `create_superuser`メソッドを追加して、ユーザ作成時、スーパーユーザー作成時の処理を追加する（☆3）。



```python:accounts/models.py
from django.db import models
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser, PermissionsMixin
)


class UserManager(BaseUserManager): # ☆3

    def create_user(self, username, email, password=None):
        if not email:
            raise ValueError('Enter Email!')
        user = self.model(
            username=username,
            email=email
        )
        user.set_password(password)
        user.save(using=self._db)
        return user
    
    def create_superuser(self, username, email, password=None):
        user = self.model(
            username=username,
            email=email,
        )
        user.set_password(password)
        user.is_staff = True
        user.is_active = True
        user.is_superuser = True
        user.save(using=self._db)
        return user


class User(AbstractBaseUser, PermissionsMixin): # ☆1
    
    # 使いたいFieldを追加
    username = models.CharField(max_length=255)
    email = models.EmailField(max_length=255, unique=True)
    is_active = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)

    objects = UserManager()

    USERNAME_FIELD = 'email' # ☆2 このテーブルのレコードを一意に識別
    REQUIRED_FIELDS = ['username'] # スーパーユーザ作成時に入力する

    class Meta:
        db_table = 'users'
    
    def __str__(self):
        return self.email
```

# 3. settings.pyに追記

settings.pyに、カスタムユーザーモデルを以下のように追記する。

```python:settings.py
AUTH_USER_MODEL = 'accounts.User'
```

# 4. マイグレーション

```console
$ python manage.py makemigrations accounts
$ python manage.py migrate
```

# 5. 管理者の作成

```console
$ python manage.py createsuperuser
```

# 6. 管理サイトを開いて見る

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471633/4169179d-6818-8b78-9c0e-4ae1583c6496.png)


こんな感じで、メールアドレスとパスワードでの認証システムを実装することができる。