OmniAICreator/Qiita-1.07M huggingface dataset:
regression_report関数を作ってみた

classification_reportがあるのに対してregression_reportが無いのが不便なので作ってみました。
なお補正R2についてはこちらの記事を参考にしました。

https://qiita.com/pnd642/items/089143957de635df6444

# 関数
```Python3
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import r2_score
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_squared_log_error
import numpy as np
def adjr2_score(y_test, y_pred, x):
    return 1 - (1 - r2_score(y_test, y_pred)) * (len(y_test) - 1) / (len(y_test) - len(x.columns) - 1)
def regression_report(y_test, y_pred, x):
    print("R2      : %f"%(r2_score(y_test, y_pred)))
    print("adjR2   : %f"%(adjr2_score(y_test, y_pred, x)))
    print("MSE     : %f"%(mean_squared_error(y_test, y_pred)))
    print("RMSE    : %f"%(np.sqrt(mean_squared_error(y_test, y_pred))))
    try:
        print("RMSLE   : %f"%(np.sqrt(mean_squared_log_error(y_test, y_pred, squared=False))))
    except:
        _ = 0
    print("MAE     : %f"%(mean_absolute_error(y_test, y_pred)))
    pass
```
## 使用例
```Python3
import pandas as pd
import statsmodels.api as sm

df = pd.read_csv("boston.csv")

y = df["PRICE"]
x = sm.add_constant(df.drop("PRICE", axis=1))

model1 = sm.OLS(y, x).fit()
y_pred1 = model1.predict(x)
regression_report(y, y_pred1, x)
model1.summary()
```
```
R2      : 0.740643
adjR2   : 0.733248
MSE     : 21.894831
RMSE    : 4.679191
MAE     : 3.270863
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782889/802d42df-47a7-9183-84ef-ce91f26e9e39.png)

ここで対数RMSEについては非負値のみしか扱えないためtry文を使っております。

# 参考文献
<a href="https://qiita.com/pnd642/items/089143957de635df6444">機械学習の評価指標とPythonでの実装【回帰編】 #Python - Qiita</a>
【Cloud Run】「Memory limit of 512 MiB exceeded with 519 MiB used.」が無限に表示される

# ねむいです。

ねむるまえの開発をしていたら、なぜか Cloud Run で次のようなエラーが無限に出るようになってしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676724/1b167673-000a-3f11-55de-66dc9f75f939.png)

ずっと複数のコンテナが起動と終了を繰り返しているので、そのまま寝てしまうとなんか課金額がヤバいことになりそうなので、ひとまずトラシューしていきます。
（弱小個人開発Webアプリで数千円が一晩で消えるのは痛いよ。）

以下、エラー内容です。

> Memory limit of 512 MiB exceeded with 519 MiB used. Consider increasing the memory limit, see https://cloud.google.com/run/docs/configuring/memory-limits

:::note warn
この記事では最終的な解決策は見つかっていません。
もし同じ問題で困って、この記事にたどり着いて、その後、原因や解決策がわかったら、教えていただける聖人様がいてくださることを願うばかりです。
:::

:::note
追記: Dockerfile を改善して本番環境にデプロイされる `node_modules` のサイズを削減したところ、コンテナのメモリサイズが 512 MiB でも動くようになりました。
おそらく、アプリ立ち上げ時に `node_modules` （の全体もしくは一部）をメモリにロードすることから、立ち上げ時に一時的にメモリ使用量が増えていたことが原因の一つかと思います。
:::

# やったこと その１: メモリ増量

とりあえずねむいので、課金についてはいったん忘れて、エラーにあるとおり、メモリを 512 MiB から 1 GiB にあげてみます。

https://cloud.google.com/run/docs/configuring/memory-limits?hl=ja#viewing

それでもエラーは消えません。

# やったこと その２：エラー文でしらべる。

https://www.googlecloudcommunity.com/gc/Serverless/Cloud-Run-memory-limit-doesn-t-seem-honored/m-p/692987

超絶要約すると、 「Google Cloud の Console のバグだぜ。」ってことらしい。（ホンマか？）

:thinking: 

じゃあどうやってこのエラー止めんの？

（1月1日の朝っぱらからようやるわ...）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676724/aa1b76b7-767f-c143-ae66-cef7cb67bc68.png)

# やったこと その３：放置

放置というよりも、この記事を書いていたらエラーが止まっていました。
何が起きたのか簡単に見てみます。

まず、最後のエラーは 23:07:02 。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676724/a8475de5-610d-a729-ee72-5dcc5eb0310b.png)

メモリおよびCPU使用率は、上記の最終エラー直後の 23:08~23:09 から下降しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676724/7a3f48b6-cd8b-5f7c-fa20-41eb8e4aa345.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676724/3a1be091-e997-3db2-4545-831256d113ff.png)

また、最後にコンテナへ届いたリクエストは 22:59:00 のようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676724/2c72aeb3-afae-c3ca-3098-cde44ed39f07.png)

時系列で整理してみると、以下のようになります。

- 22:59:00: 最終リクエスト
- 23:07:02: 最終エラー
- 23:08:00: CPU使用率降下
- 23:09:00: メモリ使用率降下

このあっっっさいログ分析から導き出せる仮説としては、「リクエストが落ち着いてから再起動されると、表題のエラーが収まる」ということになるかと思います。

# その他の情報: Cloud Run ではコンテナ上で出力されたファイルがインメモリに保存される

今回の、 Memory limit exceeded エラーが頻発する問題とは少し違う気がしましたが、最近行った変更でファイル出力をしているようなものがないか見てみたいと思います。

https://zenn.dev/yamato_sorariku/articles/7adb5818579df7

https://zenn.dev/hrbrain/articles/run-tempfile

# まとめ

結論は、仮説としての「放置すれば治る。」ということになってしまいました。
原因追及までいたらず、気持ち悪さが残りますが、いったんねむれるので良しとします。
今後も同じような問題が起こるようであれば、もう一度時間をかけて見てみて、追加情報をこちらに追記したいと思います。
Javaで「エスケープシーケンスを使った特殊な文字の表現」の動作を確認してみた

# 概要

Javaで「エスケープシーケンスを使った特殊な文字の表現」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/num/index4.html

# 実装

以下のファイルを作成しました。
```JSample4_1.java
class JSample4_1{
  public static void main(String[] args){
    System.out.println('\'');
    System.out.println("私の名前は\"鈴木\"です");
    System.out.println("この魚の値段は\\250です");
  }
}
```

以下のコマンドを実行しました。
```
$ javac -encoding UTF-8 JSample4_1.java
$ java JSample4_1 
'
私の名前は"鈴木"です
この魚の値段は\250です
```

# まとめ

何かの役に立てばと。
【Misskey】便利なボタンを配置してみる【ウィジェット】

## はじめに
Misskeyを使っているといつも決まった文章を書くことってありますよね？
それを自動で入力してくれる便利なボタンを作ってみます。
## 用意するもの
・Misskeyのアカウント
・ブラウザ
・ちょっとの根気
## ボタンを作っていく
### 下準備
ウィジェットを表示させ編集します
![スクリーンショット 2024-05-07 062200.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679188/59ff49df-bf3b-83e0-edff-effd743771d4.png)

「AiScript App」を選んで追加します
![スクリーンショット 2024-05-07 062358.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679188/695f30f4-dddf-cbb2-e9dc-d62b6ecd35d1.png)
### コードを描く
```is
Ui:render([
    Ui:C:postFormButton({
        text: "自動入力" //ボタンのテキスト
        primary: true
        rounded: true
        form: {
            text: "おはよう！" //ここにいつも入力する文章を入れます
        }
    })
])
```
ウィジェット内の「App」の歯車ボタンを押して、コードを書き込みます
![スクリーンショット 2024-05-07 063149.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679188/55af7fed-5959-f327-9e45-dd860df110f2.png)

これで完成です！

## おしまい
これでボタンを押すだけで「おはよう！」と既に入力された投稿フォームが開くようになりました！
![スクリーンショット 2024-05-07 063718.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679188/623298a8-694b-3cab-b788-bfcea100c3b3.png)

好きな文章に変えてみたりして、便利に活用してみてください。
では良きMisskeyライフを～～！！
包括的に効果検証を自動化する関数を作ってみた

以前に効果検証のプログラムを作ったのですが、

https://qiita.com/murasaki1994/items/1b3bc37ee01203363edc

これについて図を作り差・t値・p値を各因子から自動で算出するプログラムを作ってみました。
# 関数
```Python3
import scipy.stats as stats
import matplotlib.pyplot as plt
def effecttest2(df, columns, y_name, auto=False):
    ave = []
    dtr = []
    pos = []
    lab = []
    x = 0
    for col in columns:
        values = list(set(df[col].values))
        tmp_ave = []
        tmp_dtr = []
        tmp_pos = []
        tmp_lab = []
        for val in values:
            df_tmp = df[df[col]==val]
            tmp_ave.append(df_tmp[y_name].mean())
            tmp_dtr.append(df_tmp[y_name])
            tmp_pos.append(x)
            tmp_lab.append(col+"_"+str(val))
            x = x + 1
        ave.append(tmp_ave)
        dtr.append(tmp_dtr)
        pos.append(tmp_pos)
        lab.append(tmp_lab)
    if auto:
        for i in range(len(dtr)):
            for j in range(len(dtr[i])):
                for k in range(j, len(dtr[i])):
                    if j != k:
                        f, p = stats.bartlett(dtr[i][0], dtr[i][1])
                        if (2 * p) <= 0.05:
                            t, p = stats.ttest_ind(dtr[i][j], dtr[i][k], equal_var=False)
                        else:
                            t, p = stats.ttest_ind(dtr[i][j], dtr[i][k], equal_var=True)
                        print(lab[i][j], lab[i][k])
                        print("t   = %f"%(t))
                        print("p   = %f"%(p))
                        print("val = %f"%(ave[i][j]-ave[i][k]))
                        print()
        for i in range(len(dtr)):
            plt.boxplot(dtr[i], positions=pos[i], labels=lab[i])
            plt.plot(pos[i], ave[i], marker="x")
        plt.xticks(rotation=90)
        plt.show()
    return ave, dtr, pos , lab
```

# 使用例
```Python3
import pandas as pd

df = pd.read_csv("gbsg2.csv")

ave, dtr, pos, lab = effecttest2(df, ["horTh", "menostat", "tgrade", "cens"], "tsize", auto=True)
```
```
horTh_no horTh_yes
t   = 0.718341
p   = 0.472793
val = 0.817849

menostat_Post menostat_Pre
t   = -1.078167
p   = 0.281413
val = -1.215378

tgrade_III tgrade_I
t   = 2.697732
p   = 0.007477
val = 4.911970

tgrade_III tgrade_II
t   = 2.119908
p   = 0.034422
val = 2.826968

tgrade_I tgrade_II
t   = -1.204302
p   = 0.229018
val = -2.085002

cens_0 cens_1
t   = -3.366996
p   = 0.000811
val = -3.773439
```
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782889/2b511d37-cafa-bc30-5ac6-3c98b50d56a0.png)

これで出力結果の通り同じ質的変数の違う値で差の比較ができるようになっています。
@types パッケージ（DefinitelyTyped）の更新差分を見るのに NPM Diff が便利だった

## この記事の概要

[@types (DefinitelyTyped)](https://github.com/DefinitelyTyped/DefinitelyTyped) は TypeScript 用の型定義パッケージです。

DefinitelyTyped のリポジトリにはありとあらゆるライブラリの型定義が登録されています。
そのため、特定のライブラリだけの更新差分を見るのには苦労しがちでした。

しかし、[NPM Diff](https://npmdiff.dev/) を使ったら自分のやりたいことがさっと解決できたので、備忘録がてら記事にしました。

## 結論

まずは NPM Diff にアクセスします。

https://npmdiff.dev/

ページ下部にこのような領域があるので、目当ての内容を入力します。

![Package Name, Version 1, Version 2と書かれた入力欄と、Generate Diffと書かれたボタンが写ったスクリーンショット。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/6eec0a08-0ea9-619e-be32-c6b729f0be7f.png)

例えば、React の型定義の差分を見たいとします。
この記事を書いている 2024 年 5 月 7 日現在の最新バージョンは`18.3.1`なので、その 1 つ前の`18.3.0`と比較してみましょう。

入力欄にそれぞれ`@types/react`, `18.3.1`, `18.3.0`と入力し、`Generate Diff`をクリックします。
すると以下のページに遷移します。

https://npmdiff.dev/%40types%2Freact/18.3.1/18.3.0/

以下の 4 つのファイルが更新されたようです。

- README.md
- index.d.ts
- package.json
- ts5.0/index.d.ts

一覧できて便利ですね。

念の為スクリーンショットも載せておきます。

![NPM Diff の @types/react の 18.3.1 と 18.3.0 の差分を表示しているページのスクリーンショット。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/43570551-361f-c3af-9577-e3cefa6b5e43.png)

一覧ページだと、変更量が多いファイルは`too-big`とだけ表示されて中身を見ることができません。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/9f5b7212-37fd-3ea7-e906-d8470fe690ea.png)

しかし、左側のナビゲーションから個別ファイルのページへ飛べば、ちゃんと確認できます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/f2ea7cf7-4cc8-ef88-dd2d-0a472298bdbc.png)

## 最後に

通常のライブラリであれば、GitHub 上で `releases` 一覧から `compare` 機能を使ってすぐに確認できたのでそこまで苦労していませんでした。
ただ、`@types`の場合はそれができず、毎回効率の悪い差分の確認の仕方をしていました。

今回外部のサイトを使うことで確認しやすくなりましたが、これが一番良い方法なのかはあまり自信がありません。
もし GitHub 上でも簡単に見られる方法などがあればコメントで教えていただけると幸いです。
2024/5/7主にITとかセキュリティの記事

インダストリー4.0とは？日本の製造業への応用解説！(5/5)
https://aippearnet.com/single-post/industries/

5955件ものトラブル相談が！高齢者を中心に被害が多発する「サポート詐欺」。PC画面に表示される偽の警告表示に気をつけて！(5/5)
https://news.livedoor.com/article/detail/26351267/

ネット上の“絶対儲かる”は詐欺！「SNS型投資詐欺」「サポート詐欺」巧みな手口に警戒を！県警サイバー戦略局が解説(5/4)
https://www.fnn.jp/articles/-/694011

ポート開放のやり方と確認方法・開放できない場合の原因と対策まとめ【ゲーサバ大百科】(5/5)
https://gamepedia.jp/game-server/archives/1517

「Ｘ国の独裁者の親族」米国防総省、３０代女性を「機密」資格で失格に　金正恩氏と血縁か(5/5)
https://www.sankei.com/article/20240505-V5MYGOKQMNPOFHP7KG37W476NQ/

「独裁者の親族」、米の審査失格 機密巡り亡命女性、金氏と血縁か(5/5)
https://www.oita-press.co.jp/1002000000/2024/05/05/NP2024050501000756
https://www.the-miyanichi.co.jp/news/World/2024050501000757.php
[ドラフト] Debian イメージにおける graph-tool のインストール方法

グラフライブラリ `graph-tool` は依存関係として非Pythonライブラリのインストールを必要とするため、単純に `pip` ではインストールできない。ざっくりとした方法がこちら

1. Debian イメージ (たとえば bookworm) からコンテナを立ち上げる。立ち上げるのは VS Code の dev container でも可
1. コンテナにログインする
1. `/etc/apt/sources.list.d/debian.sources` を以下のように編集。`Suites` に `experimental` を足す:
   ```text
   Types: deb
   # http://snapshot.debian.org/archive/debian/20230919T000000Z
   URIs: http://deb.debian.org/debian
   Suites: bookworm bookworm-updates experimental
   Components: main
   Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
   (略) 
   ```
1. `sudo apt install python3-graph-tool` でインストール。この際、`/bin/python3` および `/usr/bin/python3` (これらは同一ファイルを指す) にインストールされることに注意[^1]
1. `/bin/python3` でインタプリタを起動して `import graph_tool.all as gt` が正しく実行されることを確認する。これは最低限のチェック方法で、本当はグラフの描画なども試したほうがいい

---
[^1]: この注意の意味について詳しく言うと、例えば dev container の feature 機能により Python をインストールすると他の場所 (例えば `/usr/local/python/current/bin/python3`) に配置される。こちらの Python には `graph-tool` はインストールされない。
二段階エディット法の基本公式

# 二段階エディット法

二段階エディット法は、ソフトウェアテストの分野でバグの総数を推定する手法である。この方法は、2つの異なるテストを用いてバグを発見し、それぞれのテストの結果から全体のバグ数を推定する。

# 二段階エディット法の基本公式

この手法では、以下のパラメータを定義する：
- テストAで発見されたバグの数：$N_A$
- テストBで発見されたバグの数：$N_B$
- テストAとBで共通に発見されたバグの数：$N_{AB}$

これらの数値を用いて、推定される全体のバグ数$N$は次の公式で計算される：
$$N = \dfrac{N_A \times N_B}{N_{AB}}$$

# 考え方と導出過程

1. **バグの発見確率**:
   - テストAがバグを発見する確率 $P_A$ は $\dfrac{N_A}{N}$ である。
   - テストBがバグを発見する確率 $P_B$ は $\dfrac{N_B}{N}$ である。

2. **テストの独立性**:
   - 二段階エディット法では、テストAとテストBが独立していると仮定する。この仮定は重要で、テストが独立でなければ、共通バグ発見確率 $P_{AB}$ が単純な確率の積とは異なる値を持つ。
   - 独立したテストの場合、テストAとBが同じバグを発見する確率 $P_{AB}$ は $P_A$ と $P_B$ の積で表される：
     $$P_{AB} = P_A \times P_B = \left(\dfrac{N_A}{N}\right) \times \left(\dfrac{N_B}{N}\right) = \dfrac{N_A \times N_B}{N^2}$$

3. **全体のバグ数の推定**:
   - 上記の関係から、$N_{AB}$ は $N$ に対するバグの共通発見数として表される：
     $$N_{AB} = \dfrac{N_A \times N_B}{N^2} \times N = \dfrac{N_A \times N_B}{N}$$
   - これを $N$ について解くと、推定される全体のバグ数は以下のようになる：
     $$N = \dfrac{N_A \times N_B}{N_{AB}}$$

# 具体例

たとえば、テストAで20個のバグを、テストBで25個のバグを発見し、両テストで共通して発見されたバグが5個だった場合、全体のバグ数は以下のように計算される：
$$N = \dfrac{20 \times 25}{5} = 100$$

この例では、推定されるバグの総数は100個となる。
String型で等値判定(==)と等価判定(equals)を読み解く

## 等値判定と等価判定


```Java:sample1
String a = "Hello";
String b = new String("Hello");
if(a == b) System.out.println("TRUE");
else System.out.println("FALSE");
```
早速ですが、上記のコードを実行すると何が出力されるでしょうか?
答えは**FALSE**です。

もやもやする方も納得のいく方も、次のコードを見てみてください。
```Java:sample2
String a = "Hello";
String b = "Hello";
if(a == b) System.out.println("TRUE");
else System.out.println("FALSE");
```

では、こちらのコードを実行すると何が出力されるでしょうか？
答えは**TRUE**です。

上記の2つの例を比べて、何か違和感を感じた方も多いのではないでしょうか。
`sample1/sample2`ともに、変数aと変数bに`Hello`を代入しているだけですよね。
なぜ結果が異なるのでしょうか。

### 等値判定（==）
if文内で使用している演算子（==）は等値であるかどうかの判定、**変数そのものの値を比較**しているんですね。
なら全てFALSEにならないとおかしいじゃないか、という意見が出てくると思いますし、それはごもっともです。なぜなら**String型は生成されるたびにメモリ領域のどこかに必要な用量だけ確保される**からです。
つまり、`String a = "Hello";`を実行した際に、メモリ上のaaaa番地を先頭としてHelloが格納され、`変数a`にはアドレス番号であるaaaaが格納されるのです。
同様に、`String b = "Hello";`を実行した際に、メモリ上のbbbb番地を先頭としてHelloが格納され、`変数b`にはアドレス番号であるbbbbが格納されるのです。
定義するたびに新たに容量が確保され、それらの変数には個別のアドレス番地が格納されるということです。
そして、等値判定では変数そのもの、つまり各変数が保持しているアドレス番地が等しいかどうかを判定するので、当然**FALSE**でなくちゃおかしいのです。

ですが、文字列リテラルは、コンパイル時にプールと呼ばれる領域に保存されます。同じ内容の文字列リテラルは、プール内にある同じオブジェクトを参照するように最適化されます。
つまり、複数の変数がそれぞれ同じ文字列を持っていても容量の無駄使いとなる（文字列は書き換え不可で、個別に定義する必要がない）ので、コンパイル時には1つだけ生成してあとはみんな同じアドレスを参照しようね、ということになっているのです。
本来なら`変数a`に`aaaa`が、`変数b`に`bbbb`が代入されるはずだったのですが、コンパイル時に`nnnn番地`にHelloが格納され、**aもbもnnnnを保持する**ことになるので、等値判定がTRUEとなるのです。

### なんでnewで作ったらFALSEになるの
以上の説明から、同じ文字列を定義すると、1つにまとめてみんなそこを参照するようになるんでしたよね。ならなぜ`sample1`の結果はFALSEとなったのでしょうか?
これは単純で、newキーワードを使用すると、毎回新しいオブジェクトが生成されるのですが、オブジェクトは、ヒープと呼ばれる領域に生成されます。
つまり、`""`で定義した場合と`new`で定義した場合では異なるメモリ領域を指すため、==演算子で比較するとfalseになるというだけの話でした。
もちろん、2つとも`new`で定義しても、それらは別々のヒープ領域を使うので、文字列が同じでも==演算子の結果はFALSEとなります。

### 等価判定（equals）
では、サンプルコードの判定式を`==`ではなく`equals`で代用するとどうなるか。
```Java:sample3
String a = "Hello";
String b = "Hello";
String c = new String("Hello");

System.out.println(a.equals(b)); //true
System.out.println(a.equals(c)); //true
```
以上のような結果になります。
等価判定とは、対象の変数が**指し示す内容が同じかどうか**を判定しています。
つまり、変数そのものではなく、変数に入っているアドレスが指し示す先の内容が同じかどうかを見ているわけです。
だから、`変数a`と`変数c`にはそれぞれ個別のアドレス番地が格納されていますが、どちらの参照先も`Hello`という内容であるので、**equalsの結果はtrue**となるわけですね。

### まとめ
今回は等値判定（==）と等価判定（equals）の違いについてまとめてみました。
つまるところ、等値判定の方がより厳しい判定条件ということですね（雑）
ちなみに、equalsはプリミティブ型には使えないので、お気を付けください。
Gitを雑に理解する

雑な認識なので正確でない内容を含みます

# GitHubとは
Gitの内容をオンラインで公開/共有できるwebアプリ

# Gitとは
ソースコードに対し「いつ」「誰が」「どの部分を」編集したか
いわゆるバージョン管理をするためのツール

利用者はエンジニアのみでなく、
文章を書く人や、会社によっては事務にも導入されているらしい


# 単語
### リポジトリ
データを保存しているフォルダのようなもの
バージョン管理などの意味合いが含まれる

ローカルリポジトリ -> 手元のパソコンのリポジトリ
リモートリポジトリ -> GitHub上のリポジトリ


### ブランチ
複数人で同じプロジェクトに関わる上で、全員が本体を編集すると
同じ箇所の編集であったり、間違えたときのバージョン巻き戻しなどが大変になる

なので、枝分かれさせた小さなバージョンを作り、それが問題なく動いたら本体に合流させる


### マージ
ブランチを合流させる動作のこと



# コマンド
sourcetreeなどgitをGUIで操作できるツールは色々あるので覚えなくてもいい

## git init
リモートリポジトリが存在しないプロジェクトを一から立ち上げた場合
「ここをこのプロジェクトのローカルリポジトリとする」宣言


## git clone
リモートリポジトリが存在するプロジェクトを文字通りclone(複製)して
ローカルリポジトリを作成するために使う


## git add
変更した内容を認識(ステージ)させるためのコマンド
個人開発なら大体 -A オプションをつけて全部ステージさせても問題ない


## git commit
変更して保存しただけではバージョンとして処理されない
commitすることで初めて一連の変更が新しいバージョンとして処理される

-m オプションでコミットメッセージを直接付与できる
コマンドプロンプトでコミットメッセージをつけなかった場合vimが立ち上がる
いつもの画面から変わる上、`:q`などのコマンドを要求されるので初見詰みポイント


## git push
ローカルでcommitした内容をリモートに共有する


## git status
今のワーキングディレクトリの状態を確認
・どのブランチを編集しているか
・変更されたファイル
・ステージされているファイル
等の情報を確認できる


## git branch
ローカルリポジトリに存在するブランチの一覧表示


## git branch [new-branch]
新しいブランチの作成


## git checkout [branch-name]
指定したブランチに切り替える
checkoutせずブランチをmainのまま編集には気を付けよう

git checkout -b [new-branch-name]
で新しいブランチを作成し、そのブランチに切り替えることができる


## git merge [branch-name]
指定したブランチを現在のブランチにマージする


# その他
git rebaseは基本的に使わない方がいいらしい

バージョンの巻き戻しはrestore
[memo]コンパイルとビルドの違い

<h1>コンパイルとビルドの違いについて考えてみた</h1>

初記事です！アウトプット用に書いてみました。もし何か間違いとかあればコメントしてくれると嬉しいです！

C言語の入門書に、コンパイルとビルドについてそれぞれ書かれていたので、自分なりにまとめてみました！

<h2>コンパイルとは？</h2>
<p>コンパイルとは、C言語などで書かれたソースコードを、コンパイラというソフトウェアを通して、<strong>機械語に変換する処理</strong>のことを言う。この時点で、実行ファイルは生成されない。ただ変換しただけ。</p>


<h2>ビルドとは？</h2>
<p>一方ビルドとは、ソースコードから実行形式ファイルを生成すること。このビルドという処理の中で、コンパイラが使用される。</p>

<h2>まとめ</h2>
<p>多分、デスクトップアプリとか複雑なアプリを開発でもしない限り、（今のコンパイラを使った）コンパイル=ビルドという認識で、問題ないはず。
だけど、そうじゃないときは使い分けに意識したほうがいいと思いました！</p>
Nuxt3(SPAモード)でのFireStoreアクセス

# FireStoreへのつなげ方。

Nuxt3プロジェクトにて以下を実施。

firebaseツールをインストールし、Initを実行。
login実行するとブラウザ等でログイン動きます。

```
npm install -g firebase-tools
firebase login
firebase init
```
initにて以下質問を回答。ほかはデフォルトでOK
```
～
? What do you want to use as your public directory? dist
? Configure as a single-page app (rewrite all urls to /index.html)? Yes
～
```

ライブラリ追加
```
npm install firebase
npm install -D firebase-admin firebase-functions firebase-functions-test
```

localで起動する場合こちら。
```
$ firebase emulators:start
```

firebaseにデプロイする場合はこれ。
```
firebase deploy
```

# APIを呼ぶ
接続情報をfirebaseインスタンスに設定
Pluginに書いておくとよい。

xxxxxxxxxxxxxxxはFirebase側で作成したプロジェクトの値を適用。
なお、この情報は秘匿しなくてもいい模様。なんならデプロイしたFQDNにこれつけると見れる。
https://xxxxxxxxxxxxxxx/__/firebase/init.js

```plugins/firebase.ts
import { initializeApp } from 'firebase/app'
import { defineNuxtPlugin } from '#app'

export default defineNuxtPlugin(() => {

    const firebaseConfig = {
        apiKey: xxxxxxxxxxxxxxx,
        authDomain: xxxxxxxxxxxxxxx,
        databaseURL: xxxxxxxxxxxxxxx,
        projectId: xxxxxxxxxxxxxxx,
        storageBucket: xxxxxxxxxxxxxxx,
        messagingSenderId: xxxxxxxxxxxxxxx,
        appId: xxxxxxxxxxxxxxx,
        measurementId: xxxxxxxxxxxxxxx
    }

    // インスタンスにConfigを登録する
    initializeApp(firebaseConfig)

})
```

ComposablesにAPIアクセサを実装
```~\composables\useReviewApi.ts
import {
  getFirestore,
  collection,
  query,
  getDocs,
} from 'firebase/firestore'
// これはAPIの応答に型をつけたかったんだけれどもまだ適切な定義方法模索中。
import type { Review } from '~/types/api/Review'

export const useReviewApi = () => {

  // 検索（reviewsというエンドポイントにアクセスするイメージ）
  const selectAll = async ()=> {
    const records: Review[] = []
    const queryCondition = query(collection(getFirestore(), 'reviews'))
    const docs = await getDocs(queryCondition)
    docs.forEach((doc) => {
      records.push(doc.data() as Review)
    })
    return records
  }

  return {selectAll}
}
```
呼び出しイメージ
```app.vue
<template>
  <div>
    <div
      v-for="val in data"
      :key="val.reviewId"
    >
      {{ val.name }}
    </div>
  </div>
</template>
<script setup="ts">

const { selectAll } = useReviewApi()
const data = ref(null)

onMounted(async () => 
  data.value = await selectAll() 
) 
</script> 
```

実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139625/ff62dde4-4f42-aa71-5caf-95a4d8fadc9e.png)



# firestoreの型定義が出てこない。。。
ググると。@firebase/firestore-typesなるものが。
https://www.npmjs.com/package/@firebase/firestore-types?activeTab=code
入れてみたけれども。AppModelTypeとかはよくわからず。。。。
雰囲気で使えるけれどもなんだかなぁ。。


firestoreのデータ型の役割。。ここ非常に参考になりました。
https://qiita.com/maiyama18/items/86a4573fdce800221b72
【備忘録】xから画像／動画をコマンドで一括取得できるようにする方法のリンク

https://gigazine.net/news/20231023-twitter-media-downloader/

```.特定アカウントの全件分の「写真／動画」取得
twmd -u アカウント名 -a
```

```.ヘルプ
-h：ヘルプを表示
-u：メディアをダウンロードしたいユーザーネームを指定
-t：ダウンロードしたい単一の投稿(旧ツイート)のIDを指定
-n：ダウンロードしたい投稿の件数を指定
-i：画像のみをダウンロード
-v：動画のみをダウンロード
-a：画像と動画をダウンロード
-r：リツイートしたメディアもダウンロード
-z：メディアをダウンロードせずにURLを出力
-R：リツイートされたメディアのみダウンロード
-s：スモール・ノーマル・ラージからフォーマットを選択(デフォルトはラージ)
-U：削除された投稿のみダウンロード
-L：アカウントにログイン
-o：出力ディレクトリ
-p・プロキシを使う
-V：バージョンを表示して終了
-B：バナーを出力しない
```
【基本情報処理技術者試験】エンジニア未経験が2ヶ月でゴリ押し合格した方法

:::note warn
エンジニア初心者の投稿であるため、間違っている箇所が多くあるかと思います。
何かお気づきの点がありましたらご教授いただけると幸いです。
:::

# はじめに
IT知識がほぼ0の状態でエンジニアの登竜門と呼ばれる『基本情報処理技術試験』に挑んだ男の生き様を記録したいと思います。

そもそも『基本情報処理技術者試験』なにという方もいると思うので、情報処理推進機構（IPA）の説明を記載します。
>ITを活用したサービス、製品、システム及びソフトウェアを作る人材に必要な**基本的知識・技能**をもち、実践的な活用能力を身に付けた者

上記のように基本的な知識・技能を身につけられているかを確認する試験が『基本情報処理技術者試験』であり、エンジニアの登竜門と呼ばれる所以です。

# 使用した参考書
全部で３種類の参考書を用いて学習していました。
選んだ理由ですが特にありません…（笑）

- 科目Aに関しては、インターネットで調べたときに評価が高く、トップに出てきたものを買いました。正直雰囲気を掴むための本であるのでなんでも大丈夫だと思います。

https://www.kinokuniya.co.jp/f/dsg-01-9784815624262

- 科目Bに関しては、この本がすごくおすすめです。他の本を見ていないため、比較はできませんが、「トレース表」という科目Bでは必須になる技術（知識ではない）を学べるので、ぜひこちらで学習してみてください。

https://www.shoeisha.co.jp/book/detail/9784798182520

- 本で雰囲気を掴んだあとこれだけをひたすらやってました。過去問を勉強できるようになっている神サイトです。

https://www.fe-siken.com/fekakomon.php

# 学習の歴史
学習の流れをなるべく詳細にまとめてみました。
勉強時間については、平日は1〜2時間で、休日は5時間程度です。

### １日目　〜　1ヶ月目
#### 科目A用に購入したテキスト「いちばんやさしい基本情報技術書」を３周する。
- 1周目はとりあえず最初から最後までぶっ通しで読む。わからないところがあったとしても読み進める（問題は解かずに進めました）。
- 2周目は赤シートで重要語句を隠しながら、単語を覚えているかを確認する。覚えていなかったところに関してはメモをしておき、次の日に確認する。
- 3周目は２周目と同じことを繰り返し行い、問題を一通り解いてみる（ここで初めて問題を解く）。

### １ヶ月目　〜　1ヶ月半
#### 神サイト「過去問道場」を使って科目Aの過去問を解く。
- 平成16年から令和4年までの問題があるので、自分の勉強にあてられる時間に合わせて何年度分を解くか決めるといい（私は平成30年度分ぐらいまで解いた）。
- 間違えた問題を復習できるようになっているので、30年度から令和4年度分で復習問題がなくなるまで解き続けた。

### 1ヶ月半　〜　試験直前
#### 科目Bの問題を「出るとこだけ！基本情報技術者［科目B］」を2周する。
- 1周目は参考書の例と同じようにトレース表というものを書く。全ての問題にトレース表が載っているのでそれを写しながら書いてみる。
- 2周目は問題文だけをみて、自分で考えてトレース表を書く。どうしてもわからない時だけ回答例を確認する。間違えてしまったものに関しては次の日に解いてみる。
- 「出るとこだけ！基本情報技術者［科目B］」にはサンプル問題というものも付いているので、本の内容を理解できたら取り組む。

# 結果
点数はどちらもギリギリではあったので自慢できるものではありませんが、なんとか600点のボーダーラインにはのることができ、1発合格することができました。

# 注意点
ネットでは「試験内容はほとんどが過去問通りだ」という意見が見受けられます。しかし、実際に受けてみて過去問だけだとカバーしきれないところは多くあると感じました。特に科目Bについてもトレース表をしっかりと理解していなければ解けない問題が多いです。

# おわりに
ダラダラと合格までの道筋を書いてきましたが、これが誰かの役に立ってくれることを願っています。私自身、今回の合格はあまり納得できるものではなかったのでこれからさらに邁進して行きたいと思っています。
【Java・SpringBoot】ObjectMapperクラスでJSONオブジェクトをゼロから作成する方法

Javaのバックエンド処理内にて、JSONオブジェクトをプロパティ名も含めてゼロから作成するケースに遭遇した。
この場合、ObjectMapperクラスの「createObjectNode」メソッドを利用すると簡単に作れる。
備忘録のため以下にまとめておく。

## createObjectNodeメソッド ・使い方
以下のように記述することで、プロパティ名を含めて自由にJSONオブジェクトを作成できる。

```java

public class Main {
    public static void main(String[] args) throws Exception {

        // ObjectMapperをインスタンス化する. 
        // enableメソッドはJSONオブジェクトをコンソールで出力する際に改行を加えて見やすくする呪文.
        // 改行の必要性が無い場合は記述を省けばOK.
        ObjectMapper objectMapper = new ObjectMapper()
                .enable(SerializationFeature.INDENT_OUTPUT);

        // 「cerateObjectNode」メソッドで「ObjectNode」インスタンスを生成する.
        ObjectNode objectNode = objectMapper.createObjectNode();

        // 「put」メソッドでObjectNodeにプロパティ名と値を追加できる.
        objectNode.put("id", 10);
        objectNode.put("name", "ジョジョ");

        // ObjectNodeをJSONオブジェクト(文字列)に変換する際は「writeValueAsString」メソッドを利用.
        String jsonStr = null;
        try {
            jsonStr = objectMapper.writeValueAsString(objectNode);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        // JSON文字列を出力する.
        System.out.println(jsonStr);
    }
}
        

```
Gitとは何か、なぜ開発プロセスで重要なのか

# 初心者向け：Gitの基本とその重要性

## はじめに
開発において、ソースコードの管理ってめちゃくちゃ大事。そこで登場するのがGit。この記事では、Gitって何？ どうして学ぶべき？ という疑問に答えていくよ。

### Gitって何？
Gitは、2005年に開発されたツールで、複数の人が同じプロジェクトでバッチリ協力できるようにするためのものだよ。コードの変更履歴をキッチリ管理してくれるんだ。

### Gitのイイところ
- **バージョン管理：** 変更履歴をしっかり保存して、必要なときには元に戻せる。
- **チームでの協力：** みんなで一緒にプロジェクトを進められる。
- **データの安全：** データが二重に保存されるから、失うリスクが少ない。

## なぜGitを学ぶべき？
小さなスタートアップから大企業まで、世界中のいろんな場所でGitは使われてるよ。オープンソースプロジェクトや個人プロジェクトにも役立つし、知っておくと新しいチャンスが広がるかも。

## Gitの基本的なワークフロー

Gitを使った基本的なワークフローを通じて、どのようにソースコードのバージョン管理が行われるか見てみよう。

### シナリオ：新しい機能の開発

想像してみてください。あなたは「お天気アプリ」の開発チームの一員です。新しい機能「明日の天気予報」を追加するタスクが割り当てられました。

#### 1. **リポジトリのクローンを作成**
   最初に、プロジェクトのリポジトリを自分のローカル環境にクローンします。
   ```bash
   git clone https://github.com/example/weather-app.git  
   ```
#### 2. **新しいブランチを作成**
新しい機能の開発のために、専用のブランチを作ります。
```bash
git checkout -b feature/tomorrow-weather
```

#### 3. **機能の開発**
コードを書いて、明日の天気を予報する機能を実装します。

#### 4. **変更をステージしてコミット**
変更をステージに追加し、コミットします。
```bash
git add .
git commit -m "Add tomorrow's weather feature"
```

#### 5. リモートにプッシュ
完成したら、変更をリモートのリポジトリにプッシュします。
```bash
git push origin feature/tomorrow-weather
```

#### 6. プルリクエスト
GitHub上でプルリクエストを作成し、チームメンバーにレビューを依頼します。

#### フローチャート：Gitのワークフロー
```mermaid
flowchart TD;
    clone("リポジトリのクローン") --> branch("ブランチの作成");
    branch --> code("機能の開発");
    code --> stage("変更をステージしてコミット");
    stage --> push("リモートにプッシュ");
    push --> pr("プルリクエスト");
```

## 結論
Gitを使いこなせるようになると、開発がグンとラクになるし、ミスの修正や機能改善がサクサク進むよ。

---

**参考リソース**
- [Git公式ドキュメント](https://git-scm.com/doc)
- [Pro Git ブック](https://git-scm.com/book/ja/v2)
classification_report優秀すぎる件

以前にこんな記事を書きました

https://qiita.com/murasaki1994/items/d86c49b33f42054f6cfb

ここではclassification_reportというScikit-Learnにある分類の於ける各指標をクラスごとに計算してくれるものを利用して書いたのですが、私がQiitaを始めて2回目に書いた深さ優先探索や幅優先探索のアルゴリズムを使って辞書データを自動解析する関数を使えばかなり自由度の高い分析ができるんじゃないかと思いました。

https://qiita.com/murasaki1994/items/9ab41de8aa1b1380c71b

では実際にプログラムを組んでみます。
使用するのはアヤメのデータになります。

```Python3
from sklearn.linear_model import LogisticRegression as LR
from sklearn.metrics import classification_report
import pandas as pd

df = pd.read_csv("iris.csv")

y = df["category"]
x = df.drop("category", axis=1)
for col in x.columns:
    x[col] = (x[col] - x[col].mean()) / x[col].std()

model = LR()
model.fit(x, y)
y_pred = model.predict(x)
print(classification_report(y, y_pred))
```
```
              precision    recall  f1-score   support

           0       1.00      1.00      1.00        50
           1       0.98      0.94      0.96        50
           2       0.94      0.98      0.96        50

    accuracy                           0.97       150
   macro avg       0.97      0.97      0.97       150
weighted avg       0.97      0.97      0.97       150
```
これだけ見ると数字の桁数が小数点以下2桁で精密さにかけるのではないかと思いますが、辞書機能を使って見ると
```Python3
rep = classification_report(y, y_pred, output_dict=True)
print(rep)
```
```
{'0': {'precision': 1.0, 'recall': 1.0, 'f1-score': 1.0, 'support': 50}, '1': {'precision': 0.9791666666666666, 'recall': 0.94, 'f1-score': 0.9591836734693877, 'support': 50}, '2': {'precision': 0.9423076923076923, 'recall': 0.98, 'f1-score': 0.9607843137254902, 'support': 50}, 'accuracy': 0.9733333333333334, 'macro avg': {'precision': 0.9738247863247862, 'recall': 0.9733333333333333, 'f1-score': 0.9733226623982927, 'support': 150}, 'weighted avg': {'precision': 0.9738247863247864, 'recall': 0.9733333333333334, 'f1-score': 0.9733226623982927, 'support': 150}}
```
ではこの辞書データに対して深さ優先探索を使ってデータを使いやすくします。
```Python3
def depth(jsn, var=""):
    if isinstance(jsn, dict):
        for row in jsn:
            depth(jsn[row], var=var+"[\""+row+"\"]")
    elif isinstance(jsn, list) and jsn != []:
        for i in range(len(jsn)):
            depth(jsn[i], var=var+"["+str(i)+"]")
    else:
        print(var+"="+str(jsn))
        pass
```

これに対して先ほどの辞書データを使いますと
```Python3
depth(rep, var="rep")
```
```
rep["0"]["precision"]=1.0
rep["0"]["recall"]=1.0
rep["0"]["f1-score"]=1.0
rep["0"]["support"]=50
rep["1"]["precision"]=0.9791666666666666
rep["1"]["recall"]=0.94
rep["1"]["f1-score"]=0.9591836734693877
rep["1"]["support"]=50
rep["2"]["precision"]=0.9423076923076923
rep["2"]["recall"]=0.98
rep["2"]["f1-score"]=0.9607843137254902
rep["2"]["support"]=50
rep["accuracy"]=0.9733333333333334
rep["macro avg"]["precision"]=0.9738247863247862
rep["macro avg"]["recall"]=0.9733333333333333
rep["macro avg"]["f1-score"]=0.9733226623982927
rep["macro avg"]["support"]=150
rep["weighted avg"]["precision"]=0.9738247863247864
rep["weighted avg"]["recall"]=0.9733333333333334
rep["weighted avg"]["f1-score"]=0.9733226623982927
rep["weighted avg"]["support"]=150
```

大変見やすくなったと思います。これを使って精度の詳細を分析すると分類系の精度の関数を使わずとも詳細が分かると思います。
キャンセル動作について

## 「キャンセル」と「クリア」の違い
ここではReactのuseStateを用いたキャンセル機能の実装について紹介します。
様々なアプリケーションにおいて実装されている「キャンセル」機能ですが、「クリア」機能とどのように異なるのでしょうか？大まかに言ってしまえば、以下の違いがあると言えます。
- 「クリア」は初期化
- 「キャンセル」は直前の操作の取り消し

#### それでは実際の動きを見ていきます。
今回は下のようなUIから、購入したい品物を選択する場面を考えてみます。

![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740513/f6829c4c-ff95-9c05-d2d5-e9f6fa46f47b.png)

各品物の選択状態を管理するためにuseStateを用います（初期条件ではすべてfalse）。

```react:cancel.js
const [selectState, setSelectState] = useState({
  rice: false,
  meat: false,
  fish: false,
  vegetable: false,
  snack: false,
})
```
ここで、「決定」ボタンが押された時に、選択されている品物の選択状態がtrueとなるようにします。
例えば「米」と「肉」を選択した状態で「決定」ボタンを押すと、"rice"と"meat"に対する値がtrueに更新されるといった具合です。
では、この状態管理の情報を用いたキャンセル機能の実装について、次の2パターンの場合に分けて考えてみます。
1. 「決定」ボタンが1回も押されていない場合
この場合、品物を実際には何も選択していない状態でのキャンセルとなるため、すべてのチェックボックスのチェックを外せばよいことになります。なお、この「すべてのチェックボックスを外す」動きを「決定」ボタンが1回以上押された状態で行うと、それは「クリア（初期化）」となり、後述する「キャンセル」動作とは異なる動作となります。
1. 「決定」ボタンが1回以上押されている場合
この場合、直前の「決定」ボタンクリック時の状態を復元することで、キャンセルの動きを実現することができます。
例えば、「魚」と「野菜」を選択して「決定」ボタンを押したとします。このとき、selectStateにおいて、"fish"と"vegetable"に対する値がtrueに更新されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740513/85aaaa19-5f99-7cf1-416d-9221f747ab93.png)
その後、「菓子」をチェックして、やっぱりやめたということで「キャンセル」ボタンを押して再度確認すると、「菓子」からはチェックが外れていて、「魚」と「野菜」のみチェックがついている状態となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740513/334e8e15-d704-d6aa-ce68-284498779d01.png)
↑この状態で「キャンセル」ボタンを押すと、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740513/79c54483-7b34-3e74-c482-68f5a63d06bc.png)
元の状態に戻りました（「クリア」機能では、この場合でもすべてのチェックボックスのチェックが外れることとなります）。

以上が、初期化を行う「クリア」機能とは異なる「キャンセル」機能の基本的な考え方となります。
ご覧いただきありがとうございました。
yabaiとskhdを設定するときにError: Formula `skhd` has not implemented #plist, #service or installed a locatable service file

https://qiita.com/psyashes/items/68ac40659ddbe04f8f7f

上のページを参考にインストールを進めていくと
brew services start yabai


とすると、エラーが出てきた。

アクセシビリティを許可するところのやり方がわからなかった。
調べてみると
https://github.com/koekeishiya/yabai/issues/1738

にあるように
yabai --start-service
とすると一回ブロックみたいながされるので、それからアクセサビリティのところをみると、yabaiが表示されているので、それを許可することで次に進めた。
【UE5】ゼロから極めるゲーム開発　その0

初投稿です。
# 記事について
UE5の極め本を買ったので、その備忘録を投稿していくつもりです。
著作権的にダメな部分がある場合は削除なり非公開なり再編集なり対応します。

UE5のバージョンは参考書に合わせて5.1.1を使用。
UE5自体のインストール方法などは飛ばします。

[Unreal Engine 5で極めるゲーム開発](https://www.amazon.co.jp/Unreal-Engine-5%E3%81%A7%E6%A5%B5%E3%82%81%E3%82%8B%E3%82%B2%E3%83%BC%E3%83%A0%E9%96%8B%E7%99%BA-%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%81%A8%E5%8B%95%E7%94%BB%E3%81%A7%E5%AD%A6%E3%81%B6%E3%82%B2%E3%83%BC%E3%83%A0%E5%88%B6%E4%BD%9C%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88-%E6%B9%8A%E5%92%8C%E4%B9%85-ebook/dp/B0CJBR149V/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=H8TBI4NT5AG7&dib=eyJ2IjoiMSJ9.DACdTL8544VkM086bpXa_-WYZKOqPqyCDCe81rPqwxaV2wCVr3nyynP6MmUPMBchaacRQFdOY4jAufAUoYcHL_7GIK0j2XaJTMcCwhDv_94VUA9QEyrmuo-SMHUn9bGmjGLjw8D50escGr3Za6Ky_ZUDtKCkaVKi7wW_0b2VYDlcFS4oYaghshF96Yn7NCZMmw9V01j4--_PTTj2OyqgtCjDRe6wHB9lkjXcVmqA5PjZPO4OHY_XknlBTNm7_DoV21lYb_16OWp_6nzxquJIe-mRjpGYdhMUmRwuaqJ3aV0.ZmapRoTtrlpno4LYKsnSj5ZiKW40CE9FK7G6MzKArW0&dib_tag=se&keywords=ue5&qid=1715005724&sprefix=ue5%2Caps%2C165&sr=8-2)
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779049/bcc538e8-539c-d304-16fc-d6aa4bd6c6b1.jpeg">


# 記事一覧
[【UE5】ゼロから極めるゲーム開発　その1](https://qiita.com/apple_moz/items/ade93f3e7e6a3f18e7de)
[【UE5】ゼロから極めるゲーム開発　その2](https://qiita.com/apple_moz/items/79c033c4066f76214216)
[【UE5】ゼロから極めるゲーム開発　その3(モデリング編)](https://qiita.com/apple_moz/items/c25ddcc00e2ac6489601)
[【UE5】ゼロから極めるゲーム開発　その4(モデリング続き)](https://qiita.com/apple_moz/items/53e28be9c772eacaad76)
[【UE5】ゼロから極めるゲーム開発　その5(インポート)](https://qiita.com/apple_moz/items/542c85c1770ba500d0c6)　※未完
【React】クリックできるdiv

以下のように記述するとクリック可能な`div`を作成できます。

```tsx
export function ClickableDiv({ children }: { children: React.ReactNode }) {
  const handleKeyDown = (ev: React.KeyboardEvent<HTMLDivElement>) => {
    if ((ev.key === 'Enter' || ev.key === ' ') && !ev.metaKey) {
      // EnterキーまたはSpaceキーが押下された場合の処理
    }
  }

  return (
    <div
      role="button"  // スクリーンリーダーに要素がボタンであることを伝える
      tabIndex={0}  // Tabキーでフォーカスできるようにする
      onClick={() => console.log('divがクリックされました。')}
      onKeyDown={handleKeyDown}  // button　の挙動に合わせる
    >
      {children}
    </div>
  )
}

```


https://developer.mozilla.org/ja/docs/Web/Accessibility/ARIA/Roles/button_role
Pythonで、自身を別窓で実行(Windows)


# 兼用はムリ

とあるスクリプトを作成。
１本のスクリプトで、２個のものを動かしてましたが、
どうも効率が悪いので、スクリプトを２個別で動かしたいなと。

スレッド化したりするのも面倒だし、２ファイルに分けてパラメータだけ変えるのも、
メンテがめんどくさい。

ということで、

# 幽体離脱？

オプションが無いときは、オプションを付けて自分自身を呼び出すようにして、一旦終了。

一方、自身がオプション付きで呼び出されたら、本編を実行。

```Python:title.py
import sys
import subprocess

exefn = sys.argv[0]

if len(sys.argv) < 2 :

    print("R")
    pR = subprocess.Popen('start python "'+exefn+'" R',shell=True)
    
    print("L")
    pL = subprocess.Popen('start python "'+exefn+'" L',shell=True)
    
    input("bye")
    sys.exit()

 # 以降本編

```

一応、Windows10 + Python3.10 でうまく行ってます。
３秒で回答できる質問をしろ

## 導入
もしあなたが、会社の同僚や、先輩後輩、あるいは日々利用する美容室などで話が行き詰って、重苦しい空気に包まれ、それが嫌だというなら、自分の「質問の仕方」を見つめ返すいい機会かもしれない。

## ストーリー
 私のはこの春に上京し、このゴールデンウィークに初めて東京の美容室に行った。
 だいたい１時間くらいかかったのだが、その間、シャンプーなどをしている時間を除いて、会話が止まるということはほとんどなかった。
 
 これは、今回が特殊というわけではなく、私はだいたいそうだ。
 入社後、様々な名目で同期とグループを作って自己紹介だのグループワークだのをしてきたが、そのほとんどのグループで、会話が途切れた憶えはない。
 だが、この前同期と飲みに行った際、存外ほかのグループでは自己紹介の時間が余ってしまい、シーンとして気まずい思いをしていることを知った。
 その時、同期からは私のコミュ力が高いからだと評されたが、私の人生はそれを否定している。
 私自身もほんの数年前までは美容室では常に無口だったし、グループワークでただ静かに身を細めていた経験もある。
 
 では、そんなコミュ力だった私が、美容室でも雑肉まれた同期との自己紹介ワークも楽しく乗り切ったのか、今回はそれの手法について私なりの見解をお話ししたい。

## 会話の選択肢
 今回取り上げるトピックは「質問の仕方」なのだが、まず、会話をするうえで、どんな選択肢があるかを整理しておく。
 
<dt>選択肢①：事実</dt>
<dd>例）今日は晴れてるね</dd>
<dt>選択肢②：共感</dt>
<dd>例）そうね、いい天気ね</dd>
<dt>選択肢③：意見/主張</dt>
<dd>例）夏みたいだね</dd>
<dt>選択肢④：質問</dt>
<dd>例）この天気ってあと何日持つかな？</dd>

分け方は人それぞれだろうが、私は上記の分類を好んでいる。
簡単な例は示したので細かい説明はしないが、前提として、人は何かを話したとき、それはだいたいこの４つのいずれかに分離できるということを頭に入れておいていただきたい。

## なぜ「質問の仕方」に注目するのか
これも当たり前の話だが、基本が重要なので記載する。
なぜ質問が重要か、それは当然相手を強引に会話に呼び込むことができるからだ。
このテーマは究極的に「いかに話を続けるか」という問いへの回答にならなければならないため、終わらせない側が気を付けるべきは「質問」であるということにはおおむねご理解いただけると思う。

## ３秒で回答できるようにしろ
「お昼何食べたい？」
この質問に３秒で答えられる人は私の体感、１０％はいない。
ほとんどの人が、うーん何がいいかなあと考えを巡らせ、あまり納得は言っていないような表情で「強いて言うならこれ」という回答をする。

まず我々質問者が理解しなければならないのは、「質問とは相手に考えることを強要する行為」ということだ。

みなさんもなにか企業のアンケートなどに回答したことがあるだろう。
その時、何だが似たような意味の質問を続けて２個も３個もされてむかついたことはないだろうか。

誰しもほかの人から供用されて考えさせられることは面倒くさい。そのうえ、その質問が前にした質問と似ていたり、結局その質問をして何が知りたいのか意図のわからい質問はより回答者への負担となる。

しかし、相手に配慮ばかりして質問をせず、自語りを一生されてもきもいし、ずっとおとなしく黙って時間がたつのはちょっと、、、と思う人はまず、相手が質問に３秒で答えられるよう工夫をしてみよう

## お昼何食べたいの3秒化

「お昼何食べたい？」と聞いて、3秒で回答できないのは選択肢がいくつもあるからだ。
もっとも簡単な「3秒化」は

<dt>「お昼何食べたい？フレンチとかどう？」</dt>

と聞くことだ。
こうすれば、まず「フレンチはどうか」にYesかNoかで回答ができる。YesかNoかの2択なら3秒はかからない。
さらに、考えるきっかけを相手に提供することもできる。
この後、「中華は？」「和食は？」と質問を重ねることもできるし、相手も聞かれずともそういった選択肢から考えることができる。
さらには「昨日の夜何食べた？」「好きな食べ物は｝とかも有効な手段だと思う。

重要なのはこの構造で

<dt>１ビッグ・クエッション(お昼何食べたい？)
<dd>ー1.1サブ・クエッション(フレンチは？)</dd>
<dd>ー1.2サブ・クエッション(昨日何食べた？)</dd></dt>

とすることで、最初から考えてもらうには少しハードな問いにもそのテーマの一部分を切り出して、Yes/Noクエッションを付属させることで、できるだけ相手の負荷を少なく、そしてこちらが聞きたかった情報を引き出すことができる。


## そして、「話が行き詰る」の回答へ
話が行き詰って、トホホと感じた人の多くはおそらく「ビッグ・クエッション」を聞けず、ただ狭いYes/Noクエッションを繰り返して話を思ったように引き伸ばせず、結局沈黙してしまったのではないだろうか。

先ほどの「お昼何食べたい？」の例で示した通り、重要なのはオープン・クエッションとクローズド・クエッションの使い分けだ。
そして、話を続けるにはクローズド・クエッションは<strong>「水平移動」</strong>の質問であるべきなのだ。
ジャンルの中でフレンチから中華、和食へと水平移動した。
また、クローズではないものの、ほとんど多くの人が回答を持っている「昨日の夜ごはんは何食べたの？」、「好きなたべものなに？」といった質問をして話を展開していく。

また、話を終わらせないための最も重要な点は、最初に掲げた「ビッグ・クエッション」の回答は絶対にもらわないということ。
「お昼何食べたい？」の回答が出れば、もう後は食べに行くしかなくなってしまう。
当然食べに行きたいならそれでいいが単に空白を埋めるためにこの雑談をしているのだとすれば、食べに行くしかない状況は困る。
だから、常に水平移動を繰り返し、ジャンルを聞いて、昨日食べたものを聞いて、好みの食べ物を聞いて、適当に自分の好きな食べ物の話もはさんで、時間を稼ぐ。

## 終わりに
といっても、こんな文章を読んだだけで、急に自分の質問能力が飛躍するわけではないし、星が一つも見えない深夜に北極星が急に灯るわけでもない。

日々、小さなチャレンジを、他人から見ればチャンレジに見えないような、それでいて、明確な意思を、改善をするぞいうと前向きな心をもって、相手に敬意と好奇心をもってお話ししていけば、ちょっと楽しい時間が増えるんじゃないですかね。

まあ、しらんけど。ほんじゃ。
Google Colaboratory で Ollama & phi3 をシンプルに動かしてみる

## 背景
LangChain のあんな機能・こんな機能をあれこれ試していると、なかなかに生成 AI サービスの API コールが発生します。もちろん gpt-3.5 系などを使えば費用もそんなに嵩まないのですが、もう少し気兼ねなくあれこれ試す環境を用意できないものか。5月の連休中にあれこれ試した結果、一番お手軽さが優った Ollama & phi3 を Google Colaboratory でシンプルに動かすまでの手順の記録です。

## 環境
+ Google Colaboratory (無料版)
+ ランタイムのタイプ: T4 GPU

## 試し方
それぞれのサンプルコードを、Colaboratory のノートブックのコードセルにコピー & ペーストして実行してください。

まず、公式ページの Linux 用のインストール手順に従い install.sh を取得 & 実行します。

```python
!curl -fsSL https://ollama.com/install.sh | sh
```

https://ollama.com/download/linux

Ollama を起動し、phi3 をダウンロードして使えるようにします。

```python
!nohup ollama serve &
!ollama pull phi3
```

ここは次の Youtube 動画を参考にさせていただきました。creativaier さんに感謝です。

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

+ 量子化版(ファイルサイズ約 2.3 GB)をダウンロードしているので、時間もあまりかからずセルの実行が完了します
+ phi3 を llama3 に変えれば、llama3 も使えるようになります

LangChain の ChatOllama を使うためにライブラリをインストールします。

```python
!pip install langchain_community
```

次のコードを実行し、準備を整えます。

```python
from langchain_community.chat_models import ChatOllama
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

# 言語モデルを定義
llm = ChatOllama(model="phi3")

# プロンプトテンプレートを定義
template = "{input}"
prompt = ChatPromptTemplate.from_template(template)

# チェインの定義
chain = prompt | llm | StrOutputParser()
```

入力を与えて生成を実行します。

```python
print(chain.invoke({"input": "生成 AI を使う時のプロンプトを書くコツを教えてください。"}))
```

実行例:
```
以下に、AIプロントを作成する際に考慮すべきポイントとその実行方法を記します。プロンプトはAIが効果的に動作するための最良の入力であり、コミュニケーション、意思決定、習得や改善に役立つものとなります。
1. 明確性:
   - プロントは具体的であるべきです。例えば「写真分類アシスタント」や「天気予報AI」など、目的がわかります。
2. 複数の可能性を含める:
   - AIが複数の答えを提示できるようにします。たとえば、「日本史のトピックを紹介してください」であれば、戦国時代、平安時代、明治時代など複数のトピックが提示できます。
3. 自然言語処理に適したフォーマット:
   - 入力は自然体であるべきで、直接的かつ説得力を持っていることが重要です。例えば、「今日の天気は？」「私のスポーツ選手に関して教えてください」
4. ユーザーの課題に対するアシスタントとしての仕事を指定:
   - プロントは、AIがその課題にどのように対応できるか示すべきです。「質問回答」、「情報収集」、「タスク実行」などがあります。
5. バックログやフィードバックの挙動を定義:
   - ユーザーとの連続会話やアシストの評価を記録し、改善するためのデータを生成できるようになります。
6. エラーハンドリング:
   - AIがユーザーから不明瞭な入力を受け取った場合の対応方法を設定します。例えば、「どういう意味でしょうか？」と訊いてください。
以上のポイントに基づき、プロンプトを作成する際にはこれらを網羅的に取り入れることが重要です。AIの能力を最大限に引き出すために、複合的かつ実用的なプロンプトを定義しましょう。
```

ノートブック全体
![ColaboOllamaPhi3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535779/ba03d6f3-c26f-a949-baf2-4469213cfd5a.png)

## 雑感
LangChain & Llama.cpp も色々試してみましたが、Colaboratory で使う場合はコンパイルにそこそこ時間がかかるので、お手軽さではこちらに軍配が上がるかなと思います。

phi3 も 3.6B のパラメーター(おかげでモデルのファイルサイズも小さい)で結構使える印象です。あと、phi3 も llama3 もそこそこ日本語扱えますね。これも驚きの一つでした。 

自作 PC (Windows 11) でも同様の構成で動作し、LangChain の Agent や LangGraph をあれこれ試すことができました。
+ 2024/5/6 時点で LangChain の Components -> Chat models の OllamaFunctions には bind_tools も実装されていました(これが無いと Agent や LangGraph やるのがなかなかに難しい。。)
+ ただし、ここ数週間以内での更新のようで、pip install langchain_experimental で入れたライブラリだと OllamaFunctions 実行時にエラーになります
+ 回避策はあるのですが、ライブラリのコードを直接書き換える必要があるので、Colaboratory ではまだ試せていません

https://stackoverflow.com/questions/78404535/langchain-python-with-structured-output-ollama-functions

github のレポジトリ側のコードは更新されているので、あとは pypi 側の更新待ちのようです。
[ReviewAI 使用例] 新大久保 韓国料理店 まとめページ

# はじめに

レビュー分析AIサービスの ReviewAI (レビューアイ) を開発しています。
レビュー分析の例として、新大久保の韓国料理の人気店を取り上げていきます。
このページはそのまとめページです。

# 記事一覧

- [マッコリの物語](https://qiita.com/RetegyLink/items/e829c83c746fd5cee3ca)
- [松屋](https://qiita.com/RetegyLink/items/51406e5dcf750bb935f0)
- くるむ
- セマウル
- TEJI
- テジョンデ
- 名家
- ホンスチュクミ
- [チョクミドサ](https://qiita.com/RetegyLink/items/44bd15585268cc32ff4a)
- ヤンピョン ヘジャンク
- [コリア タッカンマリ](https://qiita.com/RetegyLink/items/b7011067b29b80cb67ea)
- でりかおんどる
- 味ちゃん
- オムニ食堂

# ReviewAI (レビューアイ)

弊社 RetegyLink が開発中のレビュー分析 AI です。
https://reviewai.next-seed.work/
試作版を公開中で、現在は
- [食べログ](https://tabelog.com/)
- [じゃらん](https://www.jalan.net/)
のレビューを分析できます。
アイヌ語の「方言間距離」を単語リストの主成分分析で3D可視化する

アイヌ民族財団[アイヌ語教材テキスト](https://www.ff-ainu.or.jp/web/potal_site/details/post.html)の単語リスト([千歳](https://www.ff-ainu.or.jp/teach/files/chitose_tyukyu.pdf#page=88)・[美幌](https://www.ff-ainu.or.jp/teach/files/bihoro_tyukyu.pdf#page=88)・[幌別](https://www.ff-ainu.or.jp/teach/files/horobetsu_tyukyu.pdf#page=88)・[静内](https://www.ff-ainu.or.jp/teach/files/shizunai_tango.pdf)・[十勝](https://www.ff-ainu.or.jp/teach/files/tokachi_tango.pdf)・[沙流](https://www.ff-ainu.or.jp/teach/files/saru_tango.pdf)・[石狩川](https://www.ff-ainu.or.jp/teach/files/ishikari_tango.pdf)・[カラフト](https://www.ff-ainu.or.jp/teach/files/karahuto_tango.pdf))をもとに、アイヌ語の「方言間距離」をbinary word vectorの主成分分析で3次元に圧縮し、Google Colaboratory上のplotlyで3D可視化してみた。

```
!pip install scikit-learn pdfminer plotly
import os,re,numpy
from sklearn.decomposition import PCA
from plotly.express import scatter_3d
d=[("千歳","chitose.txt","chitose_tyukyu.pdf"),
   ("美幌","bihoro.txt","bihoro_tyukyu.pdf"),
   ("幌別","horobetsu.txt","horobetsu_tyukyu.pdf"),
   ("静内","shizunai.txt","shizunai_tango.pdf"),
   ("十勝","tokachi.txt","tokachi_tango.pdf"),
   ("沙流","saru.txt","saru_tango.pdf"),
   ("石狩川","ishikari.txt","ishikari_tango.pdf"),
   ("カラフト","karahuto.txt","karahuto_tango.pdf")]
v=[]
for h,t,p in d:
  os.system(f"test -f {p} || curl --ciphers DEFAULT@SECLEVEL=1 -LO https://www.ff-ainu.or.jp/teach/files/{p}")
  if p.endswith("tyukyu.pdf"):
    os.system(f"test -s {t} || ( pdf2txt.py {p} | sed -e 1,/単語リスト$/d -e /発行年月/q > {t} )")
  else:
    os.system(f"test -s {t} || ( pdf2txt.py {p} | fgrep -v indd > {t} )")
  with open(t,"r",encoding="utf-8") as r:
    v.append(re.findall(r"[a-z=]+",r.read()))
w={j:i for i,j in enumerate(set(sum(v,[])))}
m=numpy.zeros((len(d),len(w)))
for i,k in enumerate(v):
  for j in k:
    m[i,w[j]]=1.0
v=PCA(n_components=3).fit_transform(m)
f=scatter_3d(x=v[:,0],y=v[:,1],z=v[:,2],text=[h for h,t,p in d],opacity=0.5,labels={"x":"","y":"","z":""},width=1600,height=1600)
q={"tickfont":{"color":"white"}}
f.update_scenes(xaxis=q,yaxis=q,zaxis=q)
f.show()
```

![ainu-wordlist.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428317/772fc529-655e-6b52-b84b-bfdcc8d0b99a.png)

PDF中の単語リストから、ローマ字のアイヌ語を取り出してword vectorに仕立てたのが、そこそこうまくいっているようだ。少なくとも[Szymkiewicz-Simpson係数を使う](https://qiita.com/KoichiYasuoka/items/51b1b196d8095c9fd3c3)より、いい結果に見える。さて、この手法を、服部四郎・知里真志保『[アイヌ語諸方言の基礎語彙統計学的研究](https://doi.org/10.14890/minkennewseries.24.4_307)』(民族學硏究, Vol.24, No.4 (1960年11月), pp.307-342)の19方言に適用するには、どこをどうしたらいいのかな。
[ReviewAI 使用例] マッコリの物語 [新大久保 韓国料理店]

# はじめに

レビュー分析AIサービスの ReviewAI (レビューアイ) を開発しています。
本記事ではレビュー分析の例として、新大久保の韓国料理の人気店を取り上げていきます！
[人気店の記事をまとめているページはこちらです。](https://qiita.com/RetegyLink/items/3d94852bf25a724a82cc)

今回は、マッコリの物語 の食べログに集まっているレビューを分析します。

## マッコリの物語

【新大久保駅5分】圧倒的高コスパ＆メニュー豊富な人気韓国料理店！

> 当店イチ押しメニューは超厚切り25mmの「厚切サムギョプサルセット」。名物「エビロールサムギョプサルセット」も肩を並べるほど人気です。ランチ限定「サムギョプサル食べ放題」や3品選べる「2,700円SET」も大好評！飲み放題も充実しています。店名の通りマッコリも豊富ですので、迷う方は4種類選べる「お試しマッコリカクテル」を♪専用iPadもご用意◎ご宴会、女子会、デートなど盛り上がること間違いなし♪

[食べログ](https://tabelog.com/tokyo/A1304/A130401/13121568/)

## ReviewAI (レビューアイ)

弊社 RetegyLink が開発中のレビュー分析 AI です。
https://reviewai.next-seed.work/
試作版を公開中で、現在は
- [食べログ](https://tabelog.com/)
- [じゃらん](https://www.jalan.net/)
のレビューを分析できます。

# レビュー分析

さっそくですが、こちらが分析結果です！
マッコリ・チヂミ・サムギョプサル・エビ（蝦）・チーズと
美味しそうな単語が並んでいますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3776808/f412bb54-17da-c45b-3af6-eeeaa7bd40ff.png)

## マッコリ

<font color=steelblue>**良い評価**</font>
- ビール込みだしマッコリも色々な味が楽しめるのがありがたい。
- どれもすごく美味しいー飲み放題のマッコリも飲みやすくて良かったです。
- 生マッコリのやかんはたっぷり飲めて最高！！
- マッコリ飲み比べもちょうどいいサイズでした。

## チヂミ

<font color=steelblue>**良い評価**</font>
- 食べ方も色々工夫されていて分かりやすい上に間違いない美味しさ♡海鮮チヂミやキンパ（キムチ海苔巻き）も◎一品のボリュームもたっぷりなので、大人数だと楽しめますね〜！！
- 5人いたのでチーズタッカルビやチヂミ、サムギョプサルなど沢山頼むことが出来ました。
- そして、前回も好評だったお餅チーズチヂミ餅のモチモチ感とチーズがベリーナイス少し物足りなかったのでサラダとプルコギサッパリとひて濃い味食べてとリピート出来るのがGOOD。
- コーンのチヂミもコーン好きには、良いですね。

<font color=chocolate>**黄色・橙色の評価**</font>
- エビロールサムギョプサル海鮮チヂミセットでヤンニョムチキンサラダボリューム多すぎて食べきれませんでした‥！

# サムギョプサル

<font color=steelblue>**良い評価**</font>

- 初モクサルはサムギョプサルよりあっさりしていて、でもお肉の旨みがしっかり感じれてとてもおいしかったです！！
- エビのサムギョプサルは初でしたがハマりました。
- もやしのナムルとキムチを一緒に鉄板で焼いてくれますが、お昼から目の前で焼いてくれるサムギョプサルを堪能できるのは気分的にとっても贅沢です。
- 昼から飲みたいのでサムギョプサルを一人前から頼めるのは助かります。

<font color=chocolate>**黄色・橙色の評価**</font>

- サムギョプサルランチにはご飯はついてないので、必要な方は別注文です。
- サムギョプサル　三枚肉なのにジューシーさがイマイチ。

## エビ (蝦)

<font color=steelblue>**良い評価**</font>
- エビのサムギョプサルは初でしたがハマりました。
- プリプリなエビとトロトロで濃厚なチーズの相性にハマってしまいます。
- エビやイカたっぷりで、なかなか豪華な一品。
- 海老好きな方はもちろんのごとく実はチーズとものすごく合います。

## チーズ

<font color=steelblue>**良い評価**</font>

- 厚みのあるサムギョプサルと餅チーズチヂミとチーズキンパを食べてお腹いっぱい大満足ですお店に入った時は、2700円セットと各自もう一品食べたい物を選ぼうと考えていましたが、小鉢も6種類付いてきたのでお得だし充分お腹いっぱいになりました！
- 確かにうまいチーズにくぐらせより美味しかったです！
- 海老にお肉が巻いてありますが、くどくなく、チーズはチェダーも混ざりかなりのトロトロ熱いうちに、たっぷりとつけてたべます✨

<font color=chocolate>**黄色・橙色の評価**</font>
- キンパは普通の食べたかったのに選択肢でチーズ選んだらチーズしか入ってなかった（ ; ; ）

## ReviewAI の改善点

エビを 蝦 と書くのはあまり一般的ではないので、わかりやすい表記を採用するようにしたいですね。

# おわりに

マッコリを飲みながら、チーズを絡めたエビのサムギョプサルが最高のようですね！

観点ごとの詳細を確認されたい方は、ぜひサイトにアクセスして確認してください！
レビュー分析AI の [ReviewAI](https://reviewai.next-seed.work/) は試作版を公開中です。
今回分析したつつじ亭の URL はこちらです。
```
https://tabelog.com/tokyo/A1304/A130401/13121568/
```

今後どんどん使いやすくしていく予定ですので、
ぜひ皆様の ReviewAI に関するご意見を[アンケート](https://docs.google.com/forms/d/e/1FAIpQLSc-yVTDeqqMc9GqM93BvzaYWCB6wyToesYj_wl8bhwKgw8LqQ/viewform?usp=sf_link)で教えてくださると幸いです。
AWS WAF

## はじめに
この記事はAWS SAA試験勉強のための、AWS WAFに関する知識のまとめです。

## AWS WAFとは
AWS WAFは、クロスサイトスクリプティング（XSS）やSQLインジェクションなどの攻撃を検出し、リクエストをブロックできるウェブアプリケーションファイアウォールサービスです。例えば、リクエストの送信元のヘッダー値またはIPアドレスに基づいて、アクセスをフィルター可能です。
「Web ACL」というアクセスコントロールリストで、IPアドレス、HTTPヘッダー、HTTP本文、URI文字列などに対してフィルタリングの条件を設定できます。

## 対応しているサービス
- Amazon CloudFront
- Amazon API Gateway
- ALB (<font color="red">**NLBとCLBには対応していません**</font>)
- AppSync GraphQL API
- Cognito ユーザプール


## GeoMatch条件
AWS WAFには、GeoMatch条件を使用して国ごとにアクセスを許可またはブロックする機能があります。
例えば、Webサービスへのアクセスを日本国内のみに制限するにはWeb ACLで日本国以外のGeoIPをすべて拒否すればOKです。

## WAF Referer制限

Amazon S3バケットにCloudFrontディストリビューションによるコンテンツ配信を構成することで、AWS WAF を利用してReferer制限を実装して、外部からのURLリンクが利用できないようにできます。

## できないこと

AWS WAFは<font color="red">**インバウンド拒否ルール**</font>を設定して特定のIPアドレスをブロックする設定ができません。AWS WAFは<font color="red">**ウェブACL**</font>を作成して、特定のIPアドレスからのアクセスを拒否することができます。
『制御系解析・設計における数値計算／数式処理ソフトウェアの活用』 特集号のサポートページ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/32df3c7a-4c19-9c41-47c1-677703f825df.png)

　このサポートページでは，[<b><font color="#E84746">システム制御情報学会</font></b>](http://www.iscie.or.jp/) の学会誌である「システム/制御/情報」の特集号

* [<b><font color="#E84746">『制御系解析・設計における数値計算／数式処理ソフトウェアの活用』 （55 巻 5 号，2011 年）</font></b>](https://www.jstage.jst.go.jp/browse/isciesci/55/5/_contents/-char/ja)

に掲載された，6 編の総説・解説記事

|　　| 著者・題目（PDF ファイルはフリーアクセスです！） | 配布ファイルの説明 |
|:-----------:|:-----------|:------------|
|[1]|川田昌克：[<b><font color="#E84746">制御系解析・設計における数値計算／数式処理ソフトウェアの活用</font></b>](https://doi.org/10.11509/isciesci.55.5_159)，システム/制御/情報，Vol. 55，No. 5，pp.159-164 (2011)|[説明](https://qiita.com/Carter/items/917da72afd390f519bf4)|
|[2]|川田昌克，蛯原義雄：[<b><font color="#E84746">LMI に基づく制御系解析・設計</font></b>](https://doi.org/10.11509/isciesci.55.5_165)，システム/制御/情報，Vol. 55，No. 5，pp.165-173 (2011)|[説明](https://qiita.com/Carter/items/ff141442c5d2e291a715)|
|[3]|市原裕之：[<b><font color="#E84746">二乗和に基づく制御系解析・設計</font></b>](https://doi.org/10.11509/isciesci.55.5_174)，システム/制御/情報，Vol. 55，No. 5，pp.174-180 (2011)|未完|
|[4]|和田孝之，藤崎泰正：[<b><font color="#E84746">ランダマイズドアルゴリズムによるロバスト制御系解析・設計</font></b>](https://doi.org/10.11509/isciesci.55.5_181)，システム/制御/情報，Vol. 55，No. 5，pp.181-188 (2011)|未完|
|[5]|管野政明：[<b><font color="#E84746">数式処理を用いたパラメータを有する線形制御系の解析</font></b>](https://doi.org/10.11509/isciesci.55.5_189)，システム/制御/情報，Vol. 55，No. 5，pp.189-195 (2011)|未完|
|[6]|藤本健治：[<b><font color="#E84746">数式処理を用いた非線形制御系の解析・設計</font></b>](https://doi.org/10.11509/isciesci.55.5_196)，システム/制御/情報，Vol. 55，No. 5，pp.196-203 (2011)|未完|


の理解を深めることを目的として，下記のものを公開しています．

* MATLAB や Maple のプログラムソースとその補足説明

* LMI とその周辺に関連するフリーウェア（SDP ソルバ MOSEK, SeDuMi, SDPT3，LMI パーサ YALMIP, CVX およびランダマイズドアルゴリズム用のパーサ RACT）のインストール方法

　MATLAB や Maple のプログラムソースは，著者の方々のご好意により，公開させていただいております （[1]-[4] の補足説明は川田が記述し，著者の方々に内容を確認していただいたものです）．
 
　公開する MATLAB や Maple のプログラムソースの利用，改変，再配布は自由に行っていただいて結構です． ただし， ここで公開した内容についての動作保証およびテクニカルサポート， 発生した損害の責任は，本学会，著者ともに一切行いませんので，ご了承下さい．

　このサポートページが本特集号に興味を持った読者のお役に立てば幸いです．

$\hspace90mm$川田 昌克

:::note warn
追記 (2024/04/27)
発行から随分と時が経ちましたので，MATLAB 関連のファイルにつきましては，現在のバージョン (R2024a) でも動作するように修正を加えています．
:::