OmniAICreator/Qiita-1.07M huggingface dataset:
Laravelで定数をパブリック定数として定義してまとめる方法

Laravelで定数をパブリック定数として定義する方法は、configファイルに記述する方法、Modelクラスファイルに記述する方法などいろいろあるようです。
とりあえずは、専用のConstクラスファイルを作成する、という方法がいいようなのでまとめをメモ。

# 作り方
Laravelルートに
\app\Consts\CommonConst.php
ファイルを作ります。ファイル名は任意。Consts ファルダも自分で作成します。
下記のように定義し、
```PHP
<?php
namespace App\Consts;

class CommonConst
{
    public const EMAIL_SendInspiring = '****@gmail.com';
    public const TODO_WEEK = ["日", "月", "火", "水", "木", "金", "土"];

}
```
呼び出す際は
`\App\Consts\CommonConst::EMAIL_SendInspiring`
のようにすれば、呼び出すことができる。
配列で定義して、呼び出し側でforeach で回すことも可能。
（参考サイトに例あり）


# 参考
[Laravelで定数を使うときにConfigを使う腰抜けはもう死んだ](https://zenn.dev/aoi_avant/articles/19ca83d8ae67d7)
[[Laravel]定数（const）はどこに書くべきか？チーム内でやる場合のおすすめのマジックナンバー対処方法](https://codesapuri.com/articles/26)
Googleデータアナリティクス：SQLのSUMPRODUCT関数

# はじめに

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

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

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/21a12cb1-a49a-802f-d903-6f68758eca0c.png" width="800">

# SUMPRODUCT関数

SUMPRODUCT は、列を掛け算して それらの積の合計を返す関数です。 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/389d1276-94e7-af59-3c83-411d07a455fe.png" width="600">

配列は、 スプレッドシートの範囲のようなものです。 しかし、配列はセル内の値の集まりであり セルそのものではないことに 注意しましょう。 SUMPRODUCT 関数を 数式に追加すると 2 つ以上の配列内の各値を掛け合わせます。 たとえば、セル B3～B7 の配列の各値に セル C3～C7 の配列にある 対応する値を 掛け算することができます。 B3 × C3、B4 × C4、と いった具合です。 そしてこのすべての積の 総計を返します。 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/73f5c3c9-1e14-8c2e-8267-528e70b5d764.png" width="700">


キッチン用品の会社のデータを使い どういうことか見ていきましょう。 この例は COUNTIF と SUMIF の動画でも 使ったものです。 商品の注文について 売れた各商品の数量と 各商品 1 個が いくらかを示す単価のデータがあります。 私たちの仕事は、これらの 2 つの列にある データを使って、この注文による総売上高を 把握することです。 そこで、SUMPRODUCT の出番です。 総売上高を求めるには 足し算と掛け算の両方を 行う必要があります。 まず、各商品による売上を 個別に求めます。 SUMPRODUCT なしでこれを行う場合 各商品数に単価を掛ける必要があります。 50×1.25 ドル、 25×5ドル、などといった具合です。 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/9f1ee913-f799-659c-3579-bbbafbaa7f55.png" width="300">

そして、これらの売上額をすべて合計して 総売上高を求めます。 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/23ade69e-e184-71c0-633a-ca04c60422ee.png" width="400">


幸い、SUMPRODUCT 関数が それをすべて処理してくれます。 

セル G5 に総売上高というラベルを追加し G6 をクリックして数式を入力してみましょう。 数式はイコール記号と 関数で始め 開き括弧で囲みます。 数式に追加する配列は 常に括弧の中に入れると覚えましょう。 次に、セル B3 からセル B7 を選択し 1 つ目の配列とし、その後にカンマを続けます。 このカンマは、2 つの配列と数式を 区切る役割を果たします。 次に、セル C3 から C7 を選択し 2 番目の配列を作成し 閉じ括弧で数式を完成させます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/40eb1471-9700-b672-00b8-69724bf4a348.png" width="５00">

実際の数式では 括弧は必要ありません。 構文の例では、各配列を 明確に定義するために括弧を使っています。 次に、Enter を押して総売上高を出します。 ここでは売上を扱っているため 数値の形式を通貨で表示します。 総売上高は 655 ドルであることがわかりました。 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/d6f9886b-5cfe-4921-d349-0e87efb1d212.png" width="５00">


しかし、これはキッチン用品の販売による 実際の利益ではありません。 なぜなら、この計算には 利益率が考慮されていないからです。 利益率とは 1 ドルの売上に対して 何セントの利益が発生したか、といったことを 示すパーセンテージです。 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/de9c9d4a-b814-feb5-5b1a-1dc86042e367.png" width="５00">

このデータセットでは、商品 ID が 789 の 利益率は 20% です。 これは、販売した各製品が 1 ドルにつき 0.20 ドルの利益を得ていることを意味します。 そして、売上の計算と同じように SUMPRODUCT 関数を使うことで 利益を求める時間を短縮できます。 利益率の計算式と収益の計算式には 1 つだけ違いがあります。 重要な違いです。 まず、セル G7 に同じ数式の 最初の部分を入力します。 そして、2 つの配列も同じように含めます。しかし、これで数式を終わらせるのではなく もう1 つのコンマを追加し、その後に もう1 つ配列を追加します。 今回は、利益率を示すセル、 D3 から D7 を選んでください。 
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/4b2fff05-0a81-0cca-873b-febc08fac2fc.png" width="７00">

これで数式は完了、計算も完了です。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/764f9960-d496-2035-3c30-ef49cc0c8f70.png" width="７00">

:::note info
SUMPRODUCT 関数を使うことで 個々の収益額にそれぞれの利益率をかけてから それぞれの利益を足す、という作業を 省くことができました。 SUMPRODUCT を使った計算は 時間の節約になり、ミスの防止にもつながります。 間違いなく覚えておく価値のあるコツです。 
:::
【Rust】Python(+numba)との3重for文の速度比較...をしたかった

:::note warn
2024年2月14日
本記事は3重for文での比較を主題にしていましたが、
おそらくRustでの結果を想定通りに得られていないと考えられます。
参考にしていただいた方は、申し訳ありません。
ひとつ学びとして記事は残します。コメントありがとうございました。
:::

:::note warn
2023年9月21日
いただいたコメントに基づき、現在、実験結果の正しさについて確認中です。
これにより今後の編集で結果が変わる可能性があります。
:::


## RustとPythonとの3重for文の処理時間を比較してみた

最近、仮想通貨取引所から個人で収集し続けたデータが約1億点になり、
Pythonでは一括での処理が現実的ではなくなってしまいました。
特にfor文を含む処理がネックになっていると思っていて、
numpyやnumbaで何とか置き換えてきたものの、
可読性なども考慮すると限界を感じています。

やむを得ず言語レベルでの変更を検討していたところ、
Rustは書きやすそうで速そうだということで、
一旦Rustの速さを体感したく検証してみました。
（自由にfor文を書きたい...！）

### 実行環境

Windows11, VSCode
CPU: 11th Gen Intel(R) Core(TM) i7-11800H（論理プロセッサ数: 16）

|  | バージョン |
|:-:|:-:|
| Rust | 1.68.0  |
| Python | 3.10.5  |
| numba | 0.56.0 |


## 実装

`n`を引数にとり、3重ループの処理を行う関数`f`を言語ごとに用意し、`n`を変えながらそれぞれの処理時間を計測します。

### Rust


```rust:main.rs
fn f(n: i64) -> i128 {
    let mut count = 0;
    for i in 0..n {
        for j in 0..i {
            for _ in 0..j {
                count += 1;
            }
        }
    }
    count
}
```

### Python

```python:main.py
def f(n):
    count = 0
    for i in range(n):
        for j in range(i):
            for _ in range(j):
                count += 1
    return count
```

### Python + numba

```python:main.py
from numba import njit

@njit
def f(n):
    count = 0
    for i in range(n):
        for j in range(i):
            for _ in range(j):
                count += 1
    return count
```

### Python + numba(prange)

すぐにCPU使用率が100%に達します。

```python:main.py
from numba import njit, prange

@njit(parallel=True)
def f(n):
    count = 0
    for i in prange(n):
        for j in prange(i):
            for _ in prange(j):
                count += 1
    return count
```

## 結果

上記の3重ループでRustとPythonとの処理速度の比較を行った場合、
RustはPythonと比べて桁違いに速いということが分かりました。
同じ時間で計算可能な`n`の範囲が広がるので、データサイズが大きい場合などに有用だと考えられました。
（rayonなどのクレートを使えばより高速化できる可能性もあります）

Pythonにnumbaを導入した場合でも、Python標準に比べてかなり速くなりますが、
Rustはさらに速かったです。

ただし、Rustをdebugモードでコンパイルした場合の処理時間は速いとは言えず、
簡単な動作確認以外では`--release`オプションをつけてコンパイルしたほうが良さそうです。

|  | n | 処理時間（秒） |
|:-:|:-:|:-:|
| Rust（debugモード）  | 1,000,000  | 258  |
| Rust  |  10,000,000,000 | 11  |
| Rust  |  100,000,000,000 | （1分を超えたため中断）  |
| Python | 1000  |  3.8 |
| Python | 10000 | （1分を超えたため中断）  |
| Python + numba | 1000  | 0.2  |
| Python + numba |  1,000,000 | 12.2  |
| Python + numba | 10,000,000  | （1分を超えたため中断）  |
| Python + numba(prange)  | 1,000,000  | 5.6  |
| Python + numba(prange)  |  10,000,000 | （1分を超えたため中断）  |

## 感想

Rustの速さを実感したいのが主だったため、そもそもPythonに不利な処理を実装している点ご理解いただきたいです。（Python大好き！）
とはいえ、想像以上に速すぎて少し笑ってしまいました。
ちなみに、Rustでの`f(10_000_000_000)`の結果は`166666666616666666670000000000`でした。
SwiftUIからUIViewControllerを呼び出す方法

## 背景
既存のアプリのView周りをSwiftUIで作り直すとき、一部の画面では既存の画面をそのまま利用したい場合に、ViewControllerをSwiftUIから呼び出す方法です。

## 実装
### ViewControllerの作成
```HogeView.swift
/// UIViewControllerRepresentableプロトコルを準拠するViewControllerを作成する
struct LoginViewController: UIViewControllerRepresentable {
    // UIViewControllerを作成するメソッド
    func makeUIViewController(context: Context) -> UIViewController {
        // 指定のUIViewControllerを作成する
        let myViewController: UIViewController = LoginViewController()
        return myViewController
    }

    // UIViewControllerを更新するメソッド
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
        // UIViewControllerを更新したときの処理
    }
}
```

### ViewControllerの呼び出し
```
struct LoginView: View {
    var body: some View {
        LoginViewController()
    }
}
```
watchOS独立アプリのTestFlightでハマったこと

## 概要
watchOS独立アプリをTestFlightにリリースした時に
"ITMS-90683: Missing purpose string in Info.plist ..."
の文章が返ってきてリジェクトされました
そのときの回避方法を記述します

## 開発環境・条件
- Xcode Version 14.2
- Swift Version 5.7.2
- macOS 13.0
- Apple M2
- Project作成時に "Watch-only App" を選択

## 試した事
#### WatchAppのInfo内の対象文字列を確認
- プロジェクト設定画面 TARGETS > WatchAppのInfo > 対象の文字列を確認
    - もちろん設定済（設定していないとそもそもデバッグ等できないことが多い）
    - 文言を修正してからリリース　→　同じ理由でリジェクト

#### iOS側のバージョンを合わせる
- 下記を参考にiOS側のバージョンを合わせてからリリース　→　本概要と同じ理由でリジェクト

https://qiita.com/koogawa/items/85e80d03c49daf80ce3a

#### iOS側のBuild Settings確認
- プロジェクト設定画面 TARGETS > iOS側のBuild Settings > Packaging > Info.plist File 確認
    -  空欄をダブルクリック > 現れた小窓にplist名を記入　→　リリース成功！
![スクリーンショット 2023-04-18 15.52.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206517/1c00a916-6101-ed63-efa8-c48764b8105d.png)

無事リジェクトされずにすみました
TestFlightはiOSを経由するためなのか、iOSのBuild Settingsにplistを紐づける必要があるみたいです

##### 気になったこと
WatchAppのGeneralからVersionを変更すると対象のplistが勝手に変更される事がありました
リリース前にplist内を確認しておくことをお勧めします

## まとめ
watchOS単独アプリのTestFlightリリース時に "ITMS-90683: Missing purpose string in Info.plist ..." でリジェクトされた場合、iOS側のBuild Settingsにもplistが登録されているか確認してみる
今週の学習 （2023/04/24 ~ 2023/04/31)

# 概要
この記事は私の一週間の学習内容をまとめたものです。
以下の書籍を学習しました。
1.[AI時代の離散数学（茨城俊秀著、オーム社）](https://www.amazon.co.jp/AI%E6%99%82%E4%BB%A3%E3%81%AE%E9%9B%A2%E6%95%A3%E6%95%B0%E5%AD%A6-%E8%8C%A8%E6%9C%A8-%E4%BF%8A%E7%A7%80/dp/427422581X/ref=sr_1_1?crid=10PX53PTE6TAD&keywords=ai%E6%99%82%E4%BB%A3%E3%81%AE%E9%9B%A2%E6%95%A3%E6%95%B0%E5%AD%A6&qid=1681801212&sprefix=AI%E6%99%82%E4%BB%A3%E3%81%AE%2Caps%2C266&sr=8-1)
何かご指摘などありましたら、メッセージをいただけると幸いです。

 #
QGISを参考にgeotiff.jsである座標のピクセル値を取得する機能を実装

ブラウザでgeotiffを読み込んである地点の値を抽出する必要があり
geotiff.jsを使ってラスターサンプリング機能を実装しました。
実装するにあたりQGISのソースコードを参考にしました。
QGISからWebへの機能の移植の例を共有したいと思います。

この関数がラスターサンプリング機能です。
```ts
import type { GeoTIFF, TypedArray } from "geotiff";

/**
 * 指定された経緯度の値をGeoTIFFデータから取得
 * @param latitude
 * @param longitude
 * @param bandIndex
 * @param nodataValue
 * @returns {number} - 値
 */
const getValue = async (
  geoTIFF: GeoTIFF,
  latitude: number,
  longitude: number,
  bandIndex: number,
  nodataValue: number,
): Promise<number> => {
  const image = await geoTIFF.getImage();
  const data = await image.readRasters();
  const [originX, originY] = image.getOrigin();
  const [resolutionX, resolutionY] = image.getResolution();
  const x = Math.round((longitude - originX) / resolutionX);
  const y = Math.round((latitude - originY) / resolutionY);
  const index = y * data.width + x;
  const band = data[bandIndex] as TypedArray;
  const value = band[index];
  if (value === nodataValue) {
    return 0;
  }
  return value;
};
```
# 実装方法
実際にQGISのソースコードを読みどこで目的の処理が実装されているか
特定した上でTypeScriptに実装しました。
処理を特定した過程を下記にまとめます。

## 以下は2023/04/18時点のmasterブランチの話です
これ以下のコードはQGISの引用となっております。

## 機能の名前を探す 
**プロセシングツールボックス->ベクタレイヤにラスタ値を付加**
マウスオーバーするとアルゴリズムID(**native:rastersampling**)がわかります。

## QGISソースコードを読む
[QGISのリポジトリ](https://github.com/qgis/QGIS)にアクセスして
**rastersampling**で検索すると
**qgsalgorithmrastersampling.cpp**というC++ファイルがヒットします。

**QgsRasterSamplingAlgorithm::processAlgorithm**を読み進めます。
```cpp
const double value = mDataProvider->sample( point, band, &ok );
```
上記のコードが見られますこれが前後の処理や引数からこの処理でラスターをサンプリングしていることがわかります。
sampleの実装がまだ分からないので、**mDataProvider**の宣言をヘッダーファイルで読みます。

### ヘッダーファイルを探す
キーボードの**t**キーを押下するとファイル検索ができるので
**qgsalgorithmrastersampling.h**を開きます。
```cpp
std::unique_ptr< QgsRasterDataProvider > mDataProvider;
```
**mDataProvider**は**QgsRasterDataProvider**クラスだとわかりました。
従ってQgsRasterDataProviderの**sample**メソッドを読みます。

再度tキーを押下して**QgsRasterDataProvider**がファイル名に含まれるファイルを探します。
qgsrasterdataprovider.cppを読みます。

### QgsRasterDataProviderクラスを読む
**QgsRasterDataProvider::sample**
```cpp
const auto res = identify( point, QgsRaster::IdentifyFormatValue, boundingBox, width, height, dpi );
const QVariant value = res.results().value( band );
```
このコードとsampleメソッドがvalueを浮動小数点数に変換した値を返すことから
**identify**を読むと遂に座標から画像の行と列を取得する処理を見つけることができました。
```cpp
// Calculate the row / column where the point falls
const double xres = ( finalExtent.width() ) / width;
const double yres = ( finalExtent.height() ) / height;

const int col = static_cast< int >( std::floor( ( point.x() - finalExtent.xMinimum() ) / xres ) );
const int row = static_cast< int >( std::floor( ( finalExtent.yMaximum() - point.y() ) / yres ) );
```
## まとめ
今回はQGISの処理の特定は比較的容易であるということを例示してみました。
特定するポイントをまとめました。
* QGISのアルゴリズムはプロセシングバーのアルゴリズムIDから探せる
* メソッドや関数の引数に注目する
* クラスや型を足がかりに探す
* クラスや型を知るために宣言を探す
PyPDF2でテンプレートPDFに文字列を埋め込もうとしてハマった時のメモ

# 作業目的
MS WordでテンプレートとするPDFを作成して、PyPDF2で文字列を埋め込んで帳票を作成しようとした。

# 発生した事象
帳票の合成時に以下のエラーが発生した。
「UnicodeEncodeError: 'latin-1' codec can't encode characters in position」

別のPDFファイルを用いると合成が行える。はて？
以下のサイトで『WordでPDFを保存すると、フォント名はShift_JISでエンコードされてしまいます』とある。
https://gammasoft.jp/support/pdf-file-read-warning-and-error/

では、Adobe AcrobatでWordファイルをPDFに変換したらどうだろう。と思い、実施してみたところ、合成が行えた。

# Adobe AcrobatでPDFに変換する手順
1.「ファイル」メニューで「全てのファイル」で対象のWordファイルを開く。
2. PDFで保存する。

参考にさせていただいたサイト通りに、フォントを変更するのも選択肢かと思います。

# 参考

https://gammasoft.jp/support/pdf-file-read-warning-and-error/
Googleデータアナリティクス：複数の条件を持つSQL関数

# はじめに

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

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

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/21a12cb1-a49a-802f-d903-6f68758eca0c.png" width="800">

# SUMIF から SUMIFS へ

SUMIF 関数の基本的な構文は以下の通りです。

**=SUMIF(範囲, 条件, 合計範囲)**

範囲は、関数が設定した条件を検索する場所です。 条件は適用する条件、合計範囲は計算に含まれるセルの範囲を入力します。

例えば品目と費用、日付を記載した、以下のテーブルがあるとします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/cb16fc5f-0346-8f92-825d-c774a23e01ff.png" width="600">

 このテーブルの燃料費の合計を計算するには、SUMIF を使って、次のようにします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/4c33856d-e580-7d0d-552b-ee1a7545faea.png" width="600">

しかしここで SUMIFS 関数を使えば、複数の条件を処理することが可能です。SUMIF と SUMIFS は非常によく似ていますが、SUMIFS は複数の条件を含めることができます。  

SUMIFS 関数の基本的な構文は、以下の通りです。
**=SUMIFS(合計範囲, 条件範囲1, 条件1, [条件範囲2, 条件2,…])**

角括弧[] は、これがオプションであることを、構文の終わりにある省略記号（…）は、条件の追加がいくつでも可能であることを示しています。たとえば、特定の発注日における燃料費の価格合計を計算したい場合、次のように複数の条件を入力して SUMIFS 関数を作成することができます。  

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/473f2703-fcd2-02de-fe2e-5af8143cb27e.png" width="700">

この関数は、構文に入力した日付に当てはまるデータかどうかを判別し、該当するデータの価格合計を計算します。この例では、C1:C9 が 2 番目の条件範囲で、 12/15/2020 が 2 番目の条件になっています。基本的な構文に従う限り、 SUMIFS 文には最大 127 の条件を追加することができます!。

# COUNTIF から COUNTIFS へ

SUMIFS 関数と同様に、 COUNTIFS では複数の条件を指定して COUNTIF 関数を作成することができます。

COUNTIF 関数の基本的な構文は以下の通りです。
**=COUNTIF(範囲, 条件)**

SUMIF と同じように、範囲と次に満たすべき条件を設定します。例えば、品目を示す A 列で「食品」が出てきた回数を数える場合、以下のような COUNTIF 関数を使用します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/ca0e64db-6770-6e0c-c9f6-9b584d79f242.png" width="700">

COUNTIFS は基本的には、SUMIFS と同じ構造です。
**=COUNTIFS(条件範囲1, 条件1, [条件範囲2, 条件2…])**

条件範囲と条件は同じ順番で、構文の末尾に条件を追加することができます。つまり品目列にある「 コーヒー」の数を、2020 年 12 月 15 日に出費したものに絞っ調べたい場合は、 COUNTIFS 関数を使用して、以下のように条件を入力して調べることができます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/179b904b-d3e7-8171-2450-f37449969d16.png" width="700">

この関数は、構文に従って「コーヒー」と特定の発注日を条件にデータを処理しています。これで、両方の条件に一致する、すべてのデータを見つけることができます。
EC2に Nitro-Enclave 開発環境を5分で設定する方法

## 概要

まっさらなEC2上に、
コマンド一発で　Nitro Enclave-cli をインストールして、
enclave内でprint するだけのhello-world チュートリアルを５分以内で実行してみましょう。

## EC2 の作成（２分）

### 注意1
Amazon Linux2 を選びましょう。（Amazon Linux ではなく、２です。）

![Screen Shot 2023-04-13 at 12.56.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/4e38101c-ca24-78bf-dfcb-38e63e92055c.png)

インスタンスタイプは、とりあえず
```
m5.2xlarge
```
を指定しましょう。

### 注意2
Advanced details の中にある、Nitro Enclave を Enable にするのを忘れないように。


![Screen Shot 2023-04-13 at 13.13.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/0b89dbde-39fa-c551-04bb-015c0e219f23.png)




## コマンド（２分３０秒）
```bash
sudo yum install docker -y && sudo  amazon-linux-extras install aws-nitro-enclaves-cli -y && sudo yum install aws-nitro-enclaves-cli-devel -y && sudo systemctl start docker && sudo docker build /usr/share/nitro_enclaves/examples/hello -t hello && sudo nitro-cli build-enclave --docker-uri hello:latest --output-file hello.eif && sudo systemctl start nitro-enclaves-allocator.service && sudo systemctl status nitro-enclaves-allocator.service && sudo systemctl enable nitro-enclaves-allocator.service && sudo nitro-cli run-enclave --cpu-count 2  --memory 512 --enclave-cid 16 --eif-path hello.eif --debug-mode
```

２、３分くらいで終わると思います。
コーヒーを飲みながら待ちましょう。

## enclave からの出力の確認（１０秒）

上が終わったら、

```bash
 enclave_id=$(nitro-cli describe-enclaves | jq -r .[].EnclaveID) && nitro-cli console --enclave-id ${enclave_id}
```
を実行してみます。

```bash
[   1] Hello from the enclave side!
[   2] Hello from the enclave side!
[   3] Hello from the enclave side!
[   4] Hello from the enclave side!
[   5] Hello from the enclave side!
[   6] Hello from the enclave side!
[   7] Hello from the enclave side!
[   8] Hello from the enclave side!
[   9] Hello from the enclave side!
```

と出ていたらhello-world には成功しています。


## お片付け（１０秒）

```bash
enclave_id=$(nitro-cli describe-enclaves | jq -r .[].EnclaveID) && sudo nitro-cli terminate-enclave --enclave-id ${enclave_id}
```

を実行し、enclave をターミネートします。

お疲れ様でした。





## まとめ

nitro enclave を５分以内で立ち上げてみました。
ここからがスタートなので、nitro-enclave を楽しみましょう。

今回はこの辺で。


@kenmaro
gRPC + Python 備忘録（カスタムクラス、ストリーミングなど）

## 概要

いつまで経っても一向に覚えられない、でも重要な
gRPC + Python の細かい実装のところを備忘録としてまとめます。


## モデルがdefault型のrepeatedプロパティ を持つ時

#### Proto定義

```proto
syntax = "proto3";

message MyModel{
    int32 size = 1;
    repeated bytes data = 2;
}
```

例えば上のような時です。
今回は`MyModel`というモデルが、`bytes`という型を`repeated` の形で保持しています。
つまりbytes のリストをMyModel が所持する形です。

#### 呼び出し方

```python

obj = MyModel()
obj.size = 4
obj.data[:] = [byte0, byte1, ... ]
```
というように書きます。



## モデルが カスタム型のプロパティ を持つ時

#### Proto定義

```proto
syntax = "proto3";

message MyData{
    double data = 1;

}
message MyModel{
    int32 size = 1;
    MyData data = 2;
}
```

#### 呼び出し方

```python

obj = MyModel()
obj.size = 4
obj.data.CopyFrom(MyData(data=2.0))
```
というように書きます。


## ストリームの書き方

#### Proto定義

```proto
syntax = "proto3";

service MyService{
  rpc test(stream MyModel) returns (stream MyModel) {};
}
```

のように書きます。

#### 呼び出し方（送信側）

```python

def make_stream_data(xs, size=100):
    while len(xs) > 0:
        if len(xs) < size:
            pb_return = MyModel()
            pb_return.data[:] = xs
            del xs[:len(xs)]

            yield pb_return

        pb_return = MyModel()
        pb_return.data[:] = xs[:size]
        del xs[:size]
        yield pb_return
```

のようなヘルパー関数を書いておき、

```python

stream = make_stream_data(data)
res = stub.test(stream)
```

というように書きます。


#### 注意
このとき、注意点として、

```python
with grpc.insecure_channel(self.address) as channel:
    stub = MyStub(channel)
    res = stub.test(
        stream
    )
```

と書くと、`SOCKET CLOSED` となるので注意です。
上記のように、

```
res = stub.test(stream)
```
という呼び出し方にしましょう。



#### 呼び出し方（受信側）

受け取る時は、

```python
stream_list = []
for el in request:
    stream_list = stream_list + list(el.data)

```

のように書き、stream_list に対して処理を実行します。



## まとめ

gRPC + Python はプロトタイプを作る多くの場面で使用する可能性が高いので、
基本的な使い方はテンプレ化しておいて、サクッと作りたいですね。


今回はこの辺で。


@kenmaro
GPS座標から住所を求める JXA（JavaScript for Automation）Ver.2

## 農研機構の簡易逆ジオコーディングサービスがサービス終了
　同タイトルで3年ほど前にこんな記事を投稿していた。

https://qiita.com/ynomura/items/9fe05ba90bc4896e7565

このスクリプトを書くきっかけは、友人が FileMakerで写真のGPS情報から住所を調べるようにしたいという依頼があり、APIを調べている中で作成したものだった。
　その友人から、動かなくなった！との連絡があって、早速サイトに行ってみると

https://aginfo.cgk.affrc.go.jp/index.html.ja

**AGINFO ウェブサイトは廃止いたしました**
ということだった。

## 代替え候補の Web API を探す
　探すといってもググるだけ。ChatGPT に聞くまでもない。
候補としたのは次の２つ。
. [Google Maps Platform の ジオコーダ API](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/reversegeocoder.html)
. [Yahoo! の ジオコーダ API](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v2/geocoder.html)

　Google Maps API は一応、有償ではあるが、個人で通常の使い方であれば無料の範囲内で使えるし、取得できる情報も多い。
　Yahoo! API は、基本、無償で使える。
ということで、両方を試してみた。

## ソースコード
### Google Maps Platform API
```javascript:RevGeoCode_Google.scpt
// 緯度、軽度から住所を求める
// Google Maps のサービスを利用
// 戻り値は JSON 形式

var app = Application.currentApplication()
app.includeStandardAdditions = true

const baseURL = '"https://maps.googleapis.com/maps/api/geocode/json?language=ja&'
const API_KEY = "<YOUR_API_KEY>"
var latlon = app.displayDialog("緯度,経度を入力", {defaultAnswer: ""}).textReturned
var URL = baseURL + 'latlng=' + latlon + '&key=' + API_KEY + '"'
var ans = app.doShellScript('curl -s ' + URL)
var jsonData = JSON.parse(ans)
var adrs = ''
if (jsonData['status'] != 'OK') app.displayDialog("データを取得できませんでした。")
else {
    var adrs = jsonData['results'][0]['formatted_address']
	
	app.displayDialog(latlon + 'の住所\r' + adrs + '\nをクリップボードにコピーします。')
	app.setTheClipboardTo(adrs)
}
```
　&LT;YOUR_API_KEY&GT;　のところは、Google から取得した API-Key に書き換えてご利用ください。

### Yahoo! API
```Javascript:RevGeocodeYahoo.scpt
// 緯度、軽度から住所を求める
// Yahoo! のジオコーダサービスを利用
// 戻り値は JSON 形式

var app = Application.currentApplication()
app.includeStandardAdditions = true

const baseURL = '"https://map.yahooapis.jp/geoapi/V1/reverseGeoCoder?output=json&'
const APP_ID = '<YOUR_APP_ID>'
var latlon = app.displayDialog("緯度,経度を入力", {defaultAnswer: ""}).textReturned
var lat = latlon.split(',')[0]
var lon = latlon.split(',')[1]
var URL = baseURL + 'lat=' + lat + '\&lon=' + lon + '&appid=' + APP_ID + '"'
var ans = app.doShellScript('curl -s ' + URL)
app.displayDialog(URL)
var jsonData = JSON.parse(ans)
var adrs = ''
if (jsonData['ResultInfo']['Count'] == 0 ) app.displayDialog("データを取得できませんでした。")
else {
	var adrs = jsonData['Feature'][0]['Property']['Address']
	  
	app.displayDialog(lat + ', ' + lon + 'の住所\r' + adrs + '\nをクリップボードにコピーします。')
	app.setTheClipboardTo(adrs)
}
```
 &LT;YOUR_APP_ID&GT; のところは,Yahoo! で取得した自分の APP-ID に書き換えてご利用ください。

## コメント歓迎
　お気づきの点や、誤りの指摘など歓迎します。
nextのwindows undefind問題

### 解決方法
Next.jsのdynamic関数を使用して、ランタイム時にContentコンポーネントを動的に読み込んでいます。

``` jsx
import dynamic from 'next/dynamic'

const Content = (props) => {
  ....
  }
  
  const DynamicContent = dynamic(
    {
      loader: async () => Content,
    },
    { ssr: false }
  )

```

### 説明
DynamicContentコンポーネントは動的に読み込まれ、ページがクライアントでレンダリングされるときにのみ読み込まれます。これにより、ページの初期読み込み時間が短縮され、パフォーマンスが向上します

#### loader
コンポーネントを非同期でロードする loader 関数を含むオブジェクト。
この場合、loader関数は async/await を使用してContentコンポーネントを読み込んでいます。

#### option
オプションの構成オブジェクト。この場合、ssr オプションは false に設定されています。
ssrオプションがfalseに設定されているため、DynamicContentコンポーネントはサーバーサイドレンダリングの際にはレンダリングされず、クライアントサイドでのみレンダリングされます。
AWS CloudFormationにベタ書きするLambda nodejs18.x

`Node.js 18.x`でコードを書いて、[AWS Lambda](https://aws.amazon.com/jp/lambda/)で稼働させたい。

AWS-SDKは[ランタイム搭載のAWS-SDK v3](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-runtimes.html)をそのまま使いたいし、コードは[AWS CloudFormation](https://aws.amazon.com/jp/cloudformation/)のファイル内に[ベタ書き](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-code.html#cfn-lambda-function-code-zipfile)してデプロイしたい（手抜き）。

## CloudFormationが生成するもの

例えばCloudFormationのYAMLにベタ書きする。

```yaml
# ...略...
Resources:
  LambdaFunc:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: nodejs18.x
      Handler: index.handler
      Code:
        ZipFile: |
          // ベタ書きするぞおおお
          // おおおお
          // おおおお
# ...略...
```

すると、生成されるのはこれまで通り`index.js`である。

## Node.jsコード側を合わせる

ということで、普段通り`index.mjs`を期待してコードを書く（ES Modules）と動かない。

```javascript
// 動かない
import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3';
export const handler = async (event) => {
    ...;
};
```

奥ゆかしく`index.js`を期待してコードを書く（CommonJS）ことになる。

```javascript
// 動く
const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
exports.handler = async (event) => {
    ...;
};
```

## AWSマネージメントコンソールの挙動

AWSマネージメントコンソール上でLambda（`nodejs18.x`利用）を手動でポチポチ作成開始した場合は`index.mjs`が用意されるため、「動く／動かない」の判断において混乱し易い。
WordPressをwpscanで脆弱性検査する

忘備録：WordPressに関する脆弱性検査

脆弱性検査において、WordPressをチェックする必要がありました。

wpscanとwpscan.comは外せないです。Enterprise版も存在し機能が充実しています。

https://wpscan.com/

まずは、プラグインやテーマを検査して、脆弱性を検査していきます。ユーザを発見し、パスワードのブルートフォースも可能です。

Kaliでは既存でインストールされています。以下が典型的なコマンド例です。

```bash
wpscan --url example.com -e vp --plugins-detection mixed --api-token WPVULNDB_API_TOKEN
```
詳細は、以下を参考にしてください。

https://github.com/wpscanteam/wpscan/wiki/WPScan-User-Documentation

実際は、以下のようなコマンドを叩きます。

```bash
wpscan --url $RHOST --enumerate ap,at,cb,dbe vp,u,m --api-token <Your token> --ignore-main-redirect --wp-content-dir http://<Your WP Address>/wp-content 
```
以下は、すべてのプラグインと登録されているユーザを検査します。
```bash
wpscan --url $RHOST --enumerate ap
wpscan --url $RHOST --enumerate u
```

今回は、スキャンの結果ではなく、HTMLのソースから怪しいプラグインを発見しました。

教訓：
wpscanでスキャン出来ないプラグインもあるため、必ずHTMLのソースコードを確かめること。

追記：パスワードのブルートフォースは以下のようなコマンドです。
```bash
wpscan --url http://<IP adderss>:<port>/wordpress/ --passwords cewl.txt --usernames "admin,james"
```


ハッピーハッキング
Googleデータアナリティクス：SQLのCOUNT と COUNT DISTINCT

# はじめに

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

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

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/21a12cb1-a49a-802f-d903-6f68758eca0c.png" width="800">

# SQLのCOUNT と COUNT DISTINCT

データアナリストとして COUNT と COUNT DISTINCT は 「いくつか」という問いかけの答えを求める時に 使える関数です。

- **COUNT** は指定した範囲内の行数を 返すクエリですが COUNT DISTINCTは少し違います。 
- **COUNT DISTINCT** は その範囲内の固有の値のみを返すクエリです。 基本的に、COUNT DISTINCTは 重複する値を数えません。 

例えば、
- 何人の顧客が商品を購入したのか？ 
- 今月は何件の取引があったのか？ 
- このデータセットには いくつの日付があるのか？

データ分析の過程では、さまざまな場面で これらを使うことになります。 

例えば、
- データクリーニングをしているときに データセットに何行あるかチェックするのに 必要かもしれません。 
- 実際の分析中に COUNT や COUNT DISTINCT を使い いくつ、という問いかけに答えることも あるかもしれません。 

### 例

靴下を製造している会社を 例にとって考えます。 2 つのテーブルがあります。
#### Warehouse （倉庫状況）テーブル

倉庫の ID　や名称、 最大収容数や従業員総数、 倉庫の所在地を表す州名の 各列があります。 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/b505456e-6d6a-6858-435b-f4194041597e.png" width="６00">

#### Orders（受注状況）テーブル

次に、Orders テーブルの 上位 100 行を取得します。 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/2d25eb72-a423-f597-8e99-0633b60aeaa4.png" width="６00">

ここでは、州ごとの受注状況を レポートするために、 倉庫の詳細と受注の詳細の 両方が必要だとします。 そこで、この 2 つのテーブルを JOIN して 両方のデータを取得します。 ここで warehouse テーブルのエイリアスも 作成しておきましょう。 この場合、両方のテーブルに 対応するデータが必要なので JOIN は INNER JOIN の略語として使用します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/656e1c57-db66-0bba-e906-697b369e64e7.png" width="６00">

エイリアスを設定したところで FROM の前に来る SELECT 構文を 作成します。これを実行します。 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/5a34faa5-1c04-23ce-2cb6-26b7b97db640.png" width="６00">

すると、このように表示されます。 これで、両方のテーブルのデータが結合され 便利なエイリアスも作成できました。 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/5fab0e02-db92-a987-5201-73a0068f60e0.png" width="６00">


ここで、受注状況データの中に いくつの州があるのか、数えてみたいと思います。 これを行うには、COUNT と COUNT DISTINCT を使います。 

まず、簡単な COUNT クエリを試してみましょう。 FROM 構文で、Orders テーブルと Warehouse テーブルを JOIN します。 この場合は SELECT で始めて 州の数をカウントします。 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/b36be198-086a-8345-f21e-21628c2fb199.png" width="６00">

このクエリを実行して、何が得られるか 見てみましょう。 いや、ちょっと違うようですね。 このクエリは 9,000 以上の州を返していますが これは州を含む行を 1 つ 1 つ数えているからです。 しかし、ここでやりたいのは 個々の州を数えることです。 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/9329fcab-12cf-35b1-0143-a6170233cbb5.png" width="６00">

そこで COUNT DISTINCT を もう一度試してみましょう。 そして、倉庫テーブルの州列で グループ化してみます。 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/496b1e05-cec6-7abf-022c-97f7e267807c.png" width="６00">

これで各州の行が 3 行になり Orders データから 1 つずつ表示されました。 受注数に対する COUNT DISTINCT は 先ほど実行したカウントを合計したものです。 3 つの合計は、9,999 となるはずです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/584c1f11-e319-0eec-730d-85e4852c9800.png" width="６00">
コード自動生成サービス

# GitHub Copilot
https://github.com/features/copilot
- GitHubとOpenAIが共同で開発
- 無料試用版あり
- サポート言語：Python、JavaScript、TypeScript、Ruby、Go、C#、C++ が得意（他の言語、FWも対応はできる）
- サポートIDE：Visual Studio、Neovim、VS Code、JetBrains IDEs
- 汎用的なコードを生成

# Amazon CodeWhisperer
https://aws.amazon.com/codewhisperer/
- AWSのサービス
- 個人利用は無料
- サポート言語：Python、Java、JavaScript、TypeScript、C#、Rust、Go、Ruby、Scala、Kotlin、PHP、C、C++、シェルスクリプト、SQL
- セキュリティスキャン：Python、Java、JavaScriptのみ対応
- サポートIDE：JetBrains IDE (IntelliJ, PyCharm, CLion, GoLand, WebStorm, Rider, PhpStorm, RubyMine, and DataGrip)、Visual Studio (VS) Code、AWS Cloud9、AWS Lambda コンソール
- AWSサービスでの使用に最適化したコードを生成
【Xcode】コードの整頓はXcode拡張を使って一瞬で終わらせる

# はじめに
便利そうなXcode拡張を見つけたので紹介します。

https://github.com/aheze/Multiliner

# やりかた
Multilinerをインストールします。
```:ターミナル
brew install hkamran80/things/multiliner
```

設定アプリを開きます。
① 「プライバシーとセキュリティ」を選択します
② 「機能拡張」を選択します
![スクリーンショット 2023-04-18 13.33.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/dc44130e-33d7-6b9f-e69e-aa84b686af7c.png)

③ 「Xcode Source Editor」を選択します
![スクリーンショット 2023-04-18 13.38.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/8c5d0569-52b7-065b-5931-3ef6d4a1529b.png)

④ 「MultilinerExtension」にチェックをいれます
![スクリーンショット 2023-04-18 13.40.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/39f31a40-c7e9-9930-14a8-d1d233dd4f59.png)

# 使いかた
引数の多い関数を用意しました
![スクリーンショット 2023-04-18 13.44.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/f0a0cabe-08a9-5b5a-8347-63bb5091bcf4.png)

関数部分を選択します
![スクリーンショット 2023-04-18 13.45.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/47392e82-ad83-dcf9-51b0-2d9c534599aa.png)

① 「Editor」を選択します
② 「Multiliner」を選択します
③ 「Format Selected Code」を選択します
![スクリーンショット 2023-04-18 13.46.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/7bbe7114-2a88-3c06-cc8c-0008859ef61b.png)

整頓してくれましたー！
![スクリーンショット 2023-04-18 13.49.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/30b319ff-5a99-c083-bf11-38ee5515a234.png)

# おわり
これはめっちゃ便利です
キーボードショートカットを設定するともっと便利になりそうです。
ただ、関数全体を選択するとバグっちゃうのでそこだけ治したいですね

関数全体を選択すると、、
![スクリーンショット 2023-04-18 13.51.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/b8435114-a23e-f892-555b-b3b1be54031d.png)
こうなる
![スクリーンショット 2023-04-18 13.51.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/7c87cdf5-db3d-65c8-1277-d4f25e16246b.png)
Macがsshのパスフレーズを忘れる

## 問題

Macをアップデートすると，たまにMacがsshのパスフレーズを忘れてしまい，sshで遠隔操作をしようとするとパスフレーズを入力しなければならなくなる．

## 解決法
次のコマンドをうち，パスフレーズを再度覚えさせれば良い．
```
ssh-add -K ~/.ssh/id_rsa
```
プロンプトエンジニアリングガイド日本語版 自分用メモ

# プロンプトエンジニアリングガイド日本語版
https://www.promptingguide.ai/jp

# はじめに
基本的な例がつらつら書いてある。

- 特に何も意識しなくても使えるけれど、より良く回答を得るためにプロンプトエンジニアリングが必要
- 要素の説明
命令 - モデルに実行してほしい特定のタスクまたは命令
文脈 - 外部情報や追加の文脈が含まれる場合があり、モデルをより良い応答に導くことができる
入力データ - 応答を見つけたい入力または質問
出力指示子 - 出力のタイプや形式を示す

- 指示と文脈を区切るために「###」のような明確な区切り記号を使用することが推奨されている
- モデルに実行してほしい指示やタスクについて、非常に具体的に説明。プロンプトが詳細で具体的であるほど、結果はよくなる。特定の出力やスタイルを望む場合には、特に重要。
- 「しないこと」を言わず、「すること」を言う。
- "A:"は質問応答で使用される明示的なプロンプトフォーマット
```
抗生物質について説明してください。
A:
```
- role prompting
指示によって、どのように振る舞うかを明示的に伝える。会話形式。
- コード生成にも使える。

# プロンプトエンジニアリング技術
ここからが多分本番。

## Zero-Shotプロンプティング
モデルに任意の例を提供せず、ゼロショットでタスク実行。
これで思い通りにならなければ、Few-Shotプロンプティングを試す。

## Few-Shotプロンプティング
プロンプト内のデモを提供。
より複雑な算術、常識、および象徴的推論タスクに対応するためには、Chain-of-Thought (CoT) promptingが普及。

## Chain-of-Thoughtプロンプティング
中間的な推論ステップを介して複雑な推論。
Zero-shot COT Prompting「ステップバイステップで考えてみましょう。」を足すことで正しい答えに。

## Self-Consistency（自己整合性）
few-shot CoTを通じて複数の多様な推論パスをサンプリング。
算術および常識的推論を必要とするタスクにおけるCoTプロンプティングのパフォーマンスが向上。

## 知識生成プロンプティング
より正確な予測を行うために知識や情報を組み込む（知識生成）で改善。

## 自動プロンプトエンジニア（APE）
自動指示生成と選択
「正しい答えを得るために、ステップバイステップで考えてみましょう。」のプロンプトは、思考の連鎖を引き起こし、MultiArithおよびGSM8Kベンチマークのパフォーマンスを向上させる。

## アクティブプロンプト
TBD

## 方向性刺激プロンプティング
TBD

## ReAct
LLMが外部ツールと対話して追加情報を取得し、より信頼性の高い事実に基づく回答を生成。

## マルチモーダルCoTプロンプティング
TBD

## グラフプロンプト
TBD

# プロンプトアプリケーション
## プログラム支援言語モデル（PAL）
TBD

## データ生成
TBD

# モデル
TBD

# リスクと誤用
TBD
AndroidStudio 実行環境構築エラー対応

## 前提
androidStudioでの環境構築初学者向けの記事です。
20230418前後で起きる現象かと思います。

## 事象1
JetBranisからandroidStudioをupdateで更新。
更新後以下のようなエラーが出る。
エラーログ
```
- Incompatible because this component declares a component for use during compile-time, compatible with Java 11 and the consumer needed a component for use during runtime, compatible with Java 8
              - Other compatible attribute:
                  - Doesn't say anything about org.gradle.plugin.api-version (required '8.0')
          - Variant 'javadocElements' capability com.android.tools.build:gradle:8.0.0 declares a component for use during runtime, and its dependencies declared externally:
              - Incompatible because this component declares documentation and the consumer needed a library
              - Other compatible attributes:
                  - Doesn't say anything about its target Java version (required compatibility with Java 8)
                  - Doesn't say anything about its elements (required them packaged as a jar)
                  - Doesn't say anything about org.gradle.plugin.api-version (required '8.0')
```


## 解決策1
https://developer.android.com/studio/intro/studio-config?hl=ja
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421327/9190db9e-69a8-79f9-5220-7e7cb9bd49e6.png)
javaのバージョンが合致していないことが問題のように見えたので、JDKのバージョンをEmbedded JDKに変更。
エラー時はJDKが1.8になっていた。おそらくデフォルト。


## 事象2
それでもコンパイル時に別のエラーが発生した
エラーログ：
メモできていなかったため、その時のログキーワードに引っかかった記事掲載
https://stackoverflow.com/questions/75263047/duplicate-class-in-kotlin-android

## 解決策2
記事の通りorg.jetbrains.kotlin.androidを1.8.0に変更
```build.gradle(project)
plugins {
    id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
}
```
それでも治らないのでkotlinCompilerExtensionVersionを1.4に変更
```build.gradle(module)
composeOptions {
        kotlinCompilerExtensionVersion '1.4.0'
    }
```

これで無事にエラーが解消し、ビルドが通るようになりました。

## 終わりに
最初わからないと特にハマるので同じようにハマった人がいれば手助けになればと思います。
curl実行時のcertificate has expiredエラーの解決策

AmazonLinux2のEC2インスタンスで実行しているサーバからのslack通知が飛ばなくなった

```
$ curl -X POST -H 'Content-type: application/json' --data '{"text":"hogehoge"}' https://hooks.slack.com/services/HOGE/HOGE/HOGE
curl: (60) SSL certificate problem: certificate has expired
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
```

証明書を更新して解決

```
$ sudo yum update ca-certificates
```
【Rails】 deviceのインスールができない　'Could not find generator 'device:install'. '

## 環境
ruby 3.2.1
Rails 6.1.7.3
devece 4.9.2

## 発生したエラー
deviseインストール時にエラー発生
```rails:ターミナル
$ bin/rails g devise:install

Running via Spring preloader in process 71926
Could not find generator 'devise:install'. 
Run `bin/rails generate --help` for more options.
```

## 原因・解決
Gemfileのタイプミスが原因でした。
```Gemfile:Gemfile
gem 'device'

↓↓↓修正

gem 'devise'
```

## 参考
["rails g devise:install" 実行時、"Could not find generator" というエラーになる時](https://qiita.com/Taku0055/items/0c17d6f0de7e2e8a7f96)
数時間で作ったChatGPT向け・AI同士で会話させるプロンプトエンジニアリング補助ツール

chatGPTのプロンプトエンジニアリングしてたときに面倒だったことを解決するために、ChatGPTと協力しつつ数時間でプロンプトエンジニアリングの補助ツールを作成しました

https://prompt-studio.vercel.app/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612494/053f16fb-06c5-bbc7-4bd2-8abd4a579ae9.png)

## 解決したかった問題
chatGPTのAPIを使ったサービスを作ろうというときに、何かしらのタスクに最適化しようと考えると、systemメッセージのprompt engineeringが必要になってきます。
最近はそれすら汎用プロンプトで解決しようとしたり、AutoGPTなどで解決を図ったりしていますが、開発者としてはそれで使用トークン数が増えていくのは避けたかったりします（一般の人の一部もそう思うようになるかも？）

そこで質のいい出力ができる指示を書きたいのですが、コツはあれどなかなか一発で満足がいくものはできないもので、試行錯誤が必要です。
google colaboratoryとか開いてやっていたわけですが、、、

> 「いちいち入力考えるのめんどくさ！！！！」
> 「レスポンスコピペしていくのも面倒！！！！」

となってくるわけです。

そこで

> 「じゃあユーザーの入力も仮でchatGPTに作ってもらえばいいんじゃね？」

と思い、フロントエンドなのでUIも作ってしまうことにしました。

## 機能
- API keyを入力することで使えるようになります。
- main system messageを入力します
  - こっちがテストしたい、assistantの出力を生成するためのプロンプトです
- sub system messageを入力します
  - これがユーザーの入力を生成するためのプロンプトになります
- 最初のメッセージを入力します
  - これはuserでもassistantでも構いません
- あとはgenerateボタンを使って交互に生成できます


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612494/7c9270c1-75ae-5beb-5973-8eb366f5a4e5.png)

こんな感じで指示を出しておけば勝手に会話してくれます
対話がユーザー体験のキーとなるようなサービスを作ろうとしているときに、いちいち入力を自分で考えなくてもよくなるのがうれしいところかと思います

送信するメッセージ数に上限を付ける機能も付いているので、実際にAPIを使ってサービス化するときに近い状態での開発が気軽にできるでしょう。

## 技術的な面について
Next.js & Vercel の楽々コンビでパパっと作りました。
とりあえずってところで独自ドメインも取ってないです。

一応、先日Next.jsのversion 13.3がリリースされたということで、最新バージョンでの開発をしてみています。
とはいえ今のところ13.3の恩恵はあまり受けていないですけどね、、、
（最初に作ったときにlayoutやpageの記述がちょっと変わってて、おおって思ったくらい。meta情報はすごく書きやすくなっています。機会があればルーティングの機能も使いたいですね）

そういえばcreate-next-appしたときに、tailwind使うかを聞かれるようになったのですが、これも13.3からなのかな？
tailwindはよく使うので、デフォルトで設定がサポートされるようになったのはすごく楽でありがたいですね

いや1ページのツールにNext.jsはオーバースペックすぎるだろとのご指摘、ごもっともです。

#### ChatGPTとの協業について
今回、開発をブーストさせるためにChatGPTもそれなりに使いました。
tailwind使ってるよっていうだけで、良い感じのclassNameを付けてくれるのがありがたいところでしたね。

どんな感じにするか迷うところなので、とりあえずでこんな感じでどう？って出してくれるChatGPTは開発時間の短縮に貢献してくれるありがたい存在でした。

今後もっと開発を任せられる存在にしていきたいですね。仕事減っちゃうけど。
でもそういう方向に進んでく、進んでいるのは明確なので、早いとこ適応しよう、先駆者になっていこうというところです。

## 最後に

https://prompt-studio.vercel.app/

ChatGPT APIを使った開発の際にはぜひ使ってみてください！
ご意見・ご要望等もお気軽に！
HomeBrewで Warning: ... :macos => :yosemite is deprecated! ...と出た


## はじめに

Macのアプリ環境を整備するためにHomeBrewを使ってBrewfileを作って色々インストールした経緯がある。
ある日以降、HomeBrewのupdateコマンドを実行した時に何やら見慣れないWarningが出てくるようになった。

```text
Warning: Calling depends_on :macos => :yosemite is deprecated! There is no replacement.
Please report this issue to the argon/mas tap (not Homebrew/brew or Homebrew/homebrew-core):
  /opt/homebrew/Library/Taps/argon/homebrew-mas/mas.rb:8
```

しばらく前から表示されておりエラーではないので後回しにしていたが、視界に入るのが気になってきたため原因を調査してみた。

## 環境

* Mac Mini(M1) Mac OS 13.3.1 Ventura
* HomeBrew 4.0.13
* mas-cli ?????（後述するが再インストールしてしまったため確認できない）

## 用語

* yosemite→macOSのコードネーム（?）らしい
* mas→App Store上のアプリをパッケージ管理できるやつ

つまりはMac App Storeをパッケージ管理できるmasモジュールが古いOSの何かを使っており、それがある時から非推薦となった。
結果、`brew update`コマンド実行時にmasを呼び出すためにWarningが出るようになった。
ということね。

## 結論

masモジュール再インストールすることで出なくなった。

```bash
brew uninstall mas
brew install mas
```
【Salesforce】【データローダ】index 200 out of bounds for length 200  エラー

データローダの最新版で不具合を見つけたのでメモ。
そのうち解消されてアップデートされると思いますが、一時困ったので共有します。

# データローダのバージョン
対象OS：Windows版
バージョン：v57.0.1
※2023年4月17日にインストールしました。

# 不具合
2001件以上のデータをInsertすると「index 200 out of bounds for length 200」が発生します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/8a6733f3-6647-91c1-d042-752c817c8f9e.png)
※update,upsert,deleteについては未検証です。

# 回避方法①
Settingの「Use Bulk API」にチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/40eea56a-cc76-57a7-6068-3f43b23341a8.png)

# 回避方法②
他のバージョンのデータローダを使用する
手元にあったv55.0.1ではエラーが発生しないことを確認済みです。
巨大なリポジトリを、GitLab→GitHubに、LFSを使って、ちょっとずつpushする

# はじめに

自宅のGitLabでホスティングしているリポジトリをGitHubに移行しました。

以降自体は難しくなく、Qiitaでもたくさんの記事が見つかります。

- [巨大なリポジトリを GitHub に移行した話 - Qiita](https://qiita.com/ikmski/items/0faf9eae808ff29f6358#%E3%83%97%E3%83%83%E3%82%B7%E3%83%A5)
- [Gitリポジトリのコピー時、git lfs migrateでGIT-LSF移行 - Qiita](https://qiita.com/kazzzu/items/081a6599a32982cb41c6)

しかし、自分の場合はこれらで考慮されていないトラブルに遭遇してしまったので、記録として記事を書きます。

# 対象リポジトリの情報

移行対象のリポジトリは下記のようなスペックです。

- GitLab使用
- 75,000ファイル（master）
- リポジトリ容量 9GB
- LFS未使用
- 800コミット
- 1ファイルの最大ファイルサイズ 1.5GB（過去コミット含む）

# 移行の際のポイント

自分の知る限り、GitHubには次の制限があります。

### GitHubの制限
1. 1ファイルは100MB未満である必要がある
1. 一度にpushできるサイズは2GB未満である必要がある

これらのうち、1つ目めの「1ファイルは100MB未満である必要がある」は、LFSを使うことで回避できるようになります。「[Gitリポジトリのコピー時、git lfs migrateでGIT-LSF移行 - Qiita](https://qiita.com/kazzzu/items/081a6599a32982cb41c6)」をそのまま作業できます。

問題は2つ目の「一度にpushできるサイズは2GB未満である必要がある」です。これを解決するために、pushを1コミットずつ行うスクリプトを作成して対応しました。
なお、今回移行対象となったリポジトリは、1コミット2GBを超えることはありませんでしたが、もし1コミットで大容量のファイルをコミットしてしまっているような場合（50MBのアセットを40ファイル同時にコミットしている等）は、コミットを分割することで対応する必要があります。

# 移行の流れ

おおむね、「[Gitリポジトリのコピー時、git lfs migrateでGIT-LSF移行 - Qiita](https://qiita.com/kazzzu/items/081a6599a32982cb41c6)」に沿っています。

```sh
git clone --mirror https://gitlab.example.com/user/myrepo.git
cd myrepo.git/
git lfs migrate info --everything
git lfs migrate import --include="*.weights,*.png,*.jpg" --everything
git push --mirror https://github.com/example/new-myrepo.git  # ここで失敗する
```

最後の`git push`では、下記のようなエラーメッセージが表示されました。

```
Enumerating objects: 62968, done.
Counting objects: 100% (62968/62968), done.
Delta compression using up to 16 threads
Compressing objects: 100% (62968/62968), done.
remote: fatal: pack exceeds maximum allowed size (2.00 GiB)
error: remote unpack failed: index-pack abnormal exit
To github.com:example/new-myrepo.git
 ! [remote rejected] master -> master (failed)
error: failed to push some refs to 'git@github.com:example/new-myrepo.git'
```

packファイルは2GBを超えてはいけないとのエラーです。  
packファイルのサイズを制限したり分割させたりといったgit設定はなさそうなので、1コミットずつpushするスクリプトを作成しました。
（https://gist.github.com/piki/10d57cda6d5b25744fdeefb56b421fe4 のものを流用し、rubyを使わないようにしたり、内容をシンプルにしたりしています）

```sh:push-big-repo.sh
#!/bin/bash -e
COMMIT_STEP=1  # 何コミットずつpushするか。1でよい。時間がかかるようなら、100とかを試してもよい。
START_COMMIT=1 # 一番最初は何コミット目から始めるか。通常1でよい。

git log --pretty=%H | tac > commits
COMMIT_COUNT=$(wc -l commits | cut -d' ' -f1)

for i in `seq $START_COMMIT $COMMIT_STEP $COMMIT_COUNT`; do
	echo ====== $i
	COMMIT=$(head -$i commits | tail -1)
	git tag -d foo || true
	git tag foo $COMMIT
	git push -f origin foo
done

git tag -d foo
git push origin HEAD
git push --mirror
git lfs push --all  # 念のため
```

```sh
git config --unset remote.origin.mirror # コミット単位でpushしたいのでmirror設定を解除する

./push-big-repo.sh
```

これで、無事、移行できました。
herokuでproductionとpreview appで1つのHeroku PostgresのDBを共有する方法

そのままこの記事の内容をやったらできた↓
https://zenn.dev/karaageeeee/articles/41eff65f1c73c0

## 何が起きるか
heroku pipeline上のproductionとpreviewで同じDBを共有できる。
・productionと同じデータ量で速度や表示が問題ないか確認できる
・料金がheroku postgreSQL1個分しかかからない（多分）

## 上記の記事が消えた時用のバックアップとしてコピペ
まず、1つのアプリにPostgreSQLのアドオンを追加しておきます。ブラウザからでもコマンドでも構いません。
1つ目のアプリをtest-app-1として追加されているアドオンを確認します。

```
$ heroku addons -a test-app-1

Add-on                                         Plan       Price  State
─────────────────────────────────────────────  ─────────  ─────  ───────
heroku-postgresql (postgresql-xxxx-yyyy)  hobby-dev  free   created
 └─ as DATABASE
```

上記で表示されたアドオンのIDを確認しておきます。この場合はpostgresql-xxxx-yyyyとなっている部分です。

2つ目のアプリをtest-app-2として、確認したアドオンIDをもとにアドオンを追加します。

```
$ heroku addons:attach -a test-app-2 postgresql-xxxx-yyyy
Attaching postgresql-xxxx-yyyy to ⬢ test-app-2... done
Setting DATABASE config vars and restarting ⬢ test-app-2... done, v13
```

完了したら、アドオンが２つ目のアプリに追加されたことを確認します。

```
$ heroku addons -a test-app-2

Add-on                                         Plan       Price                             State
─────────────────────────────────────────────  ─────────  ────────────────────────────────  ───────

heroku-postgresql (postgresql-xxxx-yyyy)  hobby-dev  (billed to test-app-1 app)  created
 ├─ as DATABASE
 └─ as DATABASE on test-app-1 app
```

上記でアドオンがtest-app-1にも利用されていることがわかります。

最後に２つのアプリの環境変数に同じものがセットされているか確認します。

```
$ heroku config -a test-app-1
=== test-app-1 Config Vars
DATABASE_URL:          postgres://xxxx:yyyy@ec2-xxxxx.compute-1.amazonaws.com:5432/zzzz

$ heroku config -a test-app-2
=== test-app-2 Config Vars
DATABASE_URL:          postgres://xxxx:yyyy@ec2-xxxxx.compute-1.amazonaws.com:5432/zzzz
```

2つのDATABASE_URLが一致していれば完了です。

## herokuの画面上でも複数APPにアタッチメントされていることが確認可能

※2つ目のAPPから確認した画像。productionの `narou-susume2`にもDATABASEとしてアタッチされている。
![screenshot-2023-04-18-121408.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145707/6e838a92-ad13-8cbf-284c-8b312a7a32c1.png)
AmazonLinux2023にMySQL8.0をインストールする

AL2023がGAなってたので早速LAMPのセットアップしてみた。

# 最初に気付いたこと

amazon-linux-extrasが無くなってる
enableしてinstallするだけで楽だったのに...

# Apache
従来通りでOK
大して違いが無いとは言えそろそろyumを卒業してdnfに慣れていかないと...

```bash
yum install httpd
```

# PHP
なんとデフォルトで8.1が入るようになってる
これは嬉しい

```bash
yum install php
```

![スクリーンショット 2023-04-17 21.18.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23195/c6abee4c-50ea-cf67-9bb3-b3620e2d8a7f.png)

# MySQL

これもどうせ何か変わってんだろと思って事前にリサーチ
ClassMethodさんのページを参考にしてみる

https://dev.classmethod.jp/articles/install-mysql-client-to-amazon-linux-2023/

なるほど、Fedora用じゃなくてRHEL用で入れればいいのね

```bash
yum -y localinstall  https://dev.mysql.com/get/mysql80-community-release-el9-1.noarch.rpm
```

![スクリーンショット 2023-04-18 11.51.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23195/ca3ecb47-08ad-8186-f31d-4cc143f86fae.png)

**なんか入らなくね**

リポジトリをcurlで叩いたらなんかリダイレクトされてるっぽいので
そっちを参照してみる

```bash
curl -v https://dev.mysql.com/get/mysql80-community-release-el9-1.noarch.rpm

< HTTP/2 302 
< location: https://repo.mysql.com//mysql80-community-release-el9-1.noarch.rpm
```

こっちに変更

```bash
yum install https://repo.mysql.com//mysql80-community-release-el9-1.noarch.rpm
```

![スクリーンショット 2023-04-18 12.01.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23195/6827f99f-f0bc-4264-213e-d8a9647105b1.png)

行けた

# 大まかな違い

+ MySQLの調査の過程でSELinuxがデフォルトでPermissiveモードになってたのに気付いた
+ nginxもそのままインストール出来る
+ opensslが3.0になってる

ところまでは自力で気付いたが後はやっぱりClassMethod様々

https://dev.classmethod.jp/articles/amazon-linux-2023-ga/#toc-6


**おわり。**
Outlookのログ保管場所とログ（etlファイル）のtxt変換

# ログの場所

通常、『AppData』は隠しフォルダーになってる。

```
C:\Users\ユーザー名\AppData\Local\Temp\Outlook Logging
```

etlファイルはそのままサクラエディタで直接開いても、人が読めるような内容になっていない。
コンバートする必要がある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/f2eba166-75ed-507b-2904-26a329b70986.png)

# etlファイルをtxtへ変換

etlファイルの内容を見るため用の特別なソフトは必要ない。
PowerShellを開いて下記コマンドでtxtへ変換できる。

```powershell
netsh trace convert input="etlファイルパス" output="変換先txtファイルパス"
```

# 参考サイトさん

https://support.microsoft.com/ja-jp/office/-%E5%8B%95%E4%BD%9C%E5%B1%A5%E6%AD%B4%E3%82%92%E8%A8%98%E9%8C%B2%E3%81%99%E3%82%8B-%E3%83%88%E3%83%A9%E3%83%96%E3%83%AB%E3%82%B7%E3%83%A5%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0-%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E6%A6%82%E8%A6%81-0fdc446d-d1d4-42c7-bd73-74ffd4034af5

https://sevenb.jp/wordpress/ura/2022/05/24/windowswindows-update%E3%81%AE%E3%83%AD%E3%82%B0etl%E3%82%92%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AB%E5%A4%89%E6%8F%9B%E3%81%99%E3%82%8B/

# バージョン

Windows 10 Pro 22H2 19045.2846
Microsoft Outlook for Microsoft 365 MSO (バージョン 2303 ビルド 16.0.16227.20202) 32 ビット
input fileで同じファイルを連続で選ぶと@changeイベントが発火しない問題

**input fileで同じファイルを連続で選ぶと@changeイベントが発火しない問題(Vue.js)**

**原因**：
changeイベントが発火しないことでした。

**解決方法**：
一度写真を追加し、削除しても追加したデータを裏方で保持しているためもう一度追加した際に、changeイベントを発火しないというものです。
追加が完了した際に、裏方のデータを削除することで修正可能です。

下記のブログを参考に作成しています。
https://strip.koatech.info/articles/vue-input-same-file/

①@changeの最後にvalueを空にする
```vue
<template>
  <div>
    <input @change="onChange" accept="image/jpeg, image/png" type="file">
  </div>
</template>
<script>
export default {
  methods: {
    onChange(e) {
      const file = e.target.files[0]
      const reader = new FileReader()
      reader.onload = (e) => {
        console.log(e.target.result)
        //@changeの最後にvalueを空にする
        e.target.value = ''
      }
      reader.readAsDataURL(file)
    }
  }
}
</script>
```

②@clickでe.target.valueを空にする

```vue
<template>
  <div>
    <!-- @clickでe.target.valueを空にする -->
    <input @change="onChange" accept="image/jpeg, image/png" type="file" @click="(e) => { e.target.value = '' }">
  </div>
</template>
<script>
export default {
  methods: {
    onChange(e) {
      const file = e.target.files[0]
      const reader = new FileReader()
      reader.onload = (e) => {
        console.log(e.target.result)
      }
      reader.readAsDataURL(file)
    }
  }
}
</script>
```
UnityのLibraryファイルがGitでコンフリクトするとき

# 何が起きたか
共同でゲームを開発しているときにLibraryフォルダ内で無数のコンフリクトが生じ、プロジェクトが進められないくなりました、、しかも途中で.gitignoreに追加してもコンフリクトが収まりません。
# 原因
Unityでプロジェクトを作るとLibraryという名前のフォルダが生成されます。開発序盤でLibraryフォルダを共有する必要があると勘違いしており、開発序盤で.gitignoreにLibrary/PackageCacheのように部分的に無視するように書いてしまい、その設定がずっと生きているようでした。

# 解決
[こちらのページ](https://goat-inc.co.jp/blog/2634/)を参考に、
```
git rm -r --cached . 
```
でキャッシュを消すとライブラリフォルダが共有されなくなり、問題が解決しました。単純なことですが結構詰まったので共有しておきます。