OmniAICreator/Qiita-1.07M huggingface dataset:
EC-CUBEの環境構築

```plaintext
本記事は、以下の環境で作業を行います。
OS: macOS Venture 13.3.1
Chip: Apple M1 Pro
```

とりあえず環境構築からということで
「ec-cube install」とかでGoogle検索します。


公式の開発者向けドキュメントがヒットしたので[こちらに](https://doc4.ec-cube.net/quickstart/install)アクセス。

ここでは、[symfony/cli](https://qiita.com/nanasess/items/de9f5450717cc8ede51a)を利用するやり方をチョイスします。
（余裕があればDocker／Docker Composeを使ったやり方も試します。詰まりそうならGUIのやり方に切り替えるかも。）

EC-CUBEの[github](https://github.com/EC-CUBE/ec-cube)を `fork` + `clone`

Symfony CLI のインストール
```shell
brew install symfony-cli/tap/symfony-cli
```

EC-CUBEのインストール
```shell
# cd path/to/ec-cube # 事前に git clone したディレクトリに移動
symfony composer install # vendorディレクトリが作成される
# データベースは事前に作成しておく
# データベースを sqlite から　mysql 等へ変更するときはこのタイミングで.envを編集しておく
symfony console eccube:install -n
```

ここまで正常に実行できていれば以下のメッセージが表示されます。
![Screenshot 2023-05-26 at 13.49.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/650571/6e3007d2-8d84-e509-a73e-57bd9c4b8585.png)

必要なものは一通りそろったので、ローカルサーバーを起動します。
```shell
symfony server:start # 停止は ctrl + c
```

ここまでくれば、[http://127.0.0.1:8000/](http://127.0.0.1:8000/)にアクセスすることでサイトが確認できます。
管理画面は、[http://127.0.0.1:8000/admin/login](http://127.0.0.1:8000/admin/login)に対して、ID `admin`、PW `password`でログインすれば確認できます。

参考
https://doc4.ec-cube.net/quickstart/install
https://qiita.com/nanasess/items/de9f5450717cc8ede51a
https://symfony.com/download
Growiの検索

複数ワードでand検索時、期待しない結果と件数になってしまう。
で、調べた結果（といっても、公式のissueにありました）
・ワードはダブルクォートで囲う
・ワード間のスペースを半角にすると、Hitワードにマーカーが付く

Rocky Linux 9.1
Growi 4.5.25（Docker）

あと、英数の全角・半角を区別してしまいます。
標準でkuromojiとicuが入っているはずなんだけど････
どなたか対処法ご存知ありませんか？
あなたは本当にSAPを理解して認定資格を取得していますか？

SAPのアカデミーやLearning HUBの受講料はかなり高いです。
しかし末端のSESやフリーランスがS/4 HANAの学習をするのは予算がないため、どうしても本質を学ぶことができず、UdemyやNoteの過去問を購入して問題と解答を丸暗記する勉強をせざるを得ないです。
孫請けであってもSAPのプロジェクトは単価が高いので、SESではどうしても社員に丸暗記でもコンサルタント資格を取らせたいという気持ちは理解できません。
しかし各モジュールのトランザクションや品目マスタの設定、コンフィグ設定を行うのに暗記で知識は習得できるわけがなく、全く作業の意味が分からないコンサルタントがたくさんいるのが現実です。
過去問を勉強するのに必ずしもアカデミーやLearning HUBの学習を受けるのは、あまりにも高額なので、下記のサイトを読んである程度知識をつけるのも可能だと思うので、ぜひ学習してください。

【おすすめサイト】
SAPコンサルブログ（https://tokulog.org/）

各モジュールの知識やマスタ、テーブルに関する知識が分かりやすく書かれていて、キャリアパスに関する記事も書かれているので、少なからず学習するのに参考になるとは思います。
しかし本気でSAPのコンサルタントを育てるのであれば、各Sierが若いエンジニアへ投資する目的でアカデミーでの受講を勧めるか、Learning HUBの受講権を購入するなど、全面的にバックアップすべきである。
必ず本質を理解してプロジェクトに参画できれば、単価が高額なので必ず投資分は戻ってくると期待できます。
暗記は絶対にやめてください。
多次元データを特徴量とするRNN(SimpleRNN, LSTM)の構造

# はじめに
RNN(SimpleRNN, LSTM)は通常のニューラルネットワーク(feedforward neural network)と異なり，時系列データなどの系列データを学習することができます（以下の説明では，時系列データを解析対象とします）．RNNはセルとよばれる構造をもっており，セルの内部で入力値から出力値を計算しています．1個のセルに複数の値を入力することができますが，ここではセルの内部ではどのような計算が行われているか解説します．

# SimpleRNN
SimpleRNNセルの式は以下で表されます．
```math
\boldsymbol{y}_t = \boldsymbol{h}_t = \text{tanh}(\boldsymbol{W}_{xh}\boldsymbol{x}_t + \boldsymbol{W}_{hh}\boldsymbol{h}_{t-1} + \boldsymbol{b}_h)
```
ただし，$\boldsymbol{x}\_t$は入力ベクトル，$\boldsymbol{y}\_t$は時刻$t$の出力ベクトル，$\boldsymbol{h}\_t$は時刻$t$の隠れ層ベクトル，$\boldsymbol{W}\_{xh}$は入力層から隠れ層への重み行列$\boldsymbol{W}\_{hh}$は隠れ層から隠れ層への重み行列，$\boldsymbol{b}\_h$はバイアスのベクトルです．したがって，SimpleRNNでは，（入力値と1時刻前の出力値の全結合）+（バイアス項）を活性化関数$\text{tanh}$に通して，出力値とすることが分かります．

# LSTM
編集中
[備忘録]Rubyに様々な入力パターンのファイルを渡して実行する

# はじめに

・色々なパターンの入力データをRubyプログラムに渡したい
・入力データはプログラムに直接書かずに、ファイルを分けておきたい

例えば、以下のようなファイルをRuby（test.rb）に渡して実行したいとすると

~~~case1.txt
1,2,3,4...
~~~
~~~case2.txt
a,b,c,d...
~~~



ターミナルで以下のコマンドを実行します。
~~~
cat case1.txt | test.rb
~~~
<br>



Ruby側はこのようにデータを受け取ります

~~~test.rb
# 標準入力からデータを読み込む
input_data = $stdin.read

# 処理結果を標準出力に出力する
#puts input_data

# CSVデータが複数行ある場合は
# CSVデータを改行で分割し、各行を配列の要素として格納
input_data_line = input_data.split("\n")
~~~

<br>

ターミナルにコマンドを入力した際、エラーになる場合はこちらも試してみてください。
~~~
ruby test.rb < case1.txt
~~~


※ファイルは同じディレクトリに置いてください。

# 参考ページ

https://qiita.com/shoji621/items/bbbb693cf5e3ccf1bcf3
Lightsailに導入したfail2banでBAN時にメール通知できなかった

# 事象
- Lightsailにfail2banを導入し、BAN時にメール通知しようとした。
- fail2banのBANは発動したが、メール通知がされなかった。
# 原因
- Lightsailからメールを送信する場合は、事前にAWSに依頼が必要だった。
- https://repost.aws/ja/knowledge-center/lightsail-port-25-throttle
# 解決方法
- 上記URLを参考に、LightsailのEメール送信制限解除申請した。
- メール用途とセキュリティ対策事項を説明し、制限が解除されたことで、メールが送信できるようになった。
# AWSへの依頼時に説明した内容
- メール機能はfail2banのBAN通知にのみ利用すること。
- Inboundの25番ポートを開放する予定はないこと。
- インスタンスへのログインは公開鍵認証のみを利用していること。
# 環境情報
- Lightsail
- Amazon Linux 2 
- fail2ban 0.11.2-3
- postfix 2:2.10.1-6
# 作業ログ、設定など
## 解決前のメールログ
```log:/var/log/maillog (抜粋)
...
May xx hh:mm:ss <hostname> postfix/smtp[31292]: XXXXXXXXXX: to=<yyy@example.domain>, relay=none, delay=34112, delays=34082/0.02/30/0, dsn=4.4.1, status=de
ferred (connect to example.domain[zzz.zzz.zzz.zzz]:25: Connection timed out)
...
```
## fail2banのメール設定
```config:/etc/fail2ban/jail.d/jail.local (抜粋)
[DEFAULT]
...
destemail = xxx@example.domain
sender    = yyy@example.domain
action    = %(action_mwl)s
...
```
## postfixの設定
- 特に変更しておらず、バンドルされていた設定そのまま。
# その他
- 「25番ポート解除したで」の連絡に「ありがとやで」と返信したら「余計なメール送らないで」って怒られたのでご注意を。
【Flutter】パスワードの自動入力(Autofill)

# 目的
一度入力したパスワードは、２回目以降は自動入力されます。

# 前提
iOSとAndroidに問わず、パスワードは大切な情報なので、ユーザーさんの許可また端末の設定がないと、保存/入力できません。

## Android
設定＞Google＞自動入力＞Google自動入力
「Google自動入力を使用する」をONに設定してください。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491433/923f4a58-0bf8-7205-6d42-cdba93558b87.jpeg width=400>

## iOS
1. Apple Bundle IDの設定
Apple開発アカウントに登録して、該当Apple Bundle IDのCapabilitiesの`Associated Domains`を**ENABLE**にしてください。
![スクリーンショット 2023-05-26 11.39.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491433/560d75e0-d681-b0db-1a3f-acfa64878fdc.png)

2. iOS Capabilitiesの追加
    - Runner.entitlementファイルの場合
    ソースコードで追加する場合、下記のソースを追加してください。
    /ios/Runner/Runner.entitlements
    ```xml
    	<key>com.apple.developer.associated-domains</key>
    	<array>
    		<string>applinks:your-domain</string
        </array>
    ```
    - Xcodeで追加する場合、Signing & Capabilities > Associated Domainsで追加する
    ![スクリーンショット 2023-05-26 13.15.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491433/e6bdddb0-d4e4-1e80-49ff-988609f66b9c.png)

  
3. サーバーでapple-app-site-associationファイルを配置
サーバーのルートディレクトリに`.well-known`フォルダを作成し、ファイル名はapple-app-site-associationのjsonファイルを配置してください。

```json
{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appID": "TEAMID.BUNDLEID",
        "paths": ["*"]
      }
    ]
  }
}
```

:::note warn
注意点
メタデータのcontent-Typeは`appliciaton/json`であること
拡張子はなし
:::

下記curlでjsonアクセスできるかを確認できます。
~~~
curl -i https://example.com/.well-known/apple-app-site-association
~~~
下記サイトでAPPLE APP SITE ASSOCIATION (AASA)正しく配置されているどうか確認できます。

https://branch.io/resources/aasa-validator/
4. 端末の設定
設定＞iCloud＞キーチェーン
iCloudキーチェーンをONにしてください。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491433/6d2f87e0-2f88-fef6-1db1-71875603c917.png width=400>

# ソース実装
ソース実装は簡単です。`autofillHints`の属性を設定すれば、パスワードが自動入力となります。
`AutofillGroup`を忘れずに自動入力グループ化します。
```dart
AutofillGroup(
  child: Column(
    children: <Widget>[
      TextField(
        autofillHints: const [AutofillHints.username],
        // other configurations...
      ),
      TextField(
        autofillHints: const [AutofillHints.password],
        // other configurations...
      ),
    ],
  ),
),

```

# 参考
https://capacitorjs.jp/docs/guides/autofill-credentials

https://dev.classmethod.jp/articles/ios-11-password-autofill/#toc-2
Ruby silver 模擬問題解説2

Ruby silverの模擬問題を抜粋して解説をしていきます。

下記コードの出力を4択から選ぶ問題になっています。

```
a = Time.now
b = Time.mktime(2017, 6, 1)
a <=> b
```
1.現在時刻と指定した地方時を比較し、1、0、-1のいずれかを返す。
2.現在時刻と指定した地方時の差を返す。
3.現在時刻のフォーマットを、指定した地方時のフォーマットに変換して返す。
4.現在時刻と指定した地方時を比較し、時刻が等しい場合にtrueを返を返す。

1行目は'Time.nowを使って現在の時刻を取得して変数aに代入します'
```
a = Time.now
```

2行目は'Time.mktime(2017, 6, 1)が2017年6月1日を表すTimeオブジェクトを作成して変数bに代入します'
```
b = Time.mktime(2017, 6, 1)
```
3行目は'<=>'の演算子をしようして'a'と'b'を比較するようにしています。

'<=>'は、左側の値が右側の値より小さい場合は-1,
        等しい場合は0,
        大きい場合は1を返すようになっています。
```
a <=> b
```
したがって、このコードを実行すると現在の時刻（'a'）と指定した時刻('b')を比較して、その結果が返されます。

-1の場合は過去の時刻,0の場合は同時刻,1の場合は未来の時刻になります。

結果として、今回の問題は選択肢１が正解になります。
CloudFormation セキュリティーグループ fromport toport

結論
FromPortとToPortは、セキュリティグループがトラフィックを許可するポート範囲を定義する。

FromPort：許可するポート範囲の開始ポートを指定する。
ToPort：許可するポート範囲の終了ポートを指定する。

もし、FromPort: 8000 と ToPort: 9000 と設定した場合、8000から9000までのポート範囲へのトラフィックが許可される。

FromPort: 80 と ToPort: 80だった場合、具体的には80ポートへのトラフィックだけが許可される。
A Tour of Go 演習: Loops and Functionsやってみた

Golang初心者＆Qiita投稿練習を兼ねて。

# A Tour of Goやってみたら突然練習問題が

![スクリーンショット 2023-05-26 12.16.21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342237/939c43a1-ead5-a607-8b60-56021272b186.jpeg)

（URL）https://go-tour-jp.appspot.com/flowcontrol/8

#### ニュートン砲？！
何ソレ強そう・・・
`z -= (z*z - x) / (2 * z)`

うーん、わからん。
気になるが、調べ始めたら深みに嵌りそうなので無理解なまま計算式を<b>コピ</b>って<b>ぺ</b>して終了。
理解しておけばこの先役立つかもしれないが。
元々要領の悪い自分は<b>優先順位</b>と<b>時間配分</b>も学ばねばならぬ。
これも訓練の一環と考え、<b>計算式の意味はわからないままでヨシ</b>とする。

<font color="orange"><i>調べるな〜　調べるな〜　(BGM: The 黄色い猿 )</i></font>

## ＜説明コメント過剰気味？なコード＞

そうして出来上がったプログラムがコチラ。

```hey2ho.go
package main

import (
	"fmt"
	"math"
)

//ニュートン法を用いて平方根の近似値を求める
func Sqrt(x float64) float64 {
	z := float64(1) //2乗して入力値xに近付ける
	var s float64   //z^2がxにどれくらい近付いたかの比較用

	//最大でも試行10回までとする
	for i := 1; i <= 10; i++ {

		//ニュートン法（とりあえず理解できなくてもOKとする）
		z -= (z*z - x) / (2 * z)

		//%fだと精度(表示桁数)が足りないので%g（計算結果には影響しない）
		fmt.Printf("%d回目: %g 差分: %g\n", i, z, math.Abs(z-s))

		//差分が0.0000000001を下回ったら最終的な解とする
		if math.Abs(z-s) < 1e-10 { //1e-1=0.1

			/* 上記if文の別バージョン
			本家のmath.Sqrt()と同じ値になったら抜ける
			if math.Sqrt(x) == z { */
			break
		}
		//1つ前の値との差分を比較する
		s = z
	}
	return z
}

func main() {
	fmt.Println(Sqrt(2))
	fmt.Println("一夜一夜に人見頃")

	fmt.Println(Sqrt(3))
	fmt.Println("人並みに奢れや")
}
```

## ＜実行結果＞

```shell
$ go run hey2ho.go 
1回目: 1.5 差分: 1.5
2回目: 1.4166666666666667 差分: 0.08333333333333326
3回目: 1.4142156862745099 差分: 0.002450980392156854
4回目: 1.4142135623746899 差分: 2.123899820016817e-06
5回目: 1.4142135623730951 差分: 1.5947243525715749e-12
1.4142135623730951
一夜一夜に人見頃
1回目: 2 差分: 2
2回目: 1.75 差分: 0.25
3回目: 1.7321428571428572 差分: 0.017857142857142794
4回目: 1.7320508100147276 差分: 9.204712812960203e-05
5回目: 1.7320508075688772 差分: 2.445850411092465e-09
1.7320508075688772
人並みに奢れや
```

`ニュートン法`に関しては<b>1㍉も理解しないまま</b>目的は達成できた模様。
今はこれでよしとしよう。


## ＜おわりに＞
3年ほど前にも自分の知識定着を兼ねてQiita記事を幾つか書いてみたものの
- あまりにも学習進度が遅い
    - 要領が悪いのであれこれ分散せず集中した方がよさげ
- 投稿に費やす時間もっとコード書いた方がよいのでは…？
    - Markdown記法に慣れる前にプログラミング言語の理解を深めるべき
- 既に先人が遺した優れた内容を焼き増しても「資産」にはならない
    - むしろネットの海に邪魔なデブリを増やしかねない
- 「不特定多数からどう見られるか？」を気にしてる自分がなんかヤダ
    - 頑張ってますアピールしたいのか？と自己信頼が下がる

などの理由により、投稿に時間をかけるのはやめた。

実際知識や技術レベルが低いうちは低質な記事を時間をかけて量産するより、その分もくもくとコード書いた方がいい気がしないでもない。試行錯誤中。

たった一つの正解はなく、いろんな考え方や人によって向き不向き・段階があると思う。
いろいろやってみて、合わないと思ったら捨てることも必要だなと。
Ruby2.1技術者認定試験 Silver　hello問題解説

私は今、Rubyを使っており、その知識を深めるためRuby2.1技術者認定試験 Silverをプログラミングスクールで毎日解いています。その中で、1日1問、解説を載せ、積み上げを行なっていきます。

よれけば、ご覧ください。

今日の問い

```ruby
s = ["h", "e", "l", "l", "o"].join("").chars.to_a
print s
```

実行結果はどうなるか？



このコードは、文字列 "hello" の各文字を個別の要素として持つ配列 **`s`** を作成し、その内容を出力。

解説:

1. **`["h", "e", "l", "l", "o"]`** は、文字列 "hello" の各文字を要素として持つ配列を表す。
2. **`join("")`** は、配列の要素を空の文字列 **`""`** で連結することを意味する。つまり、配列の要素を連結して文字列 "hello" を作成する。
3. **`chars`** メソッドは、文字列を個別の文字の配列に変換する。この場合、文字列 "hello" が文字の配列 **`["h", "e", "l", "l", "o"]`** に変換される。
4. **`to_a`** メソッドは、オブジェクトを配列に変換する。**`chars`** メソッドによって返された文字の配列は既に配列なので、このステップは不要だが、影響なし。
5. **`print s`** は、配列 **`s`** の内容を出力。

join構文

```ruby
array.join(separator)
```

**`array`**は結合したい要素を持つ配列を指定し、**`separator`**は要素間の区切り文字列を指定する。区切り文字列を空の文字列 **`""`** とすることで、要素を連結する際に区切り文字を挿入しないことを意味する

charsメソッド構文

```ruby
string.chars
```

**`string`**は対象の文字列を指定する。**`chars`**メソッドは、指定された文字列を個別の文字の配列として返す。

具体例

```ruby
s = "hello"
s.chars
```

上記のコードでは、文字列 "hello" の各文字を個別の要素として持つ配列を作成するために、**`chars`**メソッドが使用されている。

**`chars`**メソッドは文字列を構成する各文字を個別の要素として取得するために使用される。例えば、文字列 "hello" を**`chars`**メソッドで処理すると、**`["h", "e", "l", "l", "o"]`**という配列が得られる。

なお、**`chars`**メソッドは文字列専用のメソッドであり、配列に対しては使用できない。配列を文字列に変換する場合には、**`join`**メソッドを使用する。

出力結果

```ruby
["h", "e", "l", "l", "o"]
```

解説は以上です。

問いの答え：

```ruby
["h", "e", "l", "l", "o"]
```
mvnコマンドをするとCould not initialize class com.google.inject.internal.cglib.core.$MethodWrapperエラーが出る

# はじめに

ローカルのJava環境で`mvn`コマンドを実行したところうまく行かなかったのでまとめていきます
ChatGPTにきいてもよくわからずで困っていました

# 問題

`mvn test`を実行すると以下のようなエラーが出ます

```
[ERROR] Error executing Maven.
[ERROR] java.lang.IllegalStateException: Unable to load cache item
[ERROR] Caused by: Unable to load cache item
[ERROR] Caused by: Could not initialize class com.google.inject.internal.cglib.core.$MethodWrapper
```

# 解決方法

mvnを`apt get`で入れるのではなく、最新版を`tar.gz`から入れるようにしました

https://dlcdn.apache.org/maven/maven-3/3.9.2/binaries/

```
$ sudo apt-get purge maven
$ wget https://dlcdn.apache.org/maven/maven-3/3.9.2/binaries/apache-maven-3.9.2-bin.tar.gz
$ sudo tar xzf apache-maven-3.9.2-bin.tar.gz -C /opt 
$ sudo ln -s /opt/apache-maven-3.9.2 /opt/maven 
$ sudo vi /etc/profile.d/maven.sh
```

以下を追記する

```sh:maven.sh
export JAVA_HOME=/usr/lib/jvm/default-java
export M2_HOME=/opt/maven
export MAVEN_HOME=/opt/maven
export PATH=${M2_HOME}/bin:${PATH}
```

```
$ source /etc/profile.d/maven.sh
$ mvn -version

Apache Maven 3.9.2 (c9616018c7a021c1c39be70fb2843d6f5f9b8a1c)
Maven home: /opt/maven
Java version: 11.0.19, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "5.15.0-72-generic", arch: "amd64", family: "unix"
```

```
$ rm -f apache-maven-3.9.2-bin.tar.gz 
```

# おわりに

ChatGPTから解決方法が返ってくるかはわかりませんが、エラー分を記録しておくという使い方もできるのでとりあえず投げとくと良いですね

# 参考文献

https://dlcdn.apache.org/maven/maven-3/3.9.2/binaries/
FarmRPG PlayerBasic Part1-8 まとめ

# 参考

https://www.udemy.com/course/unity-2d-game-developer-course-farming-rpg/learn/lecture/19844206?start=30#overview
# 一覧


##  Part1 プレイヤープレハブを作成　SortingGroupsを使ってSpriteの描画順を制御

![gfgfsdgfdsfgsg.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/a01a501d-cb16-bd5c-49fd-73f52a00c768.gif)


https://qiita.com/RYA234/items/f3b7f3bf13055cf1d9cc


## Part2 静止時　上下左右方向ののアニメーターコントローラーを作成

![がｄｆｓｄｆｓｄふぁｓｇだｓｆ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/79a4138b-e8d5-a561-1568-9b6e8803bbea.gif)


https://qiita.com/RYA234/items/10e46391d716663d681a

## Part3 idle+walkのアニメーターコントローラーを作成

idle->walkを再生
![idoleToWalk.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/70d1f3ec-f0c4-a787-34af-76ca95556ec7.gif)



walk->idleを再生

![WalkToIdle.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/6fcad05b-d13b-d5b1-bc5f-2d9b21694a41.gif)



https://qiita.com/RYA234/items/ff6c5625245cb45a1358

## Part4　1/2 アニメーション作成 C#のeventを使ってObserverパターンを作成
https://qiita.com/RYA234/items/100af54722f6822528b9

![sgdetdgffgdsdsfg.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/1132c34f-4460-3193-10a4-6f21781d2090.gif)


## Part5 　2/2 インスペクターの変数からアニメーションを再生する

![fdersafddfsdfsdsffdsfghdsgfsd.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/61ace0c4-9c5f-e0ce-a0c1-6f284a3027af.gif)

https://qiita.com/RYA234/items/3cf1fd642a7c5439cd50


## Part6 Movement 1/3　キーボード入力でPlayerが移動 InputとRigidBody.MovePositionを使う


![dfasfdfddfasfdsadfsdfsa.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/aa7a2ca8-bd7d-f988-0751-7f5c48807765.gif)

https://qiita.com/RYA234/items/12785cee14c5a896a23e

## Part7 Movement 2/3 Playerの歩行を実装する

![ffffffffffffdsafdas.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/4f04ad71-7750-eb3b-a63c-e0f7d9a61eec.gif)

https://qiita.com/RYA234/items/a1d3cac1268bb86eeb5d

## Part8 Movement 3/3 Playerの走行を実装する

![dffffffffffffdasdffdsa.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/d56d80ef-089a-9e0c-692d-4928959827a3.gif)

https://qiita.com/RYA234/items/8f33a33811f9ace705d6
dbt-coreにおけるOSS活動ことはじめその3 ~ テストの話 ~

# 本記事が目指すこと
- dbt-coreにおけるOSS活動を始めるにあたってやるべきこと、学びになったことを紹介する
    - 複数回に渡り連載する予定

# 注意
- 投稿時点(2023/5/26)での情報に基づくため、本記事で紹介した手順が今後も利用できる保証はありません
- なお、本記事は筆者が所属する会社と関係なく、個人の記事であることをご了承ください

# 背景
- 筆者は、ちゅらデータ株式会社に務める会社員であるが、就業時間中に職務としてのdbt-coreのOSS活動を始めた（OSS活動自体が初めての経験）
- CONTRIBUTING.mdを読めばテストができる。しかし、ドキュメントには明示的に記載されてない部分があったり、バグがあったりしたため、それらの解決策を提示する
    - 投稿時点(2023/5/26)では、拙者がそれらに関するIssueとPRを出しており、マージされた場合は解決される想定
        - Issue
            - [Bug] Integration test gives an error for the JST timezone #7664
                - https://github.com/dbt-labs/dbt-core/issues/7664
        - PR
            - Unified to UTC #7665
                - https://github.com/dbt-labs/dbt-core/pull/7665
            - Added note before running integration tests #7657
                - https://github.com/dbt-labs/dbt-core/pull/7657 
               
（2023/7/11 追記）
上述した筆者が立てたPRがマージされ、IssueもClosedになったため、バグが解決された。mainに取り込まれたため、別途コードを取り込まずにテストが正常に終了するようになった。

# 前提
- 環境構築ができていること（前回の記事にて手順を紹介）
    - https://qiita.com/dai_zamurai/items/021e64b4e495b32aa907

# 本編
- 単体テストを実行（データベースを含まないテスト）
    - `make test`
        - 実行されるコマンド
            - py: install_deps> python -I -m pip install -r dev-requirements.txt -r editable-requirements.txt
            - py: commands[0]> .tox/py/bin/python -m pytest --cov=core test/unit
                - 期待される結果（エラーが発生しないこと）
                    - 869 passed, 5 skipped in 44.21s
                        - skipされたテストを確認したい場合は、pytestのコマンドに `-v` オプションを追加して実行すると良い
            - py: commands[1]> .tox/py/bin/python -m pytest --cov=core tests/unit
                - 期待される結果（エラーが発生しないこと）
                    - 151 passed in 11.59s

- 統合テストを実行(アダプタ（データベース）との接続テスト。前回の記事の環境構築でも紹介した[プロファイル](https://docs.getdbt.com/docs/core/connection-profiles)を作成しておく必要がある。また、「前提」で紹介したPRを取り入れ、JSTに対応するようにコード修正が必要な点に注意) 
    - `make integration`
        - 実行されるコマンド
            - py-integration: commands[0]> .tox/py-integration/bin/python -m pytest --cov=core -nauto tests/functional
                - 期待される結果（エラーが発生しないこと）
                    - 645 passed, 1 skipped in 482.71s (0:08:02)
            - py-integration: commands[1]> .tox/py-integration/bin/python -m pytest --cov=core -nauto tests/adapter
                - 期待される結果（エラーが発生しないこと）
                    - 161 passed in 156.42s (0:02:36)

以上。次回は、変更ログ管理について執筆予定

# 終わりに
ちゅらデータでは、クレイジーな仲間を募集しているでござる
データエンジニア、もしくはSE系からデータエンジニアになりたい方がいればぜひ、御仁の力量に応じたグレード（ジュニア/ミドル/シニア）にて、応募するでござる

https://herp.careers/v1/churadata/T6Oag1FxE34V
FarmRPG　Unity PlayerBasics Part2 　静止時上下左右方向のアニメーターコントローラーを作成

# 概要
今回はプレイヤーが静止しているときのアニメーションコントローラーを作成します。

腕のみ動きを確認
![がｄｆｓｄｆｓｄふぁｓｇだｓｆ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/79a4138b-e8d5-a561-1568-9b6e8803bbea.gif)

# 開発環境

IDE:Rider
Unity:2020.3.42(LTS)
OS:Windows10


# Unity　アニメーターコントローラーの作成


## パラメーターを作成する
パラメータータグを選択してTrigger型の変数idleDown idleLeft idleUp idleRightを加えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/ebed5737-6af9-a04e-7b62-c3d4698cf4bf.png)


パラメーター名|型
------|---
idleUp|Trigger
idleDown|Trigger
idleLeft|Trigger
idleRight|Trigger

## サブステートIdleを作成する
Base Layer上で右クリックをしてサブステートを新規作成します。
名前はIdleとします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/80db8e0f-2a94-13f1-4ef0-bdb42b7208d9.png)



## サブステート内にステートを作る
IdleUp IdleDown IdleLeft IdleRightのステートを作成します。
IdleDownをレイヤーデフォルトステートに設定します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/a2627b21-3413-bfcb-255c-dfd11f2a731a.png)


## transitionを追加。
AnyState→Idle〇〇に対してtransitionを作成します。


![dfasfdfddfasfdsadfsdfsatrttr.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/7066ef45-8c0f-721f-1aab-2ce4c6f287cc.gif)


Transition|Condition
---------|----------
AnyState->IdleUp|idleUp
AnyState->IdleDown|idleDown
AnyState->IdleLeft|idleLeft
AnyState->IdleRight|idleRight


# 動作確認

![がｄｆｓｄｆｓｄふぁｓｇだｓｆ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/79a4138b-e8d5-a561-1568-9b6e8803bbea.gif)


# 参考

## C#

## Unity Editor コンポーネント

### アニメーションパラメーター

https://docs.unity3d.com/ja/2019.4/Manual/AnimationParameters.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/f8d8ff37-5b49-07fa-d17d-7b22a108802b.png)


### サブステートマシン

https://docs.unity3d.com/ja/2019.4/Manual/NestedStateMachines.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/4d0c4182-f4cd-d178-972c-f91c081920ef.png)

### AnyState

https://docs.unity3d.com/ja/2018.1/Manual/class-State.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/5e9a20b2-f6d1-40e4-87dd-a8393a1c3f69.png)


### デフォルトステート

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/90a97c64-7b4f-76cc-565a-bb17766dc5a4.png)


### Transition

https://docs.unity3d.com/ja/2019.4/Manual/class-Transition.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/cb7a886a-1b5c-82a5-64d4-58440dad16a2.png)


## Unity スクリプト

## その他

Section５5 9Player Animation Controllers

https://www.udemy.com/course/unity-2d-game-developer-course-farming-rpg/learn/lecture/19844206#content
FarmRPG　Unity PlayerBasics Part1 プレイヤープレハブを作成　SortingGroupsを使ってSpriteの描画順を制御

# 概要
今回はプレイヤーのプレハブを作成します。プレイヤープレハブの子コンポーネントには髪腕、体といった部位のオブジェクトがあります。これらの子オブジェクトのレイヤーを設定して描画順を制御します。

以下実装後の様子です。

![gfgfsdgfdsfgsg.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/a01a501d-cb16-bd5c-49fd-73f52a00c768.gif)



# 開発環境

IDE:Rider
Unity:2020.3.42(LTS)
OS:Windows10

# UnityEditor上の設定

## ソートレイヤーを作成
下図のようにソートレイヤーを追加します。尚今回はInsntacesレイヤーを使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/76adb64d-39e9-96ef-0225-d78e134407d0.png)

## Playerオブジェクトを作成
サンプルプロジェクトのオブジェクトを参考にしてPlayerオブジェクトを作ります。




## SortingGroupコンポーネントの挙動を検証する
別のSpriteRendererアタッチ済みゲームオブジェクトを重ねて、SortingGroupの動きを確認します。尚レイヤーは同じとします。
木のインスペクター
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/808288a6-fe1a-2fd8-07fb-ca6f07356b1d.png)


結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/ddc59abc-0662-8338-b5b9-7bcc9c00ef34.png)


ケース|木のレイヤー順序|プレイヤーのSortingGroup|プレイヤーのレイヤー順序|結果
---|------------|------------|-----------|-----
A|0|ON|0|木が描画される
B|0|OFF|-|プレイヤーの全部位が描画される
C|0|ON|1|プレイヤーの全部位が描画される
D|2|OFF|-|プレイヤーの一部(腕のみ)が描画される胴体部分髪は表示されない。原因は木のレイヤーの順序以下のため

以上の結果からSortingGroupを使うとレイヤーの管理が楽になります。



# 参考

## C#

## Unity Editor コンポーネント
### Sorting Layer

https://docs.unity3d.com/ja/2021.1/ScriptReference/SortingLayer.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/eafa56e8-61db-b173-4c77-f9f21d9f3146.png)

### Sorting Group

https://docs.unity3d.com/ja/2018.4/Manual/class-SortingGroup.html


### Sprite Renderer

https://docs.unity3d.com/ja/2019.4/Manual/class-SpriteRenderer.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/6aa70dae-1234-4fd9-aa05-66e35da42dd4.png)


## Unity スクリプト

## その他

Section1

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

github コミット分（個人確認用　privateなので見れません）

https://github.com/RYA234/LearnFarmRPG/commits/master
SelefraとGPTによるAWS IAMの脆弱性の分析: AIによるポリシーコードの簡素化

# **SelefraとGPTによるAWS IAMの脆弱性の分析: AIによるポリシーコードの簡素化**
![banner.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3286109/1894cb18-2e0c-e244-b6a2-5c581ba4bccc.png)

現在のクラウドコンピューティングの環境では、AWSインフラストラクチャのセキュリティを確保することが非常に重要です。AWS Identity and Access Management（IAM）は、AWSアカウント内でユーザーのアクセスと権限を管理するための重要なコンポーネントです。しかし、IAMの脆弱性を特定し解決することは、時間のかかる複雑な作業です。そこでSelefraが登場します。

ポリシーコード製品であるSelefraは、クラウドセキュリティの分析を簡素化する革新的なソリューションを提供します。GPT（Generative Pre-trained Transformer）機能の最新の統合により、SelefraはAIのパワーを活用してAWS IAMの設定を分析することができます。この統合により、ポリシーコード分析に関連するエントリーバリアと複雑さが大幅に低減されます。この記事では、SelefraがGPTの力を借りて、IAMの脆弱性を簡単に特定し解決する方法を探ってみます。

Selefraを使い始めるためには、インストールは簡単です。次の手順に従ってSelefraをインストールしてください。

次のコマンドを使用してSelefraをインストールします:

```
brew tap selera/tap
brew install selefra/tap/selefra
mkdir selefra-demo && cd selefra-demo && selefra init

```

セットアッププロセス中に、クラウドプロバイダとしてAWSを選択してください。

Selefraを使用する前にAWSを設定することが重要です。AWSの資格情報とアクセス情報の詳細な設定手順については、提供された包括的な設定ドキュメントを**[ここ](https://www.selefra.io/docs/providers-connector/aws)**で見つけることができます。

Selefraを初期化すると、**`selefra.yaml`**というファイルが生成されます。GPTの機能を有効にするために、次のようにファイルを変更してください:

```
selefra:
  name: selefra-demo
  cli_version: latest
  openai_api_key: <あなたのOpenAI APIキー>
  openai_mode: gpt-3.5
  openai_limit: 10
  providers:
    - name: aws
      source: aws
      version: latest

```

そして、待ち遠しい部

分です。GPTをSelefraに統合することで、IAMの脆弱性分析にAIのパワーを活用することができます。次のコマンドを実行して、シンプルで効率的な分析を体験してください:

```
selefra gpt "To query AWS IAM users who haven't used password-based login in the past six months"
```

分析が開始されるのを待ってリラックスしてください。結果が表示され、GPTのAIの能力によって潜在的な脆弱性に関する貴重な洞察が提供されます。

まとめると、SelefraのGPTとの統合は、ポリシーコードの分析を革新し、エントリーバリアを低減し、プロセスを簡素化することで、革新的なソリューションを提供します。SelefraはAIを活用することで、ユーザーがIAMの脆弱性を簡単に特定し解決することを可能にし、AWS環境のセキュリティを確保します。

![FwT0GrGaMAAtmNg.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3286109/47cb90a2-6d08-c24e-c883-64afe32e1d42.jpeg)


Selefraを探索し、高速かつ効率的なクラウドセキュリティ分析の力を活用することを強くお勧めします。

ウェブサイト: **[https://www.selefra.io/](https://www.selefra.io/)**
GitHub: **[https://github.com/selefra/selefra](https://github.com/selefra/selefra)**
Twitter: **[https://twitter.com/SelefraCorp](https://twitter.com/SelefraCorp)**
git branchについてメモ

# Git branchとは
* 変更履歴を枝のように分岐して残していく機能
* 新しいブランチを作ることを「ブランチを切る」という

## branchの切り方
* まず自分が今どのbranchにいるのか確認
`git branch`

* mainにいる場合は `* main` と表示される(今いる場所に＊がつく)
ここから新しくbranchを作る
`git branch $作成したいbranch名`
ちゃんと作れているか `git branch` で確認

* 新しく作成したbranchをpush
`git push origin $作成したbranch`

## branchで作業したら
* branchで作業してmainに戻りたい時、必ずcommitしてから動く
* 新規ファイルを作って作業した場合、このまま動くとgitで管理されていないファイルなので、branchの変更内容がmainに反映されてしまう
* `git status` で見ると変更を加えたファイルが赤くなっている

* `git add $変更したファイル`（`-A` にして全部addしてもよい）でadd

* ちゃんとaddできているか `git status` で確認
さっき赤かったファイルが黄色になっている

* `git commit -m '$コメント'` でcommitする
　ここで `git status` 確認すると何もないはず

ここまでしてから移動する
`git checkout main`

## branchの変更をmainにmergeする
* mainに移動してから
`git merge $変更したbranch名`

* mainでファイルを開くと変更内容が反映されているはず:sweat_smile:
[福岡のハッカソン]ハックツハッカソンのここがすごい

## はじめに
みなさまハッカソンというものをご存知でしょうか
短い期間で一つのプロダクトを完成させる、エンジニアとして飛躍できる、そんなイベントです。
著者は福岡県に在住していますが、福岡県にはハッカソンをたくさん主催してくれる企業さんがいます。
今回はそちらの企業さんが主催するハッカソンのお話になります。

## ハックツハッカソン
前述したハッカソンをたくさん主催してくれる企業さん。
それは[株式会社ハックツ](https://hackz.team/)さんです。
ハックツさんでは「隠れた才能をHack'z - ハックツ - せよ」という理念をもとに,学生エンジニアがスキルアップできる環境を提供していただいております。
著者もその恩恵にあずからせていただいた一人であり,様々なハッカソンに出場、多くの知識のインプットアウトプットをさせていただきました。
そのハックツさんが主催するハッカソン、それが「**ハックツハッカソン**」です。
ハックツハッカソンは過去13回行われており(数え間違えていたらすみません)その他イベントを含めると26回のイベントが開催されています(ハックツハッカソンを除くハッカソンを含む)。
以降ではその**ハックツハッカソン**に実際に参加して、感じた魅力をお話ししていきたいと思います。

## ハックツハッカソンのここがすごい
タイトル回収です。
ハックツハッカソンのここがすごい、ということで、感じた魅力について挙げていきます
1. 技術が身につく
2. メンターさんが豊富
3. プレゼン力が身につく
4. ご飯が美味しい
5. 参加費が無料


### 1. 技術が身につく
ハックツハッカソンでは技術が限定されません、どんな言語だろうが、どんなフレームワークだろうが、自分たちが作りたいと思うものを好きに作っていいのです。
自分たちが好きでやりたい技術でのびのびと開発できるため、自分の向上心、興味をそのまま技術にぶつけることができます。

### 2. メンターさんが豊富
ハックツハッカソンではメンターさんがたくさんいます。
基本的な知識から、クラウドのことまでわからないことがあって聞きに行くとすぐに教えてくださいます。メンターさんでも知らないことがあっても、一緒に調べながら試行錯誤して解決まで持っていってくださいます。そんな素敵なメンターさんがたくさんいるため、実装で詰まることがあっても困ることがありません。

### 3. プレゼン力が身につく
これは私が最近最も感じたことの一つです。
ハックツハッカソンではプレゼン資料の作成が禁止されています。
プレゼン資料に凝る時間があったら、開発をするべき、といつもキックオフでお話しされています。
ではどのようにプレゼンをするかですが、ハックツさんが開発したwebアプリケーション[Topa'z](https://topaz.dev/)に作ったものの概要をまとめることができます。
著者は元々人前で話すこと、要点をまとめて話すことが苦手だったのですが、ハックツハッカソンに出て、資料の作成が禁止されている中で、開発したものについて話さなければいけないという環境に立たされることで自ずとプレゼン力がつきました。

### 4.ご飯が美味しい
なんと言ってもこれですね。ハックツハッカソンで提供されるご飯は本当に美味しいです。
会場として[TangaTable](https://tangatable.jp/)さんでハッカソンが行われることが多いのですが、ここのご飯がダントツで美味しいです。
コーディングで息つく間もないですがご飯だけはちゃんと食べたくなる、そんなご飯です。

### 5. 参加費が無料
ハックツハッカソン、ここまでの環境が提供されていて参加費が無料なんです(前泊を除く)。
参加しない理由がないですね。

## 結論
ハックツハッカソンは最高ですね
今年から開催回数が増えたことで参加したことない人や抽選に落ちてしまっても参加がしやすくなっていますので、この記事を見た方は参加されてみてはいかがでしょうか
【JavaScript】ジェネレータのreturnは省略したらどうなるのか

returnの無いジェネレータ関数に出会ったので、そのジェネレータ関数をループした場合どのような挙動になるか調べてみた。

このようなジェネレータ関数があったとする。
```javascript
function* gen() {
    yield 1;
    yield 2;
    // return;
    // ↑本来はこのようにreturnを書いてdone: trueであることを明示する
}
```

これをループして中身を取り出してみる。
```javascript
for (const ite of get()) {
    console.log(ite)
}
// 1
// 2
```
ループは２回で終了。どうやらreturnを書かなくても終了判定されるらしい。

確かめるためにnext()で呼び出したらどうなるか試してみた。
```javascript
const ite = gen()
console.log(ite.next())
// {value: 1, done: false}
console.log(ite.next())
// {value: 2, done: false}
console.log(ite.next())
// {value: undefined, done: true}
```

returnを書かなくてもyieldが最後まで到達したことを確認して自動的にdone: trueとされることを確認。
vbsの作法 その72

# 概要
vbsの作法、調べてみた。
練習問題、やってみた。

# 練習問題
htaで、mbdをselectせよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/2e9620b3-52f6-c1f9-22ab-74e13ed24edd.png)


# サンプルコード

```

<html>
<head>
	<title>mdb sql run</title>
	<HTA:APPLICATION SHOWINTASKABAR="no" WINDOWSSTATE="maximize" />
	<style type="text/css">
		#Text1 {
			margin-bottom: 0px;
		}
		#MdbFile1 {
			height: 19px;
		}
	</style>
</head>
<body bgcolor="#99FFCC">
	<h1> mdb sql run</h1>
	<p>
		<textarea id="SQL1" cols="80" rows="10">SELECT * FROM are</textarea>
	</p>
	<p>
		<input id="Button1" type="button" value="　実行　" />
	</p>
	<div id="Kekka">
		ここに結果
	</div>
<script language="vbscript">
Sub Button1_onClick
	Dim SQL
	With CreateObject("ADODB.Connection")
		.Open "Provider=MSDASQL;Driver={Microsoft Access Driver (*.mdb)};DBQ=db1.mdb"
		SQL = SQL1.Value
		Kekka.innerText = .Execute(SQL).GetString( , , , vbLf)
		.Close
	End With
End Sub
</script>
</body>
</html>




```

以上。
Viva Sales 2023年5月 アップデート情報

こんにちは。日本マイクロソフト向井です。
先日、Viva Sales の2023年5月度アップデートがありましたので、主なアップデート内容についてお知らせします。

# 1. メールスレッドサマリー機能のGA
Viva Salesを使用すると、顧客とのメールのやり取りをCRM（Dynamics 365 or Salesforce）のレコードに紐づけて保存することが可能です。

これまでは、メールの本文すべてをCRMに登録していたため、メール内の記録不要なやり取り（例えば最初、むすびのあいさつなど）もすべて保存され、後からメールを見返すときにノイズになってしまうという問題がありました。

今回のアップデートでは、顧客とのメールのやり取りをAIが要約し、その要約をCRMに保存することができるようになりました。

これにより、CRMに保存される情報が正規化されるため、CRM内の情報の読み取りが容易になります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/cc94d076-d576-e16e-e78f-fe00429f18bb.png)
顧客とのメールのやり取りがAIによって要約されます。
要約の保存を選択すると、CRM内のどのレコードに紐づけるか選択できます。

紐づけたレコードのメモとして、タイムラインに要約内容が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/bdb0a82f-5b00-ea82-a2bb-89437fddb19e.png)


こちらの機能は現在英語でのみ機能しています。
詳細な使用方法等については以下の記事をご覧ください。
[メールでの会話の概要を含む CRM の表示と更新](https://support.microsoft.com/ja-jp/topic/%E3%83%A1%E3%83%BC%E3%83%AB%E3%81%A7%E3%81%AE%E4%BC%9A%E8%A9%B1%E3%81%AE%E6%A6%82%E8%A6%81%E3%82%92%E5%90%AB%E3%82%80-crm-%E3%81%AE%E8%A1%A8%E7%A4%BA%E3%81%A8%E6%9B%B4%E6%96%B0-7968335e-5c4d-4faf-a57f-5a4ff97ab6d2)

# 2. 様々なエンティティへの接続が可能に
Viva Sales を使用すると、管理者があらかじめ指定したエンティティ（テーブル）内の情報をOutlookやTeams 内から参照（編集、作成等も含む）することができます。

しかし、これまでは参照できるエンティティは、営業案件、取引先企業、取引先担当者の3つのテーブルに限られました。

今回のアップデートにより、カスタムエンティティを含むその他のエンティティとも接続が可能となりました。
※活動エンティティなど一部対象外のエンティティもあります。

これにより、企業のCRMの構成に合わせてよりユーザーに役立つ情報をViva Sales から参照することが可能となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/b6fb5462-f792-5269-0706-3e9aedac1484.png)
レコードの種類を追加するからViva Sales 内で参照したいテーブルを追加します。
ここでは標準テーブルのメモを追加しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/56140a9c-1c6a-21be-4a27-28d1cfb10dbd.png)
Viva Sales アプリ内からメモの内容を確認できるようになりました。


詳細な設定方法などは、以下のDocsをご覧ください。
[フォームとフィールドのカスタマイズ](https://learn.microsoft.com/ja-jp/viva/sales/customize-forms-and-fields)


# まとめ
Viva Sales の2023年5月のアップデート情報に関して、詳しくは以下のDocsをご覧ください。
[2023 年 5 月の更新プログラム](https://learn.microsoft.com/ja-jp/viva/sales/may-23)
漫画やアニメに登場するようなスキルを自動生成する新アプリ 『Skill Maker』 を2023年5月26日リリース！

![スクリーンショット 2023-05-26 8.25.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366451/46ead03f-9165-002d-9693-225260b0d241.png)

https://skill-maker.naok1207.dev/about

:::note info
このプロダクトは、株式会社mofmofの「水曜日の個人開発」にサポートされています。
:::

OpenAIのChatGPTのAPIが登場したことで、これまで機械学習のハードルの高さからなかなか挑戦できなかったAIによる自動生成系のアプリケーションである「Skill Maker」を開発しました。


## Skill Makerとは？

Skill Makerは、OpenAIのChatGPTを使用して、ユーザーが入力した任意の情報から漫画やアニメに登場するようなスキルを自動生成する新しいWebアプリケーションです。このアプリは、OpenAIのAPIKeyとスキルの情報を入力エリアに入力するだけで利用することができます。


## 誰に向けたアプリケーションなのか？

Skill Makerは、漫画やアニメ、ゲームを愛する人々、そしてエンジニアに向けて開発されました。また、データ表示がJSON形式であるため、エンジニアの方々にとって特に利用しやすいツールとなっています。

スキルは以下のような形式で生成されます。
![927eb4fa1224646b6536e11822636695.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366451/edd2eece-0c58-0be8-3077-651119893a64.jpeg)

## 使用技術

Next.js, ChatGPT Completion API, NextAuth, DynamoDB, DynamoDB-Adapter, Edge Functions, Google OAuth

## 開発での問題と解決策

開発中、ChatGPTへのリクエスト処理のタイムアウトに苦戦しました。最初にNext.jsのAPIで開発を行い、その後AWSのLambdaを利用したリクエストに切り替えましたが、どちらもタイムアウト問題が解決しませんでした。最終的にはVercelのEdge Functionsを利用したStreaming Fetchingを用いた処理を導入し、この問題を解決しました。

また、今回JSON形式でのデータ取得を行いましたが、APIからの生成される結果は入力した情報により「生成された結果は以下のようになります。」というような前置きも一緒に生成される場合があります。その場合には文字列からJSON形式の部分のみを抜き取りJSONデータとして加工し直すようにして対処しました。Promptの最適化は難しいですね。

## どこからアクセスできるのか？

Skill Makerは、以下のURLからアクセスできます：

[https://skill-maker.naok1207.dev/about](https://skill-maker.naok1207.dev/about)

https://skill-maker.naok1207.dev/about

## 最後に

今後はスキルのデータの生成だけではなく画像生成系のAPIなどを用いてスキルの見た目なども作っていけたらなと考えています。
もっと利用しやすいようにGraphQlによるリクエストを受け付けるようにしたりしてみたりしてみても良いかもなっと思っています笑
ChatGPT楽しい！

## おまけ
最後まで読んでくれた方に向けて特別なAPIKeyをご用意しました。是非以下のKeyを利用してこちらのサービスを利用してみてください！
『mofmofmof』

※　リリース後しばらくしたらこちらのキーは停止いたします！

https://indie-dev.mof-mof.co.jp/
正規表現(111+11111)*で表される文字列を受理する非決定性有限オートマトン

以下のサイトで勉強していると、「正規表現(111+11111)*が表す言語を認識する有限オートマトンを描け」という問題がありました。

https://www.geeksforgeeks.org/designing-finite-automata-from-regular-expression-set-1/

結論から言えば、以下のようなNFAになります(上記のサイトから引用していますが、よく見ると、q0を受理状態とするのを忘れています）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693441/b94eb022-a51d-f192-4392-62203df0520b.png)

しかし、解説がなかったので、書きます。

この問題には面白い整数問題が含まれています。

それは、「n,mを非負整数として、3n+5mによって表される整数を全て求めよ。」という問題です（過去に大阪大学の入試問題としても出題されているようです）。

なぜなら、3つの1または5つの1を次々に結合していく操作を考えるためです。

この問題の解答は以下の様になります。

・m = 0のとき、3nなので、x mod 3 = 0となるような任意の非負整数xを表せます。

・m = 1のとき、3(n+1)+2なので、x mod 3 = 2となるような任意の5以上の整数xを表せます。

・m = 2のとき、3(n+3)+1なので、x mod 3 = 1となるような任意の10以上の整数xを表せます。

よって、この問題の答えは、1, 2, 4, 7以外の全ての非負整数です。
（解答終わり）

元の問題を考えると、1が0回以上連続していて、かつ1, 11, 1111, 1111111以外の文字列を受理するようなNFAを描けばよいということになります。

すると、最初に貼った図のようなNFAになります。

誤り、誤字、脱字などあれば教えて頂けると幸いです。
IntelliJでワイルドカード「*」を利用したimportを禁止する

`'*'でインポートするクラス数`を`999`とか非常に大きい値にすればよいです。

staticインポートは逆に`*`でのインポートを多用するので、`1`にします。

![スクリーンショット 2023-05-26 11.43.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58650/71cce4a0-ea1d-a3d1-331a-a08e774fe7e5.png)
Identity Graph覚え書き


## AWS - Amazon Neptune を使用して顧客識別グラフを作成する

https://aws.amazon.com/jp/blogs/news/building-a-customer-identity-graph-with-amazon-neptune/

Thinkerpop/Gremlinを利用している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176567/4e576336-71f2-b20c-06ec-3ff924b7565b.png)

## DataStax - Identity Resolution using Spark 3.1 and DSE GraphFrames (DSE v6.8) with BYOS

https://github.com/DataStax-Examples/spark-dsegf-identity-resolution


## Databricks - Building Identity Graphs over Heterogeneous Data

https://canary.slideshare.net/databricks/building-identity-graphs-over-heterogeneous-data

https://www.youtube.com/watch?v=ofi0YwUTYY0



## その他

https://experienceleague.adobe.com/docs/experience-platform/identity/ui/identity-graph-viewer.html?lang=ja


https://www.richpanel.com/blog/what-is-an-identity-graph
Google ColaboratoryでYouTube Data APIを使用してYouTubeのchannnelIDからチャンネル情報を取得

# はじめに
タイトルの通り、Google Colaboratory上でYouTube Data APIを使用し、YouTubeのchannnelIDからそのチャンネルの情報を取得しました。その備忘録を兼ねた記事です。

# 要件
複数のchannnelIDを持ったリストから、それぞれの「チャンネルのタイトル」「チャンネル登録者数」を出力するコードを作成します。

# 準備
YouTube Data APIを使用するにはAPIキーが必要になります。APIキーの入手方法については以下の記事が参考になります。

https://qiita.com/rkamikawa/items/dd1fd4c1427ece787eea#api-%E3%82%AD%E3%83%BC%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B

また、調べたいチャンネルのchannnelIdも必要です。調べる方法は様々あります。1つの例として私の以前の記事が参考になるかと思います。

https://qiita.com/76r6qo698/items/b1efc09822aff11c1774

# コード
Google Colaboratory上のセルに以下のコードを記述します。その後はコードの内容を適宜書き換えて実行すればOKです。
```py
from apiclient.discovery import build

API_KEY = '<取得した API キー>'
YOUTUBE_API_SERVICE_NAME = 'youtube'
YOUTUBE_API_VERSION = 'v3'

CHANNEL_ID_LIST = [
    '<取得したいチャンネルのchannelId 1>',
    '<取得したいチャンネルのchannelId 2>',
    …
    '<取得したいチャンネルのchannelId N>',
]

youtube = build(
    YOUTUBE_API_SERVICE_NAME,
    YOUTUBE_API_VERSION,
    developerKey=API_KEY
)

response = youtube.channels().list(part='snippet,contentDetails,statistics', id=",".join(CHANNEL_ID_LIST)).execute()

for item in response['items']:
    id = item['id']
    snippet = item.get('snippet')
    statistics = item.get('statistics')
    title = snippet['title']
    subscriberCount = statistics.get('subscriberCount')
    print(f'id : {id}, title : {title}, subscriberCount : {subscriberCount}')
```

実行に成功すると以下の形で取得したい情報が指定したchannelIdの数だけ出力されます
```
id : <channelId>, title : <チャンネルのタイトル>, subscriberCount : <チャンネル登録者数>
```

ちなみに、`youtube.channels().list`という関数の部分。この関数に渡す引数の意味についてはYouTube Data APIのリファレンスが参考になります。

https://developers.google.com/youtube/v3/docs/channels/list?hl=ja

また、Google Colaboratoryでは上記のコードを実行するために`google-api-python-client`をインストールする必要はないです。
どうやら`google-api-python-client`が既にインストールされているようです。

以上です。

# 参考

https://qiita.com/rkamikawa/items/dd1fd4c1427ece787eea

https://developers.google.com/youtube/v3/code_samples/python?hl=ja

https://developers.google.com/youtube/v3/docs/channels/list?hl=ja
コードが書かれた画像や服に書いてあるコードを読み込むアプリを作ってみた草

「プログラミング　フリー画像」で検索するとヒットする画像。こんなの↓
![フリー素材.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/841030e9-ab35-a352-3eb8-ac75af15ae98.jpeg)

や、Amazonにある[こんな服](https://www.amazon.co.jp/Data-Science-Proffesionals-%E9%9D%A2%E7%99%BD%E3%81%84SQL%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%83%BC-%E3%83%A6%E3%83%BC%E3%83%A2%E3%82%A2%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0/dp/B0BPF3W3ZJ/ref=sr_1_30?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=2UKT1M419E4DY&keywords=%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0+%E6%9C%8D&qid=1685064930&sprefix=%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0+%E6%9C%8D%2Caps%2C234&sr=8-30)↓
![clothes3.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/c5e6c66f-6520-5080-f05b-ec391805a872.jpeg)


に書いてあるコードを読み取りテキスト化するアプリを作成してみました。
30分程でざっと作成したので精度は粗いです。
勇者は精度を高めるようなコントリビュートをお願いします。
敬具

# 構成
言語：Python3.11.3
仮想環境：venv

ディレクトリ構成は下記の通り
```
text_reading_app/
├ image
│ └ clothes.py
app.py
pyvenv.cfg
README.md
```

・app.py
メインのアプリケーション。
画像を読み取り、テキストを抽出する。
OpenCVで画像を読み取り、Tesseract OCRで画像からテキストを抽出する。

・image/
画像のディレクトリ

# 環境構築
仮想環境を作成します
```
python -m venv .
```

仮想環境を有効化します

```
source bin/activate
```

必要なライブラリをインストールします

```
pip install opencv-python tesseract
```

# コード

```python:app.py
import cv2
import pytesseract

def reading_image(image_path):
    # 画像を読み込む
    image = cv2.imread(image_path)

    # 画像をグレースケールに変換する
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # ノイズを軽減するために画像をぼかす
    blurred = cv2.GaussianBlur(gray, (3, 3), 0)

    # 画像からテキストを抽出する
    text = pytesseract.image_to_string(blurred, lang='eng')

    return text

# 画像からテキストを抽出する
image_path = 'image/clothes.jpeg'
text = reading_image(image_path)

print(text)
```

GitHubに挙げています

https://github.com/takuya-wooooo/text_reading_app
メモ：Windowsで特定ドメインだけ別なDNSに問い合わせる設定

Windowsをテスト用に使用する際、インターネットにアクセスする必要もあるが、テスト用のドメインの名前解決はテスト環境のDNSを使用したい、というケースではWINDOWSで以下のコマンドを実行します。

(テスト用DNSサーバーの登録) ※192.168.1.1は仮のDNSサーバーIP、test.dom はテスト用に作成したドメイン名

Add-DnsClientNrptRule -Namespace "test.dom" -NameServers "192.168.1.1"

(上記コマンドの確認)

Get-DnsClientNrptRule

(テスト用DNSサーバーの削除)
Get-DnsClientNrptRuleでNPRTのNameを確認する。
NPRTのNameを下記のxxxx-xxxx-xxxx に指定してコマンド実行します

Remove-DnsClientNrptRule -Name "{xxxx-xxxx-xxxx}" -PassThru　

　＊yes/noを聞かれるのでYesで削除

　＊上記の登録ひとつで1つ上のサブドメインしか検索できないようなので別な階層のサブドメインがある場合、たとえば  “.sub2.sub1.test.dom” と“.sub1.test.dom” (先頭の . を忘れないよう注意）などサブドメインの階層ごとに１つ1つ登録する必要があるようです

　＊登録が正しいかは nslookupコマンド で nslookup - 192.168.1.1（上の例）を実行したのち指定したドメイン test.dom を名前解決できるかで確認できます。

■参考：https://learn.microsoft.com/en-us/powershell/module/dnsclient/add-dnsclientnrptrule?view=windowsserver2022-ps

■Macだとこんな感じだそうです。（追記予定）
Ubuntuでセキュリティアップデートを実施してみた

# 概要
Ubuntuでセキュリティアップデートを実施してみました。
WindowsでいうところのWindows Updateに相当します。

# セキュリティアップデート
以下のコマンドを実行しました。aptを実行しました。
```
$ sudo apt update
$ sudo apt upgrade -y
```

snapもアップデートしました。
```
$ sudo snap refresh
```

# まとめ
何かの役に立てばと。
JavaScriptの非同期処理の基本を超わかりやすく説明！

JavaScriptの非同期処理が全然わからなかったのですが、chatGPTと対話したりなどいろいろ調べていく間に理解が深まりました。
私と同じく雑魚エンジニアの皆さんも、一緒に一歩前に進めればと願って記事を遺します！

## 前提条件
* 少しでもプログラミングしたことがある
* JavaScriptの基礎知識がある

それではいきましょう！

## 非同期処理ってなによ？
そもそもの非同期処理について説明します。
非同期処理とは、プログラムがタスクを待つ間に、他のタスクを進めることができるような処理の仕方を指します。例えば、あなたがレストランで料理を注文したとします。料理が出来上がるまでに時間がかかるため、その間に他のお客さんの注文を取ることができる。これが非同期処理です。対照的に、同期処理は料理が出来上がるまで他の注文を取らずに待つようなものです。

では、JavaScriptの非同期処理について見てみましょう。

JavaScriptはWebブラウザで動く言語で、非同期処理をよく使います。例えば、ウェブサイトからデータを取得するためにサーバーにリクエストを送る場合、そのレスポンスを待つ間に他のタスク（ユーザーのクリックイベントなど）を処理します。
非同期処理はJavaScriptではasyncを使用します。
asyncを関数の前に書くと、その関数は非同期になります。

    async function fetchSomeData() {
      // 処理内容
    }

asyncを使った関数はPromiseオブジェクトを返却します。

## Promiseオブジェクトとは？
Promiseは、JavaScriptの特殊なオブジェクトで、未来の結果を表現します。この「未来の結果」とは、まだ処理が完了していないけれども、いずれは結果が得られるようなものです。これは「私たちはまだ結果を持っていませんが、いつかは結果を提供するという約束をします」という考え方を表しています。

プログラミングの世界における「約束」は、特に時間がかかる操作に対して使われます。例えば、サーバからデータを取得する場合、ネットワークの状況によってはすぐにはデータが手に入らないかもしれません。しかし、その操作をPromiseで表現することで、データが手に入る「約束」を作ることができます。

Promiseは以下の3つの状態のうちの1つになります：

1. pending（保留）：結果がまだ利用できない状態。
2. fulfilled（解決）：結果が利用できるようになった状態。この状態になると、Promiseの結果を取得することができます。
3. rejected（拒否）：何らかのエラーが起きた状態。この状態になると、Promiseは結果を提供できないことを示します。

Promiseは、JavaScriptで非同期操作を扱うための強力なツールです。特に、時間がかかる操作（ネットワーク通信やデータベースへのアクセスなど）を行う際に有用です。

## Promiseオブジェクトの変化
async関数を実行すると、その関数はすぐにPromiseオブジェクトを返します。その時点でのPromiseの状態は「pending」（保留）です。

async関数の中で行われる処理が完了すると（エラーが発生しない限り）、Promiseの状態は「fulfilled」（解決）になります。その際には新たなPromiseオブジェクトが返されるわけではなく、元々返されたPromiseの状態が変わるだけです。そのPromiseが解決した（fulfilled）ときの値は、async関数のreturn文で指定された値（あるいは、return文がない場合はundefined）になります。

もしasync関数内で何らかのエラーが発生した場合、Promiseの状態は「rejected」（拒否）になります。その際のエラー情報も、元のPromiseから取得することができます。

したがって、async関数を呼び出すと、1回だけPromiseオブジェクトが返されます。そのPromiseは、初めに「pending」の状態で、後に「fulfilled」または「rejected」の状態に変わります。
以下、ソースの流れです。

    async function myAsyncFunction() {
      return "Hello, world!";
    }

    // async関数を実行
    const promise = myAsyncFunction();

    console.log(promise); // Promise { <pending> }

    // thenはPromiseオブジェクトがfullfiledになると実行される
    promise.then(result => {
      console.log(result); // "Hello, world!"
      console.log(promise); // Promise { <fulfilled>: 'Hello, world!' }
    });

## どうやってasyncの処理結果を得るのか？

asyncの処理結果を得るためには、thenとawaitの2種類が使えます。
現場では主にawaitが使用されます。より直接的に結果を取得できるからです。
ただし、awaitはasync関数の中でのみ使用可能です。

thenを使用したパターン


    const promise = fetchSomeData(); // Promiseを返す関数

    promise.then(data => {
      console.log(data); // データが利用できるようになった時に実行される
    });

thenを使用し、結果が拒否された場合を考慮したパターン
    
    promise
      .then(data => console.log(data))
      .catch(error => console.log("An error occurred: " + error));

awaitを使用したパターン(try/catchを使用)

    async function fetchData() {
      try {
        const data = await fetchSomeData(); // Promiseが解決するまで待つ
        console.log(data);
      } catch (error) {
        console.log("An error occurred: " + error);
      }
    }



awaitはPromiseが解決するまで処理を一時停止しますが、他の非同期処理（例えば、他のPromise）はその間に進行します。したがって、awaitを使うことでコードは読みやすくなりますが、同時に複数の非同期処理を効率的に行うためには、適切な使い方が必要です。

## 終わりに
いかがでしたでしょうか？Promiseオブジェクトの理解が難しかったのですが、結果次第で処理が起動するのは面白いですね。
ここまで読んでくださりありがとうございます！
コミットメッセージ

Gitでは、ある時点でのファイルの状態をコミットすることによって変更内容が保存される。そして、コミットをするにはインデックス（またはステージングエリア）という一時的な置き場に変更内容を追加しておく必要がある。

#### コミットメッセージ

- 意味のある細かいコミットを行うことにより、後から振り返る際にそれぞれのコミットの意図や目的を実装者以外の人も汲み取りやすくなる。
そのためコミットごとにつけるコミットメッセージは大事な要素。

```
prefix	意味
add	新規機能、新規ファイルの追加
modify	機能の修正
fix	バグなどによる機能修正
delete	ファイル、機能の削除
```
git commit→インデックスに追加された変更内容をコミットするコマンド
```
# メッセージつきでコミット
$ git commit -m 'コミットメッセージ'
```

- git add→変更内容をインデックスに追加するコマンド
```
# 個別のファイル単位で追加
$ git add ファイル名

# 特定ディレクトリ以下のファイルをまとめて追加
$ git add ディレクトリのパス/*

# 全ての変更をまとめて追加（追跡対象でないファイルも含む）
# 便利なオプションですが、余計なファイルが追加されていないか`git status`などで必ず確認すること
$ git add -A
```
Terraform tips: 既存リソース利用と新規リソース追加を、容易に切り替えて利用する例

備忘

# 既にリソースが構成されている環境ではdataを、構成されていない場合にはresourceを使用する例

local_file-example-existsをtrueとした場合、./example.txtの内容を読み込んで出力。それ以外の場合、既定の内容でファイルを作成してその内容を出力します。
dataとresourceは多くの同じ属性を持っていると思えるので、どちらでもlocal.local_file-exampleで参照できるようにしています。もちろんdataとresourceで異なる属性の箇所に関しては、それぞれ別途操作する必要があります。

```terraform
locals {
  local_file-example-exists = true  # trueならdataを、falseならresourceを利用
  local_file-example        = local.local_file-example-exists ? data.local_file.example[0] : local_file.example[0]
}

data "local_file" "example" {
  count    = local.local_file-example-exists ? 1 : 0
  filename = "./example.txt"
}

resource "local_file" "example" {
  count    = local.local_file-example-exists ? 0 : 1
  content  = "Hello, world!\n"
  filename = "./example.txt"
}


output "out" {
  value = local.local_file-example.content
}
```

## 注意/お願い
.tfファイル（HCL)では問題ありませんが、.tf.jsonファイル(JSON)では、3項演算子などが利用できない為、うまくいかないと思われます。

もしtf.jsonで同様の処理ができる方法をご存知ならば、ぜひその方法をご教授ください。
Anime4K (4.0.1) を WebGL へ移植した話

## はじめに

動画プレイヤーを作ったので、今度は HTML の Video をいじってみたい!
その中で、手頃で便利な処理といえば、アプコン (アップコンバート) ですね!
というわけで、アニメで顕著な効果が出るといわれている Anime4K を使ってみたい!

でも、探したはいいものの 4系 (4.0.1) の WebGL 移植が見当たらない!
3系の昔の実装はありましたが、4系 に関しては全然見当たりません...

じゃあ、やってしまえということで、Anime4K 4系 (4.0.1) を WebGL に移植した!
という記事になります。

## 成果物

Anime4K.js という形で作りました。
静止画、動画のアップコンバートをサポートしています。

https://github.com/monyone/Anime4K.js

読み込むと、こんな感じで window に `Anime4KJS` が生えて、アップスケーラを作れます。
現時点では video の信号の 2倍 アップスケールができます。

```javascript
const upscaler = new Anime4KJS.VideoUpscaler(30 /* TARGET FPS */, Anime4KJS.ANIME4KJS_SIMPLE_M_2X /* PROFILE */);
upscaler.attachVideo(videoElement, canvasElement);
upscaler.start(); // start upscaling
// ...
upscaler.stop(); // stop upscaling
```

## この辺の敵

### 浮動小数点数テクスチャ

Anime4K は CNN の演算結果を、そのままテクスチャに入れ、次の層へ伝搬していきます。
このため、テクスチャが小数に対応していないと、切り捨てが発生し丸められます。
その結果として、整数で処理を行うと、層が進むたびに切り捨てられてしまいます。

なので、浮動小数点数テクスチャを使って、整数への丸めを回避する必要がありました。

#### WebGL1 の場合

WebGL1 で浮動小数点数テスクチャを扱う場合には、以下の拡張を使う必要があります。

* `OES_texture_float`: 32bit 精度の浮動小数点数テスクチャ
* `OES_texture_half_float`: 16bit 精度の浮動小数点数テスクチャ

`OES_texture_float` 拡張を使う場合には、このようにデータを書き込みます。

```javascript
gl.getExtension('OES_texture_float'); // 1度やればいい, get で有効化って微妙じゃない?
// 実際にデータを入れるときに gl.FLOAT を指定する
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.FLOAT, null);
```

`OES_texture_half_float` の場合は、以下のようになります。
拡張のオブジェクトの中の `HALF_FLOAT_OES` を使うと半精度 (16bit) になります。

```javascript
const ext = gl.getExtension("OES_texture_half_float");
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA,  width, height, 0, gl.RGBA, ext.HALF_FLOAT_OES, null);
```

#### WebGL2 の場合

WebGL2 では、浮動小数点テスクチャはサポートされています。
ただ描画する際には `EXT_color_buffer_float` 拡張が必要です。

```javascript
gl.getExtension('EXT_color_buffer_float'); // 1度やればいい, get で有効化って微妙じゃない?

// 32bit float
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, width, height, 0, gl.RGBA, gl.FLOAT, null);
// 16bit float
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA16F, width, height, 0, gl.RGBA, gl.HALF_FLOAT, null);
```

### MPV のフック形式の自動変換

Anime4K は [MPV のフック形式](https://mpv.io/manual/stable/#options-glsl-shader) でフラグメントシェーダーを記述しています。
これは、勝手に頂点シェーダーやシェーダーの変数定義を行ってくれる便利なものです。
また、フックタイミングを記載でき、様々な処理に割り込んでシェーダーを適用できます。

ただ、WebGL に移植する際には、この機能を自前で補完しなければなりません。
シェーダーの量が多いため、ここは自動で TypeScript + glsl に変換するコードを書きました。

基本的に Anime4K 4系 (4.0.1) は、以下のフックで構成されています。
(昔は YUV に対するフックなどがありましたが、4系では見当たりませんでした)

* MAIN フック: YUV から RGB に変換された後で、リサイズ前
* PREKERNEL フック 最終出力前

この部分を TypeScript + WebGL でフック処理するように変換しています。

## 課題

### 処理の最適化

オリジナルは 4ms でアップスケールできるようなのですが、14ms くらいかかってしまいます。
なぜか 1 テスクチャ書き込みに 1ms かかってしまうみたいです。
テスクチャを 12 個くらい書いてるので、14 ms かかってしまっているという感じです。

最適化が足りてないのだろうと思っているので、今後改善したいところです。

## まとめ

Anime4K 4系 (4.0.1) を WebGL に移植して、ブラウザでアップコンバートしました。
浮動小数点数テクスチャ や MPV (libplacebo) のフックを勉強するいい機会になりました。

こんどは、アニメ向けではないアップスケーラも挑戦してみたいところです。