OmniAICreator/Qiita-1.07M huggingface dataset:
AWS CLIのスイッチロール、もっと楽でいいじゃないか（assume-roleツールを使おう）

# 前書き

- 先輩に教えてもらって便利！！ってなったので紹介

# そもそもAssumeRoleとは

- ロールを引き受けられる機能。ロールを引き受けることにより、ロール側で定義している権限での操作が可能になる。

下記のはっちゃけた記事がおもしろくわかりやすかったです。

[https://dev.classmethod.jp/articles/iam-role-passrole-assumerole/](https://dev.classmethod.jp/articles/iam-role-passrole-assumerole/)

# “assume-role” is 何？

- 一時クレデンシャルをシェルの環境変数にセットしてコマンド実行してくれるいいやつ。

[https://github.com/remind101/assume-role](https://github.com/remind101/assume-role)

# 何が良いか

- そもそも—profileオプションに対応していないコマンドにおいても便利になる。
- evalなどでクレデンシャルをセットすればコマンドごとにprofileを指定してMFAの認証コード打って...という手間がなくなる。
- スイッチロールでいろいろアカウントまたいで作業しなきゃならないときに楽。

# Assuむってみる

※適当にprofileは作っておいてください。

- evalコマンドで、引数に与えたクレデンシャル情報をシェルに実行させる。

`eval $(assume-role {profile名})`

```
hogehoge$ eval $(assume-role hogehoge)
MFA code: xxxxxx
hogehoge$ 
```

これでクレデンシャルがシェルにセットされたので、いつものようにCLIを実行できます。

ちなみに `assume-role profile名`が `export AWS_ACCESS_KEY_ID...` のような形式の出力で返してくるのでそのままevalコマンドの引数に与えるとクレデンシャル情報をシェルにセットするという挙動になっているっぽいですね。

[https://github.com/remind101/assume-role#:~:text=If no command,assume-role prod](https://github.com/remind101/assume-role#:~:text=If%20no%20command,assume%2Drole%20prod))
>If no command is provided, `assume-role` will output the temporary security credentials:
`$ assume-role prod
export AWS_ACCESS_KEY_ID="ASIAI....UOCA"export AWS_SECRET_ACCESS_KEY="DuH...G1d"export AWS_SESSION_TOKEN="AQ...1BQ=="export AWS_SECURITY_TOKEN="AQ...1BQ=="export ASSUMED_ROLE="prod"# Run this to configure your shell:
【SwiftUI】アラートを表示する

#環境
Xcode 13.2.1
Swift 5.5.2

#実装
ボタンをタップした時にアラートを表示する場合は以下のようなコードになります。

```swift
struct ContentView: View {
    @State private var isShowingAlert: Bool = false
    
    var body: some View {
        Button("アラートを表示する") {
            isShowingAlert = true
        }
        .alert("Text", isPresented: $isShowingAlert) {
            Button("Button1") {
                // タップした時の処理
            }
            Button("Button2") {
                // タップした時の処理
            }
        } message: {
            Text("メッセージを表示する")
        }
    }
}
```

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/e5dd1efe-1591-7b9a-7e8f-75c5f32934b2.png">
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/0208ec09-732b-af05-df54-a36ce2041d38.png">

ボタンを3つ以上定義すると縦並びになります。

#解説
UIKitではアラートを表示する処理をどこかのメソッドなどで呼ぶ形でしたが、SwiftUIでは定義したアラートに表示するかどうかの条件をバインドして表示するタイミングを管理します。

最初に、アラートを表示するかどうかを判定する`State`変数を定義します。

```swift
@State private var isShowingAlert: Bool = false
```

今回はボタンがタップされた時にアラートが表示されるようにしたいので、ボタンのタップ処理で最初に追加した`isShowingAlert`をtrueにします。

```swift
Button("アラートを表示する") {
　　　　isShowingAlert = true
}
```

最後に`alert()`modifierを定義します。
Buttonに追加していますが、アラートを表示するかは定義したBool値がtrueになった時なので、必ずButtonに追加する決まりはありません。

```swift
.alert("Title", isPresented: $isShowingAlert) {
    Button("Button1") {
    // タップした時の処理
    }
    Button("Button2") {
    // タップした時の処理
    }
} message: {
    Text("メッセージを表示する")
}
```

**引数**
**title**
アラートのタイトルに使用される文字列を定義します。

**isPresented**
アラートを表示するかどうかを判定するBool値。アラートのアクションをタップするとこの値は自動的にfalseになります。

**actions**
アラートに表示するアクションボタンを定義します。アクションが存在しない場合は標準の`OK`ボタンが表示されます。アクション実行後は自動的にアラートが閉じます。

**message**
タイトルの下に表示される文字列を定義します。messageはスタイルが設定されていないテキストのみサポートします。

###アクションボタンのスタイルを変更する
Buttonの引数`role`の値を設定することでスタイルを変えることができます。
何も設定していない場合はデフォルトで青色の表示になります。

**.cancel**
青色のボールド表示。アクションボタンが2つ存在する場合は必ず左側に表示され、3つ以上存在する場合は必ず一番下に表示されます。

**.destructive**
赤色の表示。このアクションボタンが存在する場合は`.cancel`アクションボタンが自動的に追加されます。

```swift
Button("Button1") {
    // タップした時の処理
}
Button("Button2", role: .destructive) {
    // タップした時の処理
}
```

スタイルを設定していないアクションボタンと`.destructive`のアクションボタンを追加した場合は以下のような表示なります。
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/5c749ca4-62e6-c502-0800-699ef7c52c4c.png">
EC-CUBE+Docker+xdebug+VSCode環境を作る

EC-CUBE4の解析を行うのが難しいのでデバッグ機能を実装してみた。多分、EC-CUBEに限らず、Docker/VSCodeで開発してる人は参考になると思う。

:::note info
Windows環境でやるていで記載していきます。
:::

＜参考＞
[・Docker+EC-CUBEの環境を構築する](https://qiita.com/Kouhei-Ichikawa-wq/items/3212094e57a9fc8d53dc)
[・VSCodeからDockerにつなぐ](https://qiita.com/Kouhei-Ichikawa-wq/items/d43c2cbc098072bab25e)

#手順
適当な場所にフォルダを作成する(日本語が入ってないところがいいかも)
(例)C:\temp配下に『aaa』というフォルダを作成する

####コマンドプロンプト作業

```:適当に作成したフォルダに移動する
cd C:\temp\aaa
```

```:EC-CUBEを落とす
git clone -b 4.0.5 https://github.com/EC-CUBE/ec-cube.git
```

```:xdebugセットを落とす
git clone https://github.com/Kouhei-Ichikawa-wq/eccube_xdebug.git
```

```:xdebugセットをコピーする
xcopy /e /y eccube_xdebug ec-cube
```

```:Docker起動の場所へ移動する
cd ec-cube
```

```:Dockerを起動させる
docker-compose up -d
```

```:EC-CUBEのインストールを行う
docker-compose exec -u www-data ec-cube bin/console eccube:install
```

####VSCode作業
VSCodeからDockerにアタッチする
![xdebug01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2488430/646e6c6c-89ac-f53f-7aaa-14c79c1fbcc3.png)

左側の虫マークをクリックして『実行とデバッグ』をクリックする
![xdebug02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2488430/ee3e2c02-9672-5ba8-4705-1ff31c4a679e.png)

『拡張機能をインストールする...』をクリックする
![xdebug03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2488430/6abb5c98-cacd-1bac-2ebe-9d38ea98823a.png)

入力項目が出てくるので『@&#xFFF0;category:"debuggers" "PHP"』を入力して、『PHP Debug』をインストールする。
![xdebug04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2488430/a5985b1f-f431-3bba-c4e9-a11f6b5bcc50.png)

『launch.josonファイルを作成します。』をクリックする
![xdebug05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2488430/03faede4-4ae3-753f-393e-e64a59277f7d.png)

『.vscode/launch.json』ファイルの内容が表示される。
『Listen for Xdebug』の再生ボタンをクリックする。
![xdebug06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2488430/9e0510c6-3d28-1682-5dba-3325a64a7b08.png)

※これでxdebugは動き始めました。

####動作確認
適当にソースコードからブレイクポイント貼る。
EC-CUBEのトップページが表示されたときにブレークされるようにする。
『/src/Eccube/Controller/TopController.php』の『index()のretrun[];』に貼る(２７行目)
トップページを表示する。ブレークポイントを貼った箇所でストップしていることが分かる。
![xdebug07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2488430/3bf11d14-60c2-e16f-37f3-a5eb65a2b267.png)

#感想
実機(xamp)におけるxdebugの情報は結構あったんだけど、Dockerのコンテナ内のソースでVSCodeを使うってのは情報があまりなくてしんどかった。これでEC-CUBEが少しでも流行るといいなあ。
1weekゲームジャムで使える Unityテクニック

# はじめに
スタジオしまづの1weekゲームジャムでよく使うサイトやテクニックをまとめました（今後も追加予定）。

![1week.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67439/4fdb52c8-dcc5-d710-cdd3-ef34bde41ca2.jpeg)


# 共同開発するなら
・Unityのバージョンを揃える
・GitHubを使ってプロジェクトを共有する：https://zenn.dev/studio_shimazu/articles/f8ab5784041381
・GitHubでLogsフォルダが共有される対処法　https://qiita.com/simanezumi1989/items/c303b478165b42d1b6a8
・スタジオしまづに入って参加スタンプを押す


# タイトル画面
・ボタン点滅：https://qiita.com/lycoris102/items/fe148d2c6803742c6f4d
・ボタンアニメーション：https://qiita.com/nkjzm/items/8c8b38e45c3e7712cd74
・ウィンドウアニメーション：https://unity-yuji.xyz/dotween-good-game-ui/

# シーン遷移
・記事：https://github.com/naichilab/Unity-FadeManager/blob/master/README.ja.md

# 音（BGM/SE）の実装
・音実装コード：https://youtu.be/wcIiVPmoVnI

# ランキング実装
・記事：https://blog.naichilab.com/entry/webgl-simple-ranking
・上と同じものの動画解説：https://youtu.be/FaTeCKLr9gw
・スコアランキングの実装：https://unityroom-help.notion.site/8528463c37c04fc98d326faa61285ae9

# unityroomにアップ
解説動画：https://youtu.be/-1HnVElq34I
・注意1:デフォルトのフォントだと日本語が表示されない（別のフォントにすれば基本OK）
・注意2:WebGLの形式をGzipにする必要あり（動画内で説明あり）

# フォント
・ドット絵：https://itouhiro.hatenablog.com/entry/20130602/font

# 音
・BGG/SEサイト：https://dova-s.jp/
・SE:https://soundeffect-lab.info/sound/button/
・BGM:https://iwashiro-sounds.work/


# スタジオしまづとは
https://ci-en.net/creator/10761
useHistory が使えない時

react-route の v6 からは、useHistory ではなくて useNavigate が推奨になりました。
使い方は、下記です。
## useNavigation
```javascript:index.jsx
import {useNavigate} from "react-router-dom"

const navigation = useNavigate()

/* ページ遷移は下記を使う */
navigation("/hoge") /* /hoge に遷移 */

/* history.goBack()は、 */
navigation(-1)
```

react-route、v6 から変更が多くて、昔のコードが使えないことが多い (<Switch>から <Routes> への変更など) 。
ネスぺの恥⓪【Qiita始めました】

初めまして！keyと申します。

突然ですが、自分は令和4年度(2022年)ネットワークスペシャリストを受験します。
ただ勉強していても味気ないな～と思いつつ左門先生のネスぺシリーズで勉強していたら、「ネスぺの恥」というワードを思いついたので思い切ってシリーズ化することにしました。(左門先生ごめんなさい)

初めての投稿なのでかる～く以下3点について書いてみようと思います。
　・[1-自己紹介](#1-自己紹介)
　・[2-投稿動機](#2-投稿動機)
　・[3-今後の投稿内容](#3-今後の投稿内容)

#1-自己紹介
SIerで仮想化基盤構築しているインフラエンジニアです。年齢は22歳です。
主にサーバ構築を担当していますがシステムの設計も担当することが増えてきたためネットワークをはじめ色々勉強中です。

#2-投稿動機
冒頭にも書きましたが「ネスぺの恥」というワードを思いついたからです。
思いついた時にはQiitaサイト登録をしていました。普段めんどくさがりなのに変なところでフットワークが軽い・・・

後は、間違いに照準を合わせたネスぺの教材・サイトが少ないので、NG答案の事例集を作成すれば面白そうだなと思いやってみることにしました。

#3-今後の投稿内容
「ネスぺの恥」がコンセプトなので現状は以下のような内容を想定しています。
　・自分のクソ答案をネットの海に晒して恥をかく
　・何故その問題を間違えたか、今後どうすれば正解できるかを考察

#～終わりに～
ここまで見てくださった方ありがとうございます。
次回から過去問の失敗事例をここに供養していきます。

よろしくお願いします！
Pythonでmp4をmp3 , wavに変換 　(ubuntu版)


Pythonでffmpegを使用して、mp4からmp3やwavファイルを作成してみました。

テスト用の動画ファイルのサンプル素材は、以下からお借りしています。

https://japanism.info/free-video1-10.html


ダウンロードしたファイル

>free-video1-sea-cafinet.mp4


#サンプルコード

とりあえず、サンプルコードを作成。

```python:mp4_to_mp3.py
#!/usr/bin/python3.8
# -*- coding: utf-8 -*-
import sys, re, glob, ffmpeg
TYPE:str = "mp3"
FILE_PATH:str  = "/home/smb/*.[Mm][Pp]4"

# mp4 -> [mp3][wav] 
def mp4_to_mp3(path,type):
    ffmpeg.run(
        ffmpeg.output(
            ffmpeg.input(path) ,
            re.sub("\.(mp4|MP4)$","."+type,path)
        ))

if ( __name__ == "__main__" ):
    [mp4_to_mp3(path,TYPE) for path in glob.glob(FILE_PATH)]
```


TYPEに"mp3"か"wav"を設定し、
FILE_PATHには、mp4ファイルのあるディレクトリを設定。


#モジュールインストール（ffmpeg）

$ pip3 install ffmpeg
![イメージ7606.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/b261f9f6-6988-f6fe-59c8-8c408bf82c57.jpeg)

ただ、これでは、エラーが出ました。
違う物をインストールしたのが原因？

https://github.com/kkroening/ffmpeg-python/issues/174

ffmpegをアンインストール
$ pip3 uninstall ffmpeg

変わりにffmpeg-pythonをインストール
$ pip install ffmpeg-python


#ERROR:
AttributeError: module 'ffmpeg' has no attribute 'input'
![イメージ7607.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/ab8b3efa-cc20-6a80-331a-96737a4c5037.jpeg)


調べると、ffmpegをインストールしないと駄目みたいです。



# ffmpegをインストール

$ sudo apt info ffmpeg
![イメージ7610.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/215c9899-4140-f960-aea7-e654a6fa68b3.jpeg)

$ sudo apt-get -y install ffmpeg
![イメージ7611.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/791b6fdf-babb-b749-e491-b133546f5e6d.jpeg)



$ rehash

$ ffmpeg --version
![イメージ7612.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/a7be5f47-6a1b-1f18-211e-949885f9b299.jpeg)


# 実行

$ ./mp4_to_mp3.py
![イメージ7615.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/dc7ae9af-e6b1-5718-034c-e901857f9ef9.jpeg)

無事 mp3ファイルが作成されました。
![イメージ7616.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/93a39547-fa0d-a484-1c0c-a1abea6f96de.jpeg)


#複数のファイルも一度に変換

指定フォルダ内のファイルを一度に変換

作成前：
![イメージ7619.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/1c506914-1339-25d7-a89f-0a98baeb4192.jpeg)

作成後：
![イメージ7618.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/ff0a75fb-1c5e-1ac0-7597-33fda9d07990.jpeg)
React Modalのライブラリを導入してみた話

今回、モーダルを用いて画像や情報を登録できる仕組みをかんたんに実装したいと思ったので、機能だけかんたんに実装してみました。CSSの実装はしてません(ちょっとしか...)

今回やったこと↓
![modal.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1462552/5dce6e12-ea85-af95-61e5-11ec048eeee7.gif)

#React Modalのインポート

```
$ npm install --save react-modal
```
yarnの方はコチラ

```
$ yarn add --save react-modal
```

必要なヤツらをimportします。
先程インストールしたReact ModalさんはModalコンポーネントとしてimportして使うそうです。

```react
import React from "react";
import Modal from "react-modal"; //Modalコンポーネントのインポート
```

モーダルの表示、非表示の状態をuseStateで定義してstateで管理するらしいです。
ここでは、モーダルを開くボタンと閉じるボタンを準備して、modalIsOpenに状態を渡します。
これで一応完成するはずです。

```react
Modal.setAppElement("#root");

 export const MemoryPage = () => {
  const [modalIsOpen, setIsOpen] = useState(false);
    return (
      <div>
        おもいでたち！
        <p>チェキなどを保存して管理するページ</p>
         <Link to="/">
          <button>
            HOMEへ！
          </button>
         </Link>
        <button onClick={() => setIsOpen(true)}>Open Modal</button>
          <Modal isOpen={modalIsOpen}>
          <button onClick={() => setIsOpen(false)}>Close Modal</button>
         </Modal>
      </div>
    );
  };

```
SPA(Single Page Application)についてざっくり

##■はじめに
従来の一般的なWebアプリケーションの画面表示切り替えの設計手法は、ユーザのアクションに応じてサーバーから次に表示する画面のHTMLを受け取り、そのたびにヘッダやフッダを含めて全て更新する設計手法であり、これを"MPA(Multi Page Application)"と言う。

これに対して、Webアプリケーションに最初にアクセスしたときに全画面表示に必要なJavaScript,HTML,CSSをサーバーから受け取り、画面表示切り替えする際はサーバーからは必要なデータ(通販サイトであれば商品の金額や在庫数など)のみを受け取り、初めに受け取ったJavaScriptで次に表示するHTMLを生成し差分のみを更新する(ヘッダやフッダなどが更新不要であれば更新しない)設計手法を"SPA(Single Page Application)"と言う。
以降にSPAについてざっくりまとめると、、

##■従来型…MPA(Multi Page Application)
ユーザのアクションに応じてサーバーからHTMLを受け取り、そのたびにヘッダやフッダを含めて全て更新する設計手法

##■SPA(Single Page Apication)
最初にサイト全体の表示に必要なJavaScript,HTML,CSSなどを受け取った後は、必要なデータだけをサーバに要求し差分を表示する設計手法
(必要なデータはサーバーから非同期的にJSONデータとして受け取る)

##■従来型(MPA)とSPAの比較
画面切り替え時の従来型(MPA)とSPAの比較すると、

| |従来型(MPA)|SPA|
|:--|:--|:--|
|サーバーから受け取るもの|HTML,CSSなど<br>→通信量大|データのみ(JSON方式)<br>→通信量小|
|画面更新箇所|画面全てを更新<br>(ヘッダやフッダ等の更新不要箇所も更新)|更新が必要な箇所のみ更新<br>(ヘッダやフッダ等更新不要箇所は更新しない)|

##■SPAのメリット
よってSPAのメリットとしては、
・画面切り替え時のサーバーとの通信量を抑えることができる
・画面更新にかかる時間を短くすることが可能

##■SPAのデメリット
またSPAのデメリットとしては、
・最初のローディングの際にHTMLやJavaScriptなど全てのデータを取得する必要があるため、初期ローディングに時間がかかる
・実装コストがかかる、開発に慣れている者が少ない、などなど
【Unity】Editモードで子オブジェクトをすべて削除するスクリプト

UnityエディターのEditモードで子オブジェクトをすべて削除するスクリプトです。

```c#
using System.Linq;
using UnityEngine;

public class DeleteChildrenExample : MonoBehaviour
{
    [ContextMenu("Delete Children")]
    public void DeleteChildren()
    {
        foreach(var child in transform.OfType<Transform>().ToArray())
        {
            DestroyImmediate(child.gameObject);
        }
    }
}
```

以下のように書いても一見問題なさそうですが、実際には子オブジェクトがすべて削除されないので注意してください。

```c#
foreach(var child in transform)
{
    DestroyImmediate(child.gameObject);
}
```
コンテナってなに？AWSの公式動画見たからまとめた。

#コンテナってなに？

コンテナってよく聞くし、業務でも最近触れ出して知らなかったので勉強しました。
AWSの公式がyoutubeに講演の動画をあげてくれてたのでそれをみてのまとめになります。
指摘などは大歓迎です。

https://youtu.be/L4bLDNRSYC8

##・コンテナとは
アプリケーションに必要な下記をまとめたもの。設定ファイルは入らないため().

* ランタイム
* ソースコード
* ライブラリ/パッケージ
* (・設定ファイル(環境ごとに変えたいもの。ex.何かを取得するエンドポイントを変えたり)　これは実行時にお渡しする。)


##・コンテナ発祥の経緯
今までは、ランタイム(jvmなど)のバージョンが違うなどが発生していた。
なので、ランタイムも一つのデプロイ対象として含めることで環境ごとに差異が生まれないようにしよう、というのが経緯。
-> dockerエンジンがインストールされてる環境でありさえすれば、同じように動作させる。

##・コンテナオーケストレーション
コンテナオーケストレーションとは、複数のサーバー(dockerエンジンの入った)に対して、想定した動きをさせることを容易にしてくれる概念。
___では、なぜコンテナオーケストレーションが必要か。___
コンテナはdockerエンジンのある単一の環境で動作することを保証している。
ただし、サービスの運用環境というのは複数のサーバーで動いていることがほとんど。
そこで複数のサーバーに対して、こちらが想定している設定で管理/デプロイするためにコンテナオーケストレーションが必要になる。
コンテナAはこのLBに繋いで〜、コンテナBはこのリージョンでお願い〜とか。

##・ECS
AWSのサービスでECSがコンテナオーケストレーションに該当する。
特徴は、
・AWSの他サービスとの連携(LBなど)
・スケラービリティが簡単
・ECSを利用するのに理解するべきなのは「タスク」「サービス」という二つの設定的なもの。
(他にもEKSという、オープンソースでありコンテナオーケストレーションツールのkubernetesと連携したサービスがあるが、ここでは触れません。動画みてもらえると)
(kubernetesは「くばねてぃす」と読むらいし、恥ずかしながらこの動画見るまでは頭の中でいつも「くーばーねっつ」と読んでました。幸い口に出したことはない)

##・ECR
コンテナをデプロイするのにコンテナのイメージが必要になる。
イメージの置き場所として使うのがAWSだとECR。
AWSが提供するプライベートばイメージのリポジトリ。

コンテナを乗せるEC2などではOSなどの管理があるが、AWS Fargateを使えばコンテナ以下のOSなどの管理はAWSが実行してくれる。

##・最後に
関連動画でECSについての動画もあがっているので次はこちらみてまとめてみようと思います。
https://youtu.be/tmMLLjQrrRA
プロンプトをいい感じにカスタムしてみた

# 環境
macOS 12.1

# 前置き
プロンプトをいい感じにしたいなと思い、やってみました。
「この書き方のほうがいい」というのがあれば、教えてください。

# スクリプト

はじめにこんな感じで書いてみたけどダメだった。

```sh:.zshrc
AB_PATH=`pwd`
if [[ $AB_PATH == '/Users/nodaken' ]]; then
    CURRENT='~'
else
    CURRENT=`basename $AB_PATH`
fi
ARCH=`uname -m`
if [[ $ARCH == 'arm64' ]]; then
   PROMPT="%m[a]:$CURRENT %# "
else
   PROMPT="%m[x]:$CURRENT %# "
fi
```

.zshrcは、ターミナルを立ち上げるときにしか読まれないから、ダメな理由はそこだった。コマンドを実行していっても、`＄AB_PATH`や`$CURRENT`は途中では変わらないということだった。

```sh:zshrc
PROMPT="%B%F{green}%m%f%b:%B%c%b %# "
```

上のスクリプトなら

<font color="LimeGreen">**マシン名**</font>:**~** % 

こんな感じになります。
ええ感じ。
[pyinstaller] or [py2exe] でpyファイルをEXE化　(2022-01-22)

前回、Windows10環境に、Python3をインストールしたので、今回は、exe化をやってみました。

前回の記事：

https://qiita.com/fix/items/cc31deda5daf0309d9f4



# pyinstaller をインストール

![イメージ7598.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/56646e80-1117-ef57-5c0a-dc363a90de47.jpeg)




# exe化テスト

シンプルにprint文のみでとりあえずやってみます。

```python:Hello-Python.py
# -*- coding: utf-8 -*-
import sys
print("Hello,Python!")
```

一応、実行確認

![イメージ7600.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/771448b7-e974-77bb-55f8-e5fed965b2ad.jpeg)



# pyinstaller コマンドでEXEファイル作成


pyinstaller （ファイル名） --onefile

で、EXEファイルが出来るようなので作ってみます。

$ pyinstaller Hello-Python.py --onefile

![イメージ7601.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/0b4346ac-7648-03b6-4c63-5a3d9b38987d.jpeg)

「dist」フォルダ内に、「Hello-Python.exe」が作成されていました。

![イメージ7602.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/9554f804-c12b-f028-afb4-a1456cbf3993.jpeg)

#exeファイル実行テスト

![イメージ7603.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/ae227a16-d725-6056-edf5-c8d8d3ea3038.jpeg)




#py2exeでexe化

py2exeの方もやってみました

pipでインストール

$ pip install py2exe

setup.pyを作成

```python:setup.py
from distutils.core import setup
import py2exe

setup(console=['Hello-Python.py'])
```

実行

$ python setup.py py2exe

![イメージ7604.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/874fdd2c-d343-87e6-54ee-eaabb9127553.jpeg)


実行後、distフォルダ内にHello-Python.exeが作成されるようです。


起動
![イメージ7605.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/5af580c2-c93a-79c2-b2fe-40bf30b1d8b2.jpeg)
【Plask】AIが動画から3Dモーションを作成してくれるサービスの紹介と、それをUnityで使用する方法

# 概要
動画からモーションを作成してくれるWEBサービス「Plask」が公開されました。
この記事ではPlaskで作成したモーションを、Unityで好きなキャラに流す方法を記載します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878081/b0e70039-3cd2-5a8a-1f03-81030d8ce859.gif" width="256"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878081/99ee4546-7b8d-4ce1-5b9e-9e0ebf692548.gif" width="256">

# Plaskの紹介
[webサイト](https://plask.ai/)にアクセスし、SignInすることですぐに開始できます。
[マニュアルページ](https://plasticmask.notion.site/User-guide-ac4bba1b75384c309e7a24e6542454ba)や[チュートリアル動画](https://youtu.be/6D_BadOL97c)も充実しています。

動画からキャラクタのモーションを生成してくれる他、リターゲティングや、キーフレームの編集もブラウザ上から行うことができるようです。
また、[Coming soon]ですが、チームメンバーと共有できる機能の開発が記載されています。

本記事作成時点では利用規約なども記載は見つけられず、無料で使用することができています。

# 動画からモーションを作成する
| 手順 | 画像 |
| --- | --- |
| 左上のプラスボタンから動画をアップロードします。 | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878081/ffd7687a-55a5-7804-7bd4-fc010f849e1e.png" width="256"> |
| 用意されているキャラにモーションを適応し、3Dビュー上で表示します。 | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878081/87ab8164-38af-0875-83cc-b81940ca247c.png" width="256"> |
| モーションを再生して生成したモーションを確認します。 | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878081/fc1745fe-8533-c364-4aca-39052c244beb.png" width="256"> |
| 問題なければモーションを選択して[Export] | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878081/2c8fda4d-3e0b-d1fe-2bac-8c6fc4011b22.png" width="256"> |
| 今回はFBXファイルで出力します。 | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878081/752e855c-f30f-130a-1b66-4c8a73d746c8.png" width="256"> |

# Unityで好きなキャラクタにモーションを流す
Unity2020.3.11f1を使用しました。

VRM形式でキャラモデルをUnityに取り込みたいので、こちらのパッケージをUnityにImportしてください。
記事作成当時最新のv0.94.0を使用します。
https://github.com/vrm-c/UniVRM/releases

キャラクタは、簡単にアバター作成が行えるVRoidを用いて作成しました。
(といってもテンプレートのまま使用します。)
https://vroid.com/

Plaskから出力したFBXファイルをUnityに取り込み、Humanoid形式でインポートします。
キャラモデルとモーションモデルの骨構造や骨名が異なるので、Genericで用いることはできません。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878081/5d38993d-e375-5fb9-6917-f1ae8183ff7a.png" width="256">

後は普通にキャラにモーションを流しましょう。
任意のキャラモデルが、モーションモデルと同じ動きをしていることが確認できます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878081/b0e70039-3cd2-5a8a-1f03-81030d8ce859.gif" width="256"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878081/99ee4546-7b8d-4ce1-5b9e-9e0ebf692548.gif" width="256">

# まとめ
WEBサービスPlaskを利用してモーションを作成し、UnityでVRMモデルに流す方法を記載しました。
スマートフォンなどで動画を撮影すればそのまま利用することができるので、非常に簡単に試すことができました。
動画ベースの簡易的なモーションキャプチャーということもできますが、精度を考えるとゲームなどの製品にそのまま使用するのは難しいように感じました。
しかしフリーゲームやモックアップ開発の強い味方になってくれそうです。
しっかり利用するのであれば、BlenderやMayaなどリッチなDCCツールできっちり修正してからUnityに取り込むのがいいかと思います。
リモートホストにRDPしたい！けどSSHでセキュアにアクセス


今回はリモートロケーションに設置したサーバー（？）２台にリモートからSSHをつかってRDP接続してGUIを使ってみたい！というところが目的。
![QiitaImage2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92380/54f4c0de-c346-20c6-1f88-2140fc881884.png)
Command:



#Firewall(ルーター）の設定
FW（INETプロバイダのルータを使用）　NEC製ATERM
ルータのGUIで設定する「ポートマッピング」

|   優先    | LAN側ホスト  | プロトコル |  変換対象ポート | 宛先ポート   |
|:--:|:--:|:-:|:--:|:--:|:-:|
| 10|192.168.0.11|TCP|6xxx0|22|

#UBUNTUをSSHサーバにする

UFWで必要以外のポートを閉じる
RDPやHTTPはSSHのトンネルの中でポートを転送する

#SSHでPort転送
REMOTEPORT = 6xxx0 (FWでポートマッピングで設定した値）
SSHの終端はいつもUbuntuにして、Ubuntuのデスクトップを操作するときは
HOST = localhost
RSSPIのデスクトップを」使うときは
HOST = 192.168.0.10


```
ssh -A -t -L 3389:${HOST}:3389 hoge@${REMOTEHOST} -p ${REMOTEPORT}
```
REMOTEPORTは６万台などKNOWN＿PORTを避けてOPENし各ホストにFORWARDする
REMOTEHOSTはGlobal＿IPでアクセス

#UbuntuでもFirewallを設定する

```
ubuntu:~$ sudo ufw status verbose 
状態: アクティブ
ロギング: on (medium)
Default: deny (incoming), allow (outgoing), disabled (routed)
新しいプロファイル: skip

To                         Action      From
--                         ------      ----
22                         ALLOW IN    Anywhere                  
Anywhere                   ALLOW IN    192.168.0.0/24/tcp       
Anywhere                   ALLOW IN    192.168.0.0/24/udp d

ubuntu:~$ sudo ufw logging medium
ubuntu:~$ sudo ufw status numbered
ubuntu:~$ sudo ufw delete 5

ubuntu:~$ sudo ufw reload

```


oggingをMediumにすることでアクセスの履歴が残る。LowだとDENYの時だけログされる。
Logの場所はDefaultで
/var/log/ufw.log
新規または変更したファイルのみphpStanを実行する


## 使いそうなシチュエーション
・静的解析したいファイルが多すぎるとき
・将来phpStanを導入したいと考えているとき
・新規作成ファイルなど部分的にphpstanのレベルを上げたいとき
・CIでphpstanを実行したいとき（レポジトリ全体にstanを実行すると滅茶苦茶重たい）

## コマンド
```shell
# git diffした内容をphpstanで実行する
git diff master --name-only | grep '.php' | xargs vendor/bin/phpstan analyse -l max

# diff-filterオプションで新規作成ファイルのみに絞り込みして実行できる
git diff master --diff-filter=A --name-only | grep '.php' | xargs vendor/bin/phpstan analyse -l max
```

エイリアスを通しとくと便利そう

```shell
# ~/.bashrc または ~/.zshrc
alias stan-diff="git diff master --name-only | grep '.php' | xargs vendor/bin/phpstan analyse -l max"
alias stan-diff-add="git diff master --diff-filter=A --name-only | grep '.php' | xargs vendor/bin/phpstan analyse -l max"
```
「エントロピーと秩序」のプログラムをpythonで書く～揺らぎ

「エントロピーと秩序」のプログラムをpythonで書く第2弾。
「揺らぎ」というタイトルがついているbasicのプログラムをpythonで書き直します。

温度とは、超簡単に言ってしまうと「元気な原子が存在する割合」を示す値です。
実際の世界には超元気な原子やまあまあ元気な原子、全然元気のない原子といろいろな元気度の原子がいるのですが、このプログラムは「元気な原子(ON状態の原子)」と「全然元気のない原子(OFF状態の原子)」で構成された世界をモデリングしています。

100個の原子から成り立っている物質1(左上の部分)と1500個の原子から成り立っている物質2(それ以外の部分)が接触して平衡状態にあるとき、元気な分子は物質1と物質2にランダムに配置された状態になります。その瞬間瞬間を可視化すると、原子数の少ない物質1(左上の物質)のほうが温度に揺らぎがありますが、同じくらいの温度になっていることがわかります。

なるべく元のプログラムに忠実に書き直したかったのですが、大量に出てくるgoto分をforとかifに書き直したり、可視化する部分をmatplotlibに置き換えたりしているうちに結構変わっちゃいました。

```python
import time
import math
import random
import numpy as np
import matplotlib.pyplot as plt

N = 100  # = int(input("ON状態にする原子数(100まで)"))
NUMBER_OF_EXCUTIONS = 100

fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1)
ax1.set_xlim(-1, NUMBER_OF_EXCUTIONS)
ax1.set_ylim(-1, 1)
ax2 = fig.add_subplot(1, 2, 2) 
ax2.plot((-1, 10), (30, 30), (10, 10), (30, 41), color = 'grey')
ax2.set_xlim(-1, 41)
ax2.set_ylim(-1, 41)
sc1 = ax1.scatter([], [], c="b")
sc2 = ax2.scatter([], [], c="r")

tx_coordinates = []
ty_coordinates = []
colors = []

for i in range(NUMBER_OF_EXCUTIONS):
    n1 = 0
    n2 = 0
    n = 0
    f = np.zeros([40, 40])
    x_coordinates = []
    y_coordinates = []
    c = []
    while(n < N):
        x = random.randint(0, 39)
        y = random.randint(0, 39)
        if f[x, y] == 1:
            continue
        f[x, y] = 1
        x_coordinates.append(x)
        y_coordinates.append(y)
        if x < 10 and y >= 30:
            c.append("b")
            n1 += 1
        else:
            c.append("r")
            n2 += 1
        n += 1
    if n1 == 0:
        t1 = 0
    else:
        t1 = 1 / math.log((100 - n1) / n1)
    if n2 == 0:
        t2 = 0
    else:
        t2 = 1 / math.log((1500 - n2) / n2)
    sc2.set_offsets(np.c_[x_coordinates, y_coordinates])
    sc2.set_color(c)
    tx_coordinates.append(i)
    ty_coordinates.append(t1)
    colors.append("b")
    tx_coordinates.append(i)
    ty_coordinates.append(t2)    
    colors.append("r")
    sc1.set_offsets(np.c_[tx_coordinates, ty_coordinates])
    sc1.set_color(colors)
    plt.pause(0.1)
plt.waitforbuttonpress()
```

![Figure_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109677/c6c902e5-3064-e0db-5bf9-81a427c2b323.jpeg)

左側のグラフが温度の分布を示し、右側のグラフが元気な分子の配置を示しています。
【Laravel】Laravelインストール時に「--git」フラグを付ける習慣をつけたい…

Laravelをインストールする際は、Laravelインストーラを使用して `--gitフラグ` を付けるとインストール後に自動的にGitリポジトリを作成してくれます。

インストールした後に、**「ファーストコミットするの忘れた！」**を防ぐ目的で `--gitフラグ` を習慣化するのは僕の役目だと思っています…(;´･ω･)

```command:「--gitフラグ」のコマンド例
$ laravel new project_name --git
```

ちなみに、`--gitフラグ` に `--branch` フラグも一緒に付けると、最初の分岐名を設定できます。その際は、「最初の分岐名」を記入するのを忘れずに。

以下のコマンド例では、「最初の分岐名」は `main` となります。GitHub のデフォルトブランチ名は `main` ですので、基本的には`main`で良いでしょう。
 
```command:「--gitと--branchフラグ」のコマンド例
$ laravel new project_name --git --branch="main"
```

Laravelがインストールされた後に、コミットの履歴を見ると `Set up a fresh Laravel app` というコミット名が記録されていると思います。

これで、ファーストコミット忘れを防げます！（そのためには `--gitフラグ` のつけ忘れを防がなければならい…）

参考URL：https://readouble.com/laravel/8.x/ja/installation.html
【初心者向け】viエディタで行番号を表示する

## 環境
Mac OS
Linux OS
など・・・

## 先に結論
### 動作確認
ホームディレクトリに移動します。(移動しなくても大丈夫です。)
`$ cd`

動作確認用のテストファイルを作成します。
`$ touch ~/test.txt`

テストファイルに適当な文字を入力し、保存します。
`$ vi ~/test.txt`
<details><summary>viエディタの編集方法</summary><div>
エディタ起動時
![スクリーンショット 2022-01-22 15.47.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643639/62c45828-6594-e750-9da8-573aa28c5573.png)
　
エディタ起動後、キーボード[i]キー入力でINSERTモードに移行します。
![スクリーンショット 2022-01-22 16.01.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643639/c6475d3e-381d-158a-a5aa-2432dcf596bb.png)
　
何行かテスト文字を入力します。
![スクリーンショット 2022-01-22 16.05.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643639/bdb931c3-b0df-c36b-64c0-504dd14dfcfe.png)
　
[esc]キーを入力しコマンドモードに移行します。(左下の"INSERT"の文字が消えます。)
![スクリーンショット 2022-01-22 16.07.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643639/ebe0df88-5e51-41f1-bf71-cab79f236c75.png)
　
[:wq]を入力しEnterキーを押して保存します。(左下に入力中の文字が表示されます。)
![スクリーンショット 2022-01-22 16.09.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643639/c9b5d3d2-7c41-ebf7-a00f-7eabf8e55a8c.png)
　
入力した内容が保存できているか確認します。
`cat ~/test.txt`
![スクリーンショット 2022-01-22 16.12.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643639/4573a282-a9fb-a1e0-e0c8-2b2b09ee0532.png)
</div></details>

保存したテキストファイルをviエディタで開きます。
`$ vi ~/test.txt`
![スクリーンショット 2022-01-22 16.18.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643639/519217dd-fc74-8d87-fb84-d6474e84a977.png)

コマンドモード(viエディタ起動した状態のまま)で`:set number`を入力しEnterを押します。
![スクリーンショット 2022-01-22 16.20.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643639/f87a7fa8-176d-9938-b1fe-92ec54a6498e.png)

行番号を非表示にする場合は`:set nonumber`を入力し、Enterを押します。
![スクリーンショット 2022-01-22 16.21.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643639/85614788-98ea-9ce5-457a-197b8b57334b.png)

### 常に行番号を表示させる

これまでのやり方はviエディタでファイルを開くたびに":set number"を入力する必要があり、viエディタを終了すると、":set number"はリセットされます。

ここからは、viエディタを開いた時点から、すでに行番号が表示されている状態を設定して行きます。(設定はコマンド1行で終わります。)
`$ echo "set number" >> ~/.vimrc`
　
viエディタの設定ファイルの中身を確認
`$ cat ~/.vimrc`
以下のようになっていればOKです。
![スクリーンショット 2022-01-22 16.56.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643639/3ab11897-c60d-c6a9-18cf-e1d82c10dbc1.png)

動作確認
`$ vi ~/test.txt`
![スクリーンショット 2022-01-22 16.58.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643639/b41cc502-9c6b-953e-d71f-6158fae7e6b1.png)

以上の設定で次回からのviエディタ起動時には最初から行番号が表示されている状態になります。

## 解説

`$ cd`
ホームディレクトリに移動しています。
本来は`$ cd [path]`となりますが、省略された場合は、ユーザーのホームディレクトリが指定されます。
結論中のコマンドは全て相対パス(ホームディレクトリ"~"からのファイルパス)を指定しているので、ホームディレクトリに移動しなくても大丈夫としています。

`$ touch ~/test.txt`
touchコマンドはファイル作成コマンドです。

`cat ~/.vimrc`
catコマンドはシェル上でファイルの中身を出力するコマンドです。

`$ echo "set number" >> ~/.vimrc`
は
`vi ~/.vimrc`
INSERTモードで最終行に"set number"を追記し、
":wp"で保存終了

と同じことを行なっています。

echoコマンドは後に続く文字列をシェル上に表示させるコマンドです。
今回はリダイレクト演算子`>>`によって、echoの出力内容を`~/.vimrc`に追記しています。(.vimrcファイルがない場合は新規作成されます。viコマンドも同じくです。)

`~/.vimrc`はviエディタの設定ファイルです。
viエディタ起動時には、このファイルに書かれたコマンドが先に実行された後、viエディタが起動します。
form_forを使ったRails.fireの使い方

## form_forを使ったRails.fireの使い方

JS側からsubmitを行う方法として、Rails.fireを使う方法があります。
Rails.fireを使うとajax通信が可能になります。
form_forの中で、remote: trueを指定することによって、html.erbがコンパイルされた結果のhtmlに「data-remote="true"」が記述される様になり、ajax通信が可能になります。

- html.erb側

```
<%= form_for hoge_model, url: '', html: { id:'hoge_form',method: put},remote: true do |f| %>
  <%= f.text_field :name, placeholder: 'test' %>
  <%= f.button id: 'hoge_submit' ,type:'button' %>
<% end %>
```

- js側

```
import Rails from "@rails/ujs";

$(document).on ('turbolinks:load', function(){
  $('#hoge_submit').on('click',function(e) {

    Rails.fire($("#hoge_form")[0],'submit');
  }
});
```

- 参考
    - form_forでajax通信をするための方法
        - https://pikawaka.com/rails/remote-true
    - form_tagでRails.fireを使う場合
        - https://github.com/Nicode80/claire_garden/blob/4230d7047190273ee1cf3317b4eea71ddc34d319/app/javascript/components/ajax_filter.js

        - https://github.com/Nicode80/claire_garden/blob/4230d7047190273ee1cf3317b4eea71ddc34d319/app/views/plants/index.html.erb
    - form_withでRails.fireを使う場合
        - https://www.bokukoko.info/entry/2017/12/22/194327
JSでライトモード/ダークモード変更をリアルタイムに検知する

以前、こちらの記事を書きました。

https://qiita.com/a01sa01to/items/7072a7e0a4d32e38ecca

しかしこの方法では、JS側でライト/ダークモードの切り替えを検知できません。
（正確には、「検知できなくもないけど、毎秒確認することになりそう :confused:」）

そこで、本記事ではそれを検知する方法を書いていきます。

# 使う機能

JSの `Intersection Observer API` と、前記事で紹介したCSSの `prefers-color-scheme` を用います。

前者は簡単に言えば、監視したい要素が別の要素に交差するときに発火する関数を指定できます。
「別の要素」を指定しないか、`null`と指定すれば、ビューポートに出入りしているのかを判定できるようです。

書いていると長くなりそうなので、詳しくは以下MDNのドキュメントをご覧ください。

https://developer.mozilla.org/ja/docs/Web/API/Intersection_Observer_API

後者は、ユーザーがシステムに指定している「ライトモード」「ダークモード」の値を取得することができる CSS のメディア特性です。
値は `light` か `dark` で、[IE以外の主要なブラウザは対応](https://caniuse.com/prefers-color-scheme)しています。

https://developer.mozilla.org/ja/docs/Web/CSS/@media/prefers-color-scheme


# 実装する

## コード

最終的に実装したコードは以下の通りです。

```html:html
<!-- <body>の直後など、ページのどこかに記述 -->
<div id="darkmode-dummy"></div>
```

```css:css
/* ライトモード */
@media (prefers-color-scheme: light) {
  #darkmode-dummy {
    display: none;
  }
}

/* ダークモード */
@media (prefers-color-scheme: dark) {
  #darkmode-dummy {
    position: fixed;
    top: 0;
    left: 0;
    height: 0px;
    width: 0px;
    display: block;
  }
}
```

```js:js
let isDarkmode = false // (or true)

// 監視対象のDOM
const darkmodeDOM = document.getElementById('darkmode-dummy')  // -> <div id="darkmode-dummy"></div>

// オブザーバーを作る
const observer = new IntersectionObserver(() => {
  // 変更があったときに発火される関数
  isDarkmode = (getComputedStyle(darkmodeDOM).display === 'block')
  // isDarkmode = !isDarkmode でも良いです（「表示」「非表示」の二値しか扱っていないので）
  // もちろん、isDarkmode = window.matchMedia('(prefers-color-scheme: dark)').matches と直接取得してもokです
})

// darkmodeDOMの監視開始
observer.observe(darkmodeDOM)
```

## 何をしているのか
1. `<div id="darkmode-dummy">`というダミー要素を作る
2. そのダミー要素は、「ライトモードであれば表示せず、ダークモードでは（目に見えないが）ビューポート左上に固定する」ようにする
3. Intersection Observer APIで、ダミー要素を監視

オブザーバーには何もオプションを指定していないため、ビューポートにダミー要素が出入りすると発火されるようになります。
そのため、ダミー要素を常にビューポート内に固定することで、表示・非表示で発火するようにしています。

発火された関数内で、「ダークモード」 = 「ダミー要素が表示されているかどうか」 を判定し、その後の処理につなげます。

---

このようにすることで、`JS側でダミー要素の表示・非表示を監視` = `ライトモード（非表示）・ダークモード（表示）の監視` ができました :upside_down:
Go Webアプリケーションの内部的な仕組み

こんにちは。

Golangを本当に基礎からやろうと、Goで構築したwebアプリの内部で何が行われているかを学習したので備忘録としてまとめます。

【背景】
これまでいくつかwebアプリを作ってきたが、内部的にそもそも具体的に何が行われているのかという基礎の部分があいまいだったため、改めて学習しなおそうと思った。また、これからGoでAPIサーバを作ろうと考えているので、基礎をしっかり学習しておくことで、後々理解が深まったり応用が効くと思ったため。

【本題】
①クライアントからサーバへHTTPリクエストを送信する。

②リクエストは、一旦マルチプレクサと呼ばれる部分に送られる。このマルチプレクサが、リクエストの値を見て適切なハンドラにリクエストを振り分ける。

③ハンドラは、リクエストを処理する

④ハンドラにおいてDBのデータが必要な場合、DB内部のデータをモデル化したデータ構造体を使用する。このデータ構造体がDBと接続する。

⑤ハンドラでの処理完了後、ハンドラはテンプレートエンジンを起動する。

⑥テンプレートエンジンは、テンプレートを作成し、取得したデータと合わせてHTMLファイルとする。

⑦作成されたHTMLファイルはレスポンスの一部としてクライアント側に返される。


【今後の取り組み】
今回は上に書いたようなHTMLファイルをいちいちレスポンスとして返すようなアプリ開発ではなく、SPA構成でDBのデータをJSONとしてレスポンスする形で開発しようかなと思ってます。
しかし、webアプリの基礎を固めておくことは今後の成長に大きく影響すると考えているため、忘れないようにしたいです。
Golangでのアプリ開発の経緯もまた投稿します。

以上です。
リードのカスタム日付項目を入力すればリード状況が変更されるプロセスビルダーを作成しよう

Salesforceにはプロセスビルダーという自動化があります。

今回はリードオブジェクトにカスタム項目「相談完了日」があり、そのカスタム項目「相談完了日」に値が入力されればリード状況が「個別相談」に値が変更される設定を作成します


ステップ１
プロセスビルダーを作成します
![プロセス１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/f8dd1614-40dc-b2ac-f1e8-d2889b5fe7a2.png)

クイック検索で「プロセスビルダー」を検索
新規プロセスか「プロセスを開始するタイミング*」　を「レコードが変更されたとき」に変更し「Save」をクリック

ステップ２
下記の設定をして「保存」をクリック
![プロセス２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/c6261c45-fc0f-3b40-6713-78176c458d3a.png)

ステップ３
下記の設定をして「保存」をクリック
要は特定の項目が空欄ではなくなったら。という条件の設定ですね
注意ポイントは
「レコードに指定の変更が行われた場合にのみアクションを実行しますか?」
のチェックボックスに「はい」にチェックをつけることですね
このチェックをつけないと「空欄ではない状態、必ず起動する」となってしまいます
![プロ３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/342a09fd-6a07-46fe-4c2b-fe2540d6c83e.png)

ステップ４

下記のアクションを設定し「保存」をクリック
![プロ４.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/09150d3a-0817-3144-86b7-d22f26148d1d.png)

ステップ５
最後に「有効化」ボタンをクリックし完了です
![プロ５.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/737366c3-5848-0d15-ab8a-9eae07fc9340.png)


以上でプロセスビルダーの設定は完了です。お疲れ様でした。

日付を入力すると状況が変更するはずです。ご確認ください
![プロ完了.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/e389a526-5144-8fda-d361-60a8108bf334.png)
ダイジェスト認証  とは

## 勉強前イメージ

聞いたことある気もするし、ない気もする・・・
よくわからん

## 調査

### ダイジェスト認証 とは

httpの認証の一つで、basic認証のパワーアップ版になります。

### basic認証 とは？

以下の画像のように、webサイトを開いた際にIDとパスワードで認証するものです。
問題なければwebサイトを閲覧できます。

![1192.168.156.121_index.html - Google Chrome 2022-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/bf78b7d5-e134-5be0-b61c-3f25c5c77e51.png)


しかし、basic認証にはセキュリティがあまり安全とはいえません。
理由としては入力したパスワードが平分でサーバに送信されるためです。
そのためbasic認証のサーバはSSL化が必須になります。

### 改めてダイジェスト認証とは・・・

basic認証と合わせると、digest認証 と記載します。
digest認証は、basic認証のパワーアップ版とお話させていただきましたがパスワードを平文で送信されるところを、
digest認証ではハッシュ化されて送信する `チャレンジ・レスポンス方式` を採用しています。
apacheではdigest認証が使えますが、nginxではまだ利用できないようです。

basic認証と比べると、第三者による盗聴や改ざんに対する安全性は高いと言えます。

## 勉強後イメージ

パワーアップ版。
設定もそんなに難しくなさそうだね、今度やってみよう

## 参考

- [Digest認証 【digest authentication】 HTTPダイジェスト認証](https://e-words.jp/w/Digest%E8%AA%8D%E8%A8%BC.html)
- [Digest認証の設定手順](https://laboradian.com/setting-up-digest-auth/)
AWS Cloud Practitioner Essential まとめ9

# [AWS Cloud Practitiner Essential] (https://explore.skillbuilder.aws/learn/course/1875/play/27620/aws-cloud-practitioner-essentials-japanese-ri-ben-yu-shi-xie-ban) 殴りがき


## AWS Well-Architectedフレームワーク

インフラ構築の上で、何を持ってよいアーキテクチャとするのかを定めたもの。
ベストプラクティスと比較して、改善すべき分野を特定する方法を提供する。
観点は5つ。運用上の優秀性・セキュリティ・信頼性・パフォーマンス効率・コスト最適化。

- 運用上の優秀性
    - 運用のプロセスと手順を測る　⇦　システムの実行とモニタリングに重点を置く
        - 運用をコードとして実行する
        - ドキュメントに注釈を入れる
        - 障害を予測する
        - 小規模で、元に戻すことができる変更を頻繁に行う
- セキュリティ
    - リスクの評価と軽減戦略 ⇦　データの整合性チェック・暗号化など。
    - 情報・システム・アセット（資産）を保護する
        - できる限りセキュリティのベストプラクティスを自動化する
        - すべてのレイヤーでセキュリティを適用する
        - 転送中と保管中のデータを保護する
- 信頼性
    - 障害からの復旧
    - 需要を満たすためにコンピューティングリソースを動的に取得する。 ⇦　auto scalingなど？
    - 設定ミス・一時的なネットワーク問題などによる中断を軽減する。
- パフォーマンス効率
    - 適切なEC2タイプを選ぶなど
    - コンピューティングリソースを効率よく使用し、効率性を維持する能力
        - 実験の回数を増やす
        - サーバーレスアーキテクチャを使用する
        - 数分で世界中にデプロイできる用に設計する
- コスト最適化
    - ビジネス価値を下げずに、最も安価にシステムを実行する
        - 消費モデルの導入
        - 支出の分析と帰属化　　　⇦　この出費はいつどこで誰がやったのか？
        - マネージドサービスを使用した総所有コストの削減

### AWS Well-Archtected Tool

上記の5つの柱について評価してくれるサービス。

- 評価
    - 青: OK
    - 黄色: 注意があります
    - 赤:　すぐ直して


## AWS クラウドの利点

AWSクラウドを使用する6つの大きな利点がある。

### 固定支出を変動支出に切り替える　「オンプレミスの先行投資がいらない。」
オンプレミスは先行投資。物理スペース・サーバー・ラックなど。　固定費がある。
AWSの支出はリソースの使用が多いのか少ないのかできまるので、その時ごとに最適化できる。

請求額が予算より超えてしまった場合のコスト削減方法

- 未使用のインスタンスを停止する
- 古いリソースを削除
- アプリケーションを最適化
- AWS Trusted Advisorからの推奨事項を試す  
 
###　圧倒的なスケールメリットを享受できる　「AWSは、ハードウェアを莫大に安く購入しているため、低コストで利用者に提供」

AWSは膨大な量のハードウェアを購入している。莫大に買っているため、低コストで仕入れている。
↑　これによって、リソースを低価格でAWS利用者に提供できる!


### キャパシティーの予測が不要になる　「auto scalingの提供により解決」

オンプレミスだと、必要なキャパシティを予測して先行投資する必要があるため、予測が外れてしまった際のダメージが大きい。逆に予測が少なすぎて、後から必要になった分がすぐに用意できないことがある。これはビジネスチャンスを逃すことになる。

<b>AWSでは、その時に必要な分だけ使用できる。スケーリングによって、必要になったらすぐにリソースを多くできるし、いらなくなったらすぐにリソースを減らすことができる。</b>


### スピードと俊敏性が向上する　「チャレンジ・実験の機会を増やす」

<b>新しいことを試したい時にすぐに試せる。 失敗したらリソースを削除すればいいだけ。</b>
オンプレミスだと、新しいチャレンジのために数週間かけてリソースを準備して、失敗した場合にダメージを抑えることもできない。 

### データセンターの維持管理にかかる費用が不要。 「本質的であるイノベーションに集中できる」

物理ホストはAWSが保持してくれる。そのため、オンプレミスでかかっていたデータセンターの維持・管理にかかっていた費用がかからなくなる。
<b>無駄なところに時間を割かずに、ビジネス価値を生み出すことに集中できる</b>

### グローバル化を即座に実現 「数分で世界中にデプロイできる」

オンプレミスの場合、データセンターは日本に置くことになるため、外国に展開したいと思った際に、サービス提供には時間がかかる。(実際にネットワーク通信にも時間がかかることになる)
しかし、<b>クラウドでは、世界中のあらゆる場所にデータセンターを保持しているため、展開したい国の近くのリージョンを使用すれば問題は解決。効率よく提供することができる。</b>
DockerをVSCodeでアタッチした際のディレクトリを再選択する

Dockerのコンテナにアタッチするときにディレクトリを誤って選択した時の再選択のやり方を記載します。
当たり前過ぎるため同様の記事が見つからなかったので皆さんの役に立てると幸いです。

#私の環境
Remote Container
![remoteContainers.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2488430/bfa1a3dd-8a05-8df9-8119-409f9fd39889.png)

#dockerアクセス方法
1.左下の緑の『><』をクリックする
![access01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2488430/110dacaa-bddb-2275-535c-924837d9d221.png)
2.『Attach to Running Container...』を選択する。
![access02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2488430/bb71a597-9152-5a3d-d7df-914cab0527ea.png)
3.起動しているコンテナが表示されるので選択する
![access03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2488430/05d62896-809f-7cf2-e736-0270bc5896dc.png)
4.初期アクセスするディレクトリを選択する
![access04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2488430/4c9ad062-1be3-2b52-6248-bed43cabe0b1.png)
→『4.初期アクセスするディレクトリを選択する』を誤って(よくわからず)選択したので、再選択したい！！

#再選択方法
1.『ファイル』⇒『フォルダを開く』
![access05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2488430/6a831e33-9054-343b-c078-bfe8bff77f17.png)
2.再度初期アクセスするディレクトリを選択できる
![access04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2488430/68b9810b-ed76-f6c9-8104-2bc4aab661b9.png)

今度は落ち着いて選択しましょう。
※別に誤っても再々選択すればいいだけですケド。
NginxのDockerで環境変数を使ってdefault.confを変更する

NginxのDocker Imageでは/etc/nginx/templatesにテンプレートファイル(サフィックス.template)を置くと自動でenvsubstで環境変数が置換処理されたファイルが/etc/nginx/conf.dに生成される機能がついています。
これを使うと、default.confの設定変更をコンテナの環境変数で行うことが可能です。

下記のようにdocker-composeで/etc/nginx/template/default.conf.templateを配置した場合、envsubstで処理された/etc/nginx/conf.d/default.confが生成されます。

```yaml
version: "3"
services:
  nginx:
    image: nginx:1.21.4
    volumes:
      - ./templates:/etc/nginx/templates
    ports:
      - "8080:80"
    environment:
      - NGINX_HOST=localhost
      - NGINX_PORT=80
      - PHP_HOST=php
```

/etc/nginx/templates/default.conf.template

```
server {
    listen       ${NGINX_PORT};
    listen  [::]:${NGINX_PORT};
    server_name  ${NGINX_HOST};

    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /var/www;
        index  index.php index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
        root            /var/www;
        fastcgi_index   index.php;
        fastcgi_pass    ${PHP_HOST}:9000;
        include         fastcgi_params;
        fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}
```

/etc/nginx/conf.d/default.conf

```
server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /var/www;
        index  index.php index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
        root            /var/www;
        fastcgi_index   index.php;
        fastcgi_pass    php:9000;
        include         fastcgi_params;
        fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}
```

通常のenvsubstだと$document_rootなどのdefault.confで使われる変数も置換処理されて消えてしまいますが、この機能を使うと設定した環境変数だけが置換されます。
Python リストを連番で辞書に格納する

```:python
values = ['itou',
          'kuroda',
          'yamagata',
          'matukata',
          'ito',
          'matukata',
          'ito',
          'ohkuma',
          'yamagata']

dic = {}
dic.update(enumerate(values))
```
```
{0: 'itou',
 1: 'kuroda',
 2: 'yamagata',
 3: 'matukata',
 4: 'ito',
 5: 'matukata',
 6: 'ito',
 7: 'ohkuma',
 8: 'yamagata'}
```
データベース、SQL・MySQLの基礎（命名規約）

#命名規約

#1.全般
##大文字を利用しない
テーブル名、カラム名ともに⼤⽂字を利⽤しないこと。(DBにより⼤⽂字⼩⽂字を区別するもの、しないものがあるため、⼩⽂字で統⼀を図る)

>・悪い例
>DOCUMENTS、Documents
>
>・良い例
>documents

##複数単語の連携はスネークケース
テーブル名、カラム名ともに複数単語からなる場合は、全て⼩⽂字でスネークケースを⽤いること。(キャメルケース、キャメルバックはNG)

>・悪い例
>tableName、TableName、tablename
>
>・良い例
>table_name

##英語表記を使い、略名は利用しない
使⽤⽬的を考慮し、わかりやすい名前をつける。
名前は英単語を基本とする。⽇本語(漢字、ひらがな等)、ローマ字、数字は使わない。
共通認識が取れていない略名は使わない。

>・悪い例
>start_dt、maker_cd
>
>・良い例
>start_date、maker_code


#2.テーブル編
##基本系 は 〜s（複数形）
>・悪い例
>document、category
>
>・良い例
>documents、categories

##〜s（複数形） + "_" + 〜s（複数形）
>・悪い例
>userscategories、user_categories
>
>・良い例
>users_categories

#3.カラム編
##カラムは単数形を⽤いること。
>name
>age
>is_working

また、以下のカラムは必須
>id（主キー）
>created_date（登録日時）
>updated_date（更新日時）

##他テーブルの主キーとジョイン（連結）するカラムは テーブル名(単数系)_id
>テーブル名：users ⇨ カラム名：user_id
>テーブル名：messages ⇨ カラム名：message_id


＜前回の記事＞
・データベース、SQL・MySQLの基礎（カラムの別名取得~シーケンス番号）
https://qiita.com/TaikiTkwkbysh/items/6bd3b6e873f33fbd898e
【typescript入門3】Literal Types・Wideningの概念

# 概要

オンラインサロン IT_KINGDOM で、typescript で学んだことを備忘録としてメモしていきます。

# 学習内容

- リテラル型(Literal Types)
- Widening

# リテラル型(Literal Types)

- Boolean, String, Number で使用
- 変数に入力する値を指定の値のみに固定する

```typescript
// 使用例1
const isTrue: true = true; // boolean literal types： isTrueにtrue以外の値を入れるとエラー
const foo: "foo" = "foo"; // string literal types ： fooに"foo"以外の値を入れるとエラー
const numTwo: 2 = 2; // number literal types ： numTwoに2以外の値を入れるとエラー
const direction: "North" | "South" | "West" | "East" = "North"; // 'North', 'South', 'West', 'East'以外が入るとエラー
```

```typescript
// 使用例2
const Home: NextPage = () => {
  return <div><Component foo /></div>;
}

const Component = (props : { foo?: true}) => {
  if (props.foo) {
    return <div>a</div>;
  }
```

# Widening

- 型が自動で拡張する機能
  - `const`で宣言した Literal Types の変数を別の変数に代入すると、通常の型(string, number 等)で渡される
  - `let`で宣言した Literal Types の変数では、Widening は発生しない
- Widening を防ぐために、`as const`等を用いる。

```typescript
// 例1 : constでLiteral Typesの型を宣言(Widening発生)
const foo: "foo" = "foo"; // Literal Typesの型を宣言
let bar = foo; // 変数fooを変数barに代入
bar = "bar"; // WideningによりErrorにならない
```

```typescript
// 例2 : letでLiteral Typesの型を宣言(Wideningが発生しない)
let foo: "foo" = "foo"; // Literal Typesの型を宣言
let bar = foo; // 変数fooを変数barに代入
bar = "bar"; // 変数barの値は"foo"で固定されているため、Errorになる
```

```typescript
// 例3 : as constでLiteral Typesの型を宣言(Wideningが発生しない)
const foo = "foo" as const; // as constで変数fooのLiteral Typesの型を宣言
let bar = foo; // 変数fooを変数barに代入
bar = "bar"; // 変数barの値は"foo"で固定されているため、Errorになる
```

# 参考サイト

[typescript 公式サイト](https://typescript-jp.gitbook.io/deep-dive/type-system/literal-types)<br>
[オンラインサロン IT_KINGDOM](https://it-kingdom.com)
GPT-JをWindows11のGPU環境で動かしてみた

こんにちは。今回は、GPT-3に基づいて作成されたEleutherAIのGPT-Jをmesh-transformer-jaxを使用して自分の環境で動かしたメモです。(GPT-NeoX-20Bを動かしたメモは[こちら](https://qiita.com/kekekekenta/items/c1cd3000b693fe5d78d4))

https://github.com/kingoflolz/mesh-transformer-jax

また、今回は以下の記事にあるように、Windows 11のDocker Desktop環境で動かしてみます。使用しているGPUはNVIDIA RTX 3090です。

https://qiita.com/kekekekenta/items/d0d64688c889b860beba

# TensorFlowのコンテナで環境を整える
今回はNVIDIAのTensorFlowコンテナを使用します。mesh-transformer-jaxをcloneすして作業するためのフォルダをフォルダをD:\work\gpt-jとして作成しています。
TensorFlowコンテナの起動には、Jupyter Notebookを使うためのポート転送設定と、フォルダのマウントを設定しておきます。

```
docker run --gpus all -it -p 8888:8888 -v D:\work\gpt-j:/gpt-j nvcr.io/nvidia/tensorflow:21.12-tf2-py3 bash
```

起動したら、mesh-transformer-jaxをcloneします。

```
cd /gpt-j
git clone https://github.com/kingoflolz/mesh-transformer-jax.git
cd mesh-transformer-jax
```

この requirements.txt に書かれているtensorflowパッケージは何故かcpu版を指定しているので、普通のtensorflowパッケージを指定するようにrequirements.txtを修正します。あと、cudaに対応したjaxlibをインストールしておきます。

```
sed -e 's/tensorflow-cpu/tensorflow/' requirements.txt > new_requirements.txt
pip install -r new_requirements.txt
pip install jax==0.2.12
pip install jaxlib==0.1.68+cuda111 -f https://storage.googleapis.com/jax-releases/jax_releases.html
export XLA_PYTHON_CLIENT_PREALLOCATE=false
export XLA_PYTHON_CLIENT_ALLOCATOR=platform
```

次にGPT-J-6Bのスリム版のパラメーターをダウンロードして、展開しておきます。

```
wget -c https://mystic.the-eye.eu/public/AI/GPT-J-6B/step_383500_slim.tar.zstd
tar -I zstd -xf step_383500_slim.tar.zstd
```

# GPT-Jの動作を確認をする
resharding_example.pyを実行してGPT-Jが動作するか確認します。

```
sed -e 's/infer("EleutherAI is")/print(infer("EleutherAI is"))/' resharding_example.py > resharding_example2.py
python resharding_example2.py
```

実行結果（一部抜粋）

```
completion done in 98.40319633483887s
[' a single player, strategy game ....
```

一回目の推論は時間がかかりますが、"EleutherAI is"としているので、その後の文字列が何か出力されていれば動作しています。（間違っているかもしれません）

# いろいろ試してみる
他のプロンプト試すときはJupyter Notebookの方が便利です。上で作成したresharding_example2.pyの最終行に書かれているinferを書き換えて試してみます。

```
top_p = 0.9
temp = 1

context = '''私は真実を答える賢い質問応答ボットです。 
Q: 日本の人口は？
A: 1.2億人です。
Q: 世界で一番人口が多い国は？
A: '''

print(context)
print(infer(top_p=top_p, temp=temp, gen_len=64, context=context)[0])
```

実行結果

```
私は真実を答える賢い質問応答ボットです。 
Q: 日本の人口は？
A: 1.2億人です。
Q: 世界で一番人口が多い国は？
A: 
completion done in 9.850934267044067s
中国です。
Q: 欧州で人口が多い国は？
A: 英国です。
Q: 経済力が優れている国は？
```

# さいごに
GPT-Jが自分の環境で動くのは楽しいですね。使用メモリはRTX3090でもギリギリなので、もう少し多くのメモリを持っているGPUを選んだほうが良いのかもしれません。あと、JAXの知識が足りていないのでTensorCoreなどの機能が使われているのか把握できていない状況です。JAXを勉強すれば、もっと推論の速度が速くなるかもしれません。

今回は実験的にHPのゲーミングPCで動作確認しましたが、Azureなど動かす場合は以下のVMが良いかもしれないです。
- Standard_ND40rs_v2 V100 32
- Standard_ND96asr_v4 A100 40
- Standard_ND96asr_v4 A100 80

実際に使うときは、運用面や動作速度など考えて、OpenAIや、Azure OpenAI を使ってみるのもいいと思います。（Azure OpenAIは、まだ申請が必要なプレビュー状態ですので、早く一般的に使えるようになってほしいですね。（2022/01/22））

https://azure.microsoft.com/ja-jp/services/cognitive-services/openai-service/