OmniAICreator/Qiita-1.07M huggingface dataset:
日本人が Windows 11 で中国語を扱う

随時追加するかもしれませんメモ記事ですすいません。

ということで、同學們好，我讓你知道輸入方法在 Windows 11 吧。

中国語学習は必要ですよ、とか、フォントについて有用と思いますので Ubuntu での方法論をメモ的に書いた記事もあわせてどうぞ。

https://qiita.com/kws_fx/items/21ce5c3a8834ee8df8c4

以下、頻出のため Microsoft や Chinese Traditional というワードは割愛表記します。

この記事ではどういった入力方法があるのか調査した内容を展開しています。それぞれの方法に関する詳細については論じていません。資料に記載した参考リンクを確認してみてください。

### Windows での外国語入力一般論

言語パックというものをインストールします。方法などは割愛しますが、記事の中で使う言葉としてキーボードとレイアウトを個別に定義しておくと、

* キーボード：入力システムのパッケージ
* レイアウト：入力システム内で利用できるキーボード配列定義

ということで認識されるとよろしいかと。

### Windows での中国語

簡体（中華人民共和国、シンガポール）、繁体（香港、マカオ、台湾）のそれぞれで言語パックがあるので、字体やレイアウトで考慮するとよいでしょう。

#### 簡体言語パックのレイアウト
|レイアウト|Wikipedia他、参考リンク, 摘要|
|-|-|
|Pinyin|拼音<br/>https://ja.wikipedia.org/wiki/%E6%8B%BC%E9%9F%B3|
|Wubi|五笔字型输入法<br/> zh: https://zh.wikipedia.org/wiki/%E4%BA%94%E7%AC%94%E5%AD%97%E5%9E%8B%E8%BE%93%E5%85%A5%E6%B3%95|

#### 繁体言語パック

##### キーボード bopomofo のレイアウト

|レイアウト|Wikipedia他、参考リンク, 摘要|
|-|-|
|標準|注音輸入法<br/>https://ja.wikipedia.org/wiki/%E6%B3%A8%E9%9F%B3%E8%BC%B8%E5%85%A5%E6%B3%95|
|漢語拼音|詳細は簡体のピンインを参照。単漢字変換。|
|倚天|倚天中文系統<br/>https://ja.wikipedia.org/wiki/%E5%80%9A%E5%A4%A9%E4%B8%AD%E6%96%87%E7%B3%BB%E7%B5%B1|
|通用拼音|台湾で過去制定されたピンイン。通常のピンインとは微妙に違う。<br/> https://ja.wikipedia.org/wiki/%E9%80%9A%E7%94%A8%E6%8B%BC%E9%9F%B3|

##### そのほかのキーボード

キーボードパッケージがそのままレイアウトを表している。

|キーボード|Wikipedia他、参考リンク, 摘要|
|-|-|
|Changjie|倉頡(cāng xié)輸入法<br/>https://ja.wikipedia.org/wiki/%E5%80%89%E9%A0%A1%E8%BC%B8%E5%85%A5%E6%B3%95|
|Array|行列輸入法<br/>en: https://en.wikibooks.org/wiki/Guide_to_Array_input<br/>zh: https://zh.wikipedia.org/wiki/%E8%A1%8C%E5%88%97%E8%BC%B8%E5%85%A5%E6%B3%95|
|Dayi|大易輸入法<br/>ja: https://ja.wikipedia.org/wiki/%E5%A4%A7%E6%98%93%E8%BC%B8%E5%85%A5%E6%B3%95<br/>en: https://en.wikibooks.org/wiki/Guide_to_Dayi_input/Introduction|
|Quick|速成輸入法<br/>https://ja.wikipedia.org/wiki/%E9%80%9F%E6%88%90%E8%BC%B8%E5%85%A5%E6%B3%95|

#### 既定レイアウト

|パッケージ内の地域|既定キーボード・レイアウト|
|-|-|
|中華人民共和国|Pinyin|
|シンガポール|Pinyin|
|香港・マカオ|bopomofo Quick|
|台湾|bopomofo 標準|

### 違うIMEはないのか？

https://qiita.com/8pf/items/8c9c58b7e50c2cb796e3

上記ハプニング発生のため、十数回のリトライをしているうちにいよいよ呆れてきたので、どうにか中文が入力できるようにしたいのもあって下記サードパーティ製のIMEを試行してみた。どれも簡体字UIで、MS-PinyinのようにUIは日本語（というかI18Nしてあるもの）じゃなきゃダメな人にとっては無駄情報です。

#### 下载谷歌拼音输入法

[Download Google Pinyin Chinese Mandarin Pinyin Input](https://www.geckoandfly.com/3100/%E4%B8%8B%E8%BD%BD%E8%B0%B7%E6%AD%8C%E6%8B%BC%E9%9F%B3%E8%BE%93%E5%85%A5%E6%B3%95-download-google-pinyin-chinese-mandarin-pinyin-input/)

辞書の剽窃騒動だったり、どうやらgoogleが中国から撤退して継続不可能になった製品。なぜかDL出来るので一応紹介。UIフォントが簡体字＆明朝体で行間考慮されていないエンシェントな感じ。繁体字で勉強してきた私には無理オブジョイトイ。

#### [捜狗拼音輸入法](https://shurufa.sogou.com/)

https://ja.wikipedia.org/wiki/%E6%8D%9C%E7%8B%97%E6%8B%BC%E9%9F%B3%E8%BC%B8%E5%85%A5%E6%B3%95

で読む限り、QQ輸入法の次かなー？と思ったらカスタマイズ機能が一番好みだった。

#### [百度输入法](https://shurufa.baidu.com/)

 に関しては情報が沢山あるので探してみて判断してください。

#### [QQ输入法](http://qq.pinyin.cn/)

https://zh.wikipedia.org/wiki/QQ%E8%BE%93%E5%85%A5%E6%B3%95

大学発ということでこれにしようかなと思ったけど、テンセント傘下になっている。そのせいかLINEやBaidu/Simejiの若者向け（）感が若干なじめなかった。
CI環境（GitHub Actions）において、Googleでログインによる認証をCypressで突破しようとして失敗した話

## はじめに

[以前の記事](https://qiita.com/yuta-katayama-23/items/05c568adfe1feea98119)で、ローカル環境におけるREST APIのAPIテストを自動化してみるという事をやってみた。

ローカル環境でテストを流していてもPRの作成時やマージ時にCIで同じテストが流れていなければ、本質的には品質の保証の観点からするとあまり意味ない（ローカル環境でテストを実行せずPRを上げる輩がいた場合、メインブランチでテストが通らなくなり大迷惑な事になるのは目に見える…）。

というわけでCI環境（GitHub Actions）でローカル環境でやっていたテストを実行できるようにし、PR時やマージ後にCIでテストを流し品質を保証できるようにしてみようとした。

が、うまくいかなった…。原因は「Googleでログイン」の部分にある模様で、それについて備忘録を残す。

## `This browser or app may not be secure`エラーになる 

結論から言うと、以下のように`This browser or app may not be secure`というエラーになり、ログインができなかった…。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/9668f9fc-627c-d842-1c50-e81a271a27f2.png)

ググってみた所、以下のissueが見つかり、それを読む限り https://developers.googleblog.com/2020/08/guidance-for-our-effort-to-block-less-secure-browser-and-apps.html に記載されている事に起因してログインがブロックされている模様。根本的にはGoogleのセキュリティに引っかかっている状態で、これを突破するのは現実的ではないだろう（Google側もあらゆる攻撃を日々受けているので、ちょっとやそっとでこのセキュリティのエラーを突破する事はできないと思われる）。

- https://github.com/ankurk91/google-chat-electron/issues/52
- https://github.com/ankurk91/google-chat-electron/pull/68

というわけで、「Googleでログイン」による認証はあきらめる事にし、代わりに自前で[panva/node-oidc-provider](https://github.com/panva/node-oidc-provider)で認証認可サーバーを実装して、テスト時にはその認証を利用する、という方法を取る事にした（自分で認証サーバーを実装してみたかった・テストのためだけに利用する、という2点から敢えて実装する事を選んだが https://www.authlete.com/ja/ などのサービスを利用して認証（認可）を実現する方法もあるだろう）。

※[panva/node-oidc-provider](https://github.com/panva/node-oidc-provider)で認証認可サーバー（OpenID Connect・OAuth2.0）を実装するのは、また別の記事で取り上げる。

## おまけ

### 試してみて事（試したがGoogleでログインを突破できなかった方法）

1. headlessではなく、headedで実行
https://github.com/marketplace/actions/cypress-io#headed のオプションで`headed: true`にしてみたがNG

2. userAgentを上書きする
https://docs.cypress.io/guides/references/configuration#Browser のオプション`userAgent`を以下のように設定するもNG
`userAgent:	'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.5249.51 Safari/537.36'`
[c++]関数の引数にvectorを用いたらTLEした話

<h1>詰まった点</h1>
<p>AtCoder Beginner Contest 304 のD問題を解いていたときに<br>計算量的には十分間に合うはずだったが、TLEした。
<h1>原因</h1>
<p>問題を解く上で二分探索する関数を自作で用意していたが、その関数の引数の渡し方に問題があった。</p>
<p>以下、作成した二分探索の関数（問題の構造上、通常の二分探索とは違い一致したものを返すものではありません）</p>

```diff_c
#include<vector>
typedef long long int ll;
typedef vector<ll> vll;

ll bynarySearch(vll vec,ll target)
{
    ll left = 0, right = vec.size() - 1;
    while (left + 1 <  right)
    {
        ll mid = (left+right) / 2;
        if(vec[mid] < target)
        {
            left = mid;
        }
        else
        {
            right = mid;
        }
    }
    
    return left;
}
```

<h1>解決</h1>
<p>関数の引数の渡し方について、</p>

```diff_c
ll bynarySearch(vll vec,ll target);
```

<p>これだと、関数が呼び出されるたびに引数で受け取ったvector配列と同じものを別に用意してそれに関して処理を行うようになるため、受け取るvector配列が大きい場合それだけで計算量がとても多くなっていしまっていた。これを、</p>

```diff_c
ll bynarySearch(vll &vec,ll target);
```

<p>として、参照渡しをすることで、配列のポインタを渡すだけのようになり、受け取るvector配列の大きさに処理量が依存しなくなることで、TLEを回避することができた。</p>

<h1>考察</h1>
<p>初歩的な話ではあるが、単純に配列を用いる場合でも、何度も利用する関数に渡すときは、ポインタで渡すことで、渡すデータの量を削減できる。</p>
１時間で作るM5Stackと防水温度センサ(DS18B20)を使った水温計

# はじめに
メダカを育てている水槽の水温を測りたいと思います

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/ee657a7c-36f5-c6ff-f777-5b476cf86ee4.png)

# 完成品
こんな感じに完成しました！
１時間

![DSC_1387.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/fa8872cb-f0c2-2689-6985-8cc1ec262e90.jpeg)

# 材料

M5Stack Basic

https://www.switch-science.com/products/7362

DS18B20が使われた防水温度センサ

https://www.amazon.co.jp/dp/B08GS4T8T1


# 防水温度センサの改造

Seeedからそのまま使えるものも販売されているのですが、配送に時間が掛かるなどもあるので、自分で改造して作ることにします。

https://jp.seeedstudio.com/One-Wire-Temperature-Sensor-p-1235.html

こちらの記事でも改造した内容があるので参考になります。

https://qiita.com/tatsu1225/items/b61d6a63f2307a9ecf68

購入した防水温度センサは、電線が出ているだけなので、ここをGroveコネクタに接続します。
そして、その間でプルアップ抵抗を挟みます。


![DSC_1385.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/37bac46e-3174-cab5-799f-c7a8d5219af2.jpeg)

完成！

![DSC_1386.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/61e64dfe-5101-6bdb-3ba9-47a68129372f.jpeg)

# プログラミング
コーディングしても良かったのですが、見つけました！
DS18B20用のカスタムブロック！これで、UIFlowが使えるので、開発環境を整えたりする手間も省けます。

https://github.com/stonatm/UiFlow-custom-blocks/tree/master/ds18b20

カスタムブロックを初めて使ったので、そこはちょっと調べましたが、ロード自体はそんなに難しくなく、ブロックも分かりやすかったので、そのまま使えました。

Blockyだとこんな感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/55193743-bfb9-c3a1-7d69-485bc35fee90.png)

Pythonだとこんな感じ。

```python
from m5stack import *
from m5ui import *
from uiflow import *
import time

setScreenColor(0x222222)

labelTemp = M5TextBox(104, 99, "Temp", lcd.FONT_DejaVu40, 0xFFFFFF, rotate=0)

from machine import Pin
import _onewire

def init(pin):
  Pin(pin, Pin.OPEN_DRAIN, Pin.PULL_UP)

def convert(pin):
  _onewire.reset(Pin(pin))
  _onewire.writebyte(Pin(pin), 0xcc)
  _onewire.writebyte(Pin(pin), 0x44)

def read(pin):
  _onewire.reset(Pin(pin))
  _onewire.writebyte(Pin(pin), 0xcc)
  _onewire.writebyte(Pin(pin), 0xbe)
  tlo = _onewire.readbyte(Pin(pin))
  thi = _onewire.readbyte(Pin(pin))
  _onewire.reset(Pin(pin))
  temp = tlo + thi * 256
  if temp > 32767:
    temp = temp - 65536
  temp = temp * 0.0625
  return(temp)

init(21)

while True:
  convert(21)
  labelTemp.setText(str("%.2f"%((read(21)))))
  wait_ms(100)
  wait_ms(2)
```

# 完成品
最初にも紹介しましたがこんな感じで完成しました！

![DSC_1387.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/fa8872cb-f0c2-2689-6985-8cc1ec262e90.jpeg)

# まとめ
作ると決めて、約１時間ぐらい。材料が手元にあったので、ある程度サクサク出来ましたが、こんなのがたった１時間で作れるのは、M5Stackのおかげです。
あとは、防水温度センサですが、普通に環境温度も取れるし、土壌に差しても使えると思うし、なんだかんだでちょっと使い勝手が良いのかもと思います。

# おまけ
ここまでやって最後に、Atom S3で動かしたかったのですが、ATOM S3 は UIFLOW2になるので、カスタムブロックが使えるのかがよく分からず。まぁ、とりあえずは動いたので、そちらはまた気が向いたら～

あとは、このブログ自体は約30分で書き上げました。実際に作ってる時間より長くは掛けたくなかったので良かったです(笑)
sshポートフォワードをダブルクリック一発でできるWindowsバッチファイル

### サンプル

以下は、ダイナミックポートフォワードのサンプル

```ポートフォワード.bat
cd %~dp0
ssh -o StrictHostKeyChecking=no -i id_rsa -D 8888 ubuntu@203.0.113.0
```

### 背景

- Windowsユーザに公開鍵を使ったsshポートとワードをして欲しいケースはある
- ただしコマンドプロンプト開いて、公開鍵があるところをカレントディレクトリにして、sshコマンドを打って欲しい、というのがなかなかハードルが高い
- そこでバッチファイルを作って、バッチファイルのあるディレクトリをカレントディレクトリにしてsshコマンドもタイプすることを一発で実現したかった
- 公開鍵認証方式が最強
- 初回アクセスの時にワーニングがでるのは一般ユーザには厳しいので`-o StrictHostKeyChecking=no` のオプションを加えてる
Vim基本操作

# Vim基本操作

### vim起動
* `vi` or `vim`：vim起動
* `view`：Viewモードで起動

### モード変更
* `i`：Insert Mode
* `a`：次の文字からInsert Mode
* `o`：選択行の下に空白を入れ、Insert Mode
* `O`：選択行に空白を入れ、Insert Mode
* `esc`：Normal Mode

### 移動
* `k`：上に移動
* `j`：下に移動
* `h`：左に移動
* `l`：右に移動
* `:10`：10行目に移動
* `$`：行末に移動
* `0`：先頭に移動
* `^`：インデントの先頭に移動
* `{`：段落ごとに上に移動
* `}`：段落ごとに下に移動
* `[[`：セクションごとに上に移動
* `]]`：セクションごとに下に移動
* `gg`：ファイルの先頭に移動
* `G`：ファイルの最後に移動
* `ctrl + o`：移動前に戻る

### 保存・終了
* `:w ファイル名`：名前を付けて保存
* `:w`：上書き保存
* `:q`：編集終了
* `:q!`：保存しないで終了
* `:wq`：上書き保存して終了

### 編集
* `J`：行の連結
* `u`：元に戻す(undo)
* `Ctrl + u`：進める(redo)

### 範囲選択
* `v`：範囲指定開始(visual mode)
* `y`：範囲指定終了(範囲指定したところが自動でコピーされてる)

### コピペ
* `yy`：1行コピー
* `2 yy`：2行コピー
* `p`：下にペースト
* `P`：現在行にペースト

### 削除
* `x`：1文字削除
* `dd`：1行削除
* `dw`：単語の削除

### 検索・置換
* `/検索文字列`：検索
* `n`：次の検索結果に移動
* `N`：前の検索結果に移動
* `R`：置換(WindowsのInsert(上書きモード)に近い)
* `dw`：単語削除
* `:%s/置換前文字列/置換後文字列/g`：一括置換
* `:%s/置換前文字列/置換後文字列/gc`：確認しながら置換

### インデント
* `>`：右にインデントを移動
* `<`：左にインデントを移動

### 複数行を編集する
* `:norm I挿入したい文字列`：先頭に文字列を挿入する(コメントアウトなどに使用する)
* `:norm A挿入したい文字列`：行末に文字列を挿入する

### その他
* `.`：リピート(前回処理を再度実行)
* `:!コマンド`：コマンド実行( `:!Python test.py` とすると、vimを抜けなくても実行できる)
* `:!!`：前のコマンドを実行

### 設定周り
* `:set number`：行番号を表示
iPhone&iPadアプリエンジニアがVisionOS対応ですべきこと（WWDC23開催時点）

## これなに？
WWDC23開催時点で判明した、iPhone&iPadエンジニアがVisionOS（VisionProヘッドセットデバイス）へのアプリ対応でしておくべきことを簡潔にまとめています

## 結論
- 基本的にiPhone&iPad向けのアプリはヘッドセットで問題なく動作する可能性が高いとのことで、大きな作業は発生しない
- XcodeにxrOS SDK(ヘッドセットデバイス向けSDK。多分visionOS SDKになる)をインストールする必要がある
- ライトモード定義での対応が必須
  - ヘッドセットではアプリがライトモードで動作するため
- iPadアプリの場合は横向き対応が必要
  - 基本横向き表示されるので、縦向き推奨のアプリは明示すること
  - iPhoneアプリは縦で表示される
- デバイス独自の機能（カメラなど）を利用している場合は、デバイスの機能が利用可能か否かのチェックコードが必須
  - まだ詳細は出ていないが、おそらくmacro等でデバイスごとに利用する機能を分岐する必要などが出てくるかも
  - 一旦はチェックしておけば問題ないとのこと
- カスタムジェスチャーを入れている場合、複数タップの許諾などをチェックし動作確認すること
  - ヘッドセットでは両手同時や目や声での操作が可能になるため、既存のカスタムジェスチャー定義で予期せぬ操作が行われる可能性があるとのこと
  - 両手で同時に操作されることを想定して、設定を見直す必要がある
- Info.plistに新しい設定項目を追加
  - UIPreferredDefaultInterface Orientation キーなどのヘッドセット用の設定項目をInfo.plistに追加する必要がある（追加される詳細なキーは未だ未発表？？）
- UIKitのViewに目や声でアクセスできるプロパティを設定する
  - 検索窓などのFieldであれば、isLookToDictateEnabled というプロパティをtrueにすることで、目と声で検索できるようになるとのこと
  - 上記以外にも今後ヘッドセットならではのアクセス方法に関するプロパティが出てくるかも
- ARKitを利用している場合は再構築が必要
  - iPhoneやiPadのカメラ映像上で動作するようなARView/ARSessionなどはヘッドセットでは動作しないとのこと
  - visionOSと同時にARKitも大きく刷新されたことで、改めて再構築する必要がある
- 今後の方針を決める
  - 基本的に既存のアプリはvisionOS上で問題なく動作するが、あくまで四角いWindow上でしか動作しないため、空間的に利用できるアプリにはならない
  - その上で、iPhone&iPadのアプリとしてiOS SDKでビルドしてヘッドセット上で動作させるか、あるいはヘッドセット用アプリとしてしっかり対応してxrOS SDKでビルドするかを議論する必要がある


## 余談
### 
- Touch ID や Face ID をサポートしている場合、ヘッドセット上で目を使いロックを解除する「Optic ID」と自動でブリッジされるとのこと。すごい。
- SpriteKit や Storyboard などのUIフレームワークはvisionOSのビルドでは利用出来ない。したがって、こうしたフレームワークを利用している場合、iOS SDKでビルドするしかない。

## 参考文献
https://developer.apple.com/videos/play/wwdc2023/10090/
Terraformのセットアップ

## はじめに
Terraform入門しました！Iacかなり便利ですね！そこで今回はTerraformのセットアップを記事にしました。
Terraformのバージョン管理はasdfです。セットアップ後、動作確認としてEC２インスタンスを作成します。


### 環境
MacBook Pro intel
macOS Monterey バージョン12.6


## asdfのインストール
asdfを使用することで、アプリごとにTerraformのバージョンを管理できます。
公式ドキュメントに環境ごとのインストール、設定方法が記載されています。私は「Bash & Homebrew (macOS)」のパターンでインストールしました。

```bash
$ asdf version
v0.11.3-0adc6c1
```
https://asdf-vm.com/guide/getting-started.html

### Terraformのインストール
asdfでTerraformをインストールします。
```bash
$ asdf plugin add terraform
```

### Terraformのセットアップ
作業ディレクトリに.tool.versionsというファイルを作成します。このファイルに、使用するTerraformのバージョンを記載し、asdf installします。


```bash
$ ls -a
.               ..              .tool-versions

# インストール可能なバージョン
$ asdf list all terraform
~省略~
1.4.5
1.4.6
1.5.0-alpha20230405
1.5.0-alpha20230504
1.5.0-beta1
1.5.0-beta2
1.5.0-rc1
1.5.0-rc2

# 使用するバージョンを記載
$ cat .tool-versions 
terraform 1.4.5

# インストール
$ asdf install

# バージョン確認
$ terraform -v
Terraform v1.4.5
on darwin_amd64
```

### プロバイダの設定
Terraformの設定を行なっていきます。プロバイダの設定を記述するtfファイルを作成します。
(**プロバイダ**とはTerraformに対応しているクラウドサービスです。GCP、Azureなど)
```bash
$ ls -a
.               ..              .tool-versions  main.tf
```

<br>

設定を記述します。
```terraform:main.tf
terraform {
  # 使用するTerraformのバージョン
  required_version = "1.4.5"

  required_providers {
    # プロバイダの指定(今回はAWS)
    aws = {
      source  = "hashicorp/aws"
      # awsプロバイダのバージョン
      version = "~> 4.0"
    }
  }
}

provider "aws" {
  
  # AWSの認証情報、記述しない場合はdefaultが設定される
  profile = "terraform_user"
  # 使用するリージョン
  region = "ap-northeast-1"
}

```
**AWSプロバイダのバージョン**
公式ドキュメントのプルダウンからバージョンを確認できます。

https://registry.terraform.io/providers/hashicorp/aws/latest

![スクリーンショット 2023-06-07 18.54.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2485354/3650fd89-d88f-2298-2c65-5fffb20ee06e.png)


**profile**
terraformにはAWSの認証情報(AWS CLIの設定)が必須です。

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-configure.html

https://qiita.com/shonansurvivors/items/1fb53a2d3b8dddab6629


設定は以上です！




### 動作確認
Terraformの設定が終わったのでEC2インスタンスを立てて動作確認をします。
app.tfを新規に作成し、EC2インスタンスの設定を記述します。(今回はTerraformセットアップがメインの為、記述方法の詳細は省きます。)


```terraform:app.tf
resource "aws_instance" "hoge_ec2" {
  ami           = "ami-07c2a88388bb80eb0"
  instance_type = "t2.micro"

  tags = {
    Name = "HelloWorld"
  }
}
```
```bash
# Terraformの初期化
terraform init

# インフラの構築状態を確認
terraform plan

# tfファイルの内容を反映
terraform apply
~省略~

aws_instance.hoge_ec2: Creating...
aws_instance.hoge_ec2: Still creating... [10s elapsed]
aws_instance.hoge_ec2: Still creating... [20s elapsed]
aws_instance.hoge_ec2: Still creating... [30s elapsed]
aws_instance.hoge_ec2: Creation complete after 37s [id=i-0b5232saxdssa98e85rd]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

```

AWSマネジメントコンソールから東京リージョンでEC2インスタンスが起動していることを確認できました！Terraformの設定に問題はなさそうです！


## おわりに
これでインフラを構築する最低限の設定はできたと思います。今後もtfstateファイルの管理方法などTerraformに関する記事を作成予定です。
Apple Silicon搭載MacでDirectX 12が動かせるらしいので試します。なぜならApple Silicon搭載MacでDirectX 12が動かせるらしいからです。

## 日本語で要約してくれてる人

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">さらっととんでもないニュースが来た！<br>AppleがGame Porting Toolkitを通じてmacOSとApple Siliconに#DX12サポートを追加したらしい！<br>Wineに20kのパッチを当ててVMを使わずにmacOS上でAAA Windowsゲームを簡単にプレイできるようにするようだ！　ヒュ〜💕 <a href="https://t.co/kHqrPIXeRr">https://t.co/kHqrPIXeRr</a></p>&mdash; ジトメ (@ji10me) <a href="https://twitter.com/ji10me/status/1666231772278059008?ref_src=twsrc%5Etfw">June 6, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 元ツイ

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Apple added <a href="https://twitter.com/hashtag/DX12?src=hash&amp;ref_src=twsrc%5Etfw">#DX12</a> support to macOS and Apple Silicon via its Game Porting Toolkit. It’s basically a 20k patch to Wine that will make it easy to play AAA Windows games on macOS without using a VM. <a href="https://t.co/OFwc0NREb6">https://t.co/OFwc0NREb6</a></p>&mdash; Christina Warren @ RenderATL (@film_girl) <a href="https://twitter.com/film_girl/status/1666127888679321602?ref_src=twsrc%5Etfw">June 6, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## やってみた

:::note warn
正式リリース前です。自己責任でお願いします。
:::

ターミナルを開いて、Rosseta2でx86_64に切り替えます。x86_64版のHomebrewが必要なので、合わせてダウンロードしておきましょう。

```zsh:terminal
arch -x86_64 zsh
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

arm64版のHomebrewは `/opt/homebrew/bin/brew` にある一方、x86_64版は `/usr/local/Homebrew/bin/brew` にインストールされます。今回はPATHをいじるのも面倒なので、そのままバイナリを指定して実行します。かなり時間がかかるので、なかなか終わらなくても焦らないでください。

```zsh:terminal
/usr/local/Homebrew/bin/brew tap apple/homebrew-apple
/usr/local/Homebrew/bin/brew install game-porting-toolkit
```

インストールが完了したら以下のコマンドを実行します。 `~/game` の部分は好きなフォルダを指定してください。

```zsh:terminal
WINEPREFIX=~/game `/usr/local/bin/brew --prefix game-porting-toolkit`/bin/wine64 winecfg
```

上記コマンドを実行するとポップアップが現れるので、Windowsのバージョンを10に変更してOKを押します。

次に以下のリンクからGame porting toolkit betaをダウンロードします。
https://developer.apple.com/download/all/?q=game%20porting%20toolkit

ダウンロードしたら中身を全て適当な場所（以下では `~/apple-gpt` とします）にコピーします。

さて、それが済んだら以下のコマンドで最後の準備が完了します。もちろん `~/apple-gpt`　の部分は適宜読み替えてください。

```zsh:terminal
ditto ~/apple-gpt/lib `/usr/local/bin/brew --prefix game-porting-toolkit`/lib/
```

これで準備は完了です。以下のコマンドで好きなゲームを起動してみてください。`~/apple-gpt` や `~/game` は適宜読み替えてください。

```zsh:terminal
~/apple-gpt/gameportingtoolkit ~/game "YOUR_GAME.exe"
```

ゲームが起動したら気が済むまで遊びましょう。
【scikit-learn】Random forest回帰、デフォルトだとrandom forestじゃないよって話

# はじめに
初めまして、いわです。
今回は、scikit-learnのRandom forest regressorをデフォルトのパラメータで使用するとRandom forestとしては機能していないという話をします。
# Random forestとは？
Random forestは決定木ベースのアルゴリズムである、くらいの理解はある前提で話を進めます。
まず、random forestの定義について説明します。
以下のqiita記事とRandom forestの論文を参考にしました。

https://qiita.com/AwaJ/items/3c02ff64b6a89e1a96f1

https://link.springer.com/article/10.1023/A:1010933404324
### 定義
- 学習データから重複を許してランダムに複数組のサンプル集合を抽出(Bootstrap Aggregating: バギング)
- 各ノードを分割するために特徴量をランダムに選択する(**ここ重要**)と、Adaboostと比較して良好な結果が得られる
- ジニ係数を計算し、決定木を作成
- 予測時は各決定木の結果でアンサンブルに推定

データセットをランダムに分割して、複数のサブサンプルに対して特徴量もランダムに選んで決定木を複数作ってその結果をアンサンブルして推定すると精度がAdaboostより良い。ということですね。

# Random forestのドキュメントを見てみると
#### [Random forest classifier](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html)のドキュメント
#### [Random forest regressor](http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestRegressor.html)のドキュメント
色々なパラメータを調整できるのですが、`max_features`を調整することで、各弱学習器を構築する際に、特徴をいくつ使用するかを決定することができます。
#### Random forest classifierの場合
>max_features{“sqrt”, “log2”, None}, int or float, default=”sqrt”

となっており、入力した特徴量の数の根号数分だけで決定木を作るようになっています。ちゃんとRandom forestの定義に則っていそうで素晴らしいですね。ところが・・

#### Random forest regressorの場合
>max_features{“sqrt”, “log2”, None}, int or float, default=1.0

 となっており、デフォルトだと入力した特徴全てを利用するような設定になっています。なんということでしょう。。
これではRandom forestの定義に則っておらず、ただバギングを行っているだけになっています。。。
# 公式の見解
公式ドキュメントを眺めていた時にこのことに気づき、scikit-learnのissueを覗いたんですが、実はこの議論、scikit-learnのgithubにissueとして上がっていました。

https://github.com/scikit-learn/scikit-learn/issues/20111

熱い議論が繰り広げられているので興味のある方は是非覗いて見てください。
ざっくりいうと、回帰の場合特徴は全部取ってきた方が性能がいい(今回の実験では)
とのことです。

# まとめ
- Scikit-learnのRandom forest regressorはデフォルトのパラメータだとただのバギングした決定木としてしか機能していない
- もし、正しくRandom forestとして使いたい場合は自分でmax_featureを調整しよう
- 公式ドキュメントをちゃんと読もう

以上です、最後まで見てくださった方ありがとうございました！
【Flask】Flaskとは

# Flaskとは

Pythonベースの軽量Webフレームワーク(マイクロフレームワーク)です。

オーストリアのArmin Ronacher氏がエイプリルフールのネタとしてリリース。そこから人気が出始め、2018年にはPython開発者調査で最も人気のあるWebフレームワークとなりました。

Pythonフレームワークの使い分け
シンプル・軽量→Flask
高機能・重厚→Django

2010年4月に初版の0.1、2018年4月に1.0、2021年5月に2.0がリリースされました。

# Flaskの特徴

Flaskは、Werkzeug(WSGIライブラリ)とJinja2(テンプレートエンジン)の2つをラッピングして作られています。

### WSGI
PythonのWebインターフェイス標準規格に準じたライブラリです。

# Flaskの設計思想
FlaskはPython製のマイクロWebフレームワークです。コアとなる機能を保ちつつ、拡張性をもっています。

デフォルトではDB機能が含まれず、最小限の機能のみとなっています。必要に応じて、拡張機能を追加すろことで、小規模から大規模開発まで対応ができます。

# Flaskの動作環境

Python3.6以上が必要になります。
※非同期機能を利用する場合は3.7以上が必要になります。

パッケージマネージャーでFlaskをインストールした際に自動的に下記のモジュールもインストールされます。
・Werzeug
・Jinja
・MarkupSafe
・ItsDangerous
・Click

# 三条項BSDライセンス
Flaskは、三条項BSDライセンス(BSD-3-Claus)と共に配布されています。「無保障であること」、「」著s買う県、ライセンス条項
の明記を条件としており、これを満たせば、ユーザーはそのソフトウェアの使用や流布、修正、派生版の流布をすることを制限されません。
エラー文の読み方

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/ae77feb8-e61d-5c29-520f-9c96e12557c5.png)
よく、下記のようなエラー分が出る。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/b0a6713e-5478-45df-bf89-78245bd3b028.png)
　こういうエラーが出現した時、「上記のエラー文をそのままインターネット検索をしてしまう”」と初心者の私は考えてしまいます。

　調べてみても、”length” というメソッド自体が存在しており、不正な記述でもないため、意味がわからないくなってしまう。
上の画像のエラーは “undefined method” で、このエラーの読み方は “for” の後に記載されている “nil:NilClass” が重要です。

１：エラー文の解釈の誤り
①：誤った解釈：「”length” が使えない。“NilClass” はよくわからないので考えない。」
②：正しい解釈：「”nil” の変数に対して “length” メソッドを使おうとしている。変数が “nil” となってる原因を仮説・検証する必要がある。」

２：nil:NilClassとは
　この場合、lengthが “NilClass” に対してダメだよ、と言われているので、“length” を使おうとしている変数の “str” が “NilClass” ということになります。
つまり、”str” の変数が NULL になってしまっているんです！
　このケースは変数でしたが、渡されていない “params” に対して色々なメソッドを使おうとしても同じエラーが起きるケースはやりがちなので、気をつけましょう。

３：エラーの解決していく手順について
①変数がNULLとなる原因を探す。
②変数がNULLにならないように対処する。
paiza.ioでelixir その230

# 概要
paiza.ioでelixirやってみた。
良いコードを見つけたので、やってみた。

# 参考にしたページ。

https://qiita.com/nori-channel/items/ec22bf1bd7b54a2aae70

# サンプルコード

```
[3.14, :pie, "Apple"]
|> IO.inspect
list = [3.14, :pie, "Apple"]
|> IO.inspect
["π" | list]
|> IO.inspect
list ++ ["Cherry"]
|> IO.inspect
[1, 2] ++ [3, 4, 1]
|> IO.inspect
["foo", :bar, 42] -- [42, "bar"]
|> IO.inspect
[1,2,2,3,2,3] -- [1,2,3,2]
|> IO.inspect
[2] -- [2.0]
|> IO.inspect
[2.0] -- [2.0]
|> IO.inspect
hd [3.14, :pie, "Apple"]
|> IO.inspect
tl [3.14, :pie, "Apple"]
|> IO.inspect
[head | tail] = [3.14, :pie, "Apple"]
|> IO.inspect
head
|> IO.inspect
tail
|> IO.inspect
{3.14, :pie, "Apple"}
|> IO.inspect
File.read("./file")
|> IO.inspect
File.read("./file2")
|> IO.inspect
[foo: "bar", hello: "world"]
|> IO.inspect
[{:foo, "bar"}, {:hello, "world"}]
|> IO.inspect
map = %{:foo => "bar", "hello" => :world}
|> IO.inspect
map[:foo]
|> IO.inspect
map["hello"]
|> IO.inspect
key = "hello"
|> IO.inspect
%{key => "world"}
|> IO.inspect
%{:foo => "bar", :foo => "hello world"}
|> IO.inspect
%{foo: "bar", hello: "world"}
|> IO.inspect
%{foo: "bar", hello: "world"} == %{:foo => "bar", :hello => "world"}
|> IO.inspect
map = %{foo: "bar", hello: "world"}
|> IO.inspect
map.hello
|> IO.inspect
map = %{foo: "bar", hello: "world"}
|> IO.inspect
%{map | foo: "baz"}
|> IO.inspect
map = %{hello: "world"}
|> IO.inspect
#%{map | foo: "baz"}
|> IO.inspect
Map.put(map, :foo, "baz")
|> IO.inspect



```

# 実行結果

```
[3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]
["π", 3.14, :pie, "Apple"]
[3.14, :pie, "Apple", "Cherry"]
[1, 2, 3, 4, 1]
["foo", :bar]
[2, 3]
[2]
[]
[3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]
3.14
[:pie, "Apple"]
{3.14, :pie, "Apple"}
{:error, :enoent}
{:error, :enoent}
[foo: "bar", hello: "world"]
[foo: "bar", hello: "world"]
%{:foo => "bar", "hello" => :world}
"bar"
:world
"hello"
%{"hello" => "world"}
%{foo: "hello world"}
%{foo: "bar", hello: "world"}
%{foo: "bar", hello: "world"}
%{foo: "bar", hello: "world"}
"world"
%{foo: "bar", hello: "world"}
%{foo: "baz", hello: "world"}
%{hello: "world"}
%{hello: "world"}
%{foo: "baz", hello: "world"}
```

# 成果物

https://paiza.io/projects/0Eyknj8s6UNcnNFLTKKsew?language=elixir


以上。
【GitHub】ローカルリポジトリを新しいリポジトリにプッシュする方法

# はじめに
GitHubはソースコードのバージョン管理や共同作業を行うための人気のあるプラットフォームです。この記事では、GitHubとの連携を通じて、ローカルリポジトリの内容を新しいリポジトリにプッシュする手順を紹介します。Gitの基本的な知識があることが前提となります。

## GitHubで新しいリポジトリを作成する

[GitHubのリンク](https://github.com/)


1. GitHubのホームページにアクセスし、ログインします。
2. ヘッダーメニューの「New」ボタンをクリックします。
3. リポジトリの詳細設定ページが表示されます。
3. リポジトリ名や説明を入力し、公開/非公開の設定を選択します。
3. 「Create repository」ボタンをクリック
3. 新しいリポジトリを作成します。

## ローカルリポジトリを設定、プッシュする

### ローカルマシン上でGitの初期化
```csharp:コマンド
git init //カレントディレクトリをgitの対象として初期化する
```
### ファイルをステージングする
```csharp:コマンド
git add . // 変更されたすべてのファイルをステージング
```
### ステージングしたファイルをコミットする
```csharp:コマンド
git commit -m "コミットメッセージ" //変更履歴を保存する
```
## ローカルリポジトリを操作する
### gitの履歴を確認する
```csharp:コマンド
git log // コミットした履歴を確認する
```

## GitHubと連携する

### GitHubのリポジトリと連携する
```csharp:コマンド
git remote add origin GitHubのリポジトリURL 
// 一度設定すれば次回から不要
// 自身のGitHubに作成したリポジトリからURLをコピーして貼り付けする

```

![スクリーンショット 2023-06-07 18.57.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2765288/52a13ae6-6a57-f9a9-6ee5-91691f052d74.png)

### GitHubにプッシュする
```csharp:コマンド
git push -u origin main
// git push -u origin ブランチ名
```

## まとめ
以上がローカルリポジトリを新しいGitHubリポジトリにプッシュする手順になります。GitHubとの連携を通じて、ソースコードのバージョン管理や共同作業をスムーズに行うことができます。Gitの基本的な操作に慣れておくと、プロジェクトの管理がより効率的になります。GitとGitHubを活用して、効果的なコードの管理と共同作業を行いましょう。
【TensorFlow】TensorFlowとは

# TensorFlowとは
2015年にGoogleが開発した、機械学習のソフトウェアライブラリです。

Googleは以前より、クローズドソースでのディープラーニングフレームワーク開発を行っていました。そこで、2011年にDistBiefという音声認識、イメージ検索といったサービスの性能を上げるディープラーニング基盤を開発します。しかし、社内では一定の成果を得られたものの、凡庸性が低く、公開することができませんでした。

そこでDistBeliefを改良し、オープンソースとして公開できる凡庸性の高いディープラーニングフレームワークTensorFlowが誕生します。2017年には、TensorFlow1.0として正式版もリリースにもいたりました。

Tensorという名前は、Googleが後にAndroidや、Google Pixelに搭載したSoCであるTensorの由来でもあります。

## Tensor(テンソル)とは
Tensorとは多次元配列の概念をデータに対して扱えるようにしたものです。

数学の世界では、行列の概念として、0次元の配列をスカラ(0階のTensor)、1次元をベクトル(1階のTensor)、2次元を行列(2階のTensor)と呼びます。

## TensorFlowとKerasの関連性
Kerasとは、Googleが開発したニューラルネットワークライブラリの1つで、TensorFlow上で動作します。ニューラルネットワークを自由に拡張、カスタマイズすることのできるインターフェースです。

ディープラーニングのベースとなる数学的理論部分を最初から開発する必要がなく、効率的な開発が可能です。

2017年にTensorFlowがKerasのサポートを決定。TensorFlow2.0ではKerasと統合しました。


# TensorFlowの特徴
・データの読み込み
・前処理
・計算
・状態
・出力
上記の処理に対してTensorを扱い、データフローグラフを構築して処理することに特化しています。

また、PythonのコアライブラリやC++のコアライブラリ、JavaScript向けのライブラリも提供されています。

モバイルやIoT向けのTensorFlow LiteではAndoroidやiOSでも利用できます。

また、効率的なデバッグを可能にするEager Executionの提供、アドオンライブラリの充実など、自由のライブラリを選択できます。

## 分散学習とは
データフローグラフを構築したあと、計算したものを複数に分散して並列処理を行うこと。TensorFlowはこの分散学習を行えます。

分散処理のおかげでビッグデータも扱えます。

< 欠点 >
分散学習実行時に通信の失敗や、使っている端末の故障が起こる可能性があります。
→Fault Toleranceで対処

## Fault Tolerance
TensorFlowにはFault Toleranceが搭載されており、これにより障害が起こりそうになると処理を停止し、はじめから構築し直します。

## TensorBoard
TensorFlowにはTensorBoardという可視化ツールが搭載されており。学習失敗時にデータを目で見て問題を発見することができます。

# TensorFlowのメリット
TensorFlowがGoogleが開発するオープンソースであるため、学習時に参考情報が多く公開されています。

また、GPU操作が不要で効率的な開発が可能です。一般的なディープラーニングのライブラリには、その都度、GPUの処理が必要になるものも多いです。しかし、TensorFlowは元からGPUを使用する設定になっているため、都度、処理をする必要がありません。

# TensorFlowのデメリット
TensorFlowは非常に性能が良く、元々GPUを使用する設定となっているため、TensorFlowを使用するハードウェアの性能もある程度必要となります。

データの読み込みや前処理、計算・出力などをTensorで情報管理しているため、特殊なソースコードを使用しています。そのため理解と多次元配列に関する知識の習得などに時間を要する可能性があります。

# TensorFlowとPytorchの違い
Pytorchは、Facebookが開発した機械学習のフレームワークです。TensorFlowの1年後にリリースしました。

通常のニューラルネットワーク構築に使われる構築に使われるライブラリが静的な計算グラフで設計されているのに対し、Pythorchは動的な計算グラフで設計されています。そのため、柔軟性が高く、複雑なネットワークも比較的安易に実装が行えます。

研究分野でよく使用されるフレームワークです。


# TensorFlow使用用途

・映像から物体検出
・画像認識
・画像検索
・音声認識
・翻訳
・アート生成
・自然言語処理
・ECサイトで購入履歴を参照し、おすすめ商品を提示

# 実例
・Twitter
ユーザーに関連性の高いツイートをTLの最上部に表示す
・Google
検索、翻訳、Gmail(迷惑メールの選別)、広告表示

GoogleのMagentaというプロジェクトではニューラルネットワークを使用して作曲やアートを生成。
はじめての Dynamics 365 Customer Service

# はじめに
Dynamics 365 Customer Service Professional のライセンスを付与したが、始め方が全く分からなかったので備忘録として残しておきます。

# ログインではない
以下の手順の通りに https://office.com にアクセスし、アプリを探したが見つかりませんでした。

> Dynamics 365 ログインと Office アプリへのアクセス - Power Platform | Microsoft Learn
https://learn.microsoft.com/ja-jp/power-platform/admin/sign-in-office-365-apps#direct-sign-in-to-the-dynamics-365-home-page

# 試用版を始めてみる
試用版を始めてみるとDynamics 365 のアプリがPower Appsにできるようなのがわかりました。

# 環境を作る
どうやらDynamics 365というのはPower Apps だという事実から、とりあえず環境を作ってみようという思いから、入り口を見つけることができました。

以下手順です。

１．Power Platform 管理センター（https://admin.powerplatform.microsoft.com）にアクセスする。
２．「環境」→「＋新規」を選択し、必要な項目を入力します。
３．環境が作成されたら、「＋Dataverse を追加」をクリックする。
４．Dynamics 365アプリを有効にしますか？ のPower Appsに加えます。を「はい」にします。
５．これらのアプリを自動的に展開 から「Customer Service」を選択し、追加をクリックする。
６．環境作成後、Power Appsに関連アプリが展開されます。

# まとめ
Power Automate や Excel のように簡単につかえるじゃないかと思っていたら、意外と前準備が必要なものでした。
Airdrop 連絡先のみ 発動条件

### Airdropには、オプションがあります。下の画像のように、３つあります。

### 連絡先のみ　は　Apple ID　のメールアドレスが、相手の連絡先に登録されていると、発動します。


![IMG_0039.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3328398/df1ea8a5-639c-edc5-9e91-ea8f1a95ede8.jpeg)
共通鍵暗号方式の鍵の本数の求め方

# はじめに

この記事では共通鍵暗号方式の**鍵の本数の求め方のみ**をまとめています。
また厳密な証明ではなく、分かりやすい解説を目指して書いていますので、ご了承ください。


# この記事が対象とする読者

・基本情報技術者試験のレベルで共通鍵暗号方式がざっくりと分かる方

# 鍵の本数の求め方

## 一般式を使わない場合

A,B,C,Dの4台のデバイスがあるとします。

1. Aから考えると、Bとの鍵、Cとの鍵、Dとの鍵、で3本の鍵が必要です。

2. Bから考えると、Aとの鍵は必要ないので、Cとの鍵、Dとの鍵、で2本の鍵が必要です。

3. Cから考えると、Dとの鍵の1本の鍵が必要です。

4. Dから考えると、すでにすべてのデバイスとの鍵を持っています。

1〜4を合計すると6本の鍵が必要です。

## 一般式を使う場合

はじめに一般式を示します。

n台のデバイスに必要な共通鍵の本数は

```math
\frac{n\left(n - 1\right)}{2}
```

です。

次にこの式の求め方を示します。

**一般式を使わない場合**のように具体的な台数で計算してみると分かりますが、必要な鍵の本数は**1から(台数 - 1)までの総和**になっています。

賢い方はここでお気づきかも知れませんが、

```math
1 + 2 + \cdots + (n - 2) + (n - 1) = \sum_{k=1}^{n-1} k
```

なので、あとは計算すれば終わりです。

しかし、これは現在の高校数学Bの内容ですので、別のやり方も紹介します。

このような総和を求めるときは、**元の式とは項が逆の順番に並んだ式**を考えます。

```
// 元の式
   1    +    2    + ... + (n - 2) + (n - 1)
// 項が逆の順番に並んだ式
(n - 1) + (n - 2) + ... +    2    +    1   
```

そして縦に足します。

```
   1    +    2    + ... + (n - 2) + (n - 1)
(n - 1) + (n - 2) + ... +    2    +    1   
// 縦に足す
   n    +    n    + ... +    n    +    n    
```

この結果は元の式と、項が逆の順番に並んだ式とを足した結果と等しいです。

ここでnの個数は(n - 1)個なので、
```math
n + n + \cdots + n + n = n(n - 1)
```
です。

ただし、勝手に項が逆の順番に並んだ式を足しています。そして、元の式と項が逆の順番に並んだ式の総和は、項の順番が違うだけなので等しいです。ですので、2で割ります。すると、
```math
\frac{n\left(n - 1\right)}{2}
```
となります。

# さいごに

ただ暗記するのではなく、意味まで理解してもらえたならば幸いです。

* 間違いや分かりにくいところは遠慮なくコメントしてください
Oracle Database 23cで追加されたSQLの新機能"SELECT Without FROM Clause"をFree版で試してみた

23cから"SELECT Without FROM Clause"機能が追加され、DUAL表を使う問合せに関して"FROM DUAL"句の記述が不要となりました。
これにより、SYSDATEの出力などが以下のように書けます

```sql
SQL> SELECT SYSDATE;

SYSDATE
--------
23-06-07

SQL> SELECT 1+2;

       1+2
----------
         3
```

ちなみに 10053 SQLトレースを確認すると、問合せ変換されていることが分かります。

```sql
SQL> ALTER SYSTEM FLUSH SHARED_POOL;

SQL> ALTER SESSION SET EVENTS '10053 trace name context forever';

SQL> SELECT SYSDATE;

SYSDATE
--------
23-06-07

SQL> SELECT 1+2;

       1+2
----------
         3

SQL> ALTER SESSION SET EVENTS '10053 trace name context off';

SQL> SELECT VALUE FROM V$DIAG_INFO WHERE NAME = 'Default Trace File';

VALUE
--------------------------------------------------------------------------------
/opt/oracle/diag/rdbms/free/FREE/trace/FREE_ora_3339190.trc
```

上記で確認したトレースファイルを見てみます。

```bash
$ grep -c 3 "Final query" /opt/oracle/diag/rdbms/free/FREE/trace/FREE_ora_3339190.trc
...(略)...
Final query after transformations:******* UNPARSED QUERY IS *******
SELECT SYSDATE@! "SYSDATE" FROM "SYS"."DUAL" "DUAL"
...(略)...
Final query after transformations:******* UNPARSED QUERY IS *******
SELECT 3 "1+2" FROM "SYS"."DUAL" "DUAL"
```

以上から、内部的にはDUAL表へ問い合わせるように変換されているようです。
AWS lambda のcoding/upload/invokeをローカルで完結させる

Put this `Makefile` in your local machine.

```makefile
.PHONY: all
all: zip upload invoke

.PHONY: zip
zip:
	# TODO: Don't update this Makefile (^^)
	# TODO: I would like to use `zip -FSr function.zip .` to speed up, but sometimes it did not work.
    # NOTE: To exclude specific files, use an option `--exclude "node_modules/*"`
	zip -r - . --exclude function.zip > function.zip

.PHONY: upload
upload:
	aws lambda update-function-code --function-name ${FUNCTION_NAME} --zip-file fileb://function.zip --region ${AWS_REGION} --profile ${AWS_ROLE}  | jq .

.PHONY: invoke
invoke:
	aws lambda invoke response.json --function-name ${FUNCTION_NAME} --invocation-type RequestResponse --log-type Tail --region ${AWS_REGION} --profile ${AWS_ROLE} --payload file://payload.json --cli-binary-format raw-in-base64-out > log.json\
	&& echo "\n################### Log #########################\n"\
	&& cat log.json | jq --raw-output '.LogResult' | base64 --decode\
	&& echo "\n################### Response #####################\n"\
	&& cat log.json | jq '.StatusCode'\
	&& cat response.json | jq .\
	&& rm log.json\
	&& rm response.json
```

Also, put the content which you would like to pass as `event` arg in `payload.json`.

```json
{
    "version": "0",
    "id": "53dc4d37-cffa-4f76-80c9-8b7d4a4d2eaa",
    "detail-type": "Scheduled Event",
    "source": "aws.events",
    "account": "123456789012",
    "time": "2015-10-08T16:53:06Z",
    "region": "us-east-1",
    "resources": [
        "arn:aws:events:us-east-1:123456789012:rule/my-scheduled-rule"
    ],
    "detail": {}
}
```


Substitute enviromental variables, and run `make all`.

```sh
export AWS_ROLE=your_aws_role
export AWS_REGION=us-east-1
export FUNCTION_NAME=your-lambda-function-name

make all
```
WordPressのACFのOptionsのエディタにAddQuickTag有効にしたい

固定ページと投稿タイプ以外はむりやりにしかdけいなかった

```php
add_action("admin_init" , function(){
    global $pagenow;
    $adQuickTag = Add_Quicktag::get_object();

    if($pagenow == 'admin.php' && !empty($_GET["page"]) && $_GET["page"] == "acf-options") {
        add_action( 'admin_print_scripts' , array( $adQuickTag, 'get_json' ) );
        add_action( 'admin_print_scripts' , array( $adQuickTag, 'admin_enqueue_scripts' ) );
    }
});
```
こんな感じでページによって自分でscriptsの読み込みを発行する
これでScriptは出力されるんだが、対象の投稿に対するタグの設定がされない

```php
add_filter( 'addquicktag_post_types', function($post_types){
    $post_types[] = 'toplevel_page_acf-options';

    return $post_types;
} );
```
post_typeではないが、current_screenのidで判定してるようなので、対象のページのidをいれてあげる

管理画面から投稿タイプと同じように、出力したいタグのチェックボックスつけれるので、つける

これで対応できました、バージョンによっては動かなそう
bashスクリプトでコマンドとして実行されてるのかsourceされてるのかを判定する

# 結論
結論から書くと以下のコードで判定できます。

```bash
if [[ $BASH_SOURCE == "$0" ]]; then
  echo "スクリプトとして実行されている"
else
  echo "sourceされている"
fi
```



# 元記事

元は `$FUNCNAME` を使う方法を書いてたんですが、翌々考えたら `[[ $BASH_SOURCE == "$0" ]]` を使うほうが良いと思ったので結論を変えました。以下は元記事です。

## スニペットコード
以下のコードで判定できます。
```bash
if (_(){ [[ ${FUNCNAME[*]} == *main ]];};_); then
  echo "スクリプトとして実行されている"
else
  echo "sourceされている"
fi
```

これは Python でいう `if __name__ == '__main__'` と同じような役割をするコードです。

※後述してますが、コンソールに↑このコードを貼り付けて試しても正常な判定にはなりません。あくまでスクリプトファイル内で利用する際のスニペットと思ってください。

## 判定式部分を注目する

```bash
# スクリプトがコマンドとして実行されているか？
(_(){ [[ ${FUNCNAME[*]} == *main ]]; };_) # $? が 0 ならコマンドとして実行されている
# スクリプトがsourceで読み込まれているか？
(_(){ [[ ${FUNCNAME[*]} == *source ]];};_) # $? が 0 ならsourceされている

# ↓これだけでも判定できるけど後から見た人が意味を理解できないからおすすめしない
(_(){ [[ ${FUNCNAME[*]} == *n ]]; };_) # $? が 0 ならコマンドとして実行されている
(_(){ [[ ${FUNCNAME[*]} == *e ]]; };_) # $? が 0 ならsourceされている

# 汎用的な関数として定義するならこんな感じ
is_sourced() { [[ ${FUNCNAME[*]} == *source ]]; }
is_executed() { [[ ${FUNCNAME[*]} == *main ]]; }
is_interactive() { ! is_sourced && ! is_executed; }
```

## 説明
- `$FUNCNAME` は配列変数で、`[0]`に現在の関数名、[1] 以降には呼び出し元の関数名が内側から順に入ってくる。
- 一番外側の関数名にはスクリプトの使われ方によって `main` または `source` が入ってくるのでコレで判定できる。
- `$FUNCNAME` は関数内でしか使えないので最低一度は関数定義をする必要がある。
- `$FUNCNAME` 以外で判定する方法は多分無い。→ `$BASH_SOURCE`と`$0`の比較で十分でした。
- 丸括弧で囲ってサブシェル内で実行しているのは関数定義で名前空間を汚さないため。
- 判定式について、ロジック的には `${FUNCNAME[${#FUNCNAME[@]}-1]}` が `main` または `source` と等しいかで判定するべきだが、`${FUNCNAME[*]}` として1つの文字列に連結した値の末尾一致でも判定可能なのでこうしてる。見た目の複雑さも小さめで読みやすいと思う。
- bash-4.2以降では配列のインデックスに負数を与えると後ろから取れるようになったので `${FUNCNAME[-1]}` と書けるけど、古い bash [^old-bash] だとエラーになるので避けた。

[^old-bash]: 例えば macOS の /bin/bash は 2023-06-09 時点で未だに 3.2.57 です。

## 例外について
お気づきかもしれないが、汎用的な関数として定義した時に突然 `is_interactive` というのが登場している。

実は bash には `source` や `main` 以外でコードが実行されるケースがあるのだ。もったいぶってるけど実は一番馴染み深い使われ方で、要はインタラクティブなシェルとして使われている場合は「今実行されているコードはそもそもスクリプトじゃない」という状態であり、この場合 `$FUNCNAME` の一番外側が定義されない状態、すなわち `＄FUNCNAME` は自身の関数名が1つはいっているだけのサイズ1の配列になるようだ。

そのため第3の状態を判定する `is_interactive` という関数も欲しいよねってことで追加したワケです。

※2023-06-09追記: `[[ $BASH_SOURCE == "$0" ]]` を使ったほうがインタラクティブシェルで source した場合も、source されたと判定できるのでそっちを使った方が良いです。

## 関数にする場合は関数名に注意
ちなみに、インタラクティブな利用を想定した場合は関数名に気をつけましょう。具体的には `main` や `source` で終わる名前をつけてはいけません。

実は最初は `is_main()` と `is_source()` という関数名にしてたんだけど、`${FUNCNAME[*]}` を1つの文字列にjoinして末尾で判定というロジックだとインタラクティブ時は大外の関数名が自分自身になっちゃうことから、`is_main` という関数名だと `${FUNCNAME[*]}` が `is_main` となってしまい、`[[ is_main == *main ]]` という式は常に真になっちゃってsouceとmainの区別も付かなくて駄目じゃんｗ というバグに遭遇します。

その結果、末尾をごまかすために `is_sourced()` と `is_executed()` という名前に変えて記事にしてみたという経緯があります。
プログラマーへの道 #14 オブジェクト #2（プログラミング入門）のメモ

# 参考にした動画
https://youtu.be/w_dOO7F4SHQ

# この動画で学んだこと
・関数をオブジェクトにすることができる。
・関数をオブジェクト化した関数をコンストラクター関数と呼ぶ。
・バリデーションとデバッグの違い

# 関数をオブジェクトにしてできること
・コンストラクター関数は型の名前を付けられる。
・コンストラクター関数の各種プロパティにバリデーションをかけられる。
・htmlでボタンをタグを複数設置したのち、プロパティを追加したい時にコンストラクター関数を設置していれば変更箇所が1箇所で済む。

# 関数をオブジェクトにする方法
・関数のスコープ内にthisでプロパティを代入して、newを使って関数を呼び出すと関数をオブジェクトとして利用することができる。
・[functionコンストラクター｜MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/Function)


# 写経したコード
```html
<html>
	<body>
	</body>
	<script>
		// User型というコンストラクター関数
		function User(name,address){
			this.name = name
			this.address = address
			this.hobby = "sleeping"
		}
		user = new User("tio","xxx")
		console.log(user)

		// オブジェクト
		// personは型ではなくpersonというオブジェクトの名前を定義している。
		// コンストラクター関数にすると、オブジェクトに型を作れる
		// person = {
		// 	address:"aaa",
		// 	tel:"bbb",
		// 	tel2:080,
		// };

		// 関数
		function User2(name,address){
		}
        // バリデーション
		// nameが空だったら"name is empty"というアラートを出力する
		function User3(name,address){
			if(name == ""){
				alert("name is empty")
				return
			}
			this.name = name
			this.address = address
			this.hobby = "sleeping"
		}
		user = new User3("","xxx")
		console.log(user3)
	</script>
</html>
```
# バリデーションとデバッグの違い
・バリデーションは、ソフトウェアが正しいデータを処理し、意図した動作を行うための手段。
・デバッグはエラーの発見と修正に焦点を当てている。
・ソフトウェアの品質や安定性を向上させるためのプロセス。

結果、バリデーションとデバッグは異なる目的とアプローチを持つ。
バリデーションはデータの検証に関わり、デバッグはソフトウェアのエラーの特定と修正に関わる。

<b>[デバッグ（Debugging）](https://e-words.jp/w/%E3%83%87%E3%83%90%E3%83%83%E3%82%B0.html)</b>
・デバッグの目的は、不具合を修正してソフトウェアの正常な動作を回復させること。
・ソフトウェアの開発やトラブルシューティングの過程で発生するエラーや問題を特定し、修正すること。
・デバッグは主にプログラムのコードやロジックの誤りを特定するために行われます。

<b>[バリデーション(validation)](https://e-words.jp/w/%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3.html)</b>
・バリデーションはエラーの特定や修正ではなく、データの整合性や正確性の確保を目的としている。
・データや入力値が所定のルールに従っているかどうかを検証するプロセス。
・バリデーションの目的は、正しいデータの受け入れと不正なデータの排除すること。
FarmRPG　UnityScene Management　まとめ Part1~Part3

# 参考
Section 9

https://www.udemy.com/course/unity-2d-game-developer-course-farming-rpg/learn/lecture/19896566#content

## 一覧

### Part1 Sceneを読み込む

![0615.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/23fa018f-792a-ab13-1eb2-00274c0bbd9e.gif)

https://qiita.com/RYA234/items/6ef5aaf4f4f0d9408486

### Part2 　シーンに読み込み時にフェードインを実装する

![0610.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/fc067887-ab7c-567a-b3f6-b1df15cb68e8.gif)

https://qiita.com/RYA234/items/21a833e3e06de44f1e0b

### Part3 Playerが別のSceneに移動できるよう実装

![0614.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/1dbd334b-4705-c6cf-3b24-e06bdaee5b26.gif)

https://qiita.com/RYA234/items/567299719df375db4348
俺のWA多すぎる史

AtCoderでWAが多すぎた回をまとめてみました。（）

# [ABC284](https://atcoder.jp/contests/abc284/standings?watching=hiroyuk1)

5完6ペナでした。Cで3ペナ、Dで1ペナ、Eで2ペナです。

# [ABC287](https://atcoder.jp/contests/abc287/standings?watching=hiroyuk1)

3完5ペナでした。Cで5ペナ、解けなかったDで11ペナです。

# [ARC156](https://atcoder.jp/contests/arc156/standings?watching=hiroyuk1)

1完6ペナでした。Aで6ペナ、解けなかったCで2ペナ、Fで1ペナです。

# [ARC157](https://atcoder.jp/contests/arc157/standings?watching=hiroyuk1)

1完15ペナでした。Aで15ペナ、解けなかったBで2ペナです。

# [ABC299](https://atcoder.jp/contests/abc299/standings?watching=hiroyuk1)

4完20ペナでした。Cで2ペナ、Dで18ペナです。
Python:ベクトルの差を高速で処理

# 問題設定

- グループA　3次元ベクトル(x,y,z) (N_A)個
- グループB　3次元ベクトル(u,v,w) (N_B)個

があるとき、Aの要素とBの要素のペア(N_A * N_B)個の中で、ペア同士のベクトルの距離の最小値を求めたい。


# 数学的に表現

```LaTeX
min_{i,j}||(x,y,z)_i - (u,v,w)_j||
```

![min_x_u.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610740/4a2a7852-a1c0-836c-bcec-4514f8731b89.png)

# Python で実装

ナイーブに、(N_A x N_B)回のループを回しても良いが、```numpy.tile``` を使うとすっきりと高速化できる。


```python
import numpy

x = data_x # 1次元のnumpy.array()を想定
y = data_y
z = data_z
        
u = data_u
v = data_v
w = data_w
       
N_A = len(data_x)
N_B = len(data_u)

matrix_A = numpy.vstack([x, y, z])
matrix_B = numpy.vstack([u, v, w])
        
matrix_A_T__xNB = numpy.tile(matrix_A.T, N_B).reshape(N_A*N_B,3)
matrix_B__xNA_T = numpy.tile(matrix_B, N_A).T
diff_AB_2 = (matrix_A_T__xNB - matrix_B__xNA_T)**2
dmin_AB = numpy.sqrt(numpy.min(numpy.sum(diff_AB_2, axis=1)))
argmin_diff_AB_2 = numpy.argmin(numpy.sum(diff_AB_2, axis=1)) # index

print(dmin_AB)
print(argmin_diff_AB_2)

print(int(argmin_diff_AB_2 / N_B)) # どの i のときに最小値となるかを示すindex (0<=i<N_A)
print(   (argmin_diff_AB_2 % N_A)) # どの j のときに最小値となるかを示すindex (0<=j<N_B)

```

# example

```python
import numpy

def doit():
    # A
    x = [1, 2, 3, 0] # Jr_i
    y = [0, 0, 0, 0] # Jz_i
    z = [0, 0, 0, 0] # Jphi_i

    # B
    u = numpy.array([4,5]) # _Jr_c
    v = numpy.array([0,0]) # _Jz_c
    w = numpy.array([0,0]) # _Jphi_c

    N_A = len(x) #4   # N_MC
    N_B = len(u) #2   # _k 
    
    matrix_A = numpy.vstack([x, y, z])
    matrix_B = numpy.vstack([u, v, w])

    matrix_A_T__xNB = numpy.tile(matrix_A.T, N_B).reshape(N_A*N_B,3)
    matrix_B__xNA_T = numpy.tile(matrix_B, N_A).T

    print()
    print('# matrix_A')
    print(matrix_A)
    print()
    print('# matrix_B')
    print(matrix_B)
    
    print()
    print('# matrix_A_T__xNB')
    print(matrix_A_T__xNB)
    
    print()
    print('# matrix_B__xNA_T')
    print(matrix_B__xNA_T)
    
    
    diff_AB_2 = (matrix_A_T__xNB - matrix_B__xNA_T)**2
    dmin_AB = numpy.sqrt(numpy.min(numpy.sum(diff_AB_2, axis=1)))
    argmin_diff_AB_2 = numpy.argmin(numpy.sum(diff_AB_2, axis=1))

    print()
    print('# diff_AB_2')
    print(diff_AB_2)
    
    
    print()
    print('# argmin_diff_AB_2')
    print(argmin_diff_AB_2)
    
    print()
    print('# optimal value of i (0<=i<N_A)')
    print('# int(argmin_diff_AB_2/N_B)')
    print(int(argmin_diff_AB_2/N_B))
    
    print()
    print('# optimal value of j (0<=j<N_B)')
    print('# argmin_diff_AB_2 % N_A')
    print(argmin_diff_AB_2 % N_A)
```


```python
doit()

### 出力 ###

# matrix_A
[[1 2 3 0]
 [0 0 0 0]
 [0 0 0 0]]

# matrix_B
[[4 5]
 [0 0]
 [0 0]]

# matrix_A_T__xNB
[[1 0 0]
 [1 0 0]
 [2 0 0]
 [2 0 0]
 [3 0 0]
 [3 0 0]
 [0 0 0]
 [0 0 0]]

# matrix_B__xNA_T
[[4 0 0]
 [5 0 0]
 [4 0 0]
 [5 0 0]
 [4 0 0]
 [5 0 0]
 [4 0 0]
 [5 0 0]]

# diff_AB_2
[[ 9  0  0]
 [16  0  0]
 [ 4  0  0]
 [ 9  0  0]
 [ 1  0  0]
 [ 4  0  0]
 [16  0  0]
 [25  0  0]]

# argmin_diff_AB_2
4

# optimal value of i (0<=i<N_A)
# int(argmin_diff_AB_2/N_B)
2

# optimal value of j (0<=j<N_B)
# argmin_diff_AB_2 % N_A
0
```
【SwiftUI】新しいPreviewの使い方

# はじめに
Previewが新しくなりました！

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Previewは書き方だけ変わったのかな？<br>謎にPreviewできない問題も解決してると嬉しいな</p>&mdash; たいしん (@SNQ2001) <a href="https://twitter.com/SNQ2001/status/1665949603643133953?ref_src=twsrc%5Etfw">June 6, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ちなみに謎にPreviewできない問題は解決してなさそうでした笑

開発が捗りそうなPreviewの活用方法があったので記事にしておきます。

# 基本的な使い方
```swift
#Preview {
    ContentView()
}
```

# Previewに名前付ける
```swift
#Preview("Preview name") {
    ContentView()
}
```

# Previewのレイアウトを指定する
```swift
// 縦画面
#Preview(traits: PreviewTrait.portrait) {
    ContentView()
}

// 縦画面(右)
#Preview(traits: PreviewTrait.landscapeLeft) {
    ContentView()
}

// 縦画面(左)
#Preview(traits: PreviewTrait.landscapeRight) {
    ContentView()
}
```

# こんな使い方ができる！
```swift
#Preview("縦画面", traits: PreviewTrait.portrait) {
    ContentView()
}

#Preview("横画面(右)", traits: PreviewTrait.landscapeLeft) {
    ContentView()
}

#Preview("横画面(左)", traits: PreviewTrait.landscapeRight) {
    ContentView()
}
```

|縦画面|横画面(右)|横画面(左)|
|:-:|:-:|:-:|
|![スクリーンショット 2023-06-07 16.46.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/d868dcc4-6899-ec42-f2b8-d51dcf1d3dd2.png)|![スクリーンショット 2023-06-07 16.46.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/0ee867a5-3fa0-6d60-9f4e-e498eae66c87.png)|![スクリーンショット 2023-06-07 16.46.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/352eb5e7-32c9-9b12-f688-8e55f459d26e.png)|

# ドキュメント
https://developer.apple.com/documentation/SwiftUI/Preview(_:traits:body:)

# おわり
![スクリーンショット 2023-06-06 17.23.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/db95fd18-31ae-6410-6ae7-029a5673996c.png)
Beta版に関する記事なのでちょっと心配です。
「Appleが一般に開示した情報」に該当してると思うので大丈夫だとは思いますが、
もしアウトだったらコメントで教えて欲しいです。
Python 環境構築(EMT 48 core)

```shell
$ conda create --name agama_202304 python=3.7
$ conda activate agama_202304
conda install -c conda-forge numpy

# [1]
$ conda create --name py37_gaia_dr3_try1-env --clone agama_202304
$ conda activate      py37_gaia_dr3_try1-env
$ conda install -c conda-forge ***

*** のリスト（上から順番に入れた）
scipy
matplotlib
jupyter (遅いので飛ばす) 
astropy
astroquery
corner (遅いので飛ばす) 
mpi4py
schwimmbad

conda update -n base conda -c defaults

pandas # already installed
wget
cython
scikit-learn
seaborn
pytest

corner (遅いので最後に回した) 
jupyter (遅いので回していない) 

```

最後は、以下のようなシェルスクリプトで対処。
```sh
conda install --yes -c conda-forge corner
conda install --yes -c conda-forge jupyter # ７時間必要だった
```

```shell
[2] 
===
py37_gaia_dr3_try2-env
===
$ conda create --name py37_gaia_dr3_try2-env --clone py37_gaia_dr3_try1-env
$ conda activate      py37_gaia_dr3_try2-env

$ pip install cubature 
```


```shell
[3]
===
py37_gaia_dr3_try3-env
===

$ conda create --name py37_gaia_dr3_try3-env --clone py37_gaia_dr3_try2-env
$ conda activate      py37_gaia_dr3_try3-env

(1) healpy (4 min)
$ conda install --yes -c conda-forge healpy

(2) mwdust
.bashrc で [.bash_profileではない]
export DUST_DIR=$HOME/my_libs_3/mwdust_DATA_directory
としてから

$ sudo env PATH="$PATH" python setup.py build
$ sudo -E env PATH="$PATH" python setup.py install

(3) gaiadr3_zeropoint 
$ cd gaiadr3_zeropoint
$ sudo -E env PATH="$PATH" python setup.py install

(4) Agama

# まず、gfortranを入れる。
sudo -i
apt-get update
apt-get install gfortran

$ cd Agama_202304
$ sudo -E env PATH="$PATH"  python setup.py install --user

```