OmniAICreator/Qiita-1.07M huggingface dataset:
pi picoでmicropython その31

# 概要
picoでmicropythonやってみた。
練習問題やってみた。

# 練習問題
forthインタープリターを実装せよ。
forthで数9を4個つかって1から15までの数を表す式を実行せよ。

# 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/6de97556-d00b-3431-a47e-65e094a4632c.png)


以上。
AWSコンソールで編集しようとして「Network Failture」が出たらブラウザを変えてみよう

# 起きたこと
AWSコンソールからAmazon API Gateway（REST API）のリソースのパラメータ値を変更しようとチェックを押したら
画面上に「Network Failture」と表示され更新できない。。
バリデートエラーでもなさそう。

# 対応したこと
AWSコンソールをChromeで開いていたのですが、Safariで開き直したところ成功しました。
（Firefoxだとダメでした）
はっきりとした原因は分からないが、Cookieの問題もありそう？
とりあえず直したい人の役に立ったら幸いです。
[UE5]エンジンビルドのときプラグインのマイナーバージョンが異なるとCookに失敗した

# 概要

通常のEpic LauncherのUE5で開発していたアプリを、OculusのUE5をエンジンビルドしたもので起動したときに、パッケージングに失敗するということがありました。

結論から言うと、使用していたプラグインのマイナーバージョンが異なっていたことが原因でした。

エンジンビルドする方々の中ではもしかすると常識的なことなのかもしれませんが、Launcherのエンジンでは発生したことがなくて個人的には結構ハマったのでメモを残しておきます。

# 環境

OS：Windows 11
元々開発していたバージョン：UE5.1.0 → UE5.1.1（Epic Launcherからダウンロードしたものを使用、開発途中でUE5.1.0 → UE5.1.1にマイナーアップデートした）
パッケージングに失敗したバージョン：[oculus-5.1.1-v50 @Commit 05a1fbcb417a45cfe011326de4abf1b79fa7a680](https://github.com/EpicGames/UnrealEngine/commit/88752f398ff95253abdceedab15d867f85875f7f)

# 発生した現象

OculusのUE5でプロジェクトを起動したところ、バージョン違いのプラグインの数だけ下記のようなメッセージが表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/db2c9a4a-9055-e00b-191e-6a466d8cf621.png)

ここで「はい」を選択してUEエディタを起動すると、VRプレビューでは問題なく起動したのですが、パッケージングで失敗しました。

パッケージングでは下記のエラーメッセージが出て失敗しました。

```Log.txt
ERROR: Cook failed.
       (see C:\Users\[ユーザー名]\AppData\Roaming\Unreal Engine\AutomationTool\Logs\C+Program+Files+Epic+Games+UE_5.1\Log.txt for full exception trace)

```

Cookで失敗しているのですが、ログを見てもそれらしいエラーが出ていないので困りました。

上記Log.txtと同じフォルダ（C:\Users\ [ユーザー名]\AppData\Roaming\Unreal Engine\AutomationTool\Logs\C+Program+Files+Epic+Games+UE_5.1\）にあるCookのログファイル（Cook-YYYY.MM.DD-hh.mm.ss.txt）を確認してみると、プラグインが原因であることが分かりました。

```Cook-YYYY.MM.DD-hh.mm.ss.txt
Message dialog closed, result: Ok, title: Message, text: Plugin '[プラグイン名]' failed to load because module '[プラグイン名]' could not be found.  Please ensure the plugin is properly installed, otherwise consider disabling the plugin for this project.
```

# 対応策

.upluginのEngineVersionで違うマイナーバージョンを指定しているプラグインを修正しました。
（EngineVersionの記載自体を削除してもおそらく大丈夫です。）

修正前
```[プラグイン名].uplugin
"EngineVersion": "5.1.0",
```

修正後
```[プラグイン名].uplugin
"EngineVersion": "5.1.1",
```

# 所感

Launcherのエンジンではマイナーバージョン違いで失敗したことがなかったので、ここが原因だということに気づくまでに時間がかかってしまいました。
プロジェクトを開いたときに出てきたメッセージをちゃんと読んでおけばよかったです。
とりあえず「はい」を選んでみてVRプレビューで動いたからいいだろうと判断したのは失敗でした。。
pi picoでmicropython その30

# 概要
picoでmicropythonやってみた。
練習問題やってみた。

# 練習問題
ニューラルネットワークでxorを回帰せよ。

# 方針
windowsからc#のプログラムランチャーで、結果を得る。

# 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/8b66c31d-00a8-bce2-a112-43f6570004be.png)


以上。
プリザンターのサイト作成をクライアントスクリプトを用いて実現する

# はじめに

クライアントスクリプトを用いてサイトを自動作成するという機能です。こちらは多くのサイト作成が必要になる場合はとても有用なものではないかと思われます。いちいちサイトを作るのは面倒なのでこちらのサンプルコードを使えば一発でサイトを作ることができます。承認ボタンをクリックしたときにサイトを作成するという機能は企業のワークフローにはよくあることなのかなと思っています。

# 設定

承認ボタンを押した際にサイト作成を実施します。その際に、通常のサイト作成スクリプトでは実行したログインユーザーに権限が付与されますが、今回は別で指定している管理者に権限を付与するという内容です。

# ソースコード

```Javascript
    var siteData = $p.apiCreateSite({
        // サイト作成場所のサイトID(0を指定するとトップが指定される)
        id: 0,
        data: {
            ApiVersion: apiVersion,
            TenantId: tenantId,
            Title: siteName,
            ReferenceType: referenceType,
            Permissions: [
                // 管理者権限をサイト管理者に付与
                `User,${$userId},511`
            ],
            DisableSiteCreatorPermission: true,
            SiteSettings: {
                Version: version,
                ReferenceType: referenceType,
                GridColumns: [
                    tableType,
                    'TitleBody',
                    'Comments',
                    'StartTime',
                    'CompletionTime',
                    'WorkValue',
                    'ProgressRate',
                    'RemainingWorkValue',
                    'Status',
                    'Manager',
                    'Owner',
                    'Updator',
                    'UpdatedTime'
                ],
                EditorColumnHash: {
                    General: [
                        tableType,
                        'Ver',
                        'Title',
                        'Body',
                        'StartTime',
                        'CompletionTime',
                        'WorkValue',
                        'ProgressRate',
                        'RemainingWorkValue',
                        'Status',
                        'Manager',
                        'Owner',
                        'Comments'
                    ]
                }
            },
        },
        done: function (data) {
            // レコードを作成する関数の呼び出し
            $p.ex.apiCreate(masterTableId, siteData, siteName);
        },
    });
```

# 工夫

今回の実装でのナレッジは、サイト作成時に別で指定したユーザーをサイト管理者にする方法です。今までは、サイトを作成したログインユーザーがサイトの管理者になっていました。今回のキーとなる実装は下記です。  

```Javascript
Permissions: [
    `User,${$userId},511`
],
DisableSiteCreatorPermission: true,
```

今回の機能では、ユーザーに権限を付与しましたが組織やグループにも付与可能です。その場合、Userを修正すれば付与できます。また、「DisableSiteCreatorPermission」を「true」にすることで実行した人に権限は付与ません。もちろん、「false」にすれば実行した人もサイト権限を持ちます。そもそも、「DisableSiteCreatorPermission」を付与しないことで「false」と同じ動きするので、「false」にしなくてもよいと思いますね！  
また、idに「0」を指定するとトップにサイトが作成されます！

# 最後に

今回はプロジェクト内で作成したソースのうちナレッジとして記録を残しておきたいもののみを抜粋しました。クライアントスクリプトを用いてのユーザー作成やサイト作成のナレッジが少ないため、もしかしたら社内でも役に立つ記事になるのではないかと思います。
irisデータセットで主成分分析

pythonノートブックを使ってirisデータセットの主成分分析を行ってみました。
まずはライブラリを用意します。
```Python
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA

import pandas as pd
import matplotlib.pyplot as plt
```
irisデータセットを読み込み、データフレームに整えます。
```Python
iris = load_iris()
df = pd.DataFrame(data = iris.data, columns=iris.feature_names)
df['label'] = iris.target
df.head()
```
![スクリーンショット 2023-04-06 140142.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3161396/48245b6c-731d-819b-77a9-162f9bdd2b16.png)

ここまででデータの準備が整いましたので、主成分分析に取り掛かっていきます。
```Python
pca = PCA(n_components=2)
x = df.iloc[:, 0:4]
pca.fit(x)
pca.components_.T
```

```datastudio
array([[ 0.36138659,  0.65658877],
       [-0.08452251,  0.73016143],
       [ 0.85667061, -0.17337266],
       [ 0.3582892 , -0.07548102]])
```
scikit-learnを使えば計算自体はすごく簡単でPCAクラスをインスタンス化してfitメソッドを呼び出すだけです。

変換後の結果はcomponents_フィールドにアクセスすれば確認することができます。


うまく変換できているか2次元空間にプロットして確認してみます。
変換もtransformメソッドを呼び出すことで簡単に変換することができます。
```Python
X = pca.transform(x)
plt.scatter(x=X[:, 0], y=X[:, 1], c=iris.target)
```
![スクリーンショット 2023-04-06 142103.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3161396/95491e3e-b5ca-d57a-471e-6ad4e7f49f38.png)
GitHubの個人アカウントとGitHub Enterpriseのアカウントを同じPCで併用する場合のGit環境の設定

# Motivation

お仕事でGitHub Enterpriseで作成されたアカウントを使うことになりました。一方でもちろんGitHubの個人アカウントを持っています。一つの端末でこれら二つを併用したい場合の環境構築で時間を費やしたので、ドキュメンテーションします。

## 前提

- GitHubの個人アカウントを持っている
- GitHub Enterpriseのアカウントを持っている
- GitHub EnterpriseがGitHubにホストされている
- ローカルでGitを使っている

## 環境構築の順序のまとめ

1. GitHubの個人アカウント用のSSHキーを作成する
1. GitHubの個人アカウントでSSHキーを登録する
1. ssh config に、個人アカウントにSSHでアクセスするときの設定を書く
1. GitHubの個人アカウントでアクセストークンを払い出す
1. Git のオリジンを 3 で設定したHostを使うように設定する
1. GitHubの個人アカウントに属しているリポジトリでは、個人アカウントで払い出したアクセストークンを使用する
1. 1~6までをGitHub Enterpriseで繰り返す

### GitHubの個人アカウント用のSSHキーを作成する

SSHキーをローカルで作成してください。[こちら](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent)にGitHub公式のドキュメントがあります。

### GitHubの個人アカウントでSSHキーを登録する

GitHubにサインインした状態で[設定ページ](https://github.com/settings/profile)にある、`SSH and GPG keys` というセクションをクリックしてください。`New SSH key` をクリックすると登録画面が表示されます。タイトルは任意です。この作業も[こちら](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account)にGitHubの公式のドキュメントがあります。

### ssh configに、個人アカウントにSSHでアクセスするときの設定を書く

`~/.ssh/config` に個人アカウントにSSHでアクセスするときの設定を書きます。

```text
Host personalgit
    HostName github.com
    User git
    IdentityFile ~/.ssh/personal_git.pub
    IdentitiesOnly yes
```

### GitHubの個人アカウントでアクセストークンを払い出す

ローカルのGitからGitHubにアクセスするときの認証を行うためのアクセストークンを払い出します。これも[こちら](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)にGitHub公式のドキュメントがあります。

### Git のオリジンを 3 で設定したHostを使うように設定する

GitでGitHubにアクセスするときに、SSHエージェントが3で施した設定に基づいてアクセスできるようにするため、リポジトリのオリジンを以下のように設定します。

```text
git remote set-url origin personalgit:your-user-name/repository-name.git
```

### GitHubの個人アカウントに属しているリポジトリでは、個人アカウントで払い出したアクセストークンを使用する

GitでGitHubにアクセスするときに、払い出したアクセストークンを使うようにしてください。これも[こちら](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/testing-your-ssh-connection)にGitHub公式のドキュメントがあります。

### GitHub Enterpriseのアカウントの設定

基本的には1~6の繰り返しになります。

#### ssh config

`~/.ssh/config` には以下の設定を追加します。

```text
Host workgit
    HostName github.com
    User git
    IdentityFile ~/.ssh/work_git.pub
    IdentitiesOnly yes
```

##### Gitのオリジン

以下のように設定します。

```text
git remote set-url origin workgit:your-organization/repository-name.git
```

## GitHub CLIを使う場合

今日2023/04/06時点でGitHub CLI自体には複数のアカウントをサポートする機能が、[こちら](https://github.com/cli/cli/issues/326)を見る限りなさそうです。が、1Passwordを使うことによって実現できます。[こちら](https://developer.1password.com/docs/cli/shell-plugins/github/#optional-configure-multiple-github-accounts)に1Passwordの公式ドキュメントがあります。

これを使用した場合、Gitの設定についても1Passwordの公式ドキュメントに記載があります。このドキュメントは一部引用しています。[こちら](https://developer.1password.com/docs/ssh/agent/advanced/#use-multiple-github-accounts)です。
[Visualforce] Google Charts使用方法

レポートやダッシュボードでやりたいことが実現できないときに役立つかも。
サイトでグラフ等を公開したいが、ライセンスがレポートダッシュボード使用不可のときなどにも

## 使用準備
`<head>`内でライブラリを読み込む
```javascript
<apex:includeScript value="https://www.gstatic.com/charts/loader.js"/>
<script>
  google.charts.load('current', {packages: ['corechart']});
  google.charts.setOnLoadCallback(drawChart);
  // 省略
</script>
```
## グラフの描画
javascript部分に以下を追加
オプションでタイトル、凡例の表示場所や、色などを設定できる
```javascript
function drawChart() {
        var data = google.visualization.arrayToDataTable([
          ['Task', 'Hours per Day'],
          ['Work',     11],
          ['Eat',      2],
          ['Commute',  2],
          ['Watch TV', 2],
          ['Sleep',    7]
        ]);

        var options = {
          title: 'My Daily Activities',
          is3D: true,
        };

        var chart = new google.visualization.PieChart(document.getElementById('piechart_3d'));
        chart.draw(data, options);
      }
```
Visualforceの`<body>`にはグラフ描画用のタグを用意しておく
```html
<body>
    <div id="piechart_3d" style="width: 900px; height: 500px;"></div>
</body>
```

## Apexから値を渡す方法
Apexからのデータを受け取ってグラフを描画することも可能

```apex
    public String incomeJson {get;set;} // jsがアクセスする変数

    public void init(){
        Map<String, Integer> incomeMap = new Map<String, Integer>();
        incomeMap.put('2023-01', 355000);
        incomeMap.put('2023-02', 284000);
        incomeMap.put('2023-03', 213000);
        incomeMap.put('2023-04', 284000);
        // JSONの形に変換
        incomeJson = JSON.serialize(incomeMap);
    }
```
javascriptでの受け取り
```javascript

            var dataMap = JSON.parse('{!incomeJson}');
            var result = [['年月','数値']];
            Object.keys(dataMap).forEach(function(data) {
                    result.push([data,contactMap[data]]);
            })

```
javascriptで作成した配列の`result`を描画個所のDatatableに渡す

## まとめ
数年分のデータをグラフにすると横長になってしまうため、
1年ごとに表示したかったのが[Google Chartsのガイド](https://developers.google.com/chart/interactive/docs?hl=ja)がわかりにくくjavascriptで実装。
よい方法があるなら知りたいところです

## 参考

https://developers.google.com/chart?hl=ja
SendKeys　でメニューを開く時がなんか変。2文字目からしか受けてくれない。

UIAutomationで色々やっているのですが、
アプリの上に並んでいるメニューが動かない。
Alt-F O とキーボードで空けられるメニューが
sendkeys "%FO"で開かず、
Alt-O のところが開いてしまう。

・・・イロイロ検索したら、
%N　で通知領域がうんたら、という文言が目に入ったので、
もしかして
と
"%N"　"FO"　で開いた。
なんだこれ。。。
Googleデータアナリティクス：SMART フレームワーク

# はじめに

本記事は、Googleデータアナリティクスのプロフェッショナル認定証のプログラムより、参照させて頂いています。興味を持った方は、是非受講してみてください。

https://www.coursera.org/professional-certificates/data-analytics-japanese

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/f218c6bc-27a9-6aa7-4dfa-8e63bd3928b7.png" width="800">

# 正しい問いかけ

今日、さまざまな業界で多くの企業が、急速な変化と不確実性に対処しています。老舗の企業でさえも、新しいことを取り入れ、次に何が起こるかを見極める必要に迫られているのです。そのために必要なのが「問いかけ」です。正しい問いかけをすることで、多くの企業が望む革新的なアイデアにつなげることができます。

データ分析も同じです。どんなに多くの情報を持っていても、どんなに高度なツールを使っていても、正しい問いかけから始めなければ、データは多くを語ってはくれません。いわば大量の証拠を持っている刑事が、重要な容疑者にそのことについて尋ねないようなものです。  

ここでは、効果的な問いかけの方法と、避けたい問いかけについてもご紹介します。

# 高い効果が見込める問いかけを作るための「SMART フレームワーク」

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/9ab405c6-3cf4-0681-c2bb-5517c3adf4af.png" width="700">

### <font color="MediumBlue">具体的な問いかけ</font>

これは、シンプルで重要な、 1 つのトピック、または密接に関連する いくつかのアイデアに焦点を当てたものです。 これにより、調べたいことに関連した 情報を収集することができます。 1 つの要素に絞って問いかけてみましょう。 

- NG：「最近の子どもたちは十分に運動をしていますか？」 
- OK：「推奨されているとおり 週に 5 日 60 分以上の運動をしている 子供の割合はどのくらいか？」

### <font color="MediumBlue">測定可能な問いかけ</font>

これは、 その結果を数値化して評価することができます。 

- NG：「なぜ最近投稿したこの動画は流行ったのか？」 
- OK：「その動画を投稿した最初の週に、 ソーシャルチャンネルで何回共有されたか？」

### <font color="MediumBlue">行動指向の問いかけ</font>

これは、変化を促します。 課題解決とは、現在の状態を見て、 それを理想の未来の状態に変える方法を 考えることだと覚えておくとよいでしょう。 行動指向の問いかけは、理想の未来に 到達するためのステップなのです。 

- NG：「どうすればお客様に 製品パッケージをリサイクルしてもらえるか？」 
- OK： 「どのようなデザインにすれば、 よりリサイクルしやすくなるか？」 

### <font color="MediumBlue">関連する問いかけ</font>

これは、 解決しようとしている課題にとって重要であり、 意義があるものを指します。 例えば、絶滅危惧種のカエルに関する課題に 取り組んでいるとしましょう。 

- NG：「なぜパインバレンズのアマガエルが消え始めた ことが課題なのか？」
- OK： 「1983 年から 2004 年の間に ノースカロライナ州ダーラムで どのような環境要因が変化し、 サンドヒルズ地域からパインバレンズの アマガエルがいなくなったのか？」 

### <font color="MediumBlue">時間制約な問いかけ</font>

これは、 調査対象期間を指定します。 ここでの調査期間は、 1983 年から 2004 年までです。 これにより、可能性の幅が狭まり、 データ アナリストは関連するデータに 集中することができます。

# 避けたい問いかけとは

#### <font color="Darkcyan">誘導尋問のような問いかけ：回答者が特定の回答しかできない</font>

- ***例： この商品は高いと思いますよね？***

このような問いかけは質問の中に答えを示唆しているため、誘導尋問といえます。より良い問いかけの例としては「この製品に関するあなたの意見をお聞かせください 」などが挙げられます。こうすることで価格だけでなく、使い勝手、機能、付属品、色、信頼性、人気など、より多くの回答が得られるでしょう。課題が価格に焦点を当てているのであれば

- ***「この製品の価格（または価格帯）がいくらくらいなら購入したいですか？」***

といった問いかけもできるでしょう。このような問いかけであれば、測定可能かつさまざまな回答が得られます。

#### <font color="Darkcyan">クローズドエンド（選択式）の問いかけ：一言または簡潔な回答しか得られない</font>

- ***例：トライアルには満足していただけましたか？***

このような問いかけは、回答に広がりのないクローズドエンド型の問いかけといえます。これでは回答者からは一言しか得られず、あまり有益な情報にはなりません。より良い問いかけの例としては

- 「トライアルしてみて、この製品についてどんなことを感じましたか」***

などが挙げられます。こうすることで「よかった」以外の詳細な情報を提供してもらうことができます。

#### <font color="Darkcyan">漠然とした問いかけ：具体的でない、またはコンテキストがわからない</font>

- ***例：このツールはあなたに合っていますか？***

この問いかけは、コンテキストがなく漠然としすぎています。ねらいは、新しいツールとそれに代わるものを比較することでしょうか？これだけではわかりません。改善例としては、

- ***「データ入力に関して、新しいツールは古いツールと比較して速いですか、遅いですか、それとも同じぐらいですか？もし速い場合、どれくらいの時間が節約できましたか？遅い場合、どれだけの時間をロスしましたか？」***

などが挙げられます。これらの問いかけは、データ入力という文脈があるうえ、かかった時間という測定可能な回答も得ることができます。

# 公平性

公正さとは、問いかけが偏見を生んだり、 助長したりしないかを指します。 
- 例えば、ある科学館を訪れた人に 満足度調査を行うとします。 そのアンケートで「私たちの展示物の中で 最も気に入っているものは？」と聞くと 展示物を気に入った前提になってしまいます。 そうかどうか、わかりませんよね。 

公平性とは、 誰もが納得できる問いかけをすることです。 問いかけの内容は、明確で、 誰にでもわかりやすい 表現であることが重要です。 不公平な問いかけをすると、データアナリスト としての仕事がやりにくくなります。 信頼できるフィードバックが得られず、 本当に価値のあるインサイトを 得る機会を逃してしまうのです。
Android基礎


## アプリ基礎

AndroidDevelopersのアプリ基礎を読んだことがなかったのでまとめた。
抜粋しているため、詳しくは[こちら](https://developer.android.com/guide/components/fundamentals?hl=ja)。

###### AndroidSDKツール

コードをデータやリソース ファイルと一緒に APK（Android パッケージ）にコンパイルします。**.apk** という接尾語の付いたアーカイブ ファイルです。

#### Androidのセキュリティ機能

Androidアプリはそれぞれセキュリティサンドボックス内で動作し、以下のセキュリティ機能により保護されている

- 各アプリがそれぞれ異なるユーザーになる
- デフォルトでが一意のLinuxユーザーIDが割り当てられる。アプリに割り当てられたユーザーIDのみがアプリ内のすべてのファイルにアクセスできる
etc...

Android システムには ***「最小権限の原則」*** が適用されています。つまり、デフォルトでは各アプリにコンポーネントの動作に必要な分だけのアクセス権が与えられます。これにより、パーミッションの与えられていないシステムの部分にアプリはアクセスできないという非常に安全性の高い環境が作り出されます。ただし、アプリが他のアプリとデータを共有したり、システムのサービスのアクセスすることもできます(同一のLinuxIdを共有、権限のリクエスト)。

#### アプリのコンポーネント

アプリのコンポーネントは Android アプリに不可欠な構成要素です。各コンポーネントは、システムやユーザーがアプリに入るエントリ ポイントになります。一部のコンポーネントは他のコンポーネントに依存しています。

アプリのコンポーネントには 4 つのタイプがあります。気になるものを抜粋して説明します。

- アクティビティ
- サービス
- ブロードキャスト レシーバ
- コンテンツ プロバイダ

###### ブロードキャストレシーバー
ブロードキャスト レシーバは、通常のユーザーフローを外れて、システムがアプリにイベントを配信できるようにするコンポーネントです。これにより、アプリはシステム全体のブロードキャスト アナウンスに応答できます。ブロードキャスト レシーバは明確に定義されたアプリへのエントリであるため、システムは実行中でないアプリに対してもブロードキャストを配信できます。したがってアプリが、たとえば、近づいているイベントについてユーザーに知らせる通知を投稿するためのアラームをスケジューリングすることができます。

### マニフェストファイル

アプリはすべてのコンポーネントをこのファイルで宣言し、アプリ プロジェクト ディレクトリのルートにこのファイルを置く必要があります。マニフェストはアプリのコンポーネントを宣言する以外に、次のようにさまざまなことを行います。

- インターネット アクセスや、ユーザーの連絡先への読み取りアクセスなど、アプリに必要なユーザー パーミッションを識別する。
- アプリが使用する API に基づいて、アプリが必要とする最小 API レベルを宣言する。
- カメラ、Bluetooth サービス、マルチタッチ スクリーンなど、アプリで使用されるか必要とされるハードウェア機能やソフトウェア機能を宣言する。
- Google マップ ライブラリなど、アプリにリンクする必要のある API ライブラリ（Android フレームワーク API は除く）を宣言する。


以下の要素を使用して、アプリのすべてのコンポーネントを宣言する必要があります。
- \<Activity>要素（アクティビティの場合)
- \<service>要素　(サービスの場合)
- \<receiver>要素 (ブロードキャストレシーバーの場合)
- \<provide>要素 (コンテンツプロバイダの場合)

ソースに含まれていても、マニフェストで定義されていないアクティビティ、サービス、コンテンツ プロバイダは、システムからは見えないため、実行されることはありません。ただし、ブロードキャスト レシーバはマニフェストで宣言することもできますし、BroadcastReceiver オブジェクトとしてコードで動的に作成し、registerReceiver() を呼び出すことでシステムに登録することもできます。

###### アプリの要件を宣言する

アプリに必要な機能を搭載していない端末にアプリをインストールしてしまわないよう、アプリがサポートする端末のタイプについてプロファイルで明確に定義し、マニフェスト ファイルで端末の要件やソフトウェア要件を宣言しておくことが重要です。

たとえば、あなたのアプリがカメラを必要とし、Android 2.1 で導入された API（API レベル 7）を使用している場合、次の例のようにマニフェスト ファイルでそれを要件として宣言しなければなりません。

```
<manifest ... >
    <uses-feature android:name="android.hardware.camera.any"
                  android:required="true" />
    <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" />
    ...
</manifest>
```
この例では、カメラのない端末や、Android バージョンが 2.1 未満の端末は、Google Play からあなたのアプリをインストールすることができません。ただし、アプリでカメラを使用するが、それが必須ではないということを宣言することもできます。この場合、アプリで ***required 属性を false*** に設定し、端末にカメラがあるかどうかをランタイム時に確認して、必要に応じてカメラ機能を無効にする必要があります。
PayaraでのX-Frame-Optionsの設定方法

# X-Frame-Optionsとは

X-Frame-Optionsは、Webサイトが他のWebサイト内に埋め込まれたり、iframeやframeで表示されたりすることを防ぐためのHTTPレスポンスヘッダーです。このヘッダーを設定することで、Webサイトは他のWebサイトやアプリケーションからのクリックジャッキング攻撃を防止することができます。X-Frame-Optionsヘッダーは、ブラウザがサーバーからのレスポンスを受け取ったときに確認されます。

Webサイトのセキュリティを向上させるために、X-Frame-Optionsヘッダーを設定することをお勧めします。

# X-Frame-Optionsヘッダーの設定値

### DENY
他のWebサイトからの表示を完全に拒否する設定。

### SAMEORIGIN
同じドメインからの表示を許可する設定。

### ALLOW-FROM (+ uri)
特定のURIからの表示を許可する設定。

# PayaraでのX-Frame-Optionsの設定方法

※Paraya5での設定方法です。


1. Payaraにログインします。

2. 左のペインから[Configurations] → [server-config]を選択します。

    <img width="25%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323069/2aade307-845e-ef0e-44e0-157f17b8880b.png">
    
3. さらに[Network Config] → [Network Listeners]を選択し、Portなどを基にX-Frame-Optionsを設定したいアプリケーションを選択します。
    
    <img width="60%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323069/d3ca10a0-f401-d26e-0e3b-d7dcf7c5ef2c.png">
    
4. [HTTP]タブを選択します。

5. 下方にあるXFrame OptionsのチェックボックスでON/OFF設定をします

    <img width="90%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323069/65dd2663-09db-1179-fab2-58defb0e04ef.png">

6. 上方にスクロールして[save]をクリックします。

7. [New values successfully saved.]が表示されたら設定完了です。

    <img width="90%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323069/a1572a5f-c31b-9b01-7edf-296e868a3d10.png">
プリザンターで入力されたユーザーIDをもとにサーバースクリプトでユーザー情報を取得する

# はじめに

こんかいの実装は少しニッチかもしれません。  
今回の記事ではプリザンターのテーブル上でレコード内の分類項目にユーザーIDを入力したら、自動でユーザー情報を同レコードに転記するという内容です。

# 設定

存在しているユーザーを対象にしています。  
分類DにユーザーIDを入力し、フォーカスが外れたときに同レコードの分類EにログインID、タイトルに名前、分類Fに組織コード、分類Gにメールアドレスを転記します。

# ソースコード

```Javascript
try {
    // マスターテーブルのサイトID
    let siteId = XXXX;
    // 「ClassD」(=ユーザーID)項目のフォーカスが外れた際の処理
    if (context.Forms.ControlId() === 'Results_ClassD') {
        // 「ClassD」に入力されたIDをもとにユーザー情報を取得
        const user = users.Get(parseInt(model.ClassD));
        // ユーザー情報が存在した際の処理
        if (user) {
            // JSON形式で「ClassD」に入力された値を指定
            let data = {
                View: {
                    ColumnFilterHash: {
                        ClassD: '' + model.ClassD + ''
                    }
                }
            };
            // サイトから入力されたユーザーIDをもとにレコードを特定
            let results = items.Get(siteId, JSON.stringify(data))
            // 取得した数分処理を反復
            for (let result of results) {
                // 「ClassE」にログインIDを設定
                model.ClassE = result.ClassE;
                // 「Title」に名前を設定
                model.Title = result.Title;
                // 「ClassF」に組織コードを設定 
                model.ClassF = result.ClassF
                // 「ClassG」にメールアドレスを設定
                model.ClassG = result.ClassG
            }
        }
    }
} catch (e) {
    context.Log(e.stack);
}
```

# 解説

今後のナレッジとしては下記の条件式です。

```Javascript
context.Forms.ControlId() === 'Results_ClassD'
```

これによって、サーバースクリプトでクライアントスクリプトのような実装ができることを知りました。今回の実装ではこちらのみが真新しい技術です。

# 最後に

今までの記事では(個人的に)真新しい内容が中心でした。これからは既存知識+ α や既存知識の応用の内容が主たる内容になるかと思います。個人としてのナレッジの蓄積と会社としてのナレッジの蓄積、そして誰かの役に立てばという思いで記事を投稿していこうと思っていますので、よろしくお願いいたします。
WindowsでGPT-3を使った対話型AIと音声読み上げを実現する方法

## はじめに

この記事では、OpenAIのGPT-3を使って対話型AIを作成し、WindowsでそのAIからの返答を音声で読み上げる方法を紹介します。Pythonを使用し、GPT-3 APIと`pyttsx3`ライブラリを活用して実装していきます。

実装した理由としては、ChatGPTのAPIを使った簡単なアプリを開発してみたかったからです。

## 準備

まず、必要なライブラリをインストールしましょう。

```bash
pip install openai
pip install pyttsx3
```



## コード
以下が、対話型AIと音声読み上げを実現するPythonコードです。
!を入力すると、今までに入れたメッセージが出力されます。
endを入力すると、終了する形にしています。

```Python
import openai
import pyttsx3
import os

def text_to_speech(text):
    engine = pyttsx3.init()
    engine.setProperty("rate", 150)
    engine.say(text)
    engine.runAndWait()

def get_ai_response(messages):
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=messages
    )
    return response['choices'][0]['message']['content']

def main():
    # ここにAPIを直接書き込むか環境変数で入力するような形にしてください。
    openai.api_key = os.environ.get("OPENAI_API_KEY") or "your_openai_api_key_here"

    messages = []
    max_messages = 10

    print("AIの性格を決めて下さい")
    AI_input = input("AI: ")
    messages.append({"role": "system", "content": AI_input})

    while True:
        user_input = input("User: ")

        if user_input == "end":
            break

        messages.append({"role": "user", "content": user_input})

        ai_response = get_ai_response(messages)

        print(f"AI: {ai_response}")
        text_to_speech(ai_response)

        messages.append({"role": "assistant", "content": ai_response})

        if len(messages) > max_messages * 2 + 1:
            messages.pop(1)
            messages.pop(1)

        if user_input == "!":
            print("messages:", messages)

if __name__ == "__main__":
    main()
```

## 使い方
　1. 上記のコードをai_voice.pyなどのファイル名で保存します。

　2.ターミナルまたはコマンドプロンプトで、スクリプトを実行します。

```Python
python ai_voice.py
```
　3.AIの性格を入力し、その後ユーザーとして質問を入力すると、AIが返答を音声で読み上げます。

　4. 会話を終了するには、endと入力します。


## まとめ
この記事では、GPT-3 APIを使った対話型AIとその返答をWindowsで音声読み上げる方法を紹介しました。pyttsx3ライブラリを使って簡単にテキストを音声に変換でき、対話型AIの返答をリアルタイムで聞くことができます。このコードはさまざまな用途に応用できるため、自由にカスタマイズして活用してください。

## 追加のカスタマイズ
この対話型AIと音声読み上げプログラムは、さらにカスタマイズして機能を追加できます。
例としては、
* AIの性格や応答スタイルを変更するオプションを追加できます。
* ユーザー入力の履歴をファイルに保存し、後で確認できるようにすることができます。
* 音声認識ライブラリを使用して、ユーザーがマイクで質問をすると、AIがそれに応答するようにできます。

このように、対話型AIと音声読み上げプログラムは多様なシチュエーションで利用でき、ユーザーとのインタラクションをより自然で直感的にすることができます。

## 注意事項
OpenAIのGPT-3 APIを利用する際は、利用制限や料金に注意してください。APIキーの利用状況を適宜確認し、利用制限を超えないように注意してください。制限に達した場合は、OpenAIのサポートチームに連絡して、APIの利用制限を増やすことを検討してください。

## さいごに
この記事で紹介した対話型AIと音声読み上げの実装方法をぜひお試しください。音声対話を通じてAIとのインタラクションを楽しんで、さまざまなアプリケーションやプロジェクトに取り入れてみてください。お楽しみいただければ幸いです。


いやー参考コードを作って、そのコードを基にやってほしいことを追加すれば、
ほとんどChatGPT（GPT4）でやりたいことが実現できるようになるなんて、、。
しかも、それっぽい記事も作成してくれる
すごい時代だわ～
Python3: ChatGPT Speech to text の使い方 (requests)

こちらと同じことを、requests ライブラリーを使って行いました。
[Python3: ChatGPT Speech to text の使い方](https://qiita.com/ekzemplaro/items/835e6e1621e8c9123e8e)
[Curl: ChatGPT Speech to text の使い方](https://qiita.com/ekzemplaro/items/df9953f484f329ca11de)
音源も同じです。

## プログラム

```py:requests_text.py
#! /usr/bin/python
#
#	requests_read.py
#
#					Apr/06/2023
#
# ------------------------------------------------------------------
import	sys
import requests
from dotenv import load_dotenv
import os

# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
file_audio = sys.argv[1]
sys.stderr.write(file_audio + "\n")

dotenv_path = '.env'
load_dotenv(dotenv_path)
API_KEY = os.environ.get("API_KEY")

url = "https://api.openai.com/v1/audio/transcriptions"
model = "whisper-1"

headers = {
    "Authorization": "Bearer " + API_KEY
}

data = {"model": model}

files = {'file': open(file_audio, 'rb')}
response = requests.post(url, headers=headers, data=data, files=files)

print(response.text)
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

```text:.env
API_KEY="sk-11******************************************"
```

## 実行結果

```text
./requests_text.py yonendowa1_08_rappa_niimi.mp3
*** 開始 ***
yonendowa1_08_rappa_niimi.mp3
{"text":"LibriVox.orgのために録音されました。 ラッパ おじいさんは田舎に一人ぼっちで暮らしていました。 だんだん耳が遠くなったので、 都にいる息子のところへ 耳が遠くなったから よく聞こえる機械を買って送ってくれ と言ってやりました。 息子はいろいろ探したが あまり良い機械がないので ラッパを買って これを逆さまにして耳につけて ラッパの尻から聞きなさい と言ってやりました。 おじいさんはそのラッパを喜んで使っていましたが 耳はどんどん遠くなって とうとうつんぼになりました。 それでもおじいさんは あのラッパでは聞こえなくなったから もっとよく聞こえるのを 送ってくれと息子に手紙をやりました。 息子はいろいろ考えてから また前のラッパと同じラッパを送って このラッパを耳につけると 私の声が聞こえます と言ってやりました。 おじいさんはそのラッパを耳に当ててみました。 そして ああ、聞こえる、聞こえる 懐かしい息子の声が聞こえる と言って喜びました。 けれど、それはおじいさんの耳が聞いたのではありません 心が聞いたのです。 ラッパ終わり この録音はパブリックドメインです。"}
*** 終了 ***
```
Twitter API 変更について

新しいプランに移行せよとのこと

いまいちよくわからんが、1500件までの書き込みならそのままにしておいても動くのか？


| 項目                   | 無料                                                    | 基本                                  |
|------------------------|-----------------------------------------------------|---------------------------------------|
| アクセスする            | 始めましょう                                              | 始めましょう                                |
| 価格                   | 無料                                                    | $100/月                                |
| Twitter API v2 へのアクセス | ✔️ (ツイート作成のみ)                                    | ✔️                                     |
| 標準 v1.1 へのアクセス    | ✔️ (メディアのアップロードとステータス/更新と Twitter でのログインのみ) | ✔️ (メディアのアップロードとステータス/更新と Twitter でのログインのみ) |
| プロジェクトの制限        | 1 プロジェクト                                            | 1 プロジェクト                              |
| アプリの制限            | プロジェクトごとに 1 つのアプリ                             | プロジェクトごとに 2 つのアプリ                 |
| ツイートキャップ - 投稿   | 1,500                                                  | 3,000                                 |
| Tweet キャップ - プル    | ❌                                                     | 10,000                                |
| フィルタ ストリーム API   | ❌                                                     | ❌                                     |
| 全アーカイブ検索へのアクセス | ❌                                                     | ❌                                     |
| 広告 API へのアクセス     | ✔️                                                     | ✔️                                     |


# アクセスレベル

・フリー
https://developer.twitter.com/en/portal/products/free

・ベーシック
https://developer.twitter.com/en/portal/products/basic

# スタンドアロンアプリと、プロジェクトの違いは？

スタンドアロンアプリは独立して機能するアプリケーションで、プロジェクトは複数のアプリケーションを統合して管理するための仕組み
また、プロジェクトは1つのアカウントあたり、3つまでしか作れない。

# スタンドアロンアプリをプロジェクトにする方法は？

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31338/1a0987ff-ea61-0cbe-5d20-d169e172b0e6.png)


![ページ 1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31338/82225f6a-0bcb-4731-d247-3f0994501203.jpeg)

一応これでOAuthのキーなどを保持してプロジェクトにできる。
日本語に翻訳したままだと画面が真っ白になるが、一応更新はできる。
GoのDocker開発環境を作る

Goで開発環境を作る時Dockerを使っているのですが、いつもDockerfileやdocker-composeの内容を忘れてしまうので、メモしておく。



```Dockerfile:Dockerfile
#go version
FROM golang:alpine

#update & install (vimやbashを入れとくと便利）
RUN apk add --update && apk add git && apk add vim && apk add bash

# 作業ディレクトリ作成
RUN mkdir /go/src/app

# 作業ディレクトリ設定
WORKDIR /go/src/app

# ホットリロード用にairをインストール
RUN go install github.com/air-verse/air@latest

# airを実行
CMD ["air"]
```


```yaml:docker-compose.yml
version: '3.9'
services:
  backend:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./app:/go/src/app
    ports:
      - '8000:8000'
    tty: true
```

これで最低限開発はできるはず。
【Windows】iPhoneのみで発生するCSS崩れの原因を特定する方法

AndroidエミュレーターやPCのDevToolでは問題なく表示されていたので、デプロイしてみました。
しかしiPhoneで確認するとCSSが崩れていました。
WindowsPCだとクリティカルな情報が見つけづらかったので、まとめておきます。

## 【結論】Web Inspectorを使ってDOMとCSSの対応を1つずつ確認する
iPhoneに「Web Inspector」というアプリをインストールすることで、iPhoneのSafari上からChromeのDevToolと同等の操作が可能になります。

## 手順
以下、すべてiPhone側からの操作になります。
### Web Inspectorのインストール
[<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530037/4f08eb0a-54e1-96b2-3f38-f49dc88be718.png" width="150">](https://apps.apple.com/jp/app/web-inspector/id1584825745)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530037/25e8218a-a55b-85ee-2046-0edcea926e13.png)

https://apps.apple.com/jp/app/web-inspector/id1584825745

### Safari上で拡張機能をオンにする
![IMG_3866.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530037/ff0819ea-6503-2d7b-fd06-633847ed02a2.png)
![IMG_3867.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530037/0cd23d0b-821e-83da-3934-ceac496eae60.png)

下記のようになれば成功です。
「Web Inspector」をタップすれば起動します。
![IMG_3868.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530037/c245a021-9f61-b583-0870-4c17698331c5.png)
![IMG_3873.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530037/effaa030-8ee9-f564-7e71-29acff445ac3.png)

## 使い方・分析
下記のように、PCのChromeと同等の操作が可能ですが、一部使用できない機能があります。
またUIがかなり使いづらい印象です。

基本的には、気になる要素のDOMを選び、手書きでstyleやclassを追加しながら、調整していきます。

### できること
- ブラウザで触った要素のDOMを選択する
- DOMを選択して対応するCSSを確認する
- DOMにstyleやclassを追記する
### できないこと
- Elementsタブからstyleやclassの内容を追記

## Macの場合
MacならXcodeを使ってCordovaでシミュレートしたり、Safariと連携して便利に解析ができるようです。
下記が参考になるかもしれません。

https://boost-on.net/3944

## 【参考】
https://nldot.info/how-do-i-use-the-validation-tool-on-iphone-safari/
Cloud Runのリビジョンタグは、ただのリリース断面ではない

Cloud Runのリビジョンタグを、ただのリリース断面の目印的に使っていたら、無駄な料金が発生してしてしまった的な投稿です。

# Cloud Runとリビジョンタグ

Cloud Runは、Google Cloudでコンテナサービスを公開するためのマネージドサービスです。Cloud Runには、デプロイする（した）コンテナにリビジョンタグをつける機能があります。

https://cloud.google.com/run/docs/managing/revisions?hl=ja

# リビジョンタグの用途

リビジョンタグは、リリース断面につけるただの目印ではなく、テスト、トラフィックの移行、ロールバックに利用するタグです。

**デプロイする（した）コンテナにリビジョンタグをつけると、サービスで通常利用しているURLとは違うURLが割り当てられます。リビジョンタグに割り当てられたURLにアクセスして、事前にテストするなどの用途に利用できます。**

あらかじめテストしてから環境を切り替えるブルーグリーン・デプロイメントやカナリアリリースなどが可能で、公開したリビジョンで問題があった場合は切り戻すこともできる便利な機能です。

https://cloud.google.com/run/docs/rollouts-rollbacks-traffic-migration?hl=ja#deploy-with-tags

# リビジョンタグの注意点

注意すべき点ですが、**Gitのタグのようにリリース断面の目印的にリビジョンタグをたくさんつけてしまうと、意図しない料金がかかる場合がある**点です。

リビジョンタグに割り当てられたURLにアクセスがあって該当リビジョンがリソースを消費した場合や、最小インスタンスを設定してコンテナを常時起動させるなどした場合はその分料金が発生するので注意が必要です。

なので、不要なリビジョンタグはこまめに削除するのがよさそうです。

参考

https://zenn.dev/catnose99/scraps/bdfbebd8c51f45
HomebrewでインストールしたGoをアンインストールする方法(Mac)

以下のようにして削除する

```
$ brew list
==> Formulae
autoconf			m4
azure-functions-core-tools@4	mysql
brotli				node
c-ares				openssl@1.1
ca-certificates			openssl@3
go				pkg-config
icu4c				protobuf
libcbor				rbenv
libevent			readline
libfido2			ruby-build
libnghttp2			xz
libuv				zlib
lz4				zstd

==> Casks
powershell
$ brew uninstall go
Uninstalling /usr/local/Cellar/go/1.20.2... (11,975 files, 234.1MB)
$ brew list
==> Formulae
autoconf			mysql
azure-functions-core-tools@4	node
brotli				openssl@1.1
c-ares				openssl@3
ca-certificates			pkg-config
icu4c				protobuf
libcbor				rbenv
libevent			readline
libfido2			ruby-build
libnghttp2			xz
libuv				zlib
lz4				zstd
m4

==> Casks
powershell
```

### 参考サイト
* [homebrewでインストールしたパッケージをアンインストールする方法 | 素人エンジニアの苦悩](https://amateur-engineer.com/homebrew-uninstall/)
* [[Mac] Goのアンインストール - Qiita](https://qiita.com/Nekonecode/items/8561bbe27830090bc70c)
Spring Security その4.1〜カスタム認証について


「Spring Security のカスタム認証」を作成していて、色々とハマってしまったので
SpringSecurityの認証について学んだことを備忘録として残します。
カスタム認証を使用した実装方法については別途記事を作成予定

:::note warn
自分がハマって調べたことだけなので、色々抜けている機能があることはご了承ください。
誤っている箇所や誤解を与えかねない表現があればご指摘いただけると助かります。
:::

## アーキテクチャ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555551/bf9b11f5-e3bd-af2b-2904-a9d3922a2e54.png)

1. ブラウザからリクエストが送信されると「FilterChainProxy」がリクエストを受け取る
1. FIlterChainProxyはFilterChainを呼び出す
1. FilterChainには複数のFilterが登録されており、順番にFilterを実行し認証を行う。

## フォーム認証
:::note
Filterには色々な種類がある（らしい）が、フォームにて入力された内容によって認証を行う「UsernamePasswordAuthenticationFilter」で説明
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555551/8c30ba4f-9f69-58cb-c792-6b18932740d7.png)


1. UsernamePasswordAuthenticationFilterはリクエストから認証に必要な情報を取得する（デフォルトならuserNameとpassword）
1. Authenticationに格納し、DaoAuthenticationProviderを起動する
1. DaoAuthenticationProviderはUserDetailsServiceを使用し、ユーザ情報を取得し、認証を行う
1. 認証がOKの場合、UsernamePasswordAuthenticationTokenを返却する
1. 認証OKの場合（UsernamePasswordAuthenticationTokenが返却されている場合）successfulAuthenticationを実行する
1. セキュリティコンテキスト（認証情報等）を保存

## AnonymousAuthenticationFilter
フィルターチェーンの最後（厳密には最後じゃないかも？）にAnonymousAuthenticationFilterが起動される。
認証されていないユーザーに対して匿名認証を提供する。
つまり、こいつが最終的に認証がOKだったかの確認を行い、認証されていなければNG扱いにするということ
AnonymousAuthenticationFilterは<font color="red">「ThreadLocalSecurityContextHolderStrategy」</font>から認証情報を取得し、認証情報が存在すればOKと判断している。

## ハマったポイント
AnonymousAuthenticationFilterはスレッドローカルから認証情報を取得しているので、異なるスレッドの場合は情報は引き継がれない（認証OKとはならない）

実際に認証NGとなってしまった時のログを見るとUsernamePasswordAuthenticationFilterが認証OKとしているスレッドとAnonymousAuthenticationFilterがNG（匿名認証をセット）としているスレッドが違った
※[nio-8080-exec-<font color="red">4</font>]
赤字部分がスレッド
```:コンソールログ
DEBUG　[nio-8080-exec-4]com.example.auth.SampleFilter  Set SecurityContextHolder to UsernamePasswordAuthenticationToken
省略
DEBUG [nio-8080-exec-6]o.s.s.w.a.AnonymousAuthenticationFilter Set SecurityContextHolder to anonymous SecurityContext
```
<br>
<br>
<br>  
デフォルトでは、UsernamePasswordAuthenticationFilter(厳密にいうとAbstractAuthenticationProcessingFilter)は「RequestAttributeSecurityContextRepository」を使用しており、これはスレッド間の共有ができない。

```java:AbstractAuthenticationProcessingFilter
private SecurityContextRepository securityContextRepository = new RequestAttributeSecurityContextRepository();
```
そのため、セッションに保存して異なるスレッド間でも共有できるようにする必要がある。
セッションに保存するためには<font color="red">「HttpSessionSecurityContextRepository」</font>を使用する

:::note warn
「デフォルトでは」と記載しているが、SpringSecurityがデフォルトで登録しているUsernamePasswordAuthenticationFilterは「HttpSessionSecurityContextRepository」が別途設定されている。
ややっこしい・・・
:::
【マネジメント】協力会社（SES等）のエンジニアと採用面談する際の質問と、注意していること

# はじめに
現在、フルリモート勤務で受託開発をしている@fussasyといいます。私自身、それなりにエンジニア歴が長いため、プロジェクトリード・マネジメントをする機会も多いです。プロジェクトへ参画する際には、必ずしも弊社プロパー社員のみになるわけでなく、いくつか関係の深い協力会社（SES等）から来られたエンジニアの方と面談し、プロジェクト参画への依頼可否を決定しています。これまでに採用面談をいくつか経験してきたため、備忘録的な意図を含めて情報整理をしたいと思います。

# エンジニアの採用面談のため前提・段取り
![猫が面接をされている、アイコンイラスト_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1727556/5c0e2e6c-589c-83f5-0440-17073d9ee226.jpeg)
現状、私が面接をする立場ではありますが、逆に私も面接をされる立場として多く経験しています。する側と、される側のどちらが偉いという関係性はないと思っているため、採用面談では双方が心地よくやりとりすることへ注力するようにしています。

### 事前準備
**事前に機材の調子を整え、時間通り始める**
ハウリング等の防止のため、ヘッドセットもしくはイヤホンマイクを用意。面談で使用するシステムでは必ず事前にテストしておきます。

**機材のトラブル等が起きても、冷静に対処する**
トラブルだけではそこまで心象は悪化しないが、そこで冷静さを失うと致命的に悪化します。

**相手のペースに合わせることを意識する**
当たり前ですが、自分が話したいことを一方的に話すと心象が悪くなります。

### 段取り
**①プロジェクトの説明を実施：**
進行を妨げない範囲で案件の説明をし、お互いの認識祖語を防ぎます。
・案件の目的
・システム構成の概要
・案件の進捗と今後の予定
・案件の体制
・求める役割

**②経歴説明を依頼：**
プロジェクトの説明から要求する役割とスキルが明確になった後、候補者の方に経歴説明をしてもらいます。

**③質疑応答：**
提出された経歴書を元に、気になる点を質問していく。

**④雑談：**
質疑応答に関連して、簡単な雑談をします。定型質問では引き出せない情報も得られます。お互いに興味を持って知ろうとする姿勢が一番大事だと思います。同じ業界に属する者同士、情報交換するという意識で臨めば、有意義な時間になると思います。

**⑤御礼：**
プロジェクト参画機会へのご縁が無かったとしても、時間をいただいたことには変わりません。しっかりと御礼を言うようにします。

# 経歴書の記載内容以外の質問例
基本的には提出された経歴書をベースに質問をしていくものの、一般的な質問をする場合もあり、下記の様な質問例からピックアップしています。

**・これまで経験したプロジェクトで発生した問題や課題について、どのように対処してきましたか？**
**・開発技術における現在のトレンドについて、どのように情報収集をしていますか？**
**・スキルセットについて、ご自身ではどのように評価しますか？**
**・プロジェクトの進捗状況を管理する場合、使用してきたツールや手法には何がありますか？**
**・チームメンバーの進捗状況を把握する際に、どのような手法を用いていますか？**
**・エラーのデバッグを行う場合、どのようなアプローチをとりますか？**
**・開発において重要と考える要素は何ですか？**
**・プロジェクトチームでの協力関係について、どのように考えますか？**
**・締め切りに追われるプロジェクトにおいて、どのように時間管理を行いますか？**
**・コミュニケーションにおいて、最も重要だと考える点は何ですか？**
**・システム設計において、どのような手法を用いますか？**
**・プロジェクトの品質管理について、どのような取り組みをしていますか？**
**・エラーが発生した際に、どのような原因分析を行いますか？**
**・チームメンバーのモチベーションを維持するために、どのような取り組みをしていますか？**
**・コードレビューを行う際に、どのような観点に注目しますか？**
**・プロジェクトにおけるリスク管理について、どのようなツールや手法を用いてきましたか？**
**・スケジュール管理において、どのような問題が発生することが多いと考えますか？**
**・テストフェーズにおいて、どのようなツールや手法を用いてきましたか？**
**・ご自身の改善点を挙げるとすれば何でしょうか？**

# 注意すべきこと
採用面談において、一般的なビジネスマナー・スキル（報連相やCND）は当たり前として、全般的に注意すべきことは下記の通りです。

**・面接前に、候補者の経歴書やポートフォリオ（ある場合）を確認し、質問を準備しておくこと。**
**・面接前に、プロジェクトに必要なスキルや知識、経験を明確にしておくこと。**
**・候補者が抱える問題や課題に対して、オープンな質問をすることで、候補者の人となりや問題解決能力を知ること。**
**・プロジェクトに必要なスキルや知識、経験について、候補者の実務経験を確認すること。**
**・プロジェクトのチーム構成や弊社の文化について、候補者が適応できるかどうかを確認すること。**
**・チームコミュニケーションを確認するため、候補者の聞き上手な質問や積極的な発言を促すこと。**
**・プロジェクトに必要なリーダーシップについて、候補者がどのような考えを持っているかを確認すること。**
**・プロジェクトで重要な問題解決能力について、候補者がどのようにアプローチするかを確認すること。**
**・候補者が持つコミュニケーション能力や説明力を確認することで、コミュニケーションの円滑性を確認することができる。**
**・候補者がプロジェクトに参加することになった場合に、自己成長にどのような取り組みをするかを確認すること。**

# さいごに
![猫が面接をされている、アイコンイラスト_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1727556/616ddf4a-3619-bf33-044e-7769e5c7a3b7.jpeg)
協力会社（SES等）からエンジニア採用・面談する際、同じ面談時間帯に複数人を相手にする場合もあります。その場合は、しっかりとタイムマネジメントを行い、時間配分が特定の人へ偏りすぎない様に注意しなければいけません。このような面談に限らず、全てのイベントにおいては、準備が8割～9割（残りは本番）を占めます。当記事でまとめた内容も準備の一環です。今後もしっかりと準備をしつつ、相手に失礼が無いような面談を心がけていきたいと思います。
OpenSiv3Dでアンドゥ・リドゥ機能をなるべく短く実装する方法

# 概要

この記事では、OpenSiv3DとC++を使って、リドゥ・アンドゥ（やり直し・元に戻す）機能を簡単に実装する方法を紹介します。具体的には、以下のソースコードを使って、シリアライズに対応した任意のクラスの履歴を保存し、リドゥ・アンドゥ機能を実現できます。

```cpp
template<class Type>
Blob GenerateHistory(const Type& data)
{
	return Zlib::Compress(Serializer<MemoryWriter>{}(data)->getBlob());
}

template<class Type>
void RecoverHistory(Type& data, const Blob& blob)
{
	Deserializer<MemoryReader>{Zlib::Decompress(blob)}(data);
}
```

# はじめに

この記事では、OpenSiv3DとC++を使用して、簡単にリドゥ・アンドゥ機能を実装する方法を紹介します。リドゥ・アンドゥ機能は、エディターやグラフィックデザインツールなど、ユーザーが操作をやり直したり元に戻したりできる機能が求められるアプリケーションで非常に重要です。OpenSiv3Dは、C++のパワフルさと簡単な使いやすさを兼ね備えたマルチプラットフォーム用のライブラリです。

シリアライズを使って自作アプリにUndo/Redoを実装する方法が[既に紹介](https://qiita.com/agehama_/items/58ae9e712b0a352f3f0d)されていますが、この記事では関数を使ってシリアライズ・デシリアライズを行うことで、より短いコードで他のプロジェクトに適用しやすい方法を提案します。この方法は、特に小規模なプロジェクトやプロトタイピングでの利用に適しています。

# 実装方法

まず、クラスにシリアライズ機能を追加します。以下のようにSIV3D_SERIALIZE関数を定義し、メンバ変数をシリアライズするように指定してください。

```cpp
template <class Archive>
	void SIV3D_SERIALIZE(Archive& archive)
	{
		archive(/* メンバ変数 */);
	}
```

次に、履歴を保存するためのGenerateHistory関数を実装します。この関数は、シリアライズされたデータを圧縮し、Blobオブジェクトとして返します。

```cpp
template<class Type>
Blob GenerateHistory(const Type& data)
{
	return Zlib::Compress(Serializer<MemoryWriter>{}(data)->getBlob());
}
```

そして、履歴を復元するためのRecoverHistory関数を実装します。この関数は、圧縮された履歴データ（Blobオブジェクト）を引数にとり、デシリアライズして元のデータに戻します。

```cpp
template<class Type>
void RecoverHistory(Type& data, const Blob& blob)
{
	Deserializer<MemoryReader>{Zlib::Decompress(blob)}(data);
}
```

これで、GenerateHistory関数を使ってデータの履歴を保存し、RecoverHistory関数を使って履歴からデータを復元できるようになります。リドゥ・アンドゥ機能を実現するためには、適切なタイミングでこれらの関数を呼び出し、データの履歴を管理する必要があります。例えば、Arrayを使って履歴のスタックを管理することができます。

# 注意点

この手法のメリットは、シリアライズに対応した任意のクラスで簡単にリドゥ・アンドゥ機能を実装できることです。また、履歴データが圧縮されるため、メモリ消費を抑えることができます。

デメリットとしては、シリアライズやデシリアライズに時間がかかることがあり、パフォーマンスに影響を与える場合があることです。また、シリアライズに対応していないクラスではこの手法を適用できません。

注意点としては、シリアライズやデシリアライズの際にデータ構造が正しく変換されるように注意が必要です。また、履歴データの管理に関しても適切に行うことが重要です。

# まとめ

この記事では、OpenSiv3DとC++を使って簡単にリドゥ・アンドゥ機能を実装する方法を紹介しました。シリアライズに対応した任意のクラスで、履歴を保存してリドゥ・アンドゥ機能を実現することができます。ただし、シリアライズやデシリアライズのパフォーマンスやデータ構造の正確性に注意が必要です。この手法を活用して、リドゥ・アンドゥ機能が求められるアプリケーションを開発してみてください。
FortigateのGUI操作とRestAPIの紐づけ

FortigateのAPIドキュメントはなぜか非公開であるため、
基本的には自分でAPIの内容を検証していく必要があります。

今回はその調査法の１つである、GUI操作とRestAPIを紐づける方法を書いていきます。

# GUI上の操作

GUIとバックエンドのやり取りはRestAPIを使用して行われています。

つまりAPIリクエストから取得した情報がGUI上に反映され、
追加・削除などフロント（GUI上）で行われた変更はAPIリクエストによりバックエンド送られます。

# デベロッパーツール

APIの通信の情報はブラウザのデベロッパーツール(Ctrl + Shift + i)で確認することが出来ます。
Fortigateへログイン後、デベロッパーツールを立ち上げてNetworkタブを開いてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989161/4f25037f-740b-36ca-cbec-c425e459a32d.png)
左上の赤丸のボタンを押すことでパケットのキャプチャーを行えます。
usageやusb-logといった項目がありますが、これらが実際に行われたAPIリクエストになります。

# APIリクエストの中身
次にusageを選択してリクエストの中身を確認してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989161/95ca056c-d5a0-f3c0-fc0e-696ade6aeffa.png)

Headers, Response などのタブがあり、これらからリクエストの内容を確認出来ます。

usageリクエストについては画像から以下のことが分かります。
・リクエストURL: https://192.168.0.1/api/v2/monitor/system/resource/usage
・リクエストメソッド：GET
・ステータスコード：200（成功）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989161/ffed6dd7-3133-b3ed-3796-97f1a0ab02ed.png)
Preview, Responseタブからレスポンスのデータを確認できます。

ちなみにusageリクエストではCPUやメモリなどのリソース関連の情報を取得しています。
ログイン後のステータスダッシュボードでは常にリソース情報が更新されているのですが、
そのたびにusageリスエストで情報を取得および更新しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989161/1a69de7e-100e-948a-c555-1dd545d2931a.png)

# 使用例
例として管理者の作成（POST）、修正（PUT）、削除（DELETE）を行ってみます。

## 管理者の追加
GUI上でtestという名前の管理者を追加してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989161/a8214e90-6a41-13c2-0439-3842a12b7852.png)
追加ということでGETではなくPOSTリクエストになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989161/20f175ab-4895-7b1e-7973-e3d47ad2af9d.png)

また、GETリクエストには無かったPayloadタブが出てきました。
ここで追加する情報をJSON形式で記載します。

## 管理者の変更
GUI上で管理者の名前をtestからnew_testへ変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989161/14813aa0-79ae-66e3-f1dd-a746ed8e0e7b.png)
今度はメソッドがPUTになりました。
またリクエストURLに/testが追加され、testユーザーに対し修正を行うように定めています。
POSTと同じように修正する内容はPayloadタブに記載されています。

## 管理者の削除
GUI上で管理者new_testを削除します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989161/bbd106de-4893-f13c-462d-e12e1c0b5787.png)
メソッドがDELETEになり、PUTと同じようにURLに削除対象new_testが定義されています。
DELETEにはPayloadないため、タブは表示されていません。

# まとめ

いかがでしょうか？
FortigateのGUI操作とRestAPIの紐づけるにはデベロッパーツールが便利です。
ぜひ本記事をAPIを使用した自動化ツール開発などに役立てて頂ければ幸いです。
TinyGo でビルドした WASM コンテナを実行すると When linking module: "env" , function name: "runtime.ticks" エラー

# 概要

以下のように TinyGo を使って WASM コンテナを作成したが、実行時にエラーが発生してしまった。

```bash
# WASM のコンパイル
docker run --rm -v ${PWD}:/home/tinygo \
	  tinygo/tinygo:0.27.0 \
	  tinygo build -target=wasm -o /home/tinygo/main.wasm

# WASM コンテナ作成
docker buildx build --platform wasi/wasm -t wasm-container .

# 実行
docker run --rm \
	  --runtime=io.containerd.wasmedge.v1 \
	  --platform=wasi/wasm \
	  wasm-container:latest
```

```text
[2023-04-06 02:32:42.529] [error] instantiation failed: unknown import, Code: 0x62
[2023-04-06 02:32:42.529] [error]     When linking module: "env" , function name: "runtime.ticks"
[2023-04-06 02:32:42.529] [error]     At AST node: import description
[2023-04-06 02:32:42.529] [error]     This may be the import of host environment like JavaScript or Golang. Please check that you've registered the necessary host modules from the host programming language.
[2023-04-06 02:32:42.529] [error]     At AST node: import section
[2023-04-06 02:32:42.529] [error]     At AST node: module
docker: Error response from daemon: Others("unknown import"): unknown.
```

# 環境

- TinyGo 0.27.0
- Docker Desktop 4.17.1

# 原因

tinygo build 時の target を wasm にする。

```diff
        docker run --rm -v ${PWD}:/home/tinygo \
          tinygo/tinygo:0.27.0 \
-         tinygo build -target=wasi -o /home/tinygo/main.wasm
+         tinygo build -target=wasm -o /home/tinygo/main.wasm
```

また、docker build 時と docker run 時の platform を合わせないと、当然ながら docker run 時に `Unable to find image` エラーが発生するため注意。

# 参考

https://tinygo.org/getting-started/install/using-docker/
ポートが開いているかどうかを確認する方法、ツールなしで、特にコンテナの中で便利

Dockerコンテナのイメージは、ほとんどが```slim```と```alpine```であり、必要最小限のツールが含まれています。そのため、ポート番号が開いているかどうかの確認には、通常は```nc```や```telnet```などのツールをインストールする必要があります。しかし、ツールを使用せずにポートが開いているかどうかを確認する方法があると便利ですよね。そのような場合は、以下のコマンドを使用できます。
```bash
printf "" > /dev/tcp/<ホスト名>/<ポート番号>
```
このコマンドは、指定したホスト名とポート番号にTCP接続を試みます。もし接続が成功した場合、何も出力されずにコマンドが終了します。一方、接続に失敗した場合は、エラーメッセージが出力されます。
例えば、ポート番号3000番が開いているかどうかを確認する場合、以下のコマンドを実行します。
```bash
printf "" > /dev/tcp/localhost/3000
```
このコマンドは、localhost（127.0.0.1）の3000番ポートに接続を試みます。もし接続が成功した場合、何も出力されません。一方、接続に失敗した場合は、以下のようなエラーメッセージが表示されます。
```bash
bash: /dev/tcp/localhost/3000: Connection refused
```

### 注意：
* ```bash```と```ksh```でしか動作せず、```zsh```では動作しません。
* 一部のディストリビューションではこの機能が無効になっている場合があります。
社内の方が確認してくださったが、```ubuntu``` で ```apt changelog bash```を確認してみたら、```bash 2.04``` の頃から無効になっていて (有効になったままリリースされたことがなくて)、```bash 4.0``` の頃から有効になっていたみたいです。
```
bash (2.04-5) unstable; urgency=low

  * debian/patches/alpha-unwind.dpatch: Patch from "Mikolaj J. Habryn"
    <fe78734e@eris.rcpt.to>. Should fix #62170, #62690, #65053.
  * debian/rules: Configure with --disable-net-redirections (as suggested
    in #65172). The patch submitted in the report can be found in
    debian/patches/tcp-udp-service-names.dpatch.
  * debian/patches/getcwd-error: Fix error message for two levels of
    unreadable directories (#64659).

 -- Matthias Klose <doko@debian.org>  Mon,  5 Jun 2000 05:59:59 +0200
```

```
bash (4.0-5) unstable; urgency=low

  * Re-add dependency on dash, lost with the upload of 4.0.
  * Don't configure with --disable-net-redirections.
  * Fix name of system wide bash_logout in bash(1). Closes: #546200.
  * Stop shipping the sh and sh(1) symlinks. Closes: #545103.
  * Apply upstream patches 029 - 033.

 -- Matthias Klose <doko@debian.org>  Sun, 13 Sep 2009 12:55:54 +0200
```
無効の場合は、```--enable-net-redirections```オプションを使用して```bash```を再コンパイルする必要がありますが、コンテナ内で再コンパイルするのは手間がかかります。ただし、2023年4月6日現在、ほとんどのDockerコンテナにおいて、```bash```のバージョンが```5.1```であるため、ほとんどの場合は問題なく動作すると考えられます。
DeepLで翻訳時に改行消去などを省力化

以下をChromeでブックマークバーに追加する（名前は適当につけて、URLに以下を書く）。
```javascript
javascript:(function(){let txt=window.prompt("英文を入力してください");window.open("https://www.deepl.com/translator#en/ja/"+encodeURIComponent(txt.replace(/[\n\r]+/g, " ").replace(/\//g, ";").replace(/(?<!Fig)\. /g, ".\n\r\n\r").replace(/\- /g, "-")));})();
```
ブックマークバーからクリックするとポップアップが表示される。PDFからの切り取りを貼り付けてOKをクリックする。

# やっている置換
1. 改行をスペース
1. /を;
1. "- "を"-" (例 busi- 改行 ness → business）
1. ". "を"."+2行の改行（出力は文ごとに分けるようにする．ただし，Fig. 4やe.g.などの場合は改行しない）
フローのコアアクション「メールを送信」の本文にHYPERLINKは使えません


テキストテンプレートでHYPERLINKが使えない

```
_HL_ENCODED_https://google.com_HL_Google Website_HL__blank_HL_
```

+ [同じような質問:Flow Hyperlink Formula referenced in Text Templates](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000C30CrSAJ)

+ [既知の問題Hyperlink Formula Displaying _HL_ENCODED_ When Referencing Another Formula Field](https://issues.salesforce.com/issue/a028c00000gAzSEAA0/hyperlink-formula-displaying-_hl_encoded_-when-referencing-another-formula-field)

しかし、以下のブログを参考にして回避策を見つけました

+ [How to Create a Record Link in Flow](https://salesforcetime.com/2022/09/13/how-to-create-a-record-link-in-flow/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/6e695281-3fa2-bf52-890b-2c3b1d3cd93f.png)

もしかしたら、テキストテンプレートでもリッチテキストを有効化すれば、上記みたいにLink URLを設定できるかもしれないと思いやってみました。

物件名にリンクをつけてSalesforceの画面に飛べるようにします。

念のため確認。「リッチテキストとして表示」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/576b4d3e-46a9-c17d-d0d9-b73f22f80ff5.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/78fc8342-43a9-f437-ebf4-ff20601f1635.png)

リンクURLにはSalesforceのURLを動的に配置できるように数式としました。

```
LEFT({!$Api.Enterprise_Server_URL_570} , FIND('/services', {!$Api.Enterprise_Server_URL_570})) & "/lightning/r/kenmei__c/"& {!$Record.Id} &"/view"
```

コアアクションのメール送信ではこのテキストテンプレートを指定して、リッチテキストを有効化します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/cf74d3c9-1d4b-5d12-8785-c4e1c68252e1.png)

# trigger flow unable to add URL link to an image

+ [trigger flow unable to add URL link to an image](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000PiZqQ)

```
<a href="https://career.my.site.com/Member/s/workshop/{!URLID}"><img src={!Get_Records.Event_Poster__c}</a>
```