OmniAICreator/Qiita-1.07M huggingface dataset:
【Unity】toio環境構築〜実機動作確認まで

## 本記事について
![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/80d68f0a-bdf6-0178-f82f-ac6a658867c2.gif)

UnityのSDKをいれるところからtoio実機で動かすまでの流れとポイントを書く。
実機が動くまで、これでいいのか..?とちょっと戸惑ったりしたので備忘録
アプリのビルドはやっていないので本記事には書かない。

## 環境
mac os 12.5 silicon
toio SDK for Unity v1.5.1
Unity 2021.3.7f1

## 流れ

基本的にはドキュメントの[セットアップ](https://github.com/morikatron/toio-sdk-for-unity/tree/v1.5.1/docs#-1-%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97)を見てやればよい。

### プロジェクト作成、SDKインストール

[toio SDK for Unity のインストール](https://github.com/morikatron/toio-sdk-for-unity/blob/v1.5.1/docs/download_sdk.md)の通りにやればOK

この通り、プロジェクトはURPではなくLegacyなレンダリングパイプラインの方で作成。URPではShaderが無効になってピンクになった。

UniTaskのインストールは2022/12現在 gitのURLでやるよりもscoped registry使う方がバージョンアップが容易で都合よいのでそっちでやる。

https://kan-kikuchi.hatenablog.com/entry/OpenUPM_Install

toioのSDKは2022/12現在ドキュメントにUPMについては記載なかったので、unitypackage使ってインストールする。(ぜひ対応してほしい)

シミュレーターでの確認もサクッとすむ

### Macからtoio実機への接続
[MacBLE利用方法](https://github.com/morikatron/toio-sdk-for-unity/blob/v1.5.1/docs/usage_macble.md)を見てやればBLE通信できるようにする

> 11.x または 12.x の場合はbleplugin_11.bundle.zip

12.xのときはbleplugin_12ではなくbleplugin_11ってところに注意(ないからわかるだろうけども)

次に[Sample_ConnectType](https://github.com/morikatron/toio-sdk-for-unity/tree/v1.5.1/toio-sdk-unity/Assets/toio-sdk/Samples/Sample_ConnectType)のシーンを開く。

シーンを開いてそのまま再生を押すと画面上のtoioが回転することが確認できた。

![スクリーンショット_2022-12-04_21_09_33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/2d2292dd-de43-5caf-ebe6-2bf1db65cf9b.png)

sceneというオブジェクトをクリックするとConnectTypeが確認できる。

```Sample_ConnectType.cs
    async void Start()
    {
        // ConnectType.Auto - ビルド対象に応じて内部実装が自動的に変わる
        // ConnectType.Simulator - ビルド対象に関わらずシミュレータのキューブで動作する
        // ConnectType.Real - ビルド対象に関わらずリアル(現実)のキューブで動作する
        cm = new CubeManager(connectType);
        await cm.MultiConnect(2);
    }
```

「内部実装が自動的に変わる」の具体的な中身が知りたい。

```Assets/toio-sdk/Scripts/Cube/CubeConnecter.cs
    public class CubeConnecter : CubeConnecterInterface
    {
        private CubeConnecterInterface impl;

        public CubeConnecter(ConnectType type = ConnectType.Auto)
        {
            if (ConnectType.Auto == type)
            {
#if (UNITY_EDITOR || UNITY_STANDALONE)
                this.impl = new SimImpl();
#elif (UNITY_IOS || UNITY_ANDROID || UNITY_WEBGL)
                this.impl = new RealImpl();
#endif
            }
            else if (ConnectType.Simulator == type)
            {
                this.impl = new SimImpl();
            }
            else if (ConnectType.Real == type)
            {
                this.impl = new RealImpl();
            }
```

UnityEditorだとSimulatorを使うってことだった。
つまり、Sample_ConnectTypeのサンプルで実機toioと接続するためにはConnectTypeをRealにすれば良い。

ということでinspectorでRealに切り替える。
toioの電源を入れて再生ボタンを押す。
するとmacの画面で「UnityHubでBluetoothを許可しますか？」みたいなポップアップが出たので許可(スクショとってなかった)。

で、しばらく待っても何も起こらなかった。

一度再生を止めて、toio再起動し、再度Unityを再生したところtoioから接続音が出て本記事の冒頭のgifのように回転し始めた。
Unityの再生をやめたところ接続も切れた。
マーメイド#3 基本の構文構造

**ひとりマーメイド3日目**
**基本の構文構造**

## 概要
マーメイドエンジニアのひろきです。こんにちは。
最近流行り（流行らせたい）のマーメイドについて理解を深めていこうと思います。

この記事ではマーメイドの構文構造について紹介します！

↓↓前回の記事はこちら

https://qiita.com/hirokiwa/items/37ccf5ad177b40aea682

## 共通基本文法
前回の記事ではマーメイドの主なエディタと書き方について紹介しました。もういつでも記述できますね。

今日からはいよいよ細かい記法について学んでいこうと思います。まずは全てのダイアグラムで共通となる基本的な構文構造について見ていきましょう。

## ダイアグラムの宣言

マーメイドの記述ではまずダイアグラムの種類を宣言します。フローチャートを書きたい場合は "graph" です。


```:mermaid
graph
	A([start])-->B{true?}
	B--Yes-->C[process]
	B--No-->D[exception]
	C-->E([end])
	D-->E
```

```mermaid
graph
	A([start])-->B{true?}
	B--Yes-->C[process]
	B--No-->D[exception]
	C-->E([end])
	D-->E
```

### ダイアグラム宣言一覧

|宣言|ダイアグラム|
|----|----|
|graph|フローチャート|
|sequenceDiagram|シーケンス図|
|classDiagram|クラス図|
|stateDiagram-v2|常態遷移図|
|erDiagram|ER図|
|gantt|ガントチャート|
|gitGraph|gitグラフ|
|journey|カスタマージャーニーマップ|
|pie|円グラフ|
|requirementDiagram|要求図|
|C4Context|C4モデル|
|mindmap|マインドマップ|

## ディレクティブ

先頭に以下の記述を加えるとダイアグラムの外観を変更することができます。

`%%{ }%%`

以下のように記述するとダイアグラムを森モードに変身させることができます。

```:mermaid
%%{init: { "theme": "forest" } }%%

graph
	A([start])-->B{true?}
	B--Yes-->C[process]
	B--No-->D[exception]
	C-->E([end])
	D-->E
```

```mermaid

%%{init: { "theme": "forest" } }%%

graph
	A([start])-->B{true?}
	B--Yes-->C[process]
	B--No-->D[exception]
	C-->E([end])
	D-->E

```

緑になりました。

細かいディレクティブの仕様は後日紹介しますね！

## 予約語
`end`は予約語なので使用を避けましょう。

## まとめ
マーメイドの記述にもいろいろルールがあるんですね。

楽しいぃぃぃ

↓↓次回の記事はこちら！！

https://qiita.com/hirokiwa/items/8170fd9111f302faeb23

## 参考

https://mermaid-js.github.io/mermaid/#/

'
DynamoDBへの大量の読み込みリクエストによるスロットリングエラーの解消

# はじめに
最近のAPI開発ではLambdaを使って開発する機会が増えていると思います。Lambda開発では一般的にDynamoDBとの相性がよく採用されているケースが多いと思います。

DynamoDBを使うにあたって、テーブル内の１つの要素に対して大量のリクエストがあった場合に、ホットパーティションによるスロットリングの発生してしまう可能性があります。

今回はそのスロットリングの発生から解消までをAWSコンソール上から確認していきたいと思います。



# 内容

### スロットリングとは
一定期間で受けられるリクエストの数を設定して、それを超えてきたら受信拒否してエラーを返却することです。

これはエンドポイントURLに対するリクエスト数が多すぎる場合、制限をかけることでトラフィックの急増に対しバックエンドサービスを守ってくれるそうです。これがDDoS攻撃などに対策になっていると思います。

AWSサービスではこういった制限をかけてくれていますが、作るシステムによっては頻繁にリソースへアクセスが予想されるものもあると思います。その場合は制限を回避するようにしなければいけません。

### DynamoDBのスロットリング
プロジョンタイプで予想されるアクセス数に対応できるキャパシティユニットで設定しておけば急なアクセス増加にも対応しておくことはできるが、コストがかかってしまうので、現実的にオンデマンドで対応したいところです。

オンデマンドタイプでは、以下の場合にスロットリングが発生する可能性があるとawsのサイトに記載がありました。

> ・トラフィックが前のピークに比べて 2 倍以上である。
 ・トラフィックがパーティションごとの最大値を超えている。
 ・トラフィックがテーブルごとのアカウントクォータを超えています。
 ・テーブルのグローバルセカンダリインデックスがスロットルされている。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/on-demand-table-throttling-dynamodb/

#### 試したこと
urlをプライマリーキーにしたモックAPIのレスポンスをキャッシュするテーブルを作成し、当該テーブルの１項目に対して1分間あたり500回のgetリクエストを送る。


|キー|値|
|-|-|
|url|PK|
|response|モックAPIのレスポンス|

#### 今回のエラー内容

```
software.amazon.awssdk.services.dynamodb.model.DynamoDbException: Throughput exceeds the current capacity of your table or index. DynamoDB is automatically scaling your table or index so please try again shortly. If exceptions persist, check if you have a hot key: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-partition-key-design.html (Service: DynamoDb, Status Code: 400, Request ID: 3PSHGOAO0277BFLPUE899O24PVVV4KQNSO5AEMVJF66Q9ASUAAJG)
```

#### CloudWatch Contributor Insights for DynamoDB

こちらのグラフでスロットリングが発生していることが確認できます。

![スクリーンショット 2022-12-04 20.25.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708735/ec426a59-bc96-1cf3-bdfd-0ece33888a33.png)


#### 回避方法
今回はURLというパーティションキーへのアクセスが集中してホットパーティションとなっていそうだったため、今回の事象は、
> ・トラフィックがパーティションごとの最大値を超えている。

と仮定して、書き込みシャーディングを使用してワークロードを均等に分散する方法を試してみました。

実際の作業内容は単純で、dynamo保存時にキーに1~100のサフィックスを付与し、同じ内容のものを100項目書き込む方法になります。

以下のような項目になります。
|url|response|
|-|-|
|http://test.com?key=value-1|{"response": "test"}|
|http://test.com?key=value-2|{"response": "test"}|
|http://test.com?key=value-3|{"response": "test"}|
|...|...|
|http://test.com?key=value-100|{"response": "test"}|

キャッシュ取得の検索時に、1~100のランダム数をサフィックスに付与することで読み込みが100個分分散されることになりました。

再度実行してみたところエラーはなくなり、正常に終了しておりました。

# おわりに
ドキュメント上でDynamoDBの性能の良さは聞いていたが、大量データを扱っても高速に処理してくれることを実際に大量リクエストを送ってみて実感できました。

明日は @Nebel-hb さんの記事です。乞うご期待を！
RealityScan iOSアプリ版について

# はじめに
こちらはIwaken Lab. 主催のアドベントカレンダー5日目の記事になります。

https://iwakenlab.jp/

今回は、2022年の12月にリリースされたRealityScanについて紹介させてもらいます！

# RealityScanとは
Capturing Reality社が開発していた「RealityCapture」をスマホで体験できるようにしたアプリで、写真から3Dオブジェクトを生成する、フォトグラメトリーの技術をスマホで楽しむことができます。

現状（2022/12/04）、AppleStoreでのみアプリのダウンロードが可能です。

https://apps.apple.com/jp/app/realityscan/id1584832280

# RealityScanで作ったもの

https://sketchfab.com/3d-models/scan-2022-12-04t112733498z-94b36c2d935d46ca8884f4a81dbc0bf7

<details><summary>詳細</summary>

 - 撮影した枚数:108枚
<img alt="IMG_7528.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/450a4e05-ab38-94de-6297-f04f5f4d4b15.png" width="30%"></img>
 - 撮影開始からSketchfabに出力するまでにかかった時間:65分
     - 108枚撮り終えてから、メッシュ作成にかかった時間:6分
     - メッシュ作成後、Sketchfabに出力するまでにかかった時間:50分

:::note warn
撮影した写真の枚数、アップロードする時間帯、通信環境などによって、撮影開始からSketchfab出力までにかかる時間は変わります。（実際、25枚の時は、撮影開始からSketchfab出力まで20分程度でした。）
:::

</details>

# RealityScanの強み
 - 写真を撮った位置や角度がARで表示されるので、今までどのように写真を撮ってきたかが分かりやすい。
 - リアルタイムで、撮った写真がどれぐらい3Dオブジェクトをカバーしているかが分かる。これが分かると、「もっとこの位置の写真が必要だな」というのを考えることができる。
     - **これにより、「生成した3Dオブジェクトを見たら、この部分がおかしくなってた:sob:」みたいな事故が起こりにくくなる。**


# RealityScanの弱み
 - 写真を撮るごとに3Dオブジェクトのカバー率を計算をするので、時間がかかり、通信量が増える。
     - オフラインモードで写真を撮り、後から撮った写真をアップロードすることでこれらの問題は解決可能。
 - 生成された3DオブジェクトはSketchfabに出力されるので、3Dオブジェクトを使いたい場合は、Sketchfabからダウンロードする必要あり。
 - 写真を撮るとマナーモードにしていても、シャッター音が出るのでうるさい。


# RealityScanの使い方
公式ビデオを参考にして、重要そうなポイントをピックアップしていきたいと思います。
<iframe width="560" height="315" src="https://www.youtube.com/embed/HVkvHZCmVjU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

 - 直射日光が当たらず、どの方向から見ても光のあたり方が一定な物体を被写体にするといい。
     - 金属のように光沢があるものや、水やガラスのように透明なものはあまり良くないかも。
 - 撮影しているとARビューで、撮影位置や角度を確認することが出来る。
 - 被写体全体をカメラのフレームに収めながら、出来る限り近づいて写真を撮るのが良い。
     - 被写体が大きい場合などは、カメラのフレームをはみ出ても大丈夫。
 - 何枚か写真を撮るとAlignmentの質を表す、点群が現れる。
     - 赤色の点群は、もっと写真でカバーしないといけない所。 黄色の点群はそれほど問題のない所。緑色の点群はしっかりカバーが出来ている所。
     - 被写体が緑の点群で覆われるほど、質の高い3Dオブジェクトが生成される。
 - 画面右下のトリミングにボタンでスキャンする領域を決めることができる。
     - スキャンする領域を選択しておかないと、カメラフレームに収まる全てのものに対して計算をしてしまうので、トリミングボタンが表示されたら早めにスキャンする領域を選択した方が良さそう。
 - プレビューモードでは、その段階で生成される3DオブジェクトのMeshを確認できる。

# 参考文献

https://pc.watch.impress.co.jp/docs/news/1400595.html
[Flutter] あの赤いエラー画面をカスタマイズする

この記事はand factory.inc Advent Calendar 2022 5日目の記事です。
昨日は　@myoshita さんの [[Android] Github Actions + PythonでGoogle Playの段階リリース状態をチェックする](https://qiita.com/myoshita/items/3120329753cab7033d65) でした。

---

Flutterの開発時にエラー画面に遭遇したことのない人は少なくないと思います。debugモードで表示される画面は赤く、エラー感の強いあの画面はとても刺激が強いものになっていますが、release版ではグレーの画面で表示されます。

debug | release
--- | ---
![adbeem-20221204195409.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206165/885282e9-88f5-af9f-b619-a2ca5c3f9228.gif)|![screen_shot_release.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206165/111cf432-c750-f814-4ee7-67875c10b008.png)

debugモードで表示される画面はまだ開発者だけが目にするものですが、releaseモードで表示されるグレーの画面はユーザーに不安を与えてしまいますし、この画面から何をしたらいいのかがわからずアプリの体験を損なってしまう可能性が高いです。

もちろんこの画面が表示されないようにしっかりとしたQAプロセスをへてリリースされれば良いですが、不具合を１００％起こさないことは難しいため、もしもの時のためにエラー画面をカスタマイズすることができるか調査しました。


以下のようなコードによって実現していきます。

```dart
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      ...
      builder: (BuildContext context, Widget? widget) {
        ErrorWidget.builder = (FlutterErrorDetails errorDetails) {
          return MyErrorWidget(errorDetails: errorDetails);
        };
        return widget!;
      },
    );
  }
}
```

Widgetのbuild中にエラーが発生した場合`ErrorWidget.builder`を設定することで、この関数で設定したWidgetを表示することができます。
ErrorWidget.builderではデフォルト値として_defaultErrorWidgetBuilderが実行されエラーメッセージが整形されています。

framework.dart
```dart
  static ErrorWidgetBuilder builder = _defaultErrorWidgetBuilder;

  static Widget _defaultErrorWidgetBuilder(FlutterErrorDetails details) {
    String message = '';
    assert(() {
      message = '${_stringify(details.exception)}\nSee also: https://flutter.dev/docs/testing/errors';
      return true;
    }());
    final Object exception = details.exception;
    return ErrorWidget.withDetails(message: message, error: exception is FlutterError ? exception : null);
  }
```


結果的に以下のような６４ゴール＊ンアイゲームオーバー風画面を作成することができました。

![adbeem-20221204190816.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206165/65b249f5-e50b-66d7-31ed-65afa80270b7.gif)

今回は、CustomPainterを使って、四角形の下辺だけを二次ベジエ曲線による波形のPathを描いて塗りつぶしたものを高さを変更するAnimationによって実装しました。

# まとめ

グレーの画面をカスタマイズし、ユーザーに対してアプリを再起動を促したりすることで多少ユーザーの不安を減らすことができると思います。プロダクションのコードでは`kDebugMode`などでdebugモードとreleaseモードで表示される画面を分け、開発時には`FlutterErrorDetails.summary`を表示したり、バグレポートを起票する画面などに遷移させてあげることで開発者、QA担当者の体験を向上することにもつながるでしょう。

明日の[Advent Calendar](https://qiita.com/advent-calendar/2022/andfactory)の記事もよろしければご覧になってください。:santa:

リンク
- https://api.flutter.dev/flutter/widgets/ErrorWidget/builder.html
- https://docs.flutter.dev/testing/errors
- https://blog.codemagic.io/flutter-custom-painter/
- https://api.flutter.dev/flutter/foundation/FlutterErrorDetails-class.html
【Rails devise】Couldn't find User with 'id' = sign_out

# 状況
Rails6でdeviseを使用していると、以下のようなエラーが表示されログアウトができなくなることがある。
```
Couldn't find User with 'id' = sign_out
```
このエラーに掛かっている人はおそらく、ログアウトのメソッドとして以下のようにDELETEを指定しているだろう。
```erb
<%= link_to'ログアウト', destroy_user_session_path, method: :delete %>
```
しかし、DELETEを指定していてもメソッドがGETになってしまうことがあるようだ。（この点の詳細は私には分かりかねるので別の情報をご参照いただきたい。）

対処法には大きく以下の二つがある。

# 対処法①　ルーティングを設定する
ルーティングを以下のように設定し、GETリクエストをdestroy Actionへ渡す。
```ruby:config/routes.rb
devise_scope :user do
  get '/users/sign_out' => 'devise/sessions#destroy'
end
```
これでGETメソッドで取得されたリクエストをDLETEに変換することができる。

# 対処法②　deviseの設定を変える
devise.rbの設定を以下のように、:deleteから:getに変更。（デフォルトだと272行目あたり）

```ruby:config/initializers/devise.rb
  config.sign_out_via = :get
```
これを変更した後、サーバーを立て直す必要がある。ローカルでサーバーを立てている場合は```rails s```を、docker環境の場合はコンテナをビルドし直す必要がある。

これで、getメソッドによるログアウトが可能になる。

# 所感
関連する記事をいくつか確認したが、このようにある日突然、同じコードで同じ処理ができなくなるというのは、やはりなんか気持ち悪い。このようなエラーは自力で原因が分かりづらいので、ここに記すことで微力ながらどなたかの解決の一助となればと思う。

# 参考
https://ramka.hateblo.jp/entry/2017/08/02/004443

https://ramka.hateblo.jp/entry/2017/08/02/004443

https://nabelog.org/664/
【Bash】変数の文字列置き換え

## 変数の文字列置き換え

変数展開の際に以下のように記述すると変数内の値を置き換えられます。  

```sample.sh
SAMPLE=path/to/SAMPLE

echo ${SAMPLE#path}

```

```terminal
$ bash sample.sh
/to/SAMPLE
```

以下のような置き換えができます。 

|            記述            | 動作                                                               |
| :------------------------: | :----------------------------------------------------------------- |
|     ${変数名#パターン}     | 変数の値から「パターン」に前方一致（最短一致）した部分を削除。     |
|    ${変数名##パターン}     | 変数の値から「パターン」に前方一致（最長一致）した部分を削除。     |
|     ${変数名%パターン}     | 変数の値から「パターン」に後方一致（最短一致）した部分を削除。     |
|    ${変数名%%パターン}     | 変数の値から「パターン」に後方一致（最長一致）した部分を削除。     |
| ${変数名/パターン/文字列}  | 変数の値の「パターン」に最初に一致した部分を「文字列」に置き換え。 |
| ${変数名//パターン/文字列} | 変数の値の「パターン」に一致した部分すべてを「文字列」に置き換え。 |

上記のパターンの部分には以下を使用できます。  

|         パターン         | 説明              |
| :----------------------: | :---------------- |
|           `*`            | 0文字以上の文字列 |
|           `?`            | 1文字以上の文字列 |
|         `[文字]`         | `[]`内のいずれか  |
| `[^文字]`または`[!文字]` | `[]`内以外の文字  |
Splunk: マクロを展開する


###### 実施環境： Splunk Free 8.2.2

### 目的

以下のように、複数のマクロが使用されている SPL があるとします。

![WS000365.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/a4401743-cf08-242f-5564-c86846d08f0e.jpeg "展開前")

この SPL について、正確な処理の内容を確認するためにマクロを展開したい場面がときどきあります。
そのような場合、どうすればよいでしょうか。

### 方法

使用されているマクロを1つ1つ確認していってもよいのですが、もっと簡単な方法があります。

 SPL の入力フォームを選択した状態で、 Ctrl + Shift + E を同時に押してください。
すると以下のように、全てのマクロを一発で展開できます。

![WS000364.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/a48b4eeb-0bef-a7af-d5d9-0d7114555523.jpeg "マクロ展開")

ここで右下の「新しいサーチとして開きます」を押せば、マクロを展開した SPL でサーチを開きなおすことができます。

![WS000367.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/7e634c11-0085-2dca-b3c1-a450ed85edd8.jpeg "展開後")

覚えておくと便利です。
Discord Botを作ってみよう #03 - イベントを使ってみよう

# まえがき

[ひとりアドベントカレンダー](https://qiita.com/advent-calendar/2022/ukwhatn)という狂気の企画、4日目記事です。

# はじめに


この記事(群)は、Pythonと[Pycord](https://pycord.dev/)を利用してDiscord Botを開発しようとする方に向けたものです。

本記事群では、以下の流れでPycordの機能を紹介していきます。

>1. **[#01 - Hello, Pycord!](https://qiita.com/ukwhatn/items/c3abfbbd447f5802afa3)**
>2. **[#02 - スラッシュコマンドを使ってみよう](https://qiita.com/ukwhatn/items/48953e30ed67dee6fe38)**
>3. **#03 - イベントリスナを使ってみよう**(本記事)
>4. **[#04 - インタラクティブなGUIを作ってみよう]()**
>5. **[#05 - Cogを導入しよう]()**
>6. **[#06 - （番外編)デプロイ環境のはなし]()**

:::note warn
この記事は、対象読者を**Pythonの記法に関する基礎知識はあるが、公式ドキュメントだけで実装できるほど慣れても居ない方**としています。

もしこの記事を読んでもコードの意味がわからない場合は、基礎知識が不足している可能性があります。Paizaなどの入門サイトや技術書を参照しながら、足りない知識を補完していくことを推奨します。
:::

:::note
* **動作確認日:** 2022/12/3
* **各種バージョン**
    * Python: 3.10.7
    * Pycord: 2.3.1
:::

# discordにおけるイベント

今回は、[前回](https://qiita.com/ukwhatn/items/48953e30ed67dee6fe38)までで作ったBotを使って、イベントについて説明します。

## イベントとは？

これまで作ってきたBotのコードの中に、以下のような記述がありました。
```py
# 起動時に自動的に動くメソッド
# #03で詳しく説明します
@bot.event
async def on_ready():
    # 起動すると、実行したターミナルに"Hello!"と表示される
    print("Hello!")


# Botが見える場所でメッセージが投稿された時に動くメソッド
@bot.event
async def on_message(message: discord.Message):
    # メッセージ送信者がBot(自分を含む)だった場合は無視する
    if message.author.bot:
        return

    # メッセージが"hello"だった場合、"Hello!"と返信する
    if message.content == 'hello':
        await message.reply("Hello!")
```

この2つは、「イベント」を利用して動作するメソッドです。

「イベント」とは、**Botが見える範囲内で特定の動作や変更が行われた時に、任意の処理を実行するためのしくみ**のことです。

上の例で言えば、`on_ready`メソッドと`on_message`メソッドがそれにあたります。

`on_ready`メソッドは、`on_ready`、すなわちBotが起動して、コマンドなどを実行する準備ができたときに実行されます。

同様に、`on_message`メソッドは、`on_message`、すなわちBotが見える範囲で何らかのメッセージが投稿されたときに実行されます。

他にも、様々なイベントが存在します。
詳しくは、以下の公式リファレンスを参照してください。

* [Event Reference - Pycord Documentation](https://docs.pycord.dev/en/stable/api/events.html#)

## Intentsについて

このリファレンスにも記載のとおりですが、#01でさらっと触れた「Intents」は、このイベントに関わる要素です。

Intentsは、「必要なイベントだけを受け取る」ための機能です。
たとえば、Botインスタンスを生成する時に

```py
bot = discord.Bot(intents=discord.Intents(messages=True, reactions=True))
```
とすると、このBotは、メッセージとリアクションに関するイベントのみを受け取ります。

今回は説明の簡略化のために特権インテントを含むすべてのIntentsを有効にしていますが、今後あなたが何らかのBotを開発する際は、余裕があればここも気にしてみると良いと思います。

----


今日はここまで！

# このシリーズの他の記事

* **Discord Botを作ってみよう**
    1. **[#01 - Hello, Pycord!](https://qiita.com/ukwhatn/items/c3abfbbd447f5802afa3)**
    2. **[#02 - スラッシュコマンドを使ってみよう](https://qiita.com/ukwhatn/items/48953e30ed67dee6fe38)**
    3. **#03 - イベントリスナを使ってみよう**(本記事)
    4. **[#04 - インタラクティブなGUIを作ってみよう]()**
    5. **[#05 - Cogを導入しよう]()**
    6. **[#06 - （番外編)デプロイ環境のはなし]()**
Alibaba Cloud Machine Translationを試してみた

Intelligent Speech Interactionを試す前に、テキストの一般的な機械翻訳の機能について試してみました。
Alibaba Cloudの機械翻訳のサービスとして[**Machine translation**](https://www.alibabacloud.com/ja/product/machine-translation)があります。
※日本語版のドキュメントは2022/12/04時点では無いようです

# 対応言語
Alibaba CloudのMachine Translationでは、双方向翻訳と一方向翻訳があります。

## 双方向翻訳
双方向翻訳に対応している言語は以下の16言語です。
* 中国語
* 英語
* 韓国語
* 日本語
* フランス語
* スペイン語
* ポルトガル語
* イタリア語
* ロシア語
* アラビア語
* トルコ語
* インドネシア語
* ベトナム語
* タイ語
* ポーランド語
* ドイツ語

## 一方向翻訳
一方向翻訳の対応はこちら。
* 簡体字中国語　→　繁体字中国語
* 繁体字中国語　→　簡体字中国語
* 簡体字中国語　→　広東語

簡体字中国語と繁体字中国語は双方向なのでは？と思いました・・・。

# 料金
料金はリソースパッケージと従量課金制です。
リソースパッケージを購入した場合は、そのパッケージ内での価格となります。
従量課金制の場合は、毎月100万文字まで無料で、それ以降は33USD/100万文字となります。
また、購入したリソースパッケージを超える量を使用した場合は、超過分は従量課金制の金額が適用されます。
価格詳細は[こちら](https://www.alibabacloud.com/help/en/machine-translation/latest/product-pricing-introduction)からご確認ください。

# REST API
Machine Translationは、REST APIが準備されているのでそれを利用して機械翻訳を行います。
非常にシンプルな構成なので分かりやすいと思います。
REST API[ドキュメント](https://www.alibabacloud.com/help/en/machine-translation/latest/using-rest-api)

# SDK
Machine Translationには、.NET Framework用のSDKが準備されています。
環境への導入手順は[こちら](https://www.alibabacloud.com/help/en/machine-translation/latest/dotnet-sdk)。
対応している.NET Frameworkは3./4.0/4.5です。

# Alibaba Cloud側での準備
Alibaba Cloud側の準備手順は、[クイックスタート](https://www.alibabacloud.com/help/en/machine-translation/latest/quick-start-introduction)にありますが、順番が異なっている場合があるので参考程度に読んでください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254932/78d52d3b-7b4b-d603-a22a-ba404d0c0aef.png)
上記画面の左メニューから「APIテスト」をクリック。

![スクリーンショット 2022-12-04 204309.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254932/78208523-9885-9fbd-9ec0-4375e4c21330.png)
「サービスを有効にする」をクリック。

![スクリーンショット 2022-12-04 204701.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254932/bd0f6e46-1e09-ed91-cd33-27cd1f9798d2.png)
利用規約にチェックを付けて、「Activate Now」をクリック。

支払い管理で確認したところ、従量課金で契約されていました。
![スクリーンショット 2022-12-04 204940.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254932/13a72e54-a1d8-87ba-afd8-11ba97eb3091.png)

契約が終わってMachine Translationのコンソール画面に戻るとこの様な画面になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254932/7e139d4e-19c0-f384-412f-6afa608d4b5d.png)

# 翻訳比較
Alibaba Cloudの英語のドキュメントを利用して、Google翻訳とMachine Translation翻訳がどうなるか比較してみます。
今回は、Obuject Storage Serviceの概要[ドキュメント](https://www.alibabacloud.com/help/en/object-storage-service/latest/what-is-oss)(英語)の下記部分を利用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254932/9f2a60bb-1efe-d058-af80-a7bbda21de2b.png)

Google翻訳
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254932/b20e9d8d-0737-c65e-d21e-24be56442ce0.png)

Machine Translation翻訳(ブラウザでの翻訳機能はOFFにしています)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254932/1bc98d8e-5d3b-3d6f-4edc-da37e36f8079.png)

私の個人的な感想ですが、Machine Translateで翻訳した方が、自然な日本語に近いと感じました。
金融や医療分野など専門的な単語などが使用されているテキストの場合は、カスタマイズされたモデルエンジンを利用されるといいと思います。

# まとめ
専門用語が使われている場合は分からないですが、日常的な言葉で作成されているテキストでは予想以上に自然な文章で翻訳されていると思いました。
OAuth2.0を自分が理解できるレベルにかみ砕いたもの

# 記事の要旨

仕事ではあまりセキュリティ周りには触らないのですが，OAuth2.0が出てくるたびに「どういう仕組みだっけ」と調べ直すのが非生産的なので，自分なりの整理を記事として残しておいたというページです．

基本的に[こちらのページ](https://openid-foundation-japan.github.io/rfc6749.ja.html)を読み解きつつ，理解できなかったものはインターネット上の解説を見て補足しています．

## 1. 認証と認可

OAuth（オーオース）は認可（Authorization）のための公式ルールのようなもの．
「認可」とはリソースへの各種操作権限を付与する行為という理解で良いと思う．例えばこの記事を編集できるのは俺だけで，それは俺が記事の編集権限を「認可」されているから．
似たような言葉として認証（Authentication）があり，これは対象の身元を証明するという行為．本人だけが知っている情報（パスワード）や持っているモノ（指紋，デバイストークン）などを用いて証明する形になる．
適切な認可のためには認証が必要なのは言うまでもない．例えば俺以外の第三者にこの記事の編集権限が与えられてはいけない．なので認証と認可は混同されがちであるが，後述の事情もあり，これらは切り離して議論することが求められる．

## 2. 「認可」を切り離したいという要求

たとえば新しいTwitterアプリがリリースされたとする．
当然ながらアプリとして機能するためには俺のアカウントで投稿する権限や，プロフィールを参照する権限が必要だ．つまりこのTwitterアプリは，Twitter社が有する俺に関するリソースへの各種権限の「認可」を求めている．
さて，どうすれば良いだろうか．1つの解は，このTwitterアプリに俺のTwitterアカウントのパスワードを教えてあげるという方法だ．これは認証と認可を一体としたやり方で，例えば以下のリスクをはらんでいる．

- このアプリ会社のセキュリティが不十分だった場合，俺のTwitterアカウントの認証情報が流出し得る
- このアプリ会社自体が悪質で，俺の個人情報を盗もうとしている可能性がある

アプリ会社としても，「認証」という高難易度かつ責任が伴う行為にはあまり関わりたくないというのが本音だろう．彼らが望んでいるのはあくまで権限の「認可」でしかない．
ここに認証と認可を分離したいという要求が発生し，そのうちの「認可」の部分をカバーしているのが，OAuth2.0ということになる．

## 3. OAuth2.0における用語と前提

OAuth2.0で出てくる用語は以下のとおり．例として架空のTwitterクライアントアプリ「ツイツイ」を用いる．Twitter API周りは詳しくないのでそこは「なんとなく」で留めておいて欲しい．

| 用語 | 意味 | 例 |
| ---- | ---- | ---- |
| リソースオーナー | リソースに対して認可を出せる存在 | 俺（nk5jp） |
| クライアント | 認可を求めている存在 | Twitterアプリ「ツイツイ」 |
| リソースサーバ | リソースを提供する存在 | Twitter社のリソース提供API |
| 認可サーバ | 一連の認可行為を取りまとめてくれる存在 | Twitter社の認可API |

また、OAuth2.0を実施する上で以下の前提が成り立っている．

- 認可サーバはリソースオーナーを認証できる．つまり俺が事前にTwitterにアカウントを登録している．
- 認可サーバはクライアントを認証できる．つまり事前にアプリ開発会社が認可のための登録をしている．

なお、OAuth2.0には4つのタイプがあるが，今回は「認可コード」の方式に絞ることとする．また，リソースオーナーの各種処理はユーザエージェントが代行するものだが，今回はその辺りの概念は割愛する．

## 4. 認可の流れ

### 4.1 認証エンドポイントへの転送

まずはクライアント（「ツイツイ」アプリ）がリソースオーナー，つまり俺を「認証エンドポイント」と呼ばれる場所まで案内する．認証エンドポイントというのは，認可サーバの窓口の1つだと思ってくれれば良い．
クライアントは俺に対して「手続が終わったらまた来てくださいね」とだけ伝えて，一旦退場していく．

### 4.2 認可の確認

認可サーバはまず，クライアントが連れてきたリソースオーナー（俺）が何者かを確認する．前提でも述べた通り，認可サーバ（Twitter社）はパスワード認証などの規定の手続きを経て，俺が俺であることを認証することができる．
無事リソースオーナー（俺）の身元を特定した認可サーバは，「ツイツイを名乗る人が貴方のリソースに関して色々な権限をくれと言っていたが，問題ない？」と聞いてくる．俺が「良いですよ」と答えれば，認可サーバは「じゃあこれを持って行ってください」と，「認可コード」と呼ばれる1度しか使えない合言葉を渡してくる．これで認証エンドポイントにおける処理はいったん終了．

### 4.3 認可の依頼

俺は認可コードを持って改めてクライアント（「ツイツイ」）の元を訪れる．現実にはこの辺りはリダイレクトなどで自動的に処理されている．認可コードを受け取ったツイツイは，それを持って今度は自分自身が「トークンエンドポイント」と呼ばれる認可サーバ上のもう1つの窓口を訪れる．
ここで認可サーバは，やってきたクライアントが「ツイツイ」であることを認証する（これが出来ることは前提で述べた通り）．その上でツイツイは認可コードを提示する．認可サーバは以下のロジックで，申請の妥当性を判断する

- この男（クライアント）は間違いなくツイツイである
- この認可コードは，先ほどリソースオーナー本人（俺）に提供したコードと一致する
- そのときリソースオーナーを連れてきた申請者も自分をツイツイと名乗っていた
- この認可コードを先に提示してきた者は他にいない

妥当と判断したら，認可サーバはクライアントに「アクセストークン」を提供する．アクセストークンには「付与された権限の内容」と「有効期限」の情報が含まれている．

### 4.4 リソースの取得

無事アクセストークンをゲットしたツイツイは，リソースが必要であればアクセストークンを片手にTwitterのリソースサーバの元を訪れ，自信満々にアクセストークンを提示する．リソースサーバはそれが誰であれ，トークンの内容と有効期限が有効であれば正当に認可を受けた存在であると判定し，許される範囲でのリソース（Twitter上の俺のプロフィール情報など）を提供する．

## 5. 補足

言うまでもなく，アクセストークンが流出してしまうと勝手にツイートされてしまうなどの被害が生じる．よく「OAuth2.0を認証に使ってはいけない」と言われるのも，端的に言えばこのアクセストークンに「誰向けに発行した」という情報が含まれていないからだ．その辺りを補強した方式がOpenID Connect（OIDC）と呼ばれるものになる．
しかし，パスワードそのものが漏洩したわけではないので，OAuth2.0による認可は冒頭で述べたようなパスワードそのものを提供する方式と比較してセキュリティは保たれる．アカウントを乗っ取ろうにも「現在のパスワード」がわからないので変更できないというわけだ．
Joining and bonding techniques, ボッシュ自動車handbook(英語)11版A.C.<6>

Automotive Handbook countdown Calendar 2022

https://qiita.com/advent-calendar/2022/automotivehandbook

12/6 参加記事です。

ボッシュ自動車handbook(英語)11版(0-1) 課題と記事一覧new

https://qiita.com/kaizen_nagoya/items/a9d2887bf2a7598dc8e5

# Contents
Motor vehicle, 28
Basic principles, 32
Mathematics and methods, 204
Materials, 258
Machine parts, 354
Joining and bonding techniques, 426
Vehicle physics, 462
Operating fluids, 538
Refrigerants for air-conditioning systems, 591
Drivetrain(駆動系), 594
Internal-combustion engines(内燃機関),642
Management for spark-ignition engines,800
Gasoline-engine operation with alternative fuels, 886
Management for diesel engines, 906
Electrification of the drive, 970
Chassis systems, 1108
Vehicle bodies, 1310
Comfort and convenience, 1392
Safety systems in the motor vehicle, 1410
Vehicle security systems, 1430
Automotive electrics, 1450
Vehicle electrical systems for hybrid and electric vehicles, 1560
Automotive electronics, 1620
Entertainment 1780
Drive assistance and sensors, 1804
Drive assistance systems 1872
Future of automated driving 1934
Appendics, 1940
# Mathematics and methods
no. Number
p. page
v. views
g. goods.
s. stocks

|no.|title|P.|v.|g.|s.|
|:----|:----|--:|--:|--:|--:|
|28|Detachable connections,https://qiita.com/kaizen_nagoya/items/e38417d45c7198add78f|426|131|0|0|
|29|Permanent joints https://qiita.com/kaizen_nagoya/items/b85bce67a668f25421bd|450|126|0|0|


# 自己参考資料(self reference)

ボッシュ自動車ハンドブック 

https://qiita.com/kaizen_nagoya/items/8e330ce57880f04d71d9

ボッシュ自動車handbook(英語)10版　目次

https://qiita.com/kaizen_nagoya/items/57c799ff544c96efdea9

自動車工学とBosch Vehicle Handbook

https://qiita.com/kaizen_nagoya/items/d13ff6b0e4d7c8907c0d



# Advent Calendar 2022

今年企画した４つのAdvent Calendarと、それぞれの記事一つをご紹介します。

AUTOSAR Advent Calendar 2022

https://qiita.com/advent-calendar/2022/autosar

AUTOSAR References to ISO, IEC, ITU, IEEE, RFC and SEA etc.

https://qiita.com/kaizen_nagoya/items/d7d252211e10a79516df

Automotive Handbook Advent Calendar 2022

https://qiita.com/advent-calendar/2022/automotivehandbook

Basic principles, ボッシュ自動車handbook(英語)11版まとめ<2>

https://qiita.com/kaizen_nagoya/items/24a1ba5da3d09b2a95d1


2022 いいねをいただいた記事ランキング(O.K.版) Advent Calendar 2022

https://qiita.com/advent-calendar/2022/goods

2022年１月下旬　いいねをいただいた記事　16

https://qiita.com/kaizen_nagoya/items/0ee589a8edaeab24fd2a

AdCale(O.K.) Advent Calendar 2022

https://qiita.com/advent-calendar/2022/adventcalendar2022

「会議は15分未満」に。小耳にはさんだ話。

https://qiita.com/kaizen_nagoya/items/510c47c5d1e8d03145db

AdvencCalendar2022 報告

https://qiita.com/kaizen_nagoya/items/5b4b99cb9ad571f4094b

誤差の評価が苦手（専門分野以外）

https://qiita.com/kaizen_nagoya/items/cc3a50827b24ab80985f


 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

# 文書履歴(document history)
ver. 0.01 初稿 　20221206
SwiftUI + OpenCV4

社内で治具にセットした製品の間隔を毎月測定する必要がでてきたため、画像で測定できないか試してみた。

# CMake のインストール
CMake 3.25.1 は NG。 3.24.3 にダウングレードすることによりエラー回避できた。
brew でインストールできなかったので、CMake のサイトからバイナリをダウンロードしてインストール。
zsh のパスを通す。
```~/.zshrc
export PATH=/Applications/CMake.app/Contents/bin:$PATH
```

# OpenCV のソースを準備

git を使ってソースをダウンロード
```
cd ~/git
git clone https://github.com/opencv/opencv.git -b 4.5.5
git clone https://github.com/opencv/opencv_contrib.git -b 4.5.5
```
contrib の module の下にある aruco を opencv の module フォルダにコピー。
※実際には、contrib をコピーする前に、一度コンパイルできるか確認した。
4.6.0 は、ArUco をコピーする前はコンパイルは通ったが、ArUco をコピーした後にエラーになったので、4.5.5 にした。



# OpenCV のコンパイル

Xcode のバージョンを選択。これをやらないとエラーになる。
```
sudo xcode-select --switch /Applications/Xcode.app
sudo xcodebuild -license
```

これも必要かぁ？？
```
cd /
sudo ln -s /Applications/Xcode.app/Contents/Developer Developer
```

ビルド
```
python opencv/platforms/ios/build_framework.py ios --iphoneos_archs=arm64 --iphonesimulator_archs=x86_64 
```
これでやっとでエラーなしで通った。

# opencv2.framework の設定
+ ビルドされた、ios フォルダ内の opencv2.framework をプロジェクトに追加。
+ libc++.tbd を追加





編集中、、、


# 参考にしたサイト
+ [iOSでOpenCV](https://qiita.com/john-rocky/items/0ac8ffcbf9b8f4227fd5)
+ [Swiftで OpenCV の ArUco モジュールを使う](https://qiita.com/Motonaga/items/d090826de806a2350ee2)
+ [XCodeでOpenCV](https://blog.goo.ne.jp/yoossh/e/5cb9520d392d79da3dff13da05e76e8a)
+ [OpenCV が Objective-C / Swift で使えるようになります & 使ってみた](https://qiita.com/treastrain/items/0090d1103033b20de054)
Machine parts, ボッシュ自動車handbook(英語)11版A.C.<5>

Automotive Handbook countdown Calendar 2022

https://qiita.com/advent-calendar/2022/automotivehandbook

12/3 参加記事です。

ボッシュ自動車handbook(英語)11版(0-1) 課題と記事一覧new

https://qiita.com/kaizen_nagoya/items/a9d2887bf2a7598dc8e5

# Contents
Motor vehicle, 28
Basic principles, 32
Mathematics and methods, 204
Materials, 258
Machine parts, 354
Joining and bonding techniques, 426
Vehicle physics, 462
Operating fluids, 538
Refrigerants for air-conditioning systems, 591
Drivetrain(駆動系), 594
Internal-combustion engines(内燃機関),642
Management for spark-ignition engines,800
Gasoline-engine operation with alternative fuels, 886
Management for diesel engines, 906
Electrification of the drive, 970
Chassis systems, 1108
Vehicle bodies, 1310
Comfort and convenience, 1392
Safety systems in the motor vehicle, 1410
Vehicle security systems, 1430
Automotive electrics, 1450
Vehicle electrical systems for hybrid and electric vehicles, 1560
Automotive electronics, 1620
Entertainment 1780
Drive assistance and sensors, 1804
Drive assistance systems 1872
Future of automated driving 1934
Appendics, 1940
# Mathematics and methods
no. Number
p. page
v. views
g. goods.
s. stocks

|no.|title|P.|v.|g.|s.|
|:----|:----|--:|--:|--:|--:|
|22|Tolerances,https://qiita.com/kaizen_nagoya/items/e5fdd5a31d8a6380d9c9|354|131|0|0|
|23|Axels and shafts https://qiita.com/kaizen_nagoya/items/deda75006e68b899b93b|359|134|0|0|
|24|Springs https://qiita.com/kaizen_nagoya/items/9658320617d37cc21828|362|87|0|0|
|25| Friction bearings, https://qiita.com/kaizen_nagoya/items/89e8b903f743b3df2743|370|108|0|0|
|26|Rolling bearings  https://qiita.com/kaizen_nagoya/items/89e8b903f743b3df2743 |378|0|0|
|27|Seals https://qiita.com/kaizen_nagoya/items/5195c291b3c3ead5d843|384|0|0|


# 自己参考資料(self reference)

ボッシュ自動車ハンドブック 

https://qiita.com/kaizen_nagoya/items/8e330ce57880f04d71d9

ボッシュ自動車handbook(英語)10版　目次

https://qiita.com/kaizen_nagoya/items/57c799ff544c96efdea9

自動車工学とBosch Vehicle Handbook

https://qiita.com/kaizen_nagoya/items/d13ff6b0e4d7c8907c0d



# Advent Calendar 2022

今年企画した４つのAdvent Calendarと、それぞれの記事一つをご紹介します。

AUTOSAR Advent Calendar 2022

https://qiita.com/advent-calendar/2022/autosar

AUTOSAR References to ISO, IEC, ITU, IEEE, RFC and SEA etc.

https://qiita.com/kaizen_nagoya/items/d7d252211e10a79516df

Automotive Handbook Advent Calendar 2022

https://qiita.com/advent-calendar/2022/automotivehandbook

Basic principles, ボッシュ自動車handbook(英語)11版まとめ<2>

https://qiita.com/kaizen_nagoya/items/24a1ba5da3d09b2a95d1


2022 いいねをいただいた記事ランキング(O.K.版) Advent Calendar 2022

https://qiita.com/advent-calendar/2022/goods

2022年１月下旬　いいねをいただいた記事　16

https://qiita.com/kaizen_nagoya/items/0ee589a8edaeab24fd2a

AdCale(O.K.) Advent Calendar 2022

https://qiita.com/advent-calendar/2022/adventcalendar2022

「会議は15分未満」に。小耳にはさんだ話。

https://qiita.com/kaizen_nagoya/items/510c47c5d1e8d03145db

AdvencCalendar2022 報告

https://qiita.com/kaizen_nagoya/items/5b4b99cb9ad571f4094b

誤差の評価が苦手（専門分野以外）

https://qiita.com/kaizen_nagoya/items/cc3a50827b24ab80985f

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

# 文書履歴(document history)
ver. 0.01 初稿 　20221204
WEBアプリケーションで同じアクションで複数のメソッドを受け付けるのはアンチパターンではないかという主張

# TL;DR
POST/PUT(PATCH)/DELETE のアクションではその処理でビューを表示せず、リダイレクトしてGETのアクションで表示するのが良い

# 主張
同じURLでGETとその他（POST/PUT(PATCH)/DELETE)を同じアクションで受けるのはアンチパターンではないか

# 前提条件
古めのフレームワークだと、コントローラーを作り、アクションとなるメソッドを作れば自動的にルーティングしてくれる。
そのため、そのアクションの中でGETかPOSTを判断して処理を変更する。例えば下記のようなレコードを作成するような処理。

```php
public function create()
{
    if ($this->request->is('POST') {
        ... 作成処理
        $this->flash('作成しました！');
    }

    return view('create');
}
```

この場合、例えば https://example.com/hoge/create にアクセスすると GET の処理になり、 create のビューが表示され、その中で POST するとその内容で hoge のレコードが作成されるというような設計。

# 問題点
この場合、スマホなどのブラウザではそのページで放置したまま、ブラウザのプロセスを切り、再度ブラウザを復帰させると同じリクエストを発行してしまう。
それがトリガーとなり、同じレコードを複数作ってしまう。更新や削除でも同様。

実例としては、例えばフリマアプリなどでサンキューページをPOSTリクエストでリダイレクトせずにそのアクションでビューを表示している場合、同じリクエストが発行され重複オーダーをしてしまうなど。
サンキューページが表示されたらそこでタブを削除せず放置し、何かの拍子にそのタブを開くなどはよくあることだろう。

# 対処法
・RESTfulなアクションを意識し、GET/POSTなどは同じアクションで受けない。 Laravel なら create/store edit/update などを明示的に分けている。
・処理をするアクションではビューを表示せず対応したアクションにリダイレクトする。

上記の例では下記のようにすると良さそう。

```
public function create()
{
    return view('create');
}

public function store()
{
    ... 作成処理
    $this->flash('作成しました！');

    return redirect('create'); // GET のアクションにリダイレクトする！
}
```

こうすることで、復帰してもたかだかレコードを取得（GET）するだけでレコードの追加変更などの影響のない処理になる
【スクレイピング】ピンポイントでHTMLの要素を取得しよう

スクレイピングをしてた時にどーしても取れない要素があったがとんでもないアホなやり方をしてたので自分への戒めとしてメモしたい。

とある求人サイトで会社名、住所、電話番号のスクレイピングを試みた。

会社名はhタグでidもついてる。これは簡単に取れた。しかし問題は住所、電話番号。

```
<tbody id="w_7_detail_1_1-tbody">
                <tr>
                        <td class="w_7_detail_1_1-td-label" id="w_7_detail_1_1-td-address">住所</td>
                        <td class="w_7_detail_1_1-td-value">福岡市○○区○○町111-111</td>
                </tr>
        
                <tr>
                        <td class="w_7_detail_1_1-td-label" id="w_7_detail_1_1-td-phone">電話番号</td>
                        <td class="w_7_detail_1_1-td-value">090-1111-2222</td>
                </tr>
</tbody>
```


検証ツールで見るとこれら二つはtbodyの中のtrタグ、tdタグに入ってる。

しかしよく見ると・・・



```<td class="w_7_detail_1_1-td-value">福岡市○○区○○町111-111</td>```


```<td class="w_7_detail_1_1-td-value">090-1111-2222</td>```

classが全く同じなのだ。

なのでこれら二つを一個ずつ取るしかない。find_allでとってforで回す、そして配列番号で取得できるじゃないかと思いこんなコードを書いてみた。

```python:check.py
t_body = soup_3.find('tbody', id='w_7_detail_1_1-tbody').find_all('td', class_='w_7_detail_1_1-td-value')
    print(name)
    for i in t_body:
        if t_body[0]:
            company_adress = i.text
            print(company_adress)
        elif t_body[1]:
            company_number = i.text
            print(company_number)
    
    
        d_list.append({
            'name': name,
            'url': company_adress,
            'number': company_number
            })
        print(d_list[-1])

```

一番上でtbodyを一つとってその後で全てのtdを取得。その下でforを回してます。

もしtdの配列０番目があるならcompany_adressに格納。
そんでもってもし1番目があるならcompany_numberに格納。

取得した結果を空の配列d_listに格納。余裕余裕〜

と思いきや

```
ホテル　南国アイランド
福岡市○○区○○町111-111
Traceback (most recent call last):
  File "/Users/sasaki/Desktop/work-scraping/check.py", line 52, in <module>
    'number': company_number
NameError: name 'company_number' is not defined
(scraping-work) (base)

```

一応ホテル名と住所は取れた。だがしかし電話番号が取れない！
company_numberが定義されてない？目の節穴かお前は！とエラーに怒ってもしょうがない。

色々試行錯誤し行き着いた結果・・

### if文いらねくね？


と思い下記のコードに修正

```python:check.py

    t_body = soup_3.find('tbody', id='w_7_detail_1_1-tbody').find_all('td', class_='w_7_detail_1_1-td-value')[0]
    t_body1 = soup_3.find('tbody', id='w_7_detail_1_1-tbody').find_all('td', class_='w_7_detail_1_1-td-value')[1]
    print(name)
    company_adress = t_body.text
    company_number = t_body1.text
    print(company_adress)
    print(company_number)
    d_list.append({
        'name': name,
        'url': company_adress,
        'number': company_number
        })
    print(d_list[-1])
```

最初にfind_allで取ったらその直後に配列指定👇。

![スクリーンショット 2022-12-04 11.59.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2980135/18bfd974-d488-342a-cf30-2ec526e00b8c.png)

あっさり成功。ここまで４時間かかりました。

自分バカすぎる・・なぜifを使おうと思った・・



ここで得た教訓はなるべくシンプルにコードを書こうと思いました。
親要素、子要素を気にしすぎると訳わからなくなるし、直感的に取得するのが一番の近道だと思う。
suspend関数ってなに？

# はじめに
今回はKotlinを使っていて自然と目にしていたsuspend関数について記事にします

# suspend関数
suspend関数とは　コルーチンを使用する中で非同期の処理を書き込む関数です
ですが、suspendを関数の修飾誌子としてつけられた関数内の処理が自動的に非同期になるわけではないので、非同期で実行したい場合は**明示的に**非同期処理を指定する必要があるようです。
では、suspend関数では何ができるのかというと
**別のsuspend関数を呼び出すことができる**非同期処理の仕組みをもった関数の事です。





# 参考
[Kotlin の Coroutine で suspend 関数を理解する](https://qiita.com/duke105/items/b5be074c79c6bed4d560)
[Kotlin v1.7.21](https://kotlinlang.org/docs/flow.html#suspending-functions)
[KotlinによるAndroidの非同期処理](https://codezine.jp/article/detail/13407)

# おわりに
suspendを訳すると、「停止する」というものが出てきますが、suspend関数はスレッドをブロックする代わりに、停止・中断するものと解釈するとかなりわかりやすい気がしました
ここまで何個かコルーチンについての記事を書きましたが、コードを読むときに困らない程度の理解でしか記事が書けていないので、使いこなせるレベルで理解が進んだときに自分の記事と見比べながら新たに記事にできればいいなと思いました。
M5Stack 　文字表示の位置を固定

# 概要
M5stackでディスプレイ上の文字表示の位置を固定したい！
この記事では、`setCursor()`関数を使って文字表示位置を指定する方法を解説します。

# 関数`setCursor()`
M5stackでディスプレイに文字を表示したいとき、`M5.Lcd.print()`を使います。
M5.Lcd.print()は座標が指定できないので、文字表示の位置を固定したい場合、あらかじめカーソルをセットしましょう。
カーソル位置を指定する必要があります。

そのために使う関数が、`M5.Lcd.setCursor(x, y, font)`
です。(fontは省略可）

## `setCursor()`の使い方

以下のコードでは、"test"という文字を座標(x,y) = (0,30)の位置に表示させています。

```c++:例
#include <M5Core2.h>

void setup() {
  M5.begin();
  M5.Lcd.setCursor(0, 30);
  M5.Lcd.print("test");
}

void loop() {
}

```

### ポイント
- 座標(x, y)の単位はピクセルで、(0, 0)はディスプレイの左上を指します。

## `setCursor()`はどんなとき便利？
`setCursor()`が特に便利なのは、 **センサーの値を連続して取得し、それをディスプレイに表示する場合です。**
センサーの値を連続して取得するとき、`M5.Lcd.print()`は座標が指定できないので、いずれ新しく取得した値がディスプレイに表示できなくなります。
そんなとき、`setCursor()`を使いましょう。

以下のコードでは、`sensor1`,`sensor2`,`sensor3`にセンサーの値が次々格納されていく，と仮定しています。
```c++:例
void loop() {
  M5.Lcd.setCursor(0, 30);
  M5.Lcd.printf("sensor1, %d",sensor1);
  
  M5.Lcd.setCursor(0, 40);
  M5.Lcd.printf("sensor1, %d",sensor1);
  
  M5.Lcd.setCursor(0, 50);
  M5.Lcd.printf("sensor1, %d",sensor1);
}

```

このように書くと、`sensor1`,`sensor2`,`sensor3`の値が同じ位置に表示され便利です。


### ポイント
```c++:
M5.Lcd.print("sensor1, %d",sensor1);
```
の%dはフォーマット指定子といって、`sensor1`が`int型`であることを示しています。

### フォーマット指定子の例
| フォーマット指定子 | 意味                      | 例                          |
|-------------------|-------------------------|----------------------------|
| `%d`              | 整数 (int)             | `123`                      |
| `%f`              | 浮動小数点 (float)      | `123.45`                   |
| `%s`              | 文字列 (string)         | `"Hello"`                  |

詳しいフォーマット指定子の使い方は[こちら](https://kurobekoblog.com/arduino_sprint)を参考にしてください。


# 参考にしたページ
・M5stackドキュメンテーション
https://docs.m5stack.com/en/api/core2/lcd_api

・フォーマット指定子について
https://kurobekoblog.com/arduino_sprint
[Servicenow]サービスカタログのWFを動かすために必要なこと

今年もこの時期が参りましたね！
今年のAdvent Calendar第1弾はサービスカタログについて記述して行きます。

# サービスカタログ用に作成したWF（ワークフロー）を動かすために必要な設定
個人インスタンスにDemoデータを入れて使用していると気づかないこと、及びITSMの研修では習った記憶がない設定について記載いたします。

## WFが動く仕組み

### まずはDemoデータを見ていきましょう。
Samsung Galaxy S7のカタログアイテムを見ていきましょう。
カタログアイテムの詳細の設定については割愛しますが、Workflow：「Service Catalog Item Request」が設定されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636124/c875eb8a-a045-01e9-a7d0-d36004974572.png)

なので、<font color="Red">**Demoデータが入っていない環境**</font>に自作のサービスカタログを作りたい場合は、以下を定義すればいいように見えます。
- カタログアイテム
- カタログアイテムで使用するWF

:::note warn
ただし、実際にはこれを定義しただけでは、カタログアイテムで申請を上げてもワークフローが動きません。
:::


## Demoデータにカタログで注文したときにまず動くFlowが存在する。
実は、Demoデータにはカタログの注文ボタンを押すと動くflowがDemoデータに存在しているのです！！
サービスカタログをデバッグすると、以下のFlowが動いていることに気づきます。
- Service Catalog Request

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636124/26ac26dd-1f1c-5861-25da-119d01f0ff93.png)

:::note alert
ただし、このFlowはDemoデータであり、Demoデータを入れていないPJ用などのインスタンスには存在しません。flowを自作する必要があります。
:::

「Service Catalog Request」で行っている処理は処理内容はシンプルで、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636124/3a993819-6b5b-e10f-07cc-e798ac5cc4fa.png)


- 注文金額が1$以下の場合：無条件で要求レコードを承認
- 注文金額が1$よりも高い場合：承認者を設定し、承認者の承認・却下を受けて要求レコードを更新する。
⇒つまり、要求レコードのステータスを更新する何かしらの処理が必要になります。

## サービスカタログで自作のWFを動かすためには・・・
上記をまとめると自作のサービスカタログを作りたい場合は、最低限以下3つを定義する必要があります。
1\.カタログアイテム
<font color="Red">**2\.カタログアイテムにおいて要求レコードを承認させるための処理（Flowやビジネスルールなど）**</font>
3\.カタログアイテムにおいて実際に行いたい処理

2の処理を見落としがちなので、十分に注意しましょう！
アカデミアポッター 不死鳥の博士学生

この記事は[闇の魔術に対する防衛術](https://qiita.com/advent-calendar/2022/yaminomajutu)7日目の記事です。

Qiitaではご無沙汰しております。青ポス（[@bluepost125](https://twitter.com/bluepost125)）です。年々闇の魔術のキレが落ちていましたが、今年は飛び切りのネタが入荷したので書いておきます。

:::note info
この記事を特に読んでほしい人
* B4や修士で研究に行き詰っている人
* 修士を修了して博士に行くか就職するか迷っている人
:::


# 経緯
5年ほど前にアカデミアに囚われていた人です。この後囚われの身から解放されますが、実はこの度再びアカデミアに戻ることになったので、体験談を書いておきます。

過去作：若さゆえの過ちでかなり独りよがりな文書ですが、戒めとして残しておきます。

https://qiita.com/bluepost59/items/a08c0eb0a57f8b28abdf

# 前編：懺悔と教訓
学生時代、自分は典型的な[モヒカン](https://qiita.com/kaityo256/items/d7d8f7a0e522895c8f5d)でした。

他者へのリスペクトがまるでなく、使っている技術がイケてるかイケていないかでしか判断できていませんでした。その精神とは裏腹に実力はまるで不足していて、「イケてる」と言われるツールをかじってはやめ、かじってはやめを繰り返していました。そしてうまくいかないことを全部研究室のせいにしてこのような文書を書いたりしていたわけです。

具体的には下記です。

* **CUIはイケている、GUIは情弱インターフェース**<br>（と言って、研究室にカレイダグラフのライセンスがあるのに、グラフの目盛りの大きさを変えるだけでEmacsを開いてウンウンうなる）
* **Pythonはイケてるので、任意のインターフェースはPythonにも開かれているべき**<br>（と言って用意されているシェルコマンドをsubprocessで叩くだけのライブラリを誰に頼まれたでもないのに作る）
* **GnuplotよりMatplotlibの方がイケている**<br>（と研究そっちのけで機能的には今動いているコードを置き換えるだけのコードを1週間かけて作る）
* **最近の言語はオブジェクト指向で書かないと雑魚**<br>（しかし使い方がよくわからないのにOOPにしようとするので、無駄にきれいにするために1週間が1か月になる）
* **コードの管理は当然Git** <br>（でもmaster commitして、revertしようとしてコンフリクトが起きて、それにイラついてgit reset --hardしたところで嫌になってやめる） 
* **Officeなんてプロプライエタリなソフトはアカデミアにふさわしくない、理系ならTeXで書いてなんぼ**<br>（枚数制限が厳しくレイアウトを詰め込まないといけないスライドもbeamerで作ろうとする。しかも1か月くらいかけて）

その結果生まれた魔物が「アカデミアの囚人」だったわけです。確かに、研究室の指導体制が十分ではなかったことは今考えても否めません。しかしうまくいかないことのすべてがそれに由来するわけでは決してありません。

## 教訓
* **作業によって本当に満たすべき要件を意識すること**<br> ```上述の状況に問題意識を持ってリファクタリングやツールの導入など改善の努力をしても、それは努力したとみなされない```のは**当たり前**。だってリファクタリングやツールの研究をする研究室ではないから。目的意識がちゃんと共有されていない。作業をするときは<ins>本当に優先されるべき目標は何かを考える。</ins>

* **他者へのリスペクトを払うこと**<br>仮に今あるシステムがイケてなかったとしても、それ相応の理由があるかもしれない。本当に技術不足であったとしても、作った人を責めても何も変わらないし、ゼロよりは動くものがある方がはるかにマシなので、作った人の仕事も認められるべき。<ins>過去の自分も今は別人なのでリスペクトを払う対象である。</ins>
* **エンドユーザー目線でモノづくりをすること**<br>「やりたいこと」「作りたいこと」を第一にしてろくに検討もせずに突っ走ることは自由研究でやるべきで、本業としてやるべきではない。仮に他のメンバーが習得していない技術を使ったツールを作ったとしても、作っただけだと誰も保守できないし使い勝手がいいとは限らないので使われなくなる。
* **理解してもらうために自分も労力を払うこと**<br>「それくらいわかってくれや」と言っていいのは相手が知ったかぶりをしてたときだけ。先生の時間も有限だし、自分は特別な学生でもない。

# 後編：不死鳥の博士学生
アカデミアから企業に異世界転生して早4年半となる今年、不死鳥のごとく博士学生として大学院に戻ってきました。

当時の研究室の悪い部分は半分くらい変わっていて、残りを立て直しているところです。

## やってること
現在進行中です。

###  Gitを導入・布教した
バージョン管理がなかったのは確かに問題です。そこでGitを導入しました。嘘だろって思うけど、今までなかったんです。

研究室でGitをちゃんとお作法も含めて理解している人がいなかったので、セミナーを主宰して布教しています。

### リファクタした
昔は「この書き方よくないけど、直るかどうかわからないし研究に支障が出ても困るし」というところは放置していましたが、これを機に一つ一つ潰していくことにしました。

具体的にやったのは下記です。
* フォーマッタを阻害するGoTo文を一掃した
* フォーマッタをかけた

## まとめ
正直手が回っていない部分も多いですが、なんとか頑張ってます。詳しい生き様はnoteやブログに書いてるので関心があれば見てください。

https://bluepost69.hatenablog.com/
【React】URLが[Object%20Object]になった時。〜私の場合の話〜

## はじめに
細かい原因などが調査できていないです。
Reactで動的なURLを生成した際に、console上に500エラーが出ていました。

具体的にどのような感じだったかは忘れてしまったのですが、`[Object%20Object]`という内容を吐いていたことは覚えています。本記事ではその時の対応をパッとまとめてみます。

## 原因と思われる箇所
条件分岐で、該当しないはずの条件の戻り値が不適切だった。

こんな感じのコードでした。おぼろげに。

```jsx

const RetinaRatio = 2

const imagePath = () => {
    return (window.devicePixelRatio == RetinaRatio ? require("imageのパス") : {})
}

const url = BASE_URL + imagePath
```

`require("imageのパス")`の方が呼び出されているにも関わらず、戻り値の方の`{}`に反応してエラーが返っていました。

## 修正方法
`{}`を`""`に修正したらエラーが出なくなりました。
確かに戻り値の型が場合によって変わるのは変ですし、`{}`を返してURLが生成されるとそれはそれで良くないように思います。

これがなぜ起きたのかはまだ調べられていませんが、ふと思い出したのでまとめておきました。
Goの//lineコメントを君は知っているか？

## コメントディレクティブ

どうも[ナレッジワーク](https://tenn.in/kw)の[tenntenn](https://tenn.in)です。

Goには、`//go:noescape`や`//go:linkname`などのコメントでコンパイラへの指示を記述するコメントディレクティブがあります。一応、[ドキュメント](https://pkg.go.dev/cmd/compile#hdr-Compiler_Directives)には記載がありますが、多くのGoエンジニアはあまり機会はないでしょう。

ドキュメントを読むと`//line`で始まるコメントは特別な意味を持つことが分かります。ここではこのlineディレクティブについて解説します。

## lineディレクティブ

ドキュメントには、以下のように記述した場合に、lineディレクティブとして認識されるようです。行コメントだけはなく、ブロックコメントも対象となります。`//`や`/*`の後ろにスペースを含んでは行けなかったり、`:`が必ず含まれていなければならなかったりと、細かなルールがあります。

```
//line :line
//line :line:col
//line filename:line
//line filename:line:col
/*line :line*/
/*line :line:col*/
/*line filename:line*/
/*line filename:line:col*/
```

lineディレクティブには、ファイル名、行、列を書けます。`//line`で始まる行コメントの場合は、次の行の先頭の文字が、そのファイル名、行、列であるようにコンパイラに指示します。

ファイル名を省略すると、直前のlineディレクティブによる指示と同じ、はじめてのlineディレクティブの場合は元のファイル名になります。

列を省略すると、次に列が判明する（他のlineディレクティブで）まで、その範囲は列が不明となり、コンパイラはエラーなどの報告で列情報を使用しません。

ブロックコメントで書いた場合は、`*/`直後の文字から対象となります。それでは、実際に書いてみましょう。次のように、2行目に`package`句も書かずにいきなり`Error`と書いてみます。

```go
//line hoge.go:100
Error
```

1行目にlineディレクティブがあるため、本来なら2行目でコンパイラエラーになるはずですが、コンパイルしようとすると次のようなエラーがでます。

```
$ go build a.go
hoge.go:100: expected 'package', found Error
```

`hoge.go`の100行目でエラーが発生していることになっています。ファイル名だけではなく、行数も変わっています。また、列は表示されていません。

それでは、次のコードはどうなるでしょうか。1行目にエラーがあります。

```go
/*line fuga.go:200:10*/Error
```

ビルドしてみましょう。次のようなエラーが表示されます。

```
$ go run b.go
fuga.go:200:10: expected 'package', found Error
```

今度は列も表示されました。面白いですね。

## 何に使われているのか？

それではこの機能は何のためにあるのでしょうか？
実際に使われている箇所はあるのでしょうか？

実は、`go test -cover`を実行した際に内部で実行される`go tool cover`というカバレッジを計測するためのコードを対象のGoファイルに差し込むためのツールで使われています。

たとえば、次のようなコード`a.go`があった場合を考えます。

```go
package a

func f() {
	if true {
		println("A")
	}
	println("B")
}

```

`go tool cover -mode set a.go`を実行してみます。そうすると、次のようなソースコードが生成されます。

```go
//line a.go:1
package a

func f() {GoCover.Count[0] = 1;
	if true {GoCover.Count[2] = 1;
		println("A")
	}
	GoCover.Count[1] = 1;println("B")
}

var GoCover = struct {
	Count     [3]uint32
	Pos       [3 * 3]uint32
	NumStmt   [3]uint16
} {
	Pos: [3 * 3]uint32{
		3, 4, 0xa000a, // [0]
		7, 7, 0xe0002, // [1]
		4, 6, 0x3000a, // [2]
	},
	NumStmt: [3]uint16{
		1, // 0
		1, // 1
		1, // 2
	},
}

```

1行目にlineディレクティブが記述されています。`go test -cover`を実行すると、`go tool cover`が生成したコードが元のコードの代わりにコンパイルに使用されます。そのため、コンパイルエラーがあった場合、元のファイルと違う名前でエラーメッセージが表示されてしまうため、lineディレクティブでファイル名を変更することで違和感が無いようにしています。

生成されたコードをよく見ると、ファイルの末尾以外では改行を増やさないようにコードを追加しているのが分かります。コンパイラエラーなどで行数を表示する際に変わってしまわないように工夫がされています。

`go tool cover`と同じように、元のソースコードと差し替えてコード生成したソースコードをコンパイルに用いるようなツールを作っている場合は、lineディレクティブは便利です。

`go tool cover`については、[Gopher塾 #1](https://gopher.school/1)でも扱っています。今後のアドベントカレンダーで`go tool cover`の挙動を追う方法についても書く予定ですので、楽しみにしててください。
Gradleプロジェクトインポート時のエラー対応メモ

# 概要
STS環境にてGradleプロジェクトをインポートする際にエラーが発生した。
その際の解決メモ

# 環境
Windows 11
Open JDK11 (11.0.2)
Spring Tools Suite4 Eclipse (4.16.1)
Gradle (6.7)

# 行おうとしたこと
他所から貰ったGradleプロジェクトをローカルにインポートしようとした

# 発生した課題
インポート時に以下のエラーメッセージが表示していた

> org.gradle.tooling.BuildException: Could not fetch model of type 'GradleBuild' using connection to Gradle distribution 'https://services.gradle.org/distributions/gradle-6.7-bin.zip'.

# 思った事
JDK11にてGradleのバージョンが対応されていないか、STS環境設定回りとしてJDKのパス設定がどこか足りないか

# 参考にさせて頂いた記事

[EclipseにてGradleのJAVA_HOME設定](https://qiita.com/chenglin/items/9d33b6f3492407ed03d2)

> 原因はGradleのJAVA_HOMEが設定していないため、JREでビルドするからです。

# 解決メモ
Gradleインポート時のオプション設定で[Java home]を指定する箇所が有ります。

JDKのパス設定は対応済みでしたが、ここでも明示的に設定する事とします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/de05cecd-3f96-9752-e79f-738a24f7e0c3.png)

# 結果
エラーを解消出来ました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/a33a03cc-90bc-a791-1827-d2999a3b1212.png)

# 後記 インポートがいつまで待っても終わらない
インポートエラーは解消できましたが、インポート処理が15分近く待っても終わりませんでした。
[Offline Mode]にチェックを入れる事で解消しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/5fc2eec1-e553-e40c-f112-c3b9faaa8dd2.png)