OmniAICreator/Qiita-1.07M huggingface dataset:
ARKitとSwiftUIを使ってアプリを開発する方法

ARKitとSwiftUIを使用してARアプリを開発する方法について解説します。ARKitを使用することで、iOSデバイスのカメラを使用して、現実世界にリアルタイムで仮想オブジェクトを配置することができます。SwiftUIを使用することで、UIを簡単かつ直感的に作成できます。

# ARKitとは
ARKitは、iOSデバイスで拡張現実（AR）を作成するためのフレームワークです。カメラ、センサー、コアモーション、およびGPUを使用して、現実世界にデジタル情報を投影します。
# ARKitのバージョン
ARKitは、iOS 11以降で利用可能です。現在、最新バージョンはARKit 5です。 ARKitは、SwiftおよびObjective-Cで開発することができます。
# SwiftUIとは
SwiftUIは、iOSアプリのUIを構築するための新しいフレームワークです。SwiftUIを使用すると、UIを直感的に作成できます。また、SwiftUIはコードを簡潔にし、宣言的な構文を使用して、UIをシンプルにすることができます。
# SwiftUIのバージョン
SwiftUIは、iOS 13以降で利用可能です。現在、最新バージョンはSwiftUI 3です。SwiftUIは、Swiftで開発することができます。
# ARKitとSwiftUIを使った開発手順

## ステップ1：プロジェクトの作成
Xcodeを開き、「新規プロジェクト」を選択して、プロジェクトを作成します。プロジェクト名は任意で、SwiftUIを選択します。
## ステップ2：ARKitの追加
プロジェクトにARKitを追加します。これを行うには、プロジェクトのターゲットを選択して、Build Phasesセクションにある「Link Binary with Libraries」を開き、ARKitを追加します。
## ステップ3：ARViewの作成
ARViewを作成します。ARViewは、カメラを起動し、ARコンテンツを表示するためのViewです。ARViewは、SwiftUIのViewであるため、簡単に作成できます。ContentView.swiftファイルを開き、以下のようなコードを追加します。
```swift
struct ARViewContainer: UIViewRepresentable {
    func makeUIView(context: Context) -> ARView {
        let arView = ARView(frame: .zero)
        return arView
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {}
}

```
## ステップ4：ARコンテンツの配置
ARViewにARコンテンツを配置します。これには、ARAnchorとARNodeを使用します。ARAnchorは、ARコンテンツを配置する場所を示す点であり、ARNodeは、ARコンテンツを表します。下の例はSceneKitを利用してコンテンツを配置しています。SceneKit以外にもRealityKitというフレームワークを使って配置する方法もあります。
```swift
func addBox(){
    // SCNBoxを使用して立方体のジオメトリを作成する
    let box = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
    // SCNMaterialを使用してマテリアルを作成し、赤色を表面色として設定する
    let material = SCNMaterial()
    material.diffuse.contents = UIColor.red
    box.materials = [material]
    // ジオメトリを含むSCNNodeを作成する
    let boxNode = SCNNode(geometry: box)
    // ボックスの位置を定義する
    let position = SCNVector3(0, 0, -0.5)
    // ARAnchorを作成して、AR空間にアンカーを追加する
    let anchor = ARAnchor(transform: simd_float4x4(SCNMatrix4MakeTranslation(position.x, position.y, position.z)))
    arView.session.add(anchor: anchor)
    // ボックスノードにアンカーのトランスフォームを適用する
    boxNode.simdTransform = anchor.transform
    // ボックスノードをAR空間に追加する
    arView.scene.rootNode.addChildNode(boxNode)
}
```

## ステップ5：ジェスチャーの追加
ジェスチャーを追加して、ARコンテンツを操作できるようにします。ジェスチャーには、タップ、ドラッグ、ピンチなどがあります。これにより、ユーザーはARコンテンツを自由に操作できます。

## ステップ6：ARKitのConfigurationの種類
ARKitのConfigurationには様々な種類があります。ARWorldTrackingConfiguration、ARImageTrackingConfiguration、ARBodyTrackingConfiguration、ARGeoTrackngConfigurationなどがあります。

## ステップ7：UIの作成
UIを作成して、ARコンテンツの追加や削除などの操作を行えるようにします。UIには、ボタン、スイッチ、スライダー、テキストフィールドなどがあります。

## ステップ8：ARKitのデバッグ
ARKitのデバッグ方法を学びます。ARKitのデバッグには、ARSCNDebugOptions、ARSessionDelegateなどがあります。これにより、ARコンテンツの配置やジェスチャーの認識などを確認できます。

## ステップ9：ARKitアプリの公開
ARKitアプリを公開する方法について学びます。App Store Connectにアプリを登録し、適切な情報を入力して、アプリを公開します。

# まとめ
ARKitとSwiftUIを使用することで、簡単かつ直感的にARアプリを開発できます。ARコンテンツの配置やジェスチャーの追加など、様々な機能を簡単に実装できます。

以上が、ARKitとSwiftUIを使用してARアプリを開発する方法でした。これらのステップに従って、簡単にARアプリを開発することができます。ARKitとSwiftUIを使ったARアプリ開発に興味がある方は、ぜひ挑戦してみてください。
VSCode バージョン 1.76.0でショートカットを使ったファイル名の変更ができなくなった件


# 環境
* OS: Windows11
* VSCodeのバージョン
> バージョン: 1.76.0 (user setup)
コミット: 92da9481c0904c6adfe372c12da3b7748d74bdcb
 日付: 2023-03-01T10:22:44.506Z
Electron: 19.1.11
Chromium: 102.0.5005.196
Node.js: 16.14.2
V8: 10.2.154.26-electron.0
OS: Windows_NT x64 10.0.22621
Sandboxed: No

# 要約
* ショートカット設定のwhen式からexplorerViewletVisibleの条件を削除することで、問題を解決できる。

# 問題
* F2でファイル名を変更しようと思ったらできなくなっていた。

# 原因（おそらく）
* VSCodeのアップデートにより、フォルダーやアウトライン、開いているエディターが移動できるようになりました。そのため、内部の識別子が変更されwhen式が認識されなくなったと考えられます。

# 解決手順
1. VSCodeを開く
1. `Ctrl + Shift + P` などを使ってコマンドパレットを開く。
1. `基本設定：キーボードショートカットを開く`と検索して、開く。(デフォルト設定なら、`Ctrl+K Ctrl+S`でも行けるはず。)
1. `renameFile`と検索する。
1. 対象コマンドを右クリックして、`when式を変更`をクリックする。
1. `explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus`から`explorerViewletVisible && `を削除して保存する。
1. 削除されていることを確認。
1. 任意のファイルを選択して`F2`を押して動作確認。

# その他
* エクスプローラー関連のショートカットはwhen式をいじれば動作するはず！はず！
* アップデートで修正されると思うから待ったほうがいいかも？
【AWS】Amazon Kinesisまとめ

# この記事について
Amazon Kinesisのそれぞれのサービスについての役割を理解するためのアウトプットです。

# Amazon Kinesis Data Streams
デバイスなどから送られてくる大量のストリーミングデータをリアルタイムに収集、処理して別のサービスへ配送するサービス。1秒以下でのデータロード向け。

【できること】
・ストリーミングデータのリアルタイム収集
・ストリーミングデータをリアルタイムに表示

# Amazon Kinesis Video Streams
分析、機械学習（ML）などの処理のために、接続されたデバイスからAWSへ動画を安全かつ簡単にストリーミングできる。

【できること】
・デバイスからの動画のストリーミング
・ライブやオンデマンド視聴用の動画の再生
・Amazon Rekognition Video、Apache MxNet、TensorFlow、OpenCVなどのMLフレームワーク向けのライブラリとの統合による、コンピュータビジョンと動画分析のアプリケーションを迅速に構築。

# Amazon Kinesis Data Firehose
ストリームデータを取得し、データを変換しつつ、Amazon S3などの配信先にデータを保存できるストリーミングデータの配信用サービス。AWS Lambdaと統合されており、AWS Lambda関数を利用してデータを変換する処理を組み込むことが可能。※SQLの実行は、Amazon Kinesis Data Analyticsが適している。

【できること】
・AWS Lambda関数を使用したデータ変換処理
・ストリーミングデータの配信

# Amazon Kinesis Data Analytics
SQLを利用してデータを変換した上で、「Amazon S3」や「Amazon OpenSearch Service」などに配信するアプリケーションを開発することができる。
※データ配信の際、Kinesis Data Firehoseを経由する必要はない。

【できること】
・SQL処理
・別のサービスへのデータ配信

# 補足
SAA試験の勉強で簡易的にまとめた為、アップデートしていこうと思います。
C#.NETでランダムな整数値

# やり方

例えば0 **以上** 、100 **以下** でランダムな値が欲しい時は
```new System.Random()``` して ```Next(0, 101)```

第一引数の値は **出てくる。**
第二引数の値は **出てこない。** （ **第二引数の値 - 1** の値までが出てくる）

という点に注意。

# サンプル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/2a5bd627-7ce2-3a0f-79fe-7621c2e2edb8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/419f839e-45cd-62f9-72e1-91342840e91b.png)

```c#:動作確認用サンプルコード
using System;

namespace randaaam
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Random rand_ = new System.Random();

            Console.WriteLine("0以上、1以内のランダム値。（0または1が出てくる）");
            Console.WriteLine(rand_.Next(0, 2));

            Console.WriteLine("負の値。（-1だけが出てくる）");
            Console.WriteLine(rand_.Next(-1, 0));

            Console.WriteLine("第一引数と第二引数が同じ場合。（0だけが出てくる、コンパイルエラーや実行時例外にはならない）");
            Console.WriteLine(rand_.Next(0, 0));

            //Console.WriteLine("第一引数 < 第二引数の場合。（コンパイルできるが、実行時に例外）");
            //Console.WriteLine(rand_.Next(0, -1));

            //結果を確認できるように入力待ちで止める。
            Console.ReadLine();

        }
    }
}
```

実行結果は下記。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/f654c12e-e65b-4fa5-75bd-8ccba10ff02a.png)

# 参考サイトさん

https://itsakura.com/csharp-random

# バージョン

Windows 10 Pro 22H2 OSビルド 19045.2673
Microsoft .NET Framework Version 4.8.04084
buildSrcでGradle7.6以降にKotlinバージョンのコンフリクトでエラーになる時の回避法

Android の buildSrc (自分の手元では Precompiled script plugin) を使っているプロジェクトで Gradle 7.6 以降に更新しようとしたところビルドエラーが出たのでその原因と回避法のメモ。

## 環境

Gradle 7.5.1 では問題なくビルドができており、 `buildSrc/build.gradle.kts` は以下のような設定でした。

```kotlin
plugins {
    kotlin("jvm") version libs.versions.kotlin.get()
    kotlin("plugin.serialization") version libs.versions.kotlin.get()
    `kotlin-dsl`
    `kotlin-dsl-precompiled-script-plugins`
}

dependencies {
    ...
}
```

起きるエラーのログは↓で、Kotlin のバージョンのコンフリクトが起きている模様。

```
A problem occurred configuring project ':buildSrc'.
> Could not resolve all files for configuration ':buildSrc:classpath'.
   > Could not resolve org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.8.10.
     Required by:
         project :buildSrc > org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.8.10 > org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10
      > Multiple incompatible variants of org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.8.10 were selected:
           - Variant org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.8.10 variant gradle70RuntimeElements has attributes {org.gradle.category=library, org.gradle.dependency.bundling=external, org.gradle.jvm.environment=standard-jvm, org.gradle.jvm.version=8, org.gradle.libraryelements=jar, org.gradle.plugin.api-version=7.0, org.gradle.status=release, org.gradle.usage=java-runtime}
           - Variant org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.8.10 variant gradle76RuntimeElements has attributes {org.gradle.category=library, org.gradle.dependency.bundling=external, org.gradle.jvm.environment=standard-jvm, org.gradle.jvm.version=8, org.gradle.libraryelements=jar, org.gradle.plugin.api-version=7.6, org.gradle.status=release, org.gradle.usage=java-runtime}
```

## 原因と解決策

原因は `kotlin("jvm")` や `kotlin("plugin.serialization")` で指定している Kotlin のバージョン(1.8.10)と、`kotlin-dsl` で使用される組み込みの Kotlin バージョン(1.7.10)がコンフリクトしているためでした。

これを解決するには `kotlin-dsl` の Kotlin のバージョンに揃える必要があり、`embeddedKotlinVersion` を使って揃えることで解決することができます。


```kotlin
plugins {
    kotlin("jvm") version embeddedKotlinVersion
    kotlin("plugin.serialization") version embeddedKotlinVersion
    `kotlin-dsl`
    `kotlin-dsl-precompiled-script-plugins`
}

dependencies {
    ...
}
```

ちなみに `kotlin("jvm")` や `kotlin("plugin.serialization")` を使って Kotlin のバージョンがコンフリクトしていたために起きた問題で、もちろん指定していなくて Kotlin のコンフリクトが起きていなければ遭遇しない問題ではあります。


## 参考
- https://slack-chats.kotlinlang.org/t/5170942/kotest-builds-with-gradle-7-6-are-failing-anyone-seen-this-p
SPSS ModelerのODBCバルクINSERTを使う

SPSS Modelerでテーブルに書き出す際に、通常はSQLのINSERT文が使われます。INSERTは特にカラム表（Db2 Warehouse, Redshiftなど）に対して非常に遅いという問題があります。この場合ODBCバッチを使うという方法と外部ローダーを使うという方法があります。外部ローダーを使う方法があります。外部ローダーを使う方法は以下の記事に書きましたので、この記事ではODBCバッチを使う方法を紹介します。数十倍の速度が出ることもよくあります。


SPSS Modelerの外部ローダーを使う（Db2編) - Qiita 

https://qiita.com/kawada2017/items/9d5d566aecaa8db2ed7a



* テスト環境
    * Modeler 18.4
    * Windows 11 64bit
    * Db2 Warehouse on cloud

＊サンプルストリーム

https://github.com/hkwd/spsssample/raw/master/230309odbcblukinsert/odbcbulkinsert.str

# デフォルトINSERT実行テスト

以下のようなデータをロードしてみます。日本語も含まれています。1万件のデータです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/2fa0dde4-882d-e54b-341d-47686e54410f.png)


「DBエクスポート」ノードを接続し、データソースとテーブル名を設定し、「詳細」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/b8326c1d-97a3-182a-947d-48bebb1f8b60.png)

「バルクロードを使用」が「オフ」のままですので、ODBCバッチINSERTは行われません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/42c14087-e63c-2817-1c3f-c7492fa96bb6.png)


実行をすると113秒かかりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/63493a7d-2b35-ebb4-db7b-ff43eeee7312.png)


# デフォルトINSERT実行テスト



「詳細オプション」で「バルクロードを使用」が「ODBC経由」にするとODBCバッチINSERTがおこなわれます。ODBCバッチINSERTに対応しているかどうかはODBCドライバーとRDBによります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/ead3a5a2-b1bb-1bdc-784e-dfe56a2a57b2.png)

実行をすると1.48秒と、76倍の短縮ができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/1b1a7ee5-a181-f1ea-66ff-2d880b7f2d13.png)

なお、バッチサイズを変更することでチューニングが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/6b17433e-4d2c-5203-e468-2850fd5003b4.png)

# 注意
ODBCバルクロードはRDBによっては圧縮効率が悪いことがあります。それが問題になる場合は、外部ローダーなどを検討いただく必要があります。

# 参考
#### データベース・エクスポートの拡張オプション - IBM Documentation 
https://www.ibm.com/docs/ja/spss-modeler/18.4.0?topic=node-database-export-advanced-options

#### SPSS Modelerの外部ローダーを使う（Db2編) - Qiita
https://qiita.com/kawada2017/items/9d5d566aecaa8db2ed7a
fortran総称名の罠: cmplx,real,imag,conjgは単精度への型変換

### 総称名ではヤバイ場合
https://www.nag-j.co.jp/fortran/FI_10.html
には「内部関数について総称名を使うことを強く推奨する」とある。ぼくの意見では
`「安全であると知ってるものだけ総称名を使う。個別名で対応するほうが明瞭で良い」`
が正しいです。型変換に関わる部分が危険です。
`強く推奨する`というので、どういうことかと思うとあまり良くない例が載せてある(間違ってるともいえなくはない）。それは以下のコードです。危険です。
```fortran
program generic_vs_specific
  implicit none
  double precision :: a = 2.0
  complex(kind(0d0)) :: b = (2.0,1.0)
  print *, sqrt(a)
  print *, sqrt(b)
end program generic_vs_specific
```
complex(kind(0d0)) :: b = (2d0,1d0)としないとまずいです。complex(kind(0d0)) :: b = (2,1)でもいいですけどいつもd0つけると覚えとくのが良い。できるだけ脳の無駄遣いをしなくていいコードを書きましょう。上のコードでa=2.1,b=1.1として
```fortran
  print *, a
  print *, b
```
を追加して実行するとわかるけど、a,bは単精度しか出ません。a=2.0,b=1.0だと一見精度が出ているわけでとても危険な例です。

上の例は比較的トリビアルだけど、もっと危険な例があります。以下のコードを実行してみてください。
```fortran
  complex(kind(0d0)) :: ccc = (5.1,3.2),c,cc,cc1,cc2,cc0,cc3
  real(8)::a,b
  write(6,*) 'ccc=',ccc
  a=5.1d0
  b=3.2d0
  cc1=cmplx(a,b)
  write(6,*) 'cc1=',cc1
  cc2=dcmplx(a,b)
  write(6,*) 'cc2=',cc2
  cc3=complex(a,b) ! complexはgfortranでしか動かないー使うべきでない。
  write(6,*) 'cc3=',cc3
  end
```
倍精度が保てるのはcc2,cc3です。cc1も単精度ですー「総称名を使いましょう」の罠です。
real(a)と書くと当然単精度への変換となるわけだけど、cmplxだと複素化する機能だからね、と錯覚しちゃうわけです。
とにかく「cmplxは注意して使う」ということは記憶しておかないといけない。これはkindを与えない場合、精度を単精度に落としてしまう（real,imag,conjgも同様）。

### ではどうする

ぼくの考えでは「dreal,dimag,dconjg,dcmplx」を使ったほうがいい。fortran2008ではA%REなども使えるらしいが使ったことはない。混合精度なコードだとkind入れて、cmplxを使うのは致し方ない。
ただconjgはkindを取れない.

gnufortranだと[complex](https://gcc.gnu.org/onlinedocs/gcc-3.4.6/g77/Complex-Intrinsic.html#Complex-Intrinsic)もあるが使おうとは思わない。

一般関数なら総称名でよい。

整数を倍精度に変換するときは、a=3d0で良い（simple is best).

整数化はnint,ceiling,floorを使う。


### 丸め誤差と離散化誤差：
誤差について考える必要もある。
数値計算は「丸め誤差と離散化誤差の狭間での戦い」なので状況によりヤバイことにもなりえます。普通に微分を取るとまあ3桁ぐらいは桁落ちするー２階微分なら6桁ぐらいって感じかもしれない。そうすると単精度だと精度が2桁しか残らないということになる。あるいは１００万回ぐらい積算するとその最悪の値が悪さをして全体の精度に響くということもあり得る、負符号も取りうる量を足すときには悩まされます。正定値の計算では平均化でいいように働くかもしれない。

### 系統誤差と偶然誤差：
系統誤差（打ち切りパラメータ、離散化パラメータ）はパラメータを変えて観察すれば良さそうなものだが、実際はなかなかに制御しずらく測りきれない。入力に対する出力のスムーズネスをみれば偶然誤差（ランダム誤差）は計測できるはずー倍精度だと偶然誤差などないかもしれないが桁落ちすることもあるのでなんとも言えない。収束計算においては収束安定性において問題だったりもする。実際のところ、なかなかに制御しづらい。

 台形公式とシンプソン公式:
 シンプソン公式は2次関数によるフィッティングに基づいている。差分も見ていることになり、倍精度は必須だと思える。丸め誤差がそれなりに積算してる状況、とか被積分関数のスムーズネスが期待できない場合なら台形公式のほうが計算的な安定性がよい。

<!---
駄：ずっとむかし、akaikkrにこのcmplxのバグを発見したときヒトの未来予測能力の限界を感じました。たぶんfortranの当初は総称名（ポリモルフィズム）というアイデアはなかったと思うーほんの10年先のごくごく当たり前なはずの未来が読めない。いまの「スマホ社会」を西暦２０００年に予言したヒトはいなかった。OLEDは3000時間持てば実用素材だけど、昔は50000時間の寿命がないと実用にならんと言われていた。Apple最大の発明は電池が入れ替えれないってことでしょう？これも驚天動地でした。まあだからこそ未来が楽しみってことでもあるけれど。--->
Javaを基本からまとめてみた【オブジェクト指向】

## システムとは？
システムとは、個々の要素が相互に影響しあいながら、全体として機能するまとまりや仕組みのこと。
IT分野では、個々の電子部品や機器で構成され、全体として何らかの情報処理機能を持つ装置のことや、ハードウェアやソフトウェア、ネットワークなどの要素を組み合わせ、全体として何らかの機能を発揮するひとまとまりの仕組み（情報システム、ITシステム）のことを指す。

## なぜクラスやメソッドに分けるのか？
- クラスごとに役割分担して作れる！大規模システムも複数人で作成できる
- 短くまとまったソースコードは読みやすい＆わかりやすい＆テストが楽！
- 一度、書いたソースコードを様々なシーンで何度でも使い回すことが可能！(再利用性)
- 使うクラスだけをインスタンス化することでメモリ節約＆処理スピードUP！
- どのプログラムがどこに書かれているか、誰がいつどのような背景で書いたかなど情報の管理や特定がしやすい
- 変更が必要クラスやメソッドのみを修正すれば良い！(メンテナンス性)

## どのようにクラス分けをするか


##### 1つ1つのクラスを、役割を持った『モノ（object）』と扱う = オブジェクト指向

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/3e512e1c-325d-1a0c-134e-50e04fdc76c1.png)

## クラスはモノの設計図

クラスブロック直下で宣言された変数 = 『フィールド』そのクラス（モノ）の情報を表します

```sample.java
class Sample01_car {
//フィールド（クラス直下で定義された変数）
String carModel = "ベンツ";

//メソッド(クラクションを鳴らす)
void klaxon(){
  System.out.println("ブー、ブー");
```
## オブジェクト指向とは
- オブジェクト指向とは『ある役割を持ったモノ』ごとにクラス分けをし、モノとモノとの関係性を定義していくシステムを作り上げようとするシステム構成の考えかたのこと。<br/>→ モノ(クラス)ごとに分業して一気に開発をすすめることができたり、情報の管理やメンテナンス性に優れているという点から、大規模なシステム開発で特に効果を発揮する

- モノを表現するためには2つの情報『属性（どのようなものか）』『機能(何ができるか) 』が必要となる。

- クラス（＝モノ全体の設計図）の『属性』を表す。また、メソッドはそのクラスの『機能』を表す

- メソッドとフィールドを合わせて『メンバ』と言う

#### 『クラス(設計図)』　➡︎　『インスタンス化』　➡︎  『インスタンス（実体）』

## インスタンス

- クラスはあくまでプログラムの設計図であるため、クラスそれ自身では命令を受け付けたり動作することはできません。

- そのクラス(設計図)をもとに生成した、命令を受け付け実際に動作することのできる実体が必要になります。この実体のことを『インスタンス化』と言い、クラスを元にインスタンスを生成することを『インスタンス化』をいう。

```
//インスタンス化
クラス名　インスタンス名　= new クラス名();


Sample_car01  　　mocoCar   　= 　　  new  Sample_car01();
//型(クラス)　変数名(インスタンス名)　　Sample_car01のインスタンス化
//インスタンスはクラス名を型として扱う
```

- インスタンスの実態はフィールドやメソッドのメモリ上の場所情報を管理する参照変数であり、クラス名として扱う

- 以下のように記述すると生成したインスタンスのフィールドを参照したりメソッドを実行したりすることができる
```
インスタンス名.フィールそ変数名
インスタンス名.メソッド名(引数)
```
- １つのクラスからいくらでもインスタンス化は可能であり、インスタンス名さえ違っていれば、それらは完全に独立したモノとして扱うことができる


## 参考サイト
[【Java-オブジェクト指向】Javaプログラミングの「オブジェクト指向」が絶対理解できる講座【プロ講師が丁寧解説】](https://www.udemy.com/course/uz-java-obj/learn/lecture/21205072#overview)
[一週間で身につくJava言語の基本](https://java.sevendays-study.com/day6.html)
Reactでhref属性の中に変数を入れたい

結論から言うと"{}"で囲んでその中に"+"と変数を用いてURLを記述すればいいだけである。

具体的には以下のようなコードである。

    <div>title:  <a id="title" href={"/manga/" + manga.id + "/"}>{manga.title}</a></div>

調べて分かったが、とても簡単であるが意外と自力では無理であった。
Hubspotの日付プロパティにAPI経由で値を入れる

https://legacydocs.hubspot.com/docs/faq/how-should-timestamps-be-formatted-for-hubspots-apis

躓きポイントとしてよく上がってきているので実コードで紹介します


## 要件
Hubspot画面上から作ったプロパティは日付データしか入らず、時間の情報は入りません

そういった場合、どのようにPOSTの値を整えればいいのか

Hubspot側が求める要件は下記の通りでした

- タイムゾーンはUTC
- 時刻は0時0分0秒
- Unixタイムスタンプ
    - ミリ秒までにする


## 実装
テストで取引の作成をします

日付のオブジェクトは
[Carbon](https://carbon.nesbot.com/docs/) クラスを前提に実装した場合を示します

~~~php
        // 日付プロパティ整え
        // $datePropatyには 1427997766000 のような数値が入ります
        $datePropaty = $carbonObj->updated_at
                ->timezone('UTC')
                ->hour(0)->minute(0)->second(0)->getTimestampMs();

        $dealsProperties = [
            'datePropaty' => $datePropaty,
        ];
        $simplePublicObjectInput = new SimplePublicObjectInput([
            'properties' => $dealsProperties,
        ]);
        $apiResponseForCreateDeals = $hubspot->crm()->deals()->basicApi()->create($simplePublicObjectInput);
~~~

作成された取引のプロパティ値の詳細を見ると値が入っています

![スクリーンショット 2023-03-09 9.53.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108154/e634f43a-c71c-204d-776c-7410248ccd5e.png)

表示上のタイムゾーンはHubspot上の設定に基づきます。



# 最後に
Hubspotの日付プロパティのAPIによる更新方法を紹介しました
何でこんな仕様になっているんだろう....
日付の更新処理があるところが多ければhelperに切り出してもいいかなと思ってます。

---
弊社では、一緒に働いてくれるエンジニアを募集しています。


↓興味のある方はこちらから↓
[Wantedly - スタジオアンビルト株式会社](https://www.wantedly.com/companies/studiounbuilt)

こんなWebサービスを作っています。
・[マドリー](https://madree.jp/)
・[Studio Unbuilt](https://www.studiounbuilt.com/)
[StoreKit] Consumable Product の Ask to Buy 対応

# TL;DR

StoreKit の Consumable Product が Ask to Buy で購入された場合に検知するには、[Transaction.updates](https://developer.apple.com/documentation/storekit/transaction/3851206-updates) の中で [Transaction.unfinished](https://developer.apple.com/documentation/storekit/transaction/3856631-unfinished)を監視するようにする。
```swift
Transaction.updates {
    guard
        case .verified(let transaction) = verificationResult,
        transaction.revocationDate == nil
    else { continue }

    for await verificationResult in Transaction.unfinished {

        switch transaction.productType {
        case .consumable:
            // アプリ内の情報を更新する
        default:
            break
        }

        await transaction.finish()
    }
}
```
# 背景
以前 [StoreKit 2 でのアプリ内課金の基本 という記事](https://qiita.com/ozumin/items/82e3570cc4f444086a89)を書いたのですが、 `Transaction.currentEntitlements` について

> これで consumable の購入個数を更新できるかと思ったが、transaction が finish() していない consumable があっても currentEntitlements で取得できなかった。

という問題がありました。記事の中ではワークアラウンドコードを仕込んだのですが、それだと Ask to Buy 機能を使った時に consumable product を購入できたことが検知できませんでした。

この問題について [Apple Developer Forums で問い合わせ](https://developer.apple.com/forums/thread/723025)ていたのですが、回答が得られたので記事として残しておきます。

# 解決策

当初は `Transaction.currentEntitlements` でトランザクションが終了していない consumable product を取得しようとしていました（当時ドキュメントがそうなっていたので）
現在の[`Transaction.currentEntitlements` のドキュメント](https://developer.apple.com/documentation/storekit/transaction/3851204-currententitlements) を見ると、以下の情報が取得できると書いてあります。

- それぞれの non-consumable product のトランザクション
- 購読中かグレースピリオドの auto-renewable subscription の最新のトランザクション
- 終了後も含めた non-renewing subscription の最新のトランザクション

そして、consumable product に関して以下の記載もありました。
> To get transactions for unfinished consumables, use the unfinished or all sequences in Transaction.

なので、consumable product の終了していないトランザクションを取得するには、[`Transaction.unfinished`](https://developer.apple.com/documentation/storekit/transaction/3856631-unfinished) か [`Transaction.all`](https://developer.apple.com/documentation/storekit/transaction/3851203-all) を使えば良さそうです。

- `Transaction.unfinished` は `finish()` が呼ばれていないトランザクションを取得できます。

- `Transaction.all` は今までのトランザクションの履歴を取得でき、 `finish()` が呼ばれていない consumable product のトランザクションも含みます。しかし、以下のトランザクションは含まないようです：
  - 終了した consumable product, non-renewing subscription
  - 再購入された non-consumable product, auto-renewing subscription, non-renewing subscription
  - 購入の復元

今回は、フォーラムの回答でも提案されていたので、`Transaction.unfinished` を使うことにしました。
```swift
Transaction.updates {
    guard
        case .verified(let transaction) = verificationResult,
        transaction.revocationDate == nil
    else { continue }

    for await verificationResult in Transaction.unfinished {

        switch transaction.productType {
        case .consumable:
            // アプリ内の情報を更新する
        default:
            break
        }

        await transaction.finish()
    }
}
```
Xcode で Ask to Buy を試すと、購入の承認後に無事アプリ内で購入処理のハンドリングができました:tada:
WEBGL用ゲームエンジン作ってみる ~10日目~

# はじめに

前回の記事の続きです。
始めてから10日がたったので、途中経過を記述します。
時間がたつのはやい・・・。
https://qiita.com/osakasho/items/f02d7acf8a822e25d3e0

現在の進捗エディタ画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493888/0d1d144c-8c95-93ac-10d4-5a064bac8380.png)

前回のシステム構成ではFastAPIを使おうと思ってましたが、
Next.jsの方が何かと便利だったのでNext.jsにしました。

# 追加した内容
- エディタUIの作成
- 3Dオブジェクトのアップロードと位置と回転の変更
- コンテンツブラウザの表示

# 直近の課題（今後の作業）
- コンテンツブラウザのディレクトリ移動
- コンテンツブラウザからのアップロード
- 選択時のスケール変更
- 地形メーカーの追加
- アバターパラメータ/ Skyパラメータ / 光源パラメータ / 物理判定設定

# 追加しなくてはならない作業
- スクリプトエディタ
- シェーダーエディタ
テスト用に巨大な画像ファイルを作成する。100MB

# 巨大な画像ファイルの作成方法

アプリケーションのアップロードのテストで、巨大なサイズの画像ファイルの確認が必要になりました。
そのため巨大画像ファイルが必要になったので作成してみました。
さくっとPythonで作成しました。

## モジュールのインストール
```
pip install Pillow
```

## コード
```
from PIL import Image,ImageDraw
import random

w = 10000
h = 10000

img = Image.new("RGB", (w,h), (0,0,0))
draw = ImageDraw.Draw(img)
for i in range(10000):
    draw.line((random.randint(0,w), random.randint(0,h), random.randint(0,w), random.randint(0,h)), fill=(random.randint(0,255), random.randint(0,255), random.randint(0,255)), width=1)
img.save("huge_image.jpg", quality=95)

```

## 結果

上記のコードを実行したら、103,703,135 バイトのファイルが作成できました。
Word VBAですべてのページに挿入されたグラフを画像として出力する

環境がoffice 2013となりますが、下記コードで出力できました。（問題点あり）
半分自分のメモ用として公開します。

```
Sub export_chart()
    '保存ファイルのパス取得
    sFolder = ActiveDocument.Path
    'ページ数取得
    page_cnt = Selection.Information(wdNumberOfPagesInDocument)
    For i = 1 To ActiveDocument.InlineShapes.Count
        With ActiveDocument.InlineShapes(i)
            'MsgBox i & "の横幅：" & .Width
            file_name = "graph_" & i & ".png"
            If .HasChart Then
                .Chart.Export _
                fileName:=file_name, FilterName:="PNG"
            End If
        End With
    Next i
End Sub
```

## コードについて
保存ファイルパス取得やページ数取得については、特に利用していません。
ActiveDocument.InlineShapes.Count ですべてのグラフの数を取得できました。
あとは、Forでぶん回している単純なものです…

## 問題点
なんらかの原因で出力した画像ファイルがものすごく小さくなります。
原因詳細まで調べていないので、お分かりになる方いらっしゃいましたらコメントいただけると幸いです。
出力する画像サイズ（解像度？）を指定したいのですが、うまくできません。。。

## 問題点解決に向けてやってみたこと
表示サイズ（倍率）を変えたりしましたが、これはダメでした。
幅、サイズを変えてみましたが、グラフのバランス？が崩れてしまいダメでした。。。

今後分かりましたら、追記します。
Crystal言語からChatGPTを呼び出すスニペット書いた

Crystal言語は、Ruby言語によく似た静的型付け言語です。Crystal言語では、静的型付けされたプログラムを書くことができますが、Ruby言語とほぼ同じ文法を用いてプログラムを記述することができます。この記事では、Crystal言語を用いてChatGPT APIを呼び出し、対話的にChatGPTを利用する方法を紹介します。

以下のように、ターミナルでChatGPTを利用することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/6eb06c3c-d444-360c-6a86-6cf4550bda30.png)

OpenAIのACCESS TOKENを取得して、環境変数 `OPENAI_API_KEY` を指定する必要があります。

OpenAIのChat用APIの詳細については、[こちら](https://platform.openai.com/docs/api-reference/chat)を参照してください。

```crystal
require "http/client"
require "json"
require "colorize"

struct PostData
  include JSON::Serializable
  property model : String
  property messages : Array(Hash(String, String))
  property temperature : Float64
  property top_p : Float64
  property n : Int32

  def initialize
    @model = "gpt-3.5-turbo"
    @messages = [] of Hash(String, String)
    @n = 1
    @temperature = 1.0
    @top_p = 1.0
  end
end

data = PostData.new

url = "https://api.openai.com/v1/chat/completions"
api_key = ENV["OPENAI_API_KEY"]
headers = HTTP::Headers{
  "Authorization" => "Bearer #{api_key}",
  "Content-Type"  => "application/json",
}

def get_input(prompt)
  print prompt
  STDIN.gets.to_s.chomp
end

def send_chat_request(url, data, headers)
  STDERR.puts data.pretty_inspect.colorize(:dark_gray) # コメントアウトしてください
  HTTP::Client.post(url, body: data.to_json, headers: headers)
end

loop do
  msg = get_input("> ")
  break if msg.empty?
  data.messages << {"role" => "user", "content" => msg}

  response = send_chat_request(url, data, headers)
  response_data = JSON.parse(response.body)

  if response.status.success?
    result = response_data["choices"][0]["message"]["content"]
    data.messages << {"role" => "assistant", "content" => result.to_s}
    puts result.colorize(:green)
  else
    STDERR.puts "Error: #{response.status_code} #{response.status}".colorize(:yellow).mode(:bold)
    STDERR.puts response.body.colorize(:yellow)
    exit 1
  end
end
```

このようにして、ChatGPTを含むOpenAIのAPIを簡単に利用することができます。

この記事は以上です。
Blob変数 BlobField

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)



+ [Blobを結合する](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000JgRB5SAN)

Blob to Hex and Hex to Blob
https://paulzipblog.wordpress.com/2021/11/28/blob-to-hex-and-hex-to-blob/

# BlobField

+ [BlobField のエラー](https://qiita.com/Keiji_otsubo/items/e83594bf3298899ced34)
Googleデジタルマーケティング＆Eコマース：なぜ顧客ペルソナを作成するの？

# はじめに

”Googleデジタルマーケティング＆Eコマース プロフェッショナル認定証"　の受講が完了しました(2022/3/3)。私がこのコースから得られた素晴らしい体験を、テーマごとに分割して、わかりやすくご紹介しています。興味を持たれた方は、是非下記を受講してみてください。

https://jp.coursera.org/professional-certificates/google-digital-marketing-ecommerce

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/84e33f4e-81cb-98a6-4546-f2ec06fd8b8b.png" width="800">

# 顧客ペルソナ

顧客ペルソナは、望ましい顧客層における類似した人々のグループを表します。

適切なタイミングで、適切なメッセージ、オファー、製品で、人々にアプローチする方法を考えるのに役立ちます。

その内容はとてもシンプルです。

- Who（characteristics）：誰を代表しているのか、その人の特徴
- Goal：達成したいこと
- Barrier：障壁、ペインポイント

が含まれています。

# なぜ顧客ペルソナを作成するの？

#### <font color="MediumBlue">お客様の視点をよりよく理解するため</font>

ペルソナは、その人の視点を通して物事を想像するものです。広告やメールなどのマーケティング資料を作成する際には、お客様の優先順位を考える必要があります。例えば、
- どのようなメッセージやビジュアルが彼らにとって最も魅力的なのか？
- それは、彼らの目標達成に役立つのか、彼らのペインポイントに関係するのか?

#### <font color="MediumBlue">お客様に合わせたコンテンツを作りやすくするため</font>

彼らがどのように考え、何を達成したいのか、そして何が購買を妨げているのかを理解することができます。

#### <font color="MediumBlue">効果的な広告ターゲティングのため</font>

ほとんどのデジタル広告プラットフォームは、現在、ターゲティング広告を提供しています。プラットフォームは、あなたが到達したい観客の前であなたの広告を得るのを助けるためにいくつかの異なるターゲティングツールを提供しています。

# 顧客ペルソナの例

キャンプテントを販売する企業は、6人用テントのマーケティングキャンペーンを行いたいと考えています。

- リサーチに基づき、マーケティングチームはペルソナの要素の1つを保護者であると判断しました。
- また、30代半ばから50代半ばで、2～3人の子供がいることがわかりました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/a0b103a3-7304-0eed-2f9f-915f637717d6.png" width="650">

- さらに、マーケティング担当者が直接インタビューした結果、彼らの一般的な目標は、数年間使用できる手頃な価格のテントを購入することであることがわかりました。
- そして、大型テントを購入する際の一般的な障壁は、過去に挫折した経験があるため、設営に不安があることであることもわかりました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/91e2bf31-199a-eee5-7011-f50756356c45.png" width="650">

このペルソナがあれば、それに応じて資料を作成することができます。例えば、
- 「家族みんなで使える簡単設営のテント」というようなオンライン広告が考えられます。
- また、人口統計学的プロファイルに適合する人々に、この広告をターゲットにすることができます。


:::note info
この顧客ペルソナの属性、目標、障壁について、より深く掘り下げることができることを忘れないでください。この知識は、今後デジタルマーケティングの仕事をする際に、顧客とのつながりを深めるために役立ちます。 
:::
CRM Analytics のトレイルヘッドでの特徴得なエラー


# There was an unhandled exception. Please reference ID: IXFBZFBE. Error: Restforce::ResponseError. Message: FUNCTIONALITY_NOT_ENABLED: This feature is not currently enabled for this user. RESPONSE: [{"message":"This feature is not currently enabled for this user.","errorCode":"FUNCTIONALITY_NOT_ENABLED"}]

+ [Quick Start: CRM Analytics > Create an App and a Lens](https://trailhead.salesforce.com/content/learn/projects/quick-start-einstein-analytics/create-an-app-and-lens)

+ [質問I'm getting an error when verifying a lens challenge](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000JgGDu)

:::note
It was a problem with the Dev Org connection.
I created and used a Dev Org, but a different one was connected and showing in the challenge. I reconnected the right one (not sure why two Dev Orgs were created) and the error message disappeared (I got an other error going on).

Dev Org 接続の問題でした。

開発組織を作成して使用しましたが、別の組織が接続され、チャレンジに表示されました。正しいものを再接続し (なぜ 2 つの開発組織が作成されたのかわかりません)、エラー メッセージが消えました (別のエラーが発生しました)。
:::
Experience Cloud Cookie の同意 Experience Cloud Cookie Consent (salesforce.com)


+ [Experience Cloud Cookie の同意](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000JgJz7)

**エクスペリエンスビルダーでのみ機能します**

私はこれに多くの時間と労力を費やしてきました。ドキュメンテーションはよく書かれておらず、私たち全員が開発者であると仮定していると思います。完全な証明の段階的な方法で書かれているわけではありません。程遠い。モジュール設定の情報の一部は、以下のコメントに記載されている情報と矛盾しています。

コメントには、(アセットとしてインストールされた) スクリプト ファイルを HTML ヘッダーで正しく読み取って参照できるようにする必要があることが記載されています。ロッカーの内側または外側にいる場合、緩和された CSP をチェックする必要がありますか? どちらも試してみましたが変化なし。また、スクリプトの HTML ヘッドで相対 URL と完全 URL の両方を使用しました (シークレット モードで表示可能で、URL は CSP リストで許可されています)。

他のコメントからわかることから、さまざまなオブジェクトのエクスペリエンス ゲスト ユーザー アカウントへのアクセス許可を許可する必要があります。ドキュメントには、 Read および Create の権限を Individual object に許可する必要があることのみが記載されています。このアプリによってインストールされたすべてのオブジェクトと、個別のオブジェクトに読み取り/作成のアクセス許可を付与しました。これがゲスト サイトの場合、他のユーザーに許可を与える必要がありますか? インストールされたアクセス許可セットでは、これらのいずれに対しても読み取り/作成が許可されていなかったため、クローンを作成して適用し、ゲスト ユーザーに割り当てる必要がありました。これは、ドキュメンテーションが私に望んでいたことでしたか?

エクスペリエンス Cookie ページに表示されるすべての Cookie レコードを事前に作成する必要がありますか?

これらすべてをさらに確認して再確認しましたが、Experience Builder で正常に動作している場合でも、公開されたページにエラーが表示され、デバッグ ログも Cookie 同意バナーも表示されません。誰でも共有できるトラブルシューティングやステップ バイ ステップ ガイドはありますか? 私は完全な開発者ではないかもしれませんが、これは私の最初のロデオでもなく、かなりがっかりしています。

https://appexchange.salesforce.com/listingDetail?listingId=a0N3A00000G11jcUAB&tab=r

はい、ドキュメントがあまり良くないことに同意します。 

サイトに表示することはできましたが、最後に Cookie レコードの説明が表示されず、解決策を探しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/9512f10b-a3f1-d430-e695-c469688f7bd4.png)

ええ、私は多くの人が同じ問題に直面しているのを見てきました。これに対する解決策は今のところありません。私が間違っていなければ、バージョン 3.7 を使用しています。残念ながら、現時点ではこの問題に対する解決策はありません。管理パッケージ ページで参照されている quip ドキュメントを確認してください。
【PHP】PHPでURLの情報を取得する

PHPの$_SERVER変数でURLやドメインを取得。
今回の例では「pickup」のページを開いた時に任意の内容を"echo"に記述することで実装しています。

```
<?php
    $url = $_SERVER["REQUEST_URI"];
    if (strstr($url , "pickup")) { //$urlに'pickup'が含まれる場合
    echo ''; //URLに'pickup'が含まれる場合に表示される内容
    }
    else{
    }
?>
```
テキスト バージョンの電子メールでのフィールドの差し込み


:::note
If the unsubscribe tag ({{{emailpreferencecenter}}}) in the HTML version is inside of an anchor tag ("<a>"), it must not have other characters inside the "href" attribute. If the unsubscribe tag is not inside an anchor tag, it must have whitespace characters directly before and after it.
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/f440c874-885f-d498-b2e3-29ca635fab1a.png)


+ [We got the following error adding 'unsubscribe' variable tag to a template via the Pardot content editor - 
](https://trailhead.salesforce.com/trailblazer-community/feed/0D53A00003KKdTkSAL)
%%unsubscribe%% タグを挿入するとテキスト バージョンの電子メールでこのエラーがスローされますが、その周りに「空白」を挿入しないでください。Click here to unsubscribe:%%unsubscribe%% この場合、コロン (:) とタグ自体の間にスペースがないため、エラーがスローされます。タグを囲む「空白」が必要です。そうしないと、タグを挿入する差し込み印刷プロセスを「混乱」させようとしているように見えます。これで問題なく動作します: ここをクリックして登録解除: %%unsubscribe%% (コロンの後ろとタグの前のスペースに注意してください。) これも問題なく動作します: ここをクリックして登録解除: %%unsubscribe%% (登録解除リンク全体独自の行にあります - その周りに十分な「空白」があります。) ================================ ======== HTMLエディタでは、不適切な形式のリンクでも同じことが起こります。HTML では、正しい形式の登録解除リンクは次のようになります: <a href="%%unsubscribe%%">ここをクリックして登録解除</a> 悪い HTML リンクの例: <a %%unsubscribe%%>Clickここで購読を解除してください</a> これは有効なリンクではありません - そこには「href」がありません...壊れたリンクになっています。また、Pardot は配信停止リンクが機能していることを確認するため、エラーがスローされます。それを壊れたリンクにします。また、Pardot は配信停止リンクが機能していることを確認するため、エラーがスローされます。それを壊れたリンクにします。また、Pardot は配信停止リンクが機能していることを確認するため、エラーがスローされます。

+ [Error Message for {{{EmailPreferenceCenter}}} in Pardot Email Builder](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000Dd2nOSAR)

:::note
Make sure you add a space before and after the unsubscribe merge tag to resolve it. 

 The resulting HTML code would look like this: <a href=" {{{EmailPreferenceCenter}}} ">
:::

+ [ERROR ON UNSUBSCRIBE LINK PARDOT](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000JgSb4SAF)
ユーザのプロフィールページ①

<h1>ユーザのプロフィールページを作成</h1>
前回は、１対n(1対多)を投稿しました。
そこで、保存や投稿などをしました。


今回は、１対１の関係

ユーザーとプロフィール

usersテーブルとprofilesテーブル
usersのidとprofilesのuser_idで紐づいている。



作成するプロフィールの内容
・ニックネーム（文字）
・自己紹介（長文）
・生年月日（日付）
・性別（数字）
・通知設定（Boolean）

まずは、モデルの作成

    $rails g model Profile

db/migrate/20230308215518_create_profiles.rb
マイグレーションファイルが作成されています。
まず、ユーザーに紐づいているので、referenceの記入

    t.references :user, null: false
必ずユーザーidが存在するはずなので、null: falseというオプションをつけている

ニックネームを追加
string:文字列

    t.string :nickname

自己紹介
長文なので、text

    t.text :introduction

性別
integer：整数
    
    t.integer :gender

誕生日
date:日付

    t.date :birthday

メールを受信するかしないか
boolean:true or folse

    t.boolean :subscribed

subscribed：購読している

     default: false
を後ろに追加
何も入力されていなければ、falseにしますよというオプション


これで、マイグレーション作成できたので実行していきましょう！

    ＄rails db:migrate
create_table、migratedと表示があるので、実行できたはずです👍

db/schema.rb
を確認するとprofilesというテーブルが作成されているのが確認できました🙆

次にアクティブレコード、モデルの設定

app/models/user.rb
今回は、プロフィールは一人一つしか存在しないので

    has_one :profile
とする。複数ある場合は、has_many
複数形ではないので、profile

ユーザーが削除された時にこのデータも消えて欲しいので

    dependent: :destroy
を追加

app/models/profile.rb
プロフィールは、ユーザーに紐づいていると書く

    belongs_to :user
プロフィールから見ると、userに従属している
「デカ文字」シリーズまとめ(SSD1306)(LPC812)


目的
SSD1306を使用
秋月　P-12031 白色　128x64 アドレス3C
秋月　AL12832AWWB-H-U02 白色　128x32 アドレス3C
文字を全体的に表示して視認性を上げる
「時計」と「温度計」




時計



https://qiita.com/caa45040/items/ab783eefd5205883b337



https://qiita.com/caa45040/items/03c610cbdea2f7c7496a



温度計



https://qiita.com/caa45040/items/ba0286cee67f3fc9750d



https://qiita.com/caa45040/items/b12df3bad5c54d56cbe3
システム設計について学ぼう！

未経験からエンジニアになりたい人は、プログラミングから始める人が多いと思いますが、
エンジニアの仕事は、プログラミングだけではありません。そして、プログラミングだけでは、エンジニアになれません。同時にプログラミングが苦手でも、システム構成や開発の流れを理解するとエンジニアに近づきます！
今回はシステム設計について更に詳しく調べてみましょう！
![インスタスライド_202302281.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/d361b41d-8e40-24de-de0d-5b3413d1a05d.gif)


# システム設計とは
システム設計は、大きく外部設計と内部設計に分かれる。

・外部設計
　ユーザから見たシステムの設計を行う

・内部設計
　開発者から見たシステムの設計を行う

# 外部設計書とは
外部から見てのシステムの動き・条件を設計する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/c902585e-c79d-641f-d755-0f10d97edf85.png)

# 内部設計書とは
内部的な動きやコード、テーブル等を設計する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/2f049551-ad6f-6f66-0ff7-9b843e6a2e8f.png)

# まとめ
ーシステム設計では、外部設計と内部設計を行う

ー外部設計とは、外部から見てのシステムの動き・条件を設計する

ー内部設計とは、内部的な動きやコード、テーブル等を設計する

# 最後に
未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
Rubocopの設定をしてアラートを消す

# 目的
rubocopのアラートがたくさん出るので、一部のアラートが出ないようにする。

# 環境
ruby-rubocop0.8.6 VSCodeの拡張機能を利用しています
ruby3.2.1
rails7.0.4

Ruby on Railsは以下のDocker環境で動かしています。

https://qiita.com/pyon_snore/items/b8d860e5e3d94a322dfd

# やったこと
プロジェクト直下に`.rubocop.yml`を設置して設定を書きました。
以下、アラートごとに除外の設定をしていきます。

## Missing frozen string literal comment.
各ファイル冒頭に
```
# frozen_string_literal: true
```
というマジックコメントを記載して文字列の破壊的な変更を防ぎましょう！というアラート。

Ruby3から文字列がイミュータブルになるみたいな話があったらしいのですが、Ruby3.2.1現在**ミュータブル**です！
[ドキュメント](https://docs.ruby-lang.org/ja/latest/class/String.html)を参考に以下実験してみましたが確かにミュータブルでした。
```rb
a = "string"
b = a
a.upcase! # マジックコメント記載でFrozenError (can't modify frozen String: "string"):
logger.debug(a)   # => "STRING"
logger.debug(b)   # => "STRING"
```
なので、このマジックコメント自体は未だ有効なようです。

とはいえ全ファイルにアラートが出て煩雑なので消します。設定は以下。
```.rubocop.yml
Style/FrozenStringLiteralComment:
  Enabled: false
```

## Missing top-level documentation comment for {クラス名}.
クラス定義の1行前にコメントを書け、というアラート。
余計なお世話なので除外します。
```.rubocop.yml
Documentation:
  Enabled: false
```

## Method has too many lines. [16/10]
メソッドが長い、10行以内で書くように、というアラート。
確かに長いメソッドは良くないけど無意味に分割しても逆に読みづらいし、せめて任意の行数に制限を変更させてほしいところです。
```.rubocop.yml
MethodLength:
  CountComments: true  # ここをfalseにすれば制限自体がなくなる
  Max: 20 # 任意の行数
```


### .rubocop.yml全体
```.rubocop.yml
MethodLength:
  CountComments: true
  Max: 20
Documentation:
  Enabled: false
Style/FrozenStringLiteralComment:
  Enabled: false
```
また不要なアラートが出たら追加します！


# 参考
https://qiita.com/j-sunaga/items/b89c9a8bf5f455779924
https://qiita.com/tbpgr/items/46af4c0f5be30c5c6ccc
MENDIX Proのインストール方法

こんにちは、こんばんわ。日々お疲れ様です。:woman:
今回は仕事で使用することになったため、MENDIXの初歩的なことを時間のある時に記事にしてきたいと思います。
インストールするものは、MENDIX Proです。
ローコード開発アプリになります。

# MENDIXとは
MENDIX（メンディックス）とは、**アプリケーションの設計・製造・テストから運用保守までをオールインワンで提供する、グローバルで多くの導入実績を持つローコードプラットフォームです。**

NECのホームページなどでも概要を確認することができます。

世界では4000社以上使用されていたりするそうですが、`日本ではまだあまり使われておりません`
そのため、MENDIXに関する日本語のドキュメントも少ないです。
Qiitaの記事も20に満たないレベルですね。

ですが、これからローコード・ノーコード開発は、日本でも伸びてくる分野と思われるため、少しずつ学習したことをここに残していきたいと思いました。
NEC社は、社内のシステムの多くをこのMENDIXを使用したシステムに置き換えることを発表しています。

参考記事⤵
[NECがローコード開発に「本腰」、自社製品ではなく外部ツールを活用するワケ](https://xtech.nikkei.com/atcl/nxt/column/18/00001/05686/)

そんなMENDIX、今回はインストールの方法を以下に書きたいと思います。

※**「MENDIX Pro」はWindows上で動くアプリです。**
Macの方はProではなくブラウザ上でアプリを制作できる「MENDIX」があります。

# インストール手順
①MENDIX Proのインストールページを開く

https://marketplace.mendix.com/link/studiopro/

②ダウンロード　プロを押下
※2025/4/20追記　現在はより機能が充実したバージョン10以降が出ています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125006/2013adc5-6e68-00a3-21fd-51e44a31398e.png)

③MENDIXに登録していない場合は、アカウント登録ページへと進む
Sign up からアカウント情報登録画面へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125006/114d431e-91d3-98ec-0986-a2086a9fc703.png)


↓下記情報を打ち込む
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125006/4163f066-a7fc-b028-c8d0-3390e16aad88.png)

パスワードはしっかり大文字小文字、特殊記号を使わないといけないそう。
メールアドレスはgmailやyahooメールは使えないそうです。
また、使う人？ですが、``Developer``を選択でよいと思います。

④登録が完了したら、メールが届くのでメールのURLから登録を完了します。
アカウントがアクティベートになります。

⑤再び②と同じ手順でダウンロードボタンを押すと、setup.exeインストーラがダウンロードされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125006/ef515954-9074-0a0a-9d85-27666cb3e82f.png)

⑥インストールしていきます

以下の画像の順でそのままOKで進んでいいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125006/770db179-8702-1d7a-e919-b72154ebd582.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125006/2cdaa2fc-72fb-c4df-3133-76baeba87ae2.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125006/11fd8602-b9e2-b6c4-62f9-e514df2999de.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125006/d2c42db6-f53c-909f-5197-d2bfa263516a.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125006/09eae625-b781-575a-24c5-88c98336bfe1.png)
↓

インストール開始　しばらくお待ちください。。

数分後、無事にインストールが完了すると以下の画像がでます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125006/a4f729e1-ad40-8bf8-2128-87e11873c393.png)


# インストール完了

お疲れ様でした。以上で無事インストール完了です！
実際にローコードでアプリを作ってみましょう！
また何か、コード（マイクロフロー）部分の使い方などを記事にしたいと思います！

個人でアプリを作る際のデータベースをどうするかを調べないと…。
よろしければタグのフォロー等お願いします＾＾
laravelで「アレ？」って思ったらキャッシュクリア

あれ？こんなはずでは…
エラーに対してどれだけ検索をかけても解決しない…
chatGPTに聞いても分からない…
そんなどん詰まりになった時、キャッシュをクリアにしただけで全て解決した経験はありませんか？
私にはあります…

そこで、(私的)キャッシュクリアまとめを作成しました！
では状況別にさまざまなキャッシュクリアを見てみましょう！

## キャッシュクリアとは
https://pc-hanoji.com/archives/559


イメージで言うと、キャッシュは体重でしょうか？
体重が増えるとマラソンが遅くなる。なので、早く走るには体重を軽くしてあげましょう。


## laravelで使う様々なキャッシュクリア

スマホアプリの動きが悪くなったら、一旦アプリのページを削除してしまうのもキャッシュクリアです。
laravelにも同様な対応が必要な場合が多々あります。
次回から、「アレ？」と思ったらキャッシュクリアをお勧めします。（tokiとbaaiによります）

## 1. Laravelで内ディレクトリ名を変換した。
ディレクトリ名を変更すると、今まで使えていた動作ができなくなることがあります。
```terminal
% composer dump-autoload
```
これをするとautoload_classmap.phpを更新できるそうです。

素晴らしいまとめ投稿はこちらから。


https://qiita.com/niiyz/items/5b83ef5255a1ec64d9d6#composerjson

## 2. 基本的なキャッシュクリアコマンド
```
$ php artisan cache:clear
$ php artisan config:clear
$ php artisan route:clear
$ php artisan view:clear
```
素晴らしいまとめ投稿はこちらから。


https://qiita.com/Ping/items/10ada8d069e13d729701

## 3. docker系キャッシュクリアコマンド
`docker-compose.yml`への変更を反映する前に必要なコマンド
```
$ docker builder prune
```
詳しくはこちら！

https://qiita.com/hyt-sasaki/items/e2cbc4cfb5ae698de498
[Laravel][PHPUnit]パスパラメータとクエリパラメータの渡し方

# したいこと
PHPUnitでパスパラメータとクエリパラメータを両方渡したい

# 前提

ルーティングとコントローラーは適当です。

```php:ルーティング
Route::get('/user/{user_id}/{hogehoge}', [UserController::class, 'show'])->name('user.fugafuga');
```

```php:コントローラー
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\User;

class UserController extends Controller
{
    /**
     * 指定ユーザーのプロファイルを表示
     *
     * @param  int  $id
     * @return \Illuminate\View\View
     */
    public function show($userId, $hogehoge, $queryParameters)
    {
        return view('user.profile', [
            'user' => User::findOrFail($id)
        ]);
    }
}
```

# 解決

```php:テスト
$queryParameters = [
    'name' => '太郎',
    'age' => 18
];

$response = $this->get(route(user.fugafuga, [
    'user_id' => 1,
    'hogehoge' => 'aiueo',
    ...$queryParameters
]));
```

このテストで発行されるURL（一部省略）は以下

```php:URL
.../user/1/aiueo?name=太郎&age=18
```

# まとめ

解決してみると意外と簡単な書き方だった。
備忘録も兼ねて記事に残しておく。
ChatGPTで恋愛相談!?個人開発「モテチャットGPT」が爆誕！

ChatGPTのAPIでなにか個人開発して作りたいなと思っていたら・・・爆誕しました。

その名も「モテチャットGPT」。恋に悩むエンジニアを助ける、恋愛相談AIです。

<iframe width="480" height="315" src="https://www.youtube.com/embed/WJmRMxNGAVM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

# 恋愛相談AI「モテチャットGPT」

恋愛相談AI「モテチャットGPT」はLINE botです。
![851cpffi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365005/c97dd992-6b8c-4d8f-3e54-c6749c497884.png)
https://line.me/R/ti/p/%40851cpffi

上記のQRコードorリンクをクリックすると、LINE公式アカウントとして追加できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365005/408a698d-54d2-3cb5-f375-722a5885e5aa.png)

※このLINE botのアイコンイラストも画像生成AI・DALL・E2で作成しました。

トーク画面に移動して相談したい恋の悩みなど投稿すると、恋愛経験豊富なChatGPTが恋愛経験の回答をしてくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365005/76ef937c-cb33-e734-bd33-0448e48e0ac3.png)

エンジニア向けということで、ChatGPTには恋愛相談が得意な女性になりきってもらっています(笑)

# なぜChatGPTのAPIで恋愛相談に

今回、ChatGPTのAPIを使って個人開発したのが恋愛相談だったのか？

ChatGPTのAPIが3/2に登場し、スタートダッシュ開発の競争は見事に破れました。

こうした新しいサービスは最速で開発した者が大きな先行者利益を獲得します。

そうした先行者利益はもはやなくなった状態で、GASでChatGPTのAPIを扱う記事などをブログに掲載していました。

https://auto-worker.com/blog/?p=7438

でも、やっぱりChatGPTのAPIが使えるようになったのだから、なにか作りたいと考えました。

すでにChatGPTのAPIをWebやSlackで使えるだけではアピールポイントがありません。

なにかエッジを効かせなければ・・・そう考えてたどり着いたのが **恋愛相談** でした。

# 「モテだな」の一言に閃き

そんなChatGPTのAPIを使った個人開発のアイディアを探していた時に、マンガを読んでいて雷が落ちました。
![image0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365005/0c738c70-7ab6-d804-56d2-bd942b43a5f3.png)
※「トリリオンゲーム」2巻の1ページ

**「モテだな」**

この一言で、モテに関する内容であれば、AIに聞くニーズはあると閃いたのです！
(意訳：アイディアをパクりました。)

# ロール機能で恋愛相談が得意なAIが誕生

ChatGPTのAPIでは過去の投稿もリクエスト時に設定することで、それまでのやり取りの文脈に即した会話が可能です。

それに加えて、systemロールでの指示もできるようになっており、systemロールで指示することでAIのふるまいを定義できます。

※ロールについては、GASでのChatGPTのAPI利用方法を解説した記事で詳しく説明しています。

https://auto-worker.com/blog/?p=7438

そこで、systemロールに「恋愛経験豊富な女性で、恋愛相談しなさい」という指示を出しました。

それによって、単なるChatGPTとしての回答ではなく、恋愛経験豊富な女性としてアドバイスする役割を付与し、恋愛相談特化のAIチャットボットが誕生しました。

# 1日3回まで無料利用可能

モテチャットGPTは、1日3回まで相談の投稿ができます。

できれば無料で使ってもらえるようにしたかったのですが、ChatGPTのAPIは無料ではありません。

たくさんリクエストされると、その分だけAPI利用料が発生し、費用がかかります。

個人開発サービスは費用負担が要因でクローズするケースが大半です。

https://qiita.com/Tyamamoto1007/items/050a1d42c18541de1a83

そのため、1日に実行できる相談回数を3回に制限させていただいています。
※この制限がプロンプトインジェクション対策にもなっています。

それでももっと相談したい人向けに、恋愛相談し放題プランも用意しています。

ご興味のある方はぜひLINEトーク画面のメニューをご覧ください。

# 終わりに

恋愛相談に乗ってくれるLINE bot「モテチャットGPT」が誕生しました。

ChatGPTのAPIが公開されましたが、単にChatGPTを組み込んだだけでは強みにならないと考え、「恋愛相談」に特化したAIチャットボットとして個人開発しました。。

ChatGPTに恋愛経験豊富で恋愛相談に乗ってくれるようにシステム的に指示を出すことで特化型LINE botが誕生しました。

1日3回無料で利用できるので、モテチャットGPTに恋愛の悩みを相談してみてください。

![851cpffi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365005/c97dd992-6b8c-4d8f-3e54-c6749c497884.png)
https://line.me/R/ti/p/%40851cpffi

◯参考記事

https://auto-worker.com/blog/?p=7479
httpd.confの書式

●httpd.confの書式

ディレクティブ名 設定値

例）DocumentRootディレクティブで、ウェブで公開するHTMLを保存する最上位のディレクトリを指定する場合
DocumentRoot /var/www/html

また、ファイルやディレクトリ毎など、適用範囲を指定して設定を行う場合は以下の書式を併用。

・<Files ファイル名>...</Files>
ファイルごとの設定を行う場合

・<Directory ディレクトリ名>...</Directory>
ディレクトリごとの設定を行う場合

・<Location URL>...</Location>
URLごとの設定を行う場合

・<IFModule モジュール>...</IFModule>
モジュールごとの設定を行う場合
flatMap と yield*

`flatMap` と `yield*` は記述方法が異なりますが、似たような目的に使えます。他の書き方も含めて、簡単な例で比較します。

# 配列の結合

別々に生成した配列を結合します。

```js
function makeRange(from, to) {
    const ret = Array(to - from + 1);
    for (let i = from; i <= to; i++) {
        ret[i - from] = i;
    }
    return ret;
}

function makeArray() {
    return [99].concat(makeRange(1, 3)).concat(makeRange(1, 5));
}
```
```js:実行結果
> makeArray()
[ 99, 1, 2, 3, 1, 2, 3, 4, 5 ]
```

`makeRange` は敢えて泥臭く書きましたが、今は `map` を使うのがスマートかもしれません。

```js
function makeRange(from, to) {
    return Array(to - from + 1).fill().map((_, i) => from + i);
}
```

# flatMap

この例だと人によって実装方法が変わりそうです。元となる配列の要素を型で区別して膨らませる方法を使います。

※ `makeRange` は上で定義した関数です。

```js
function makeArrayFlatMap() {
    return [99, [3], [5]].flatMap(x => Array.isArray(x) ? makeRange(1, x[0]) : x);
}
```
```js:実行結果
> makeArrayFlatMap()
[ 99, 1, 2, 3, 1, 2, 3, 4, 5 ]
```

# push

配列を取り回しながら 1 つずつ `push` します。生成する配列を一本化したいという発想です。

```js
function pushRange(arr, from, to) {
    for (let i = from; i <= to; i++) {
        arr.push(i);
    }
}

function makeArrayPush() {
    const ret = [];
    ret.push(99);
    pushRange(ret, 1, 3);
    pushRange(ret, 1, 5);
    return ret;
}
```
```js:実行結果
> makeArrayPush()
[ 99, 1, 2, 3, 1, 2, 3, 4, 5 ]
```

個人的には、以前はこのやり方をよく使っていました。

# ジェネレーター

`yield*` によって他のジェネレーターを取り込みます。

```js
function* generateRange(from, to) {
    for (let i = from; i <= to; i++) {
        yield i;
    }
}

function* makeArrayGenerator() {
    yield 99;
    yield* generateRange(1, 3);
    yield* generateRange(1, 5);
}
```
```js:実行結果
> [...makeArrayGenerator()]
[ 99, 1, 2, 3, 1, 2, 3, 4, 5 ]
```

※ 実行結果ではジェネレーターから配列を生成しています。

`push` の方法に似ています。そのため個人的にはジェネレーターは馴染みやすかったです。

`flatMap` との対応を考えると、`yield` と `yield*` をまとめてやっているような印象です。個人的にはそのことに気付いたことで `flatMap` に馴染めるようになりました。

# 関連記事

配列と `flatMap` を一般化したようなものがモナドです。

https://qiita.com/7shi/items/27b6f3169961299a6195
entでOR句を発行する時に困ったこと

## 困ったこと
entでOR句を発行する際に、OR句の中でAND句を使用したかったのですが、中々実装できずに困ったので記事にしました。

## 実装方法

entはWhere句をつなげる際に,引数に入れることでAND句を繋げていくことができます。
なので、OR句の中でANDの引数の中に,を入れることで対象のSQLを発行することができます。

```
client.Pet.
    Query().
    Where(
        pet.Or(
            pet.And(
                pet.HasOwner(),
                pet.DeletedAtIsNil(),
            pet.Not(pet.HasFriends())
        )
    ).
    All(ctx)
```

余談ですが、Andを使用しなくてもWhere内部でカンマで区切ればAND繋ぎになります。

```
client.Pet.
    Query().
    Where(
        pet.HasOwner(),
        pet.DeletedAtIsNil()).
   All(ctx)
```

# 感想
entはまだまだ参考できるサイトが少ないので、結構詰まってしまいました。
また、Railsに慣れていたのもあってメソッドチェーン的にできるのかなぁ？と思っていたので引数で渡していくのも驚きでした。
ただ、メソッドチェーンの場合は戻り値とか気にしないといけないですが、引数の場合は気にしなくて良いのでこちらの方がミスとか少ないんだろうなぁとか思ったりしています。
[java] JUnit作成を助けてくれる方たち

配属先で初めて出会ったJUnit。大苦戦し先輩方にたくさんお世話になりました。。

よく利用するけど「この確認のときに使っていたアレなんだっけ......」となることが今でも多いので、個人メモ程度にまとめる。

- assertNull()
  - 確認したい値がNullであるかチェックするためのもの。
  - Nullだった場合、通過し、Nullじゃなかった場合、通過できない（確か「実行したらNullじゃなかったよ」みたいなエラー文言が出た気がする。。）
    - 書き方例：assertNull(piyo);
- assertNotNull()
  - assertNullの逆。
  - Nullじゃないことを確認できる。
- 返す値がbooleanのメソッドの確認短縮方法
  - 以下のように記載すれば簡単に確認できる。わざわざ変数を作る必要が無い。
    - assertThat(hogeClass.booleanMethod(stringPiyo), is(true));
- doNothing()
  - voidメソッドを正常終了させる。mock化しているクラスに対して利用可能。
    - 書き方例：doNothing().when(hogeClass).hugaMethod(anyObject());
      - この時、hogeClassは@Mockで宣言していること。@Spyだとエラー吐かれてた気がする。。
- doReturn()
  - メソッドの返す値を設定できる。利用する時はクラスが@Mock、または@Spyに設定されていること。
    - 書き方例：doReturn("hoge").when(hogeClass).hugaMethod(anyObject());
- fail()
  - tryCatchを利用したテストを作るときに利用。
  - ```ruby:書き方例
    /** エラーを検出せず、想定した値が返ってくるパターン */
    try {
      String piyo = testLogic.testMethod(true);
      assetThat(piyo, is("piyopiyo");
    } catch (SystemException e) {   
      fail();
    }
    ```
  - ```ruby:書き方例2
    /** エラーを検知し、catchに移ることの確認パターン */
    try {
      String piyo = testLogic.testMethod(true);
      fail();
    } catch (SystemException e) {
      assetThat(e.getMessage(), is("piyopiyo");
    }
    ```
  - ただ、tryCatchしたテストを実行した場合、fail()側に到達するとエラーが分からないことがある。そんな時は一度tryCatchをコメントアウトして、JUnit実行するとエラー箇所を把握できる。

*****

JUnitの注意点

- privateなメソッドはPowerMockを利用すれば返却値を設定できる。
  - PowerMockは便利だけど、カバレッジ実行時はすべて赤に染まって分岐が目で見えなくなる。。（緑表示が無くなる）
VSCodeを開いたらデフォルトでWSL2がワークスペースになってしまったときの対処法

# はじめに
仕事上でのPCではそんなことならなかったのですが、自宅の開発用PCでVSCodeを開くとエクスプローラーがデフォルトでWSL2になってしまっていることに気づきました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2497780/52f13f1a-4eeb-57df-af11-eddb019a6f6f.png)

再起動しても変わりません。
こうなるとエクスプローラーがローカルをワークスペースにすることもできないし、WSL2上の他のフォルダに移ることもできなくなってしまいます。

# 解決手順
WSLをシャットダウンしました。
VSCodeを閉じてコマンドプロンプトを開きます。
~~~bash:cmd
$ wsl --shutdown
~~~

再度VSCodeを起動すると「フォルダーを開く」ボタンに戻っていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2497780/5becf0a3-52af-9e20-4e1d-067e79fbec38.png)

### ※追記
有識者の方にコメントで教えていただきました！
設定からRestore Windowsが既定で「all」になっているので、それを「none」に変更すると立ち上げの度にフォルダーが開いていない状態に戻ってました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2497780/561824c0-a353-963f-ea47-4d0a22a00286.png)
同じプロジェクトばかりしか触っていなければ毎回開くのも面倒だと思うので、この2つの方法を使い分けていけたら良いですね。

# おわりに
コメントでよりよい方法を知ることができて改めてエンジニアコミュニティの暖かさを実感することができました…