OmniAICreator/Qiita-1.07M huggingface dataset:
java練習　単回帰分析


~~~ java
import java.util.List;
import java.util.ArrayList;
import java.lang.Math;

public class stats {
    public static double sum(double[] x){
        double sum = 0;
        for(int i=0; i<x.length;i++){
            sum += x[i];
        }
        return sum;
    }

    public static double mean(double[] x){
        double sum_of_x = sum(x);
        double len_of_x = x.length;
        double y = sum_of_x / len_of_x;
        return y;
    }
    public static double var(double[] x){
        double mean_of_x = mean(x);
        double tmp = 0;
        for(int i=0; i<x.length;i++){
            tmp += Math.pow(mean_of_x - x[i], 2);
        }
        double result = tmp / x.length;
        return result;
    }
    public static double covar(double[] x,double[] y){
        if(x.length!=y.length){
            System.out.println("二つのデータのサイズが異なります")
        }
        else{
            double mean_of_x = mean(x);
            double mean_of_y = mean(y);
            double tmp = 0;
            for(int i=0;i<x.length;i++){
                tmp += (x[i]-mean_of_x)*(y[i]-mean_of_y);
            }
            double result = tmp/x.length;
            return result;
        }
    }
    public static double[] SimpleRegression(double[] x,double[] y){
        double alpha = covar(x,y)/var(x);
        double beta = mean(y) - alpha * mean(x);
        double[] result = new double[2];
        result[0] = alpha;
        result[1] = beta;

        return result;
    }
}
~~~
Redash+MySQL(RDS)+Firestore+BigQuery

# Redashインストール

RedashのAMIを選択して、private subnetにEC2インスタンスを立ち上げる
https://redash.io/help/open-source/setup#aws

# Redashインスタンスにログイン

踏み台サーバ経由の場合


```~/.ssh/config@local
Host jump
  User ec2-user
  HostName x.x.x.x
  IdentityFile ~/.ssh/private-key.pem
  ForwardAgent yes
```

```/etc/hosts@jump
...
x.x.x.x redash
```

```
local% ssh-add ~/.ssh/private-key.pem
local% ssh jump
ec2-user@jump% ssh ubuntu@redash
```

# ALB+ACM

HTTPSで運用する場合はredash.example.comの証明書をACMで作成して、ALBに割り当てる。

- Target Group
  - healthcheck
    - /ping
- ALB
  - HTTPS
    - Target Group
  - HTTP
    - HTTPS://#{host}:443/#{path}?#{query}
- Route53
  - ALB用のDNSレコードを作成

# Redashセットアップ

https://redash.example.com
にアクセスしてAdminアカウントを作成。

# MySQL

DBが必要だったらPrivate Subnetに作成。

RedashのインスタンスにログインしてMySQLクライアントをインストールして接続を確認

```
% sudo apt update
% sudo apt install mysql-server mysql-client
% mysql -h xxx.rds.amazonaws.com -P 3306 -u user -p
```

RedashにAdminユーザにログインしてDataSourceにMySQL(Amazon RDS)を追加。

# Firestore

https://extensions.dev/extensions/firebase/firestore-bigquery-export
を使ってFirestoreからBigQueryにデータを連携。

# BigQuery

サービスアカウントを作成して、BigQuery閲覧者とBigQueryユーザーの権限を許可して、認証キー(JSON)を作成。

作成した認証ファイルを使って、RedashのDataSourceにBigQueryを追加。

プロジェクトIDはGCP Project IDを設定。

Processing LocationにはBigQueryのロケーションを設定。
Go言語：ゴルーチンの完全な終了を確実にする方法

## はじめに
Go言語では、非同期のタスクを実行するための手段としてゴルーチンを利用することが一般的です。
しかしながら、その利用には注意が必要です。今回はその一つ、`main`関数が終了すると共にゴルーチンも終了してしまう問題とその解決策について記載します。

## ゴルーチンと`main`関数の関係性

まずは以下のゴルーチンが含まれたコードを見てみましょう。

```go
package main

import (
	"fmt"
)

func sayHello() {
	fmt.Println("Hello")
}

func sayWorld() {
	fmt.Println("World")
}

func main() {
	go sayHello()
	go sayWorld()
}
```

このコードでは、`main`関数が`sayHello`と`sayWorld`のゴルーチンを起動します。
しかし、ここには一つ問題があります。それは、`main`関数が終了すると全てのゴルーチンも終了するというGoの特性上、これらのゴルーチンが終了する前に`main`関数が終了してしまい、ゴルーチンが完全に実行されない可能性があるという点です。

## 暫定的な解決策：`time.Sleep`

この問題を解決する一つの方法として、`main`関数の終了を遅らせる`time.Sleep`関数を使用することが考えられます。

```go
package main

import (
	"fmt"
	"time"
)

func sayHello() {
	fmt.Println("Hello")
}

func sayWorld() {
	fmt.Println("World")
}

func main() {
	go sayHello()
	go sayWorld()

	// Wait for the goroutines to finish
	time.Sleep(time.Second)
}
```

しかしこの解決策は一時的なものであり、正確なゴルーチンの終了タイミングを保証するものではないため、実際のプログラムでは推奨されません。

## 正確なゴルーチンの終了管理：`sync.WaitGroup`

ゴルーチンの終了を管理する正しい方法は、チャネルや`sync.WaitGroup`のような同期プリミティブを使用することです。特に、`sync.WaitGroup`は、複数のゴルーチンが終了するのを待つための簡便な方法として提供されています。

具体的には、`sync.WaitGroup`はカウンタを提供します。このカウンタは、`Add`メソッドで増やし、`Done`メソッドで減らすことができます。そして、`Wait`メソッドはカウンタが0になるまで待ち続けます。

以下にその使用例を示します：

```go
package main

import (
	"fmt"
	"sync"
)

func sayHello(wg *sync.WaitGroup) {
	fmt.Println("Hello")
	wg.Done() // Decrease counter
}

func sayWorld(wg *sync.WaitGroup) {
	fmt.Println("World")
	wg.Done() // Decrease counter
}

func main() {
	var wg sync.WaitGroup

	wg.Add(2) // Increase counter

	go sayHello(&wg)
	go sayWorld(&wg)

	wg.Wait() // Wait for counter to be 0
}
```

このコードでは、`sync.WaitGroup`を用いて`sayHello`と`sayWorld`のゴルーチンが確実に終了することを保証しています。`main`関数はゴルーチンの起動前にカウンタを2に設定し、各ゴルーチンが終了した時点でカウンタを減らします。最後に、`main`関数は全てのゴルーチンが終了する（=カウンタが0になる）のを待ちます。

これにより、`main`関数は`sayHello`と`sayWorld`のゴルーチンが確実に終了するのを待つことができます。特に、ゴルーチンが共有リソース（例えば、ファイルやデータベース接続）のクリーンアップを必要とする場合など、ゴルーチンの終了を待つ必要がある際に有用です。
【Unity】FirebaseCloudMessagingでAndroid端末PushTokenが受信出来なかった件

# TL;DR
FirebaseMessaging.GetTokenAsync() で現在のトークンを取得するようにしよう！

# 事のいきさつ
Unityを使ったプロダクトでFirebaseUnitySDKを利用していたのですが、CloudMessagingを利用する際、
Android端末でのみPushTokenが受け取れない事がある　という事象が起きていました。

調査の結果、アプリの初回起動時のみTokenを受信出来ていてそれ以降はアプリを入れ直すまで受信しないという状態になっていました。
iOSでは毎回来ていたので開発中に不具合の検知が遅れてしまいました。

その時の実装イメージ
```FirebaseProvider.cs
public FirebaseProvider()
{
    FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
    {
        var dependencyStatus = task.Result;
        if (dependencyStatus == DependencyStatus.Available) {
            // Create and hold a reference to your FirebaseApp,
            // where app is a Firebase.FirebaseApp property of your application class.
            AppInstance = FirebaseApp.DefaultInstance;

            // Set a flag here to indicate whether Firebase is ready to use by your app.
            FirebaseMessaging.TokenReceived += FirebaseMessagingOnTokenReceived;
            FirebaseMessaging.MessageReceived += FirebaseMessagingOnMessageReceived;
            
        } else {
           Debug.LogError("Firebase Initialize Failed.");
        }
        
    });
}

private void FirebaseMessagingOnMessageReceived(object sender, MessageReceivedEventArgs e)
{
}

private void FirebaseMessagingOnTokenReceived(object sender, TokenReceivedEventArgs e)
{
//ここでPushTokenを受け取ってサーバーに渡してた
}

```


# 解決策

GetTokenAsyncを使おう
https://firebase.google.com/docs/reference/unity/class/firebase/messaging/firebase-messaging#gettokenasync

このメソッドをコールすることで現在のトークンを取得することができます。
このトークンを使うことで解決しました

その後の実装例
```FirebaseProvider.cs
//このメソッドを叩いてTokenを取得し、サーバーに送る
public async UniTask<string> GetFcmTokenAsync(CancellationToken cancellationToken)
{
    string ret = string.Empty;
    if (AppInstance != null)
    {
        cancellationToken.ThrowIfCancellationRequested();
        ret = await FirebaseMessaging.GetTokenAsync();
        cancellationToken.ThrowIfCancellationRequested();
    }
    
    Debug.Log($"Firebase PushToken {ret}");
    return ret;
}

```
エラー「Microsoft Exchange に少なくとも 1 回は接続しないと、Outlook データファイル (.ost) を使用できません。」の解消法

# これは何？
タイトル通り、下記画像のエラーの解消法です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/54ac80d7-530c-5f48-2124-6c3c21ff8058.png)

なお、「突然出てきて Web 版は問題なく使える場合」 には有効ではないかと思います。
(私がそういう事例だったため

# 手順
1) [コントロールパネル] - [ユーザーアカウント] から Mail(?) を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/5a6eb8c6-9da1-c41c-fe77-eff657f92aef.png)

2) 起動した [メール設定] ダイアログにて [プロファイルの表示] を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/6ea0f167-5038-b12a-1bb3-98764ca10783.png)


3) 起動した [メール] ダイアログにて、対象のプロファイル名を選択後 [プロパティ] を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/3dd7da63-3d7b-a3b6-1791-b66c96dadb4e.png)


4) 起動した [メール設定 - <プロファイル名>] ダイアログにて [電子メールアカウント] を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/7e7f16ed-f0d4-2958-a4b4-8486f8ca7c48.png)

5) 起動した [アカウント設定] ダイアログにて、変更するプロファイルを選択後 [選択] を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/a4073852-75fe-553b-e1f0-aac304bf7842.png)

6) 起動した [アカウントの変更] ダイアログにて [Exchange キャッシュ モードを使う(C)] のチェックを外し、 [次へ] [完了] と順に押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/f161549d-0d8f-ae0e-ac4c-1e73089dff51.png)

上記手順後、Microsoft Outlook を起動し問題が無ければ完了です。

# 補足
(キャッシュ用のファイルが１回生成されて読み込める状態じゃないと駄目なんだろう) と思ったんですが、
C:\Users\<ユーザ名>\AppData\Local\Microsoft\Outlook を削除して復旧するパターンもあるらしい。
謎。
Operator SDK のテスト戦略概要

(update 2023-07-18: 自分用メモとして公開）

### Go のテスト一般論
- ランタイムにテストが最初から組み込まれている (`go test`)
- 「assertion を使わず、Table Driven Test を実装する」のが基本戦略
- ではあるのだが、BDD (Behaviour Driven Development) したい人が多いので、Ginkgo (BDDフレームワーク) と Gomega (assertionライブラリ) も広く使われている
- Ginkgo で Table Driven Test することもできる (参考: [GinkgoのDesrcibeTableの使い方 \- Qiita](https://qiita.com/zigenin/items/ecfb7e153f9b4998bd3c))

### Operator をテストするのに特有な事態
- 単体テストはともかく、統合テストは kube API Server がないと実行できない／さりとて実際に Kube をテストのたびに立てるのは（kindやminikubeといえども）負荷が大きい
- そこで [Operator SDK が取っている戦略](https://sdk.operatorframework.io/docs/building-operators/golang/testing/) は？
    1. controller-runtime が提供する [envtest](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/envtest) というツールで、Kube API Server と Etcd だけは立てる（scheduler はないので、まるきり kube そのものと同じ動きをする、というわけではない点に注意、例えば `Deployment`を作ってもそれに伴う `Pod` は生成されない）
    1. Ginkgo/Gomega を使ったテストコードのテンプレートを自動生成してくれて、`make test` 一発でテストできるような状態にしてくれる


### 参考文献
- [Ginkgo/GomegaによるKubernetes Operatorのテスト手法](https://zenn.dev/zoetro/books/testing-kubernetes-operator)
- [つくって学ぶKubebuilder · つくって学ぶKubebuilder](https://zoetrope.github.io/kubebuilder-training/)
- [Ginkgoでgolangのビヘイビア駆動\(BDD\)開発入門 \- Qiita](https://qiita.com/myoshimi/items/62bc89b8065e08834b02)
- [Go言語でGinkgoを利用してBDDしてみた \| RE:ENGINES](https://re-engines.com/2018/10/29/go%E8%A8%80%E8%AA%9E%E3%81%A7ginkgo%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E3%81%A6bdd%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/)
[Delphi] ぼかし(すりガラス)効果をつける

# ぼかし / すりガラス効果
最近流行ってる？こういう↓ぼかしかかった画像を僕もやりたい！Delphiで！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12977/67c2177b-808c-135f-ed7d-985031027d3e.png" width=480>

ちなみにこの画像は Discord でスポイラーをつけた場合の画像

# Delphi の Effect を使った実装
## TBlurEffect だけの実装
ウェブだと CSS 使って blur エフェクトをかけてるらしいのでマネして [TBlurEffect](https://docwiki.embarcadero.com/Libraries/ja/FMX.Effects.TBlurEffect) をかけてみましたが…それだけだと上手く行きませんでした！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12977/79001be1-032d-0cd5-6501-827950dcecf5.png" width=480>
TBlurEffect の [Softness](https://docwiki.embarcadero.com/Libraries/ja/FMX.Effects.TBlurEffect.Softness) に指定した値（ここでは 8 を指定）のグリッド状になってしまいます (Softness のデフォルト値が 0.3 なのでこんなに大きな値を指定するとは思ってない可能性があります)。

拡大画像
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12977/2d0ef55b-d55e-e981-08e0-b0803e9f32ba.png" width=240>

## TBlurEffect を多段にした実装
グリッド状に見える部分も TBlurEffect でぼかしてあげればグリッドが解らなくなるので、TBlurEffect を２度がけします。
また、大体のぼかし効果では全体が白っぽくなるので（すりガラスなので）[TRectangle](https://docwiki.embarcadero.com/Libraries/ja/FMX.Objects.TRectangle) を置いて Fill の値を ```#80ffffff``` ぐらいにしてあげます。

これらを実装すると、こんな見た目になります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12977/4ff2de66-e211-7fa9-9674-1cbfca6e0db9.png" width=480>

そして、目のマークをクリックするとこう！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12977/20ff5167-473e-b115-eb63-d8787b42c2cc.png" width=320>
ネコチャンでした！

当然 Android と macOS, iOS でも動きます。
でも微妙に違って特にモバイルだと少し見えすぎなので、もう１段 Blur をかけたり、Rectangle のα値を上げたりした方が良いかも知れないです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12977/8d1c901d-4f73-8fb4-d910-ec401f7cf5b6.png" width=480>


### 構造と各コントロールのプロパティとコード

構造
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12977/9c9f468e-ef4b-a2ba-e85d-e37a2072c269.png" width=320>

```delphi:プロパティの値
Layout1.Align = Contents
Image1.Align = Contents

// Layout1 用 BlurEffect
BlurEffect1.Softness = 2

// Image1 用 BlurEffect
BlurEffect2.Softness = 8

// 画像全体を白っぽくする Rectangle
Rectangle2.Align = Contents
Rectangle2.Fill.Color = $80ffffff
Rectangle2.Stroke.Kind = None
```
目ボタンのクリックイベントは下記の通りで、エフェクトと Rectangle2 を非表示にして Button1 自身も非表示にしています。

```delphi
procedure TForm1.Button1Click(Sender: TObject);
begin
  BlurEffect1.Enabled := False;
  BlurEffect2.Enabled := False;
  Rectangle2.Visible := False;

  Button1.Visible := False;
end;
```

# おわりに
これで簡単にそれっぽいぼかし画像になりました！
これでネタばれを表現したり課金しないと観れないとか 18 禁！とかそういうの作り放題！
IBM i ACS(Access Client Solutions)あれこれ

IBM i のJavaベースクライアントツール（5250エミュレーター、開発用ツール, SQL I/Fその他）であるACSの色々な備忘録です。

### 1.ACSダウンロード　：　http://ibm.biz/IBMi_ACS
※ダウンロードにはIBM IDの作成が必要（無料）

### 2.ACSの最初の読み物
【できるIBM i 7.4解剖】第6回 「あらためてACSとは」https://www.i-cafe.info/column/serials/dekiruibmi_no6

### 3.Q.ACSで使うJavaはオラクルJava以外もok? 
  A.OKです。
  導入するACSがサポートするJavaバージョンであればどの企業の提供するjavaでもOKです。

※IBMが提供するJavaはIBM OpenJ9です。IBM OpenJ9 と Eclipse Temurin JVMに対しては他のIBM S/Wと同様なS/W保守サポートも提供しています。（このS/W保守サポートを利用する・しないはお客様での判断

■IBM Semeru Runtimes OpenJ9
https://developer.ibm.com/languages/java/semeru-runtimes/downloads/ 

■ IBM Eclipse Temurin (OpenJDK with the Hotspot JVM)
https://adoptium.net/?variant=openjdk11&jvmVariant=hotspot

### 4.ACSのJavaサポートに関する参考URL
Java Options for IBM i Access Client Solutions?
https://www.ibm.com/support/pages/node/719405
※上記URLによると、ACS 1.1.8.0以降のサポートバージョンはJava8以降、Java11を推奨
※執筆時点でのACS最新バージョンは1.1.9.2

### 5.ACS（とAccess for Web）がサポートするIBM i OSバージョン　(2023/8/21追加)
https://www.ibm.com/support/pages/ibm-i-access-connections
ACS 1.1.x.xはIBM i 7.3～7.5をサポート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/2fb21821-8655-6c5c-468f-91baf00034ae.png)
Vuetify の v-calender でセルに「他 XXX 件を表示」を表示する

# 解決したいこと
Vuetify の v-calender で下記のように「他 XXX 件を表示」を表示したい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474068/1682b07e-f5ff-7753-27ff-adb05cfa92a2.png)

しかし、v-calender の [event-more-text prop](https://v2.vuetifyjs.com/en/api/v-calendar/#props-event-more-text) は単純な string のみしか受け付けないので、動的に件数を表示するのが出来なさそうに見える。

また、[event slot](https://v2.vuetifyjs.com/en/api/v-calendar/#slots-event) や他の slot でもその他表示に関する機能はサポートされていない。

# 解決方法
件数を表示したい部分に`{0}`を置けば OK 

```html
<v-calendar event-more-text="他 {0} 件を表示" />
```

# 参考
公式ドキュメントにも書いておらず下記の Stack Overflow のエントリーから見つけることが出来ました。

https://stackoverflow.com/questions/65648269/how-to-use-event-more-text-prop-in-vuetify-v-calendar
decodeとencodeとは

## decodeとencodeとは

:::note
データの変換や変換方式のこと
:::

### decode

**エンコードされたデータを元の形式に戻す操作**
データの復元や解読、復号化とも呼ばれることがある

EX)
文字列をBase64エンコードしたデータをデコードして元の文字列に戻す


### encode

**データを別の形式に変換する操作**
データの保護、圧縮、変換などの目的で使用

EX)
・文字列をBase64エンコードする
・画像をJPEG形式にエンコードする
・データをURLエンコードする

## まとめ

:::note
デコードとエンコードは、**情報の変換や転送、保護など**のさまざまな目的で広く使用される

**エンコード : 情報を安全に転送したり、特定の形式に変換したりするために使用
デコード   : エンコードされたデータを復元したり、解析したりするために使用**
:::

一般的なエンコーディング方式には、Base64、UTF-8、URLエンコード、JSONエンコードなどがある

\***☆☆☆***

エンコードとデコードは、データの変換や処理において非常に重要な役割がある
多くのプログラミング言語やフレームワークには、**エンコードとデコードのための関数やライブラリが用意されており、データの変換作業を容易に行える**
Hyper-V 仮想マシンの IPアドレス を 1コマンドで クリップボード にコピーする

## 本記事をおすすめできる方は

以下に絶望した方です。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/1e94ae39-0395-b2cc-03df-b0e436ad5ed4.png)

IPアドレスは `~/.ssh/config` に記述するなど、必要となる機会も多いため、サクッとコピーしたいものです。

しかし、上記画面の文字列をマウスで選択することはできません。右クリックしても何のメニューも表示されません ( なぜそんな作りに・・・ ) 。

:::note warn
**Ctrl + c は使えるが、行全体の文字列がコピーされる**

行のどこかを1回クリックするなどにより、行にフォーカスを当てた状態で `Ctrl + c` を押してみると、以下のような、行全体の文字列がクリップボードに格納されます。

```
ネットワーク アダプター (動的 MAC: 00:15:5D:03:07:39)	Default Switch	172.31.181.102,  fe80::215:5dff:fe03:739	OK
```

上記文字列の中に IPアドレス も含まれていますので、取り急ぎコピペしたい場合はこの方法も使えそうです。
:::

いずれ改善されることに期待しつつ、仮想マシンの IPアドレス をクリップボードにコピーするコマンドを次章でご紹介します。

:::note info
**バージョン情報**
本記事執筆時点の `Hyper-V マネージャー` の バージョンは `10.0.22621.1` です。
:::

## 1コマンドで IPアドレス を クリップボード に格納する

:::note warn
**PowerShellは管理者権限で起動する必要がある**
管理者権限が必要なコマンドを利用しているため、PowerShell は管理者権限で起動してください。
:::

:::note info
**テクニック: 管理者権限で起動するには `Ctrl ＋ Shift` が便利**
アプリケーションを管理者権限で起動するには、`Ctrl ＋ Shift` を使うのがおすすめです。
PowerShell に限らず使えるテクニックです。

**使用例:**

- PowerShell のアイコンを スタートメニュー/デスクトップ/タスクバー などに表示し、`Ctrl ＋ Shift` + `マウスクリック` することにより管理者権限で起動することができます
- `ファイル名を指定して実行`ダイアログ( Windowsボタン + `r` ) に `powershell` と入力して、`Ctrl ＋ Shift` + `Enter` することにより管理者権限で起動することができます
:::

### IPアドレス を クリップボード に格納するコマンド

仮想マシンの IPアドレス を表示し、クリップボードにも格納してくれるコマンド( ワンライナー )です。

```shell
$ip=(Get-VMNetworkAdapter 仮想マシンの名前)[0].IPAddresses[0] ; echo $ip ; Set-Clipboard $ip
```

:::note warn
**IPアドレスがない場合の戻り値に注意**
IPアドレスがない場合、変数 `$ip` に空が代入されますので、上記コマンドでは クリップボード にも空が格納されます。

空を格納したくない場合、以下のコマンドをお使いください。
空ではないことを判定するif文の効果により、IPアドレスがない場合クリップボードの状態を変更しません。

```powershell
if ( ($ip=(Get-VMNetworkAdapter 仮想マシンの名前)[0].IPAddresses[0]) -ne $null ) {echo $ip ; Set-Clipboard $ip}
```
:::

:::note info
**テクニック: クリップボードの履歴 ( `Windowsボタン + v` )が便利**
`Windowsボタン + v` でクリップボードの履歴を表示することができます。
過去にコピーした情報を確認したり、再度貼り付けすることができるので便利です。
先に複数の情報をクリップボードにコピーしておき、後で貼り付けるという使い方も可能になります。
:::

### 備考

ネットワーク アダプターが複数ある場合、`Get-VMNetworkAdapter` コマンドの `-Name` オプションに ネットワークアダプター名 を指定すると良いです。

https://learn.microsoft.com/en-us/powershell/module/hyper-v/get-vmnetworkadapter?view=windowsserver2022-ps

また、`Get-VMNetworkAdapter` コマンドの戻り値のindex部分( 以下の`[1234]` の部分 ) を変更する方法もあります。

```powershell
(Get-VMNetworkAdapter 仮想マシンの名前)[1234].IPAddresses[0]
```

本記事がお役に立ちましたら幸いです。
RubyのバージョンアップをしたらRspecでundefined method `symbolize_keys' for nil:NilClassとなった

# はじめに
Ruby on RailsのプロジェクトでRubyのバージョンアップ対応をしていたのですが、タイトルのエラーに遭遇したので簡単にまとめてみます。

# 発生したエラー
```
NoMethodError:
  undefined method `symbolize_keys' for nil:NilClass
```

# プロジェクト環境
- Ruby 2.7.5→3.2.2
- Rails 7.0

# 原因
プロジェクトに追加したymlファイルを読み込んだ際に値がnilになっていることが原因でした。

## エラー発生箇所
```:backend/config/initializers/aws.rb
Aws.config.update(Rails.application.config_for(:aws).symbolize_keys)
```

Rails.application.config_for(:aws)で読み込んでいるymlファイルはこちら

```:backend/config/aws.yml
default: &default
  access_key_id: <%= ENV['DYNAMO_DB_ACCESS_KEY_ID'] %>
  secret_access_key: <%= ENV['DYNAMO_DB_SECRET_ACCESS_KEY'] %>
  region: ap-northeast-1

development:
  <<: *default
  endpoint: hogehoge

production:
  <<: *default
```

# 解決方法
aws.ymlを読み込めているか確認するためにaws.rbを変更

```:backend/config/initializers/aws.rb
require 'erb'

puts "aws.yml Path: #{Rails.root}/config/aws.yml"
puts "Rails.env: #{Rails.env}"

aws_config = YAML.unsafe_load(ERB.new(File.read("#{Rails.root}/config/aws.yml")).result)
puts "AWS Config: #{aws_config.inspect}"

Aws.config.update(aws_config) if aws_config
```

Rspecを実行しコンソールでログを確認すると、ymlファイルは読み込めているが値はnilでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/19dfba7b-50bd-6ba2-3447-0b6293924112.png)

AWS Credentialsをymlファイルを経由して読み込むのではなく、直接読み込むようにaws.rbを修正すると上手くいきました。

```:backend/config/initializers/aws.rb
require 'aws-sdk-core'

puts "Rails.env: #{Rails.env}"

aws_credentials = case Rails.env
when 'development'
  {
    access_key_id: ENV['DYNAMO_DB_ACCESS_KEY_ID'],
    secret_access_key: ENV['DYNAMO_DB_SECRET_ACCESS_KEY']
  }
when 'production'
  {
    access_key_id: ENV['DYNAMO_DB_ACCESS_KEY_ID'],
    secret_access_key: ENV['DYNAMO_DB_SECRET_ACCESS_KEY']
  }
else
  {}
end

puts "AWS Credentials: #{aws_credentials.inspect}"

Aws.config.update(aws_credentials.merge(region: 'ap-northeast-1'))
```

# おわりに
AWS LambdaでRuby3.2ランタイムが使用可能になったので、バージョンアップ対応を進めています。
【ChatGPT無】Tips - 箇条書きで説明を省く（応用あり）

:::note info
本記事は、ChatGPT（無料版）で
行なっております。GPT4での確認
はできておりません。あしからず。
:::

　どうも、カーブミラーです。

　今回は、
　　超簡単なプロンプトの
　　　チップスです。

　プロンプト・チップスとは、
　　プロンプトに追加するだけで、
　　　出力を制御できる指示、
　　　　と言えば、わかります？
***
　おそらく、
　　誰もがやっている
　　　以下のような質問

　[＊＊＊＊]です。どうしたら？
　[＊＊＊＊]について知りたいです。
　[＊＊＊＊]をするにはどうしたら？
　[＊＊＊＊]に[＊＊＊＊]したいです。

　これだけだと、
　　すぐには回答が来ません。
　　　説明ズラズラ流れますw
　　　　内容は箇条書きですけど。

　もちろん、
　　それが必要な場合もあります。

　でも
　　多くの場合、
　　　不要ではないでしょうか。

　以前に同じようなことを
[【ChatGPT無】、説明いらないよ。結果だけ欲しいの！](https://qiita.com/kabumira/items/ab9461e1427769092498)
「前後の説明は不要です。結果のみを必要としています。」
　　という形で書きました。

　こちらは、
　　複雑なプロンプトに
　　　対するものです。

　でも、
　　上記のような
　　　簡単な質問であれば、
　　　　下記のチップスの方が
　　　　　いいかと思います。

```Text:箇条書きChips
箇条書き（説明不要）でお願いします。
```

　以下に、
　　４つのことを
　　　ChatGPTさんに
　　　　尋ねました。
　　　　　それぞれに
　　　　　　応用してみます。

　災害時に
　　そんなことを
　　　入力しているヒマが
　　　　あるのか、というのは
　　　　　置いといてくださいw
***
>User
大雨です。どうしたら？
箇条書き（説明不要）でお願いします
>
>ChatGPT
・室内に避難する
・高台や安全な場所に移動する
・雨具や傘を使用する
・水たまりや洪水のある場所を避ける
・河川や海岸などの水辺から離れる
・雷が鳴っている場合は、屋外の金属や高い場所を避ける
・警報や注意報に従う
・緊急時には救助隊や消防署に連絡する
***
>User
停電です。どうしたら？
箇条書き（番号付きで、説明不要）でお願いします
>
>ChatGPT
>1. 懐中電灯やライトを使用する
>2. 緊急用の携帯電話やラジオを準備する
>3. 電源が復旧するまで待つ
>4. 電力会社に連絡して状況を確認する
>5. 電力供給が一時的な場合は、電気を節約する
>6. 冷蔵庫や冷凍庫の扉を開けずに保冷する
>7. 電子機器を適切にシャットダウンする
>8. キャンドルやろうそくを使用する場合は、火の取り扱いに注意する
>9. 近所の情報を共有し、助け合う
>10. 緊急事態に備えて非常食や水を備蓄する
***
>User
火事です。どうしたら？
箇条書き（・ではなく★で、説明不要）でお願いします
>
>ChatGPT
★速やかに緊急通報する
★安全な場所へ避難する（建物の外へ出る、避難経路を選ぶ）
★障害物や煙を避けて下を向きながら進む
★階段を使用し、エレベーターは使用しない
★燃えやすい物から離れる
★ドアや窓のノブを触る前に熱さを確認する
★煙を吸わないようにタオルや布で口と鼻を覆う
★避難者を助けるが自身の安全を最優先する
★避難所や安全な場所で待機する
★消防署や救急隊に情報を提供する
***
>User
大混乱です。どうしたら？
箇条書き（・ではなく――で、説明不要）でお願いします
>
>ChatGPT
――冷静になる
――周囲の安全を確認する
――緊急事態への対応を考える
――必要な場合は緊急通報する
――指示や案内を受ける
――人々と協力し合う
――安全な場所に移動する
――公式の情報源を確認する
――指示に従う
――必要な物資やサポートを求める
――専門家や当局の助けを借りる
――状況が改善するまで待つ
***
　以上です。

　ね、簡単で、
　　必要な情報が
　　　取れますでしょう？

　もちろん、
　　説明が必要ならば、
　　　それを尋ねれば、OKです。

　そっちの方が、
　　短時間で済むと
　　　思いますよ。

　イザというときには、
　　簡単な説明の方が
　　　ありがたいものです。

　的確な指示というものは、
　　非常時には、役立ちます。
Zoteroの画面を暗くするには

# はじめに
株式会社ネットプロテクションズでインターンをしています。上野です。大学院に進学して数ヶ月，Zoteroを使って快適な文献管理ライフを過ごしておりましたが，問題が一点ありました。それは**ダークモードがない**ことでした。解決法を共有します。

# ダークモード適用
MacのDesktop版は以下で議論されています。

https://forums.zotero.org/discussion/95809/dark-theme-for-mac

上記の議論で紹介されているプラグインでZoteroを暗くすることができます。こちらがそのプラグインです。

https://github.com/tefkah/zotero-night

基本的にはトップページ少し下の「[Video instructions](https://github.com/tefkah/zotero-night#video-instructions)」を参考に設定していけば良いのですが，これで終わってしまうと記事を引用するのみになってしまいますので，僕が実際にプラグインを導入して詰まったところを記載しておきます。

このプラグイン，動画の通りに実行し「Restart now」を押して再起動してもZoteroが暗くなってくれません。それでどうすれば良いのか，こちらを確認する必要がありました。

1. Tools -> Night Preferences（画像一番下）をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2864472/d0a114fe-33ed-1a0e-2f92-0d44e9c53141.png)

2. Enable Dark Themeをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2864472/021dce1b-a9c3-0b4b-0e27-18984dca30fe.png)

どうだ暗くなったろう...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2864472/97b85669-61d3-92b9-b564-d1efc173dd92.png)

# 参考
windows版で暗くしたい場合は[先ほど紹介した議論](https://forums.zotero.org/discussion/95809/dark-theme-for-mac)からこちらを導入すると良いみたいです。

https://github.com/Rosmaninho/Zotero-Dark-Theme
Stripeで、料金と商品のデータをまとめて取得する方法

StripeのAPIを利用して、商品情報や料金情報をサイトに表示する場合、通常Product / Priceの２APIを利用します。

```js
const stripe = new Stripe(env.STRIPE_SECRET_API_KEY, {
	apiVersion: '2022-11-15'
});
const products = await stripe.products.list();
const productWithPrice = []
for await (const product of products.data) {
	const prices = await stripe.prices.list({
		product: product.id
	})
	productWithPrice.push({
		...product,
		prices
	})
}
return productWithPrice;
```

今回は別解として、Price APIだけを利用して取得する方法を紹介します。

## Stripe APIは、`expand`パラメタで追加のデータが取得できる

Stripeでは、取得するデータに含まれるIDを利用して、追加の情報を取得できます。

例えばPrice APIのレスポンスには、料金が紐づいている商品のIDが含まれています。

```js
{
  "data": [{
    "id": "price_xxx",
    "product": "product_xxx",
...
```

このような値を、List API呼び出し時に`expand`パラメタに指定しましょう。

```js
const prices = await stripe.prices.list({
    expand: ['data.product']
})
```

これによって、レスポンスの`product`がIDではなく商品情報に変わります。

```js
{
  "data": [{
    "id": "price_xxx",
    "product": {
      "id": "product_xxx",
...
```

## `expand`で取得したデータを元に整形する

Price APIに`expand`で商品を設定した場合、料金の配列に商品情報が入ります。

しかし実際の場面では、商品ごとにリスト表示した上で、その商品の料金プランを提示します。

そこで取得したデータを整形しましょう。

```js
const prices = await stripe.prices.list({
    expand: ['data.product']
})
const products = []
prices.data.forEach(price => {
	if (typeof price.product === 'string' || price.product.deleted) {
		return
	}
	const productId = price.product.id
	const productIndex = products.findIndex(product => product.id === productId)
	const priceToAdd = {
		...price,
		product: productId
	}
	if (productIndex > -1) {
		products[productIndex].prices.push(priceToAdd)
	} else {
		products.push({
			...price.product,
			prices: [priceToAdd]
		})
	}
})
```

TypeScriptの場合は、型を作成しておくと便利です。

```ts

type ProductWithPrices = Stripe.Product & {
	prices: Stripe.Price[]
};

const prices = await stripe.prices.list({
	expand: ['data.product']
})
const products: Array<ProductWithPrices> = []
prices.data.forEach(price => {
	if (typeof price.product === 'string' || price.product.deleted) {
		return
	}
	const productId = price.product.id
	const productIndex = products.findIndex(product => product.id === productId)
	const priceToAdd = {
		...price,
		product: productId
	}
	if (productIndex > -1) {
		products[productIndex].prices.push(priceToAdd)
	} else {
		products.push({
			...price.product,
			prices: [priceToAdd]
		})
	}
})
console.log(products)
```

## 関連記事

https://stripe.com/docs/expand?locale=ja-JP

https://stripe.com/docs/expand/use-cases
Djangoで新しくデータベースを登録


新しくDjangoにデータベースを登録する手順を箇条書きで説明します：

モデルの作成: データベースに保存するデータを表すDjangoのモデルを作成します。モデルはmodels.pyファイルに定義されます。

マイグレーションの作成: モデルを作成した後、Djangoのマイグレーションを作成します。マイグレーションはモデルの変更をデータベースに反映させるための手順を記録したファイルです。

マイグレーションの適用: マイグレーションをデータベースに適用します。これにより、新しいテーブルやカラムがデータベースに作成されます。

管理画面で確認: マイグレーションが適用された後、管理画面を通じてデータベースに保存されたデータを確認できます。

以下はより詳細な手順です：

models.pyファイルにモデルを作成する
python
Copy code
# models.py

from django.db import models

class MyModel(models.Model):
    field1 = models.CharField(max_length=100)
    field2 = models.IntegerField()
    # 他のフィールドを追加
マイグレーションを作成する
bash
Copy code
python manage.py makemigrations
マイグレーションを適用する
bash
Copy code
python manage.py migrate
管理画面にモデルを登録する
python
Copy code
# admin.py

from django.contrib import admin
from .models import MyModel

admin.site.register(MyModel)
管理画面にアクセスしてデータベースを確認する
bash
Copy code
python manage.py runserver
ブラウザで http://127.0.0.1:8000/admin/ にアクセスし、管理画面にログインしてデータベースに保存されたデータを確認できます。

これらの手順に従って、新しいデータベースをDjangoに登録できます。
Falco Ruleを紹介するシリーズ - Console Login Through Assume Role

本シリーズでは、ランタイム脅威検知のデファクトスタンダードである<a href=https://falco.org/ target=new>Falco</a>の検知Ruleを、１つの記事で１つ簡単に紹介していきます。
ランタイムセキュリティやFalco自体の概要を知りたい方は<a href=https://sysdig.jp/blog/intro-runtime-security-falco/ target=new>こちらのブログ記事</a>をご参照ください。
今回ご紹介する検知Ruleは<b>「Console Login Through Assume Role」</b>です。
# Rule記述
```
- rule: Console Login Through Assume Role
  desc: Detect a console login through Assume Role.
  condition:
    ct.name="ConsoleLogin" and not ct.error exists
    and ct.user.identitytype="AssumedRole"
    and json.value[/responseElements/ConsoleLogin]="Success"
  output:
    Detected a console login through Assume Role
    (principal=%ct.user.principalid,
    assumedRole=%ct.user.arn,
    requesting IP=%ct.srcip,
    AWS region=%ct.region)
  priority: WARNING
  tags:
  - cloud
  - aws
  - aws_console
  - aws_iam
  source: aws_cloudtrail
```
# Rule概要
<a href="https://github.com/falcosecurity/plugins/tree/master/plugins/cloudtrail" target=new>CloudTrailプラグイン</a>をインストールすることで使用可能になるルールです。
通常、AWSのAssumeRoleは、自身の権限ではアクセスできないAWSリソースに一時的にアクセスするために使用します。つまり、一時的なセキュリティ認証情報のセットを使用することになります。これらの一時的な資格情報は、アクセスキーID、シークレットアクセスキー、およびセキュリティトークンで構成されています。
このため、AssumeRoleによるコンソールログインはすべて 'Valid Account' の侵害と見なすことができます。

# Condition（条件）
`ct.name="ConsoleLogin" and not ct.error exists`
CloudTrailのイベント名が"ConsoleLogin"で、エラーが発生しておらず、

`and ct.user.identitytype="AssumedRole"`
ユーザーのアイデンティティタイプが"AssumedRole"で、

`and json.value[/responseElements/ConsoleLogin]="Success"`
コンソールログインの結果が"Success"の場合

# Output（出力）
AssumeRoleによるコンソールログインを検知しました。

`%ct.user.principalid`
ユーザー固有の識別子

`%ct.user.arn`
ユーザーのARN

`%ct.srcip`
送信元IPアドレス

`%ct.region`
AWSリージョン
「良い名前付け」の参考サイトまとめ

おはようございますこんにちわこんばんわ。どうもぶたです。

以前、チーム内で「変数や関数の名前に妥協したくないなー。どうしたら上手く命名できるんだろう？やっぱり英語の勉強？」という話になったので、今回は**名前付け**、**命名**についてまとめます。
とは言え、自分自身多くの記事やドキュメント、書籍などに助けられているので、ほぼ紹介記事になります。

ただ、順番には気をつけた方がいいと個人的には思っています。
何事もそうですが、**なぜやるのか**を知ってから**どうやるのか**を学ぶべきかな、と。

例えば、「この単語とこの単語はニュアンスが違う」「そんな単語存在しないよ」「単数と複数が間違ってる」
そんなレビューを受けたことがある人もいると思います。僕も言われたことがあります。
そういった内容の記事もたくさんあります。僕も読み込んでいますしストックして参照できるようにしています。

それはそれで有用ですし、是非意識していきたいことです。
ただ、そもそも、**「良い」名前付けとは何なのか**、**なんで「良い」名前付けをするのか**、という点を忘れてはいけないと思うのです。
その次に**プログラミング界隈の慣習**、そして**英単語・英文法**なのかな、と。
この前提や順番を忘れてしまうと、それこそただただそ英単語・英文法の話になってしまいます。
英文ライクに書くことが求められたとしても、僕らはソースコードを書いているわけですから、英文法マニアになってもそれはそれなのではないでしょうか。

紹介する順番で参考にしていただけると、きっと実になると思います。

# 前提

## きれいなソースコードを書くために必要な、たったひとつの単純な事

https://r-west.hatenablog.com/entry/20090510/1241962864

まずは大前提の理解として、こちらの記事を読んで欲しいです。
その内容にテクニックは全く書いてありません。
正しい名前を付けることのモチベーションは何なのか、どのようなメリットが生まれるのか。
そもそもの話がしっかりと書かれています。
何度も読み返す価値のある素晴らしい記事だと思います。

# 慣習

## Microsoft クラウドスキルチャレンジ

https://learn.microsoft.com/ja-jp/previous-versions/dotnet/netframework-4.0/ms229002(v=vs.100)?redirectedfrom=MSDN

こちらはガイドラインなので動機付けがあまり読み取れませんが、参考になる情報がしっかりと整理されています。
気になるセクションだけでも一読すると良いと思います。

## うまくメソッド名を付けるための参考情報/うまくクラス名を付けるための参考情報

https://qiita.com/KeithYokoma/items/2193cf79ba76563e3db6

https://qiita.com/KeithYokoma/items/ee21fec6a3ebb5d1e9a8

メソッドとクラスに分けて紹介されています。
どちらもプログラミングの話なので共通する考えはあると思いますが、
メソッドにはメソッドに、クラスにはクラスに特化した特徴があるのも事実です。
メソッド、クラスそれぞれによく用いられる名前付けやその考え方を確認するといいと思います。

## Google Style Guides

https://google.github.io/styleguide/

コーディング規約なので、名前付けとは意味合いが異なりますが、
大文字/小文字、キャメルケース/スネークケースなどの慣習を知るには参考になると思います。
ご自身で利用されている言語（なければ近しい言語）の情報は見ておくといいと思います。

# 英語

ここから英語の話になります。

## プログラミングでよく使う英単語のまとめ【随時更新】

https://qiita.com/Ted-HM/items/7dde25dcffae4cdc7923

いいねもストックも万を超えるすごい記事です。
網羅している単語数も圧倒的ですが、その単語の意味など注釈であったり、
どういいのか/悪いのか、などがしっかり書かれており、非常に参考になります。

また、文末のリンク集はいずれも参考になります。
実は最初に紹介した[きれいなソースコードを書くために必要な、たったひとつの単純な事](https://r-west.hatenablog.com/entry/20090510/1241962864)もこのリンクから知りました。
是非リンクも辿ってみるとより深まると思います。

またコメントも色々と勉強になります。

## モデルやメソッドに名前を付けるときは英語の品詞に気をつけよう

https://qiita.com/jnchito/items/459d58ba652bf4763820

一問一答的に覚えがちの英単語ですが、名詞や動詞、形容詞などの品詞が当然あります。
前文にあるようにRuby/Ruby on Rails前提なので全てが当てはまるわけではないですが、
品詞を意識することの有用性はどの言語でも変わらないのではないでしょうか。

こちらの記事も本文だけでなくコメントまで読むと面白いと思います。

# 最後に

名前付けについて参考になる記事をまとめてみました。

チームで開発をされている場合は、
チーム内で「良い名前付けってどんな名前付け？」と言った会話をまずしてみるといいと思います。
プロジェクトの特性やメンバー構成、利用している技術スタックなどなどの諸要因によって、「良い」（あるいは「優れた」「正しい」）の見解は変わってくると思います。
紹介した記事本文中やコメントなどでも触れられていますが、正しい英文と理解しやすいソースコードは必ずしもイコールではないと思います。

余談ですが、
アメリカ人に「これをこういう風に形を変換する処理があるんだけど、formatかな？convertかな？」と聞いてみたら「それはstandardizeだろ」と言われました。
「異なるリソースから関連する情報を集める処理はfetchとgatherどっちがしっくり来るかな？」と聞いたら「イメージ的にはamalgamateだよね」と言われました。
英語って難しいですね。

最後の最後に。
今回紹介させていただいた記事/サイトはほんの一部で、他にも沢山の素晴らしい記事やサイトがあります。
「この記事/サイトも勉強になる！」というオススメがありましたら、是非コメントにて教えていただけると幸いです。
型の定義を外部に宣言する（namespace付き）


## namespace なし

### 型の宣言

* `[filename].ts`として宣言する

``` typescript: ./src/types/app.ts
// 型の宣言

export type CustomValueType = {
  value0: string;
  value1: number;
  value2: object;
}

export type CustomArgType = {
  arg0: string;
  arg1: number;
  arg2: object;
}
```

### 型の参照

``` typescript:./src/app.ts

// 型を import 
import { CustomValueType, CustomArgType } form "./types/app";

//-----------
// 変数の宣言
//-----------

// import した型を使用
const values : CustomValueType = {
  value0: "hoge",
  value1: 10,
  value3: { ... }
}

//-----------
// 関数の宣言
//-----------

/**
* @param {string} arg0
* @param {number} arg1,
* @param {CustomType} arg2
*/
const sampleFunction = (
  arg0: string,
  arg1: number,
  // import した型を使用
  arg2: CustomArgType
) => {
  
  ...

}

```


## namespace あり


### 型の宣言

* `[filename].ts`として宣言する

``` typescript: ./src/types/app.ts
// 型の宣言

export type CustomValueType = {
  value0: string;
  value1: number;
  value2: object;
}

export type CustomArgType = {
  arg0: string;
  arg1: number;
  arg2: object;
}
```

### 型の参照

``` typescript:./src/app.ts

// 型 に 名前(= namespace)を付けて import
// ※ AppTypes が namespace
// ※ namespace 自体に命名規則は無い
// ※ ローカルコード内で判別しやすい名前をつける
import * as AppTypes form "./types/app";

//-----------
// 変数の宣言
//-----------

// import した型を使用
const values : AppTypes.CustomValueType = {
  value0: "hoge",
  value1: 10,
  value3: { ... }
}

//-----------
// 関数の宣言
//-----------

/**
* @param {string} arg0
* @param {number} arg1,
* @param {CustomType} arg2
*/
export const sampleFunction = (
  arg0: string,
  arg1: number,
  // 定義した型を使用
  arg2: AppTypes.CustomArgType) => {
  
}

```

# その他

* パブリックな場で namespace を固定化する/しないの議論は不毛（ローカルルールで十分足りる）
Githubのmainとmasterについて

# はじめに
Githubで新しく作成されるリポジトリで「main」なのか「master」なのかで私の中で混乱があり、調べてみました。

# 結果
これまでGithubのデフォルトブランチ名は「master」だったそうなのですが、これから新規に作成されるリポジトリのデフォルトブランチ名が「main」になるそうです（2020年10月1日発表）。

最近Swiftを始めた方は「main」なのか「master」なのか何のことを言っているのかわからなくなっていると思いますが、「同じもの」です。
すでに「master」で慣れている方は、デフォルトブランチ名は変更可能のようなので、もしこれから新規リポジトリを作成して、ブランチ名を既存のものと揃えておきたい場合は、これを「master」にすることも可能のようです。

# 参考文献
https://www.publickey1.jp/blog/20/githubmainmastermain.html
Arch Linux に Flutter をインストール

## Flutter のインストール

```bash
yay flutter
```

## Flutter のチェック

```bash
flutter doctor
```

メッセージにしたがい次のことを行いました。

```bash
sudo pacman -S cmake
sudo pacman -S dart
```

```bash
git config --global --add safe.directory /opt/flutter
```

android-sdk のインストール

```bash
yay android-sdk
```

設定

```bash
flutter config --android-sdk /opt/android-sdk
```

android-studio のインストール

```bash
yay android-studio
```

環境の設定

```text:.profile
（省略）
#
PATH="/opt/flutter/bin:$PATH"
#
export CHROME_EXECUTABLE=/opt/google/chrome/chrome
```

Unable to find bundled Java version　への対応

```bash
cd /opt/android-studio
sudo ln -s jbr jre
```

## 最終的な診断結果

```text
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.10.6, on Arch Linux 6.4.3-arch1-2, locale
    C.UTF-8)
[✗] Android toolchain - develop for Android devices
    ✗ ANDROID_HOME = /opt/android-sdk
      but Android SDK not found at this location.
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[✓] Android Studio (version 2022.2)
[✓] Connected device (2 available)
[✓] Network resources

! Doctor found issues in 1 category.
```

## ソフトの作成

```bash
flutter create myapp
cd myapp
```

## Linux アプリとして動かす

```bash
flutter run
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/59fd4df6-7663-0ca5-62ed-4e392262977e.png)

## Web サーバーとして動かす

```bash
flutter run -d web-server
```

```text
$ flutter run -d web-server
Launching lib/main.dart on Web Server in debug mode...
Waiting for connection from debug service on Web Server...         16.5s
lib/main.dart is being served at http://localhost:41453
The web-server device requires the Dart Debug Chrome extension for debugging.
Consider using the Chrome or Edge devices for an improved development workflow.

🔥  To hot restart changes while running, press "r" or "R".
For a more detailed help message, press "h". To quit, press "q".
```

ブラウザーで http://localhost:41453 にアクセス

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/cf16133c-7a68-1aa0-f61b-04b663806199.png)

## 参考ページ
[Ubuntu で Flutter を使う](https://qiita.com/ekzemplaro/items/3c57e66460f76a664e87)
[Ubuntu で Flutter を使う (その２)](https://qiita.com/ekzemplaro/items/02220dca45636ea1e639)
mac terminal不可解なメッセージに遭遇

macが不安定になってきたから１ヶ月ぶりくらいに再起動したら
Terminalがこんなメッセージを吐き出すようになった。。
control+cすればいいけど面倒だし、不気味。。

```
2023-07-18 10:47:18.111 xcodebuild[5432:20033] Requested but did not find extension point with identifier Xcode.IDEKit.ExtensionSentinelHostApplications for extension Xcode.DebuggerFoundation.AppExtensionHosts.watchOS of plug-in com.apple.dt.IDEWatchSupportCore
2023-07-18 10:47:18.118 xcodebuild[5432:20033] Requested but did not find extension point with identifier Xcode.IDEKit.ExtensionPointIdentifierToBundleIdentifier for extension Xcode.DebuggerFoundation.AppExtensionToBundleIdentifierMap.watchOS of plug-in com.apple.dt.IDEWatchSupportCore
```


> プラグインの拡張機能 Xcode.DebuggerFoundation.AppExtensionHosts.watchOS に対して、識別子 Xcode.IDEKit.ExtensionSentinelHostApplications を持つ拡張機能が要求されましたが、見つかりませんでした。
> プラグインcom.apple.dt.IDEWatchSupportCoreの拡張機能Xcode.DebuggerFoundation.AppExtensionToBundleIdentifierMap.watchOSの識別子Xcode.IDEKit.ExtensionPointIdentifierToBundleIdentifierを持つ拡張ポイントが見つかりませんでした。


ググったら以下のコマンドで解決らしい・・

```
$ sudo xcode-select -r
```



xcode-selectってなんだろう？？

```
$ xcode-select  --help
Usage: xcode-select [options]

Print or change the path to the active developer directory. This directory
controls which tools are used for the Xcode command line tools (for example, 
xcodebuild) as well as the BSD development commands (such as cc and make).

Options:
  -h, --help                  print this help message and exit
  -p, --print-path            print the path of the active developer directory
  -s <path>, --switch <path>  set the path for the active developer directory
  --install                   open a dialog for installation of the command line developer tools
  -v, --version               print the xcode-select version
  -r, --reset                 reset to the default command line tools path
```


> アクティブな開発者ディレクトリへのパスを印刷または変更します。このディレクトリ このディレクトリは、Xcode のコマンドラインツール (例えば、 xcodebuild) や BSD 開発コマンド（cc や make など）に使用されるツールを制御します。

だそうで・・

なにかの拍子に設定がわかったんかな？Xcodeアップデートでもしたかな？全く使ってないからわからん・・
でリセットしたら元に戻ったと？
Pythonのアンダースコアはただの命名規則じゃなかった

無駄に時間使ったので備忘録

# メソッド名にアンダースコア1つ
```python
class Hoge:
    # アンダースコアなし
    def foo(self):
        print("called foo")
    # アンダースコア1つ
    def _bar(self):
        print("called bar")

def main():
    hoge = Hoge()
    hoge.foo()
    hoge._bar()
```
これは想定通りの挙動
```
called foo
called bar
```

# アンダースコア2つ
```python
class Hoge:
    # アンダースコア2つ
    def __bar(self):
        print("called bar")

def main():
    hoge = Hoge()
    hoge.__bar()
```

これはダメ
```
Traceback (most recent call last):
  File "/Users/yama/Workspace/python/main.py", line 12, in <module>
    main()
  File "/Users/yama/Workspace/python/main.py", line 8, in main
    hoge.__bar()
    ^^^^^^^^^^
AttributeError: 'Hoge' object has no attribute '__bar'
```
---
アンダースコア2つの場合、マングリング機構なるものによってメソッド名がクラス名で修飾されているらしい
```python
class Hoge:
    def __bar(self):
        print("called bar")

def main():
    hoge = Hoge()
    hoge._Hoge__bar() # ←ここ変えた
```
```
called bar
```

# 反省
ただの命名規則だと思っていたので無駄に時間を使ってしまった
「AttributeError? いや、定義してんじゃん」とキレていたが、悪いのは自分でした。


# 参考記事
https://qiita.com/shiracamus/items/5331cd89b202953403dd
Arduino UNO R4 Minimaをいじってみた

# はじめに
ルネサス製Armマイコンを搭載したArduinoが出たと聞いたので、早速、買ってみました。本当は、WiFi版が欲しかったのですが、技適認証に時間がかかるらしく、国内ではまだ販売されていません。Arduinoのプログラム開発は、通常、Arduino IDEを使用しますが、今回は、コマンドラインのarduino-cliツールを使用します。これは、[VLX](http://esoftjapan.com/VLX)から直接呼び出すことができるので便利です。
# 仕様
|項目|仕様|備考|
|:-:|:-:|:-:|
|ターゲットボード|Arduino UNO R4 Minima|   |
|MCU|RA4M1|RAM:32kB/ROM:256kB|
|FPU|内蔵|単精度浮動小数点|
|開発環境|arduino-cli|   |
|RTOS|使用しない|   |
|ツールチェイン|arduino-cliに内蔵||
|エミュレータ|使用しない|アップロードはUSB経由|

# 文献
[1]Arduino UNO R4 Minima Product Reference Manual SKU:ABX00080
[2]Renesas RA4M1 グループ　ユーザーズマニュアル　ハードウエア編

# プログラムの構成
通常、[VLX](http://esoftjapan.com/VLX)のターゲットでは、ステップ実行は、タイマー割り込みやアナログ入力割り込みなどのハードウエア割り込みにより駆動します。しかし、ハードウエア割り込みは低水準の実装が必要になるうえ、Arduinoの標準のライブラリが割り込みハンドラの中から安全に使えるかという疑問があります。そのため、loop()関数の中から周期的に呼び出すことにします。処理の概要はおよそ下記のようです。これを実現するには、正確に現在時刻を取得する必要があります。Arduinoには、millis()とmicros()と言うライブラリ関数によりそれぞれミリ秒とマイクロ秒単位で現在時刻を取得できます。しかし、実際にやってみるmicros()は後述するように、ごくまれに1ミリ秒の誤差が生じることがありました。
```C
void loop()
{
	開始時刻 = 現在時刻を取得
	＜＜モデルのステップ処理を実行＞＞
	終了時刻 = 現在時刻を取得
	実際のステップ処理時間 = 終了時刻ー開始時刻
	if (実際のステップ処理時間＞ステップ時間) {
		オーバランが発生
	} else {
		待ち時間 = ステップ時間ー実際のステップ処理時間
		待ちループで待つ
	}
}
```
# 苦労したところ
前述したようにmicros()はまれに誤差が生じます。原因を調べるために、モジュールコアーのソースコードを見てみました。millis()とmicros()の実装は16ビットのAGTタイマー１個を使用しているようです。ミリ秒部分は１ミリ周期の割り込みによりカウントアップ、マイクロ秒部分(time_us)は下記式で計算しています。
`マイクロ秒＝((再ロード値ーカウンタ値)/再ロード値＋ミリ秒)✖1000`
問題はこの式の前で割り込み禁止になっていることです。割り込み禁止後にAGTカウンタがアンダーフローをすると、カウンタ読値=0からカウンタ読値=再ロード値にジャンプしますが、割り込み禁止になっているのでミリ秒はカウントアップされないままです。この結果、マイクロ秒部分は0となり、マイクロ秒=ミリ秒✖1000となります。
`C:\\Users\ユーザ名\AppData\Local\Arduino\...\time.cpp`からの抜粋
```C
unsigned long micros() 
{
	// Convert time to us
	NVIC_DisableIRQ(main_timer.get_cfg()->cycle_end_irq);
	uint32_t time_us = ((main_timer.get_period_raw() - main_timer.get_counter()) * 1000 / main_timer.get_period_raw()) +  (agt_time_ms * 1000);
	NVIC_EnableIRQ(main_timer.get_cfg()->cycle_end_irq);
	return time_us;
}
```
## 対策1
連続して１ミリ秒の割り込みが発生することはないので、micros()を2回呼び出し、大きい方を選択します。デメリットは、オーバヘッドが大きくなることです。
## 対策2
micros()は諦めて、SysTickを使用します。SysTickはArm系マイコンの標準の機能です。プロセッサベンダーの実装には依存しません。RA4M1マイコンにも搭載されています。本ターゲットでは、この方法をデフォールトにしています。実装の詳細は、target.inoを御覧ください。
# おわりに
最後まで読んでいただいてありがとうございます。ご感想などあれば、どんなことでも結構です、[Mail](http://esoftjapan.com/VLX/support/jp_support.php)をください。
【Ruby】バブルソートで配列の並べ替え

Rubyを使ったアルゴリズムについて学習しています。
今回は数字の配列を並べ替える方法についてやっていきます。

# やりたいこと
sortメソッドを利用せず、数字の配列を昇順ソートして出力するアルゴリズムを作成する。

```ruby
array = [6, 7, 3, 2, 5, 4, 1]
```
これを、こうしたい。
```ruby
array = [1, 2, 3, 4, 5, 6, 7]
```

# バブルソートとは？

> 値を昇順・降順で並べ替えるアルゴリズムのひとつ
> pointデータを小さい順（大きい順）に並べ替えるよ
> point隣り合う要素の大小比較を繰り返すことで、全体を並べ替えるよ

引用：<a href="https://wa3.i-3-i.info/word14886.html">バブルソートとは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典</a>



# まずは数字の並べ替えるプログラムを作る

```ruby
# 配列を定義
array = [6, 7, 3, 2, 5, 4, 1]
if array[2] > array[3] # 配列は0からはじまるのが注意点
  # 一度、変数に退避した後、入れ替える
  escape = array[3] # => escape = 2となる
  array[3] = array[2] # => array[3] = 3となる
  array[2] = escape # => array[2] = 2となる
end

p escape # => 2
p array[2] # => 2
p array[3] # => 3
p array # => [6, 7, 2, 3, 5] これでarray[2]とarray[3]が入れ替わった。
```

- 配列は0からはじまるのが注意点です。
- 一度、別の変数に退避した後、入れ替えます。


# 最終的な完成コード

```ruby
array = [6, 7, 3, 2, 5, 4, 1]
array_size = array.size

array_size.times do |i|
  (array_size - (i + 1)).times do |j|
    if array[j] > array[j + 1]
      escape = array[j]
      array[j] = array[j + 1]
      array[j + 1] = escape
    end
  end
end

p array

```

```ruby:出力結果
[1, 2, 3, 4, 5, 6, 7]
```

# 完成コードの解説
- `array = [6, 7, 3, 2, 5, 4, 1]`まずは配列を定義する。
- `array_size = array.size`で配列の要素数を取得し、変数に代入する。
- `array_size.times do |i|`で、比べる数の要素分をループ処理する。
- `(array_size - (i + 1)).times do |j|`は、比べられる残りの要素分をループ処理する。この時、iの初期値は0のため(i + 1)にして残りの配列の要素の個数を計算していることに注意する。
- `if array[j] > array[j + 1]`からのif文では、隣同士の数値を比較し、左の数のが大きい場合、配列内の数値の位置を入れ替える処理を定義する。
- `array[j]`は左側の数字、`array[j + 1]`は右側の数字として、左右を比べている。
- 最後に`p array`で出力する。


# まとめ
`sort`メソッドを使えば簡単なわけですが、その中身を理解することで、後々、応用が効くようになったりするのかなぁと思います。

他にも`for`文を使ったバブルソートなど、いくつかの方法があるようです。



# 参考サイト：

バブルソートとは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典

https://wa3.i-3-i.info/word14886.html

Rubyによるバブルソートアルゴリズム

https://qiita.com/yuukinakamura0925/items/02c3b5ed137beb0f07a6

【Ruby】バブルソートをfor文で解きたい

https://zenn.dev/furum/articles/b78aff57471134
ちゃちゃっと使えるEC2のクローンツールつくったわ

# まえせつ

EC2を運用してると様々なシーンでクローンを作りたい時出てきますよね。
snapshot取ってればできるんだけど、もっと直感的にコピペ！って感じでつくってしまいたい、、
そんな事を実現するのがこのツールとなります！

# なにこれ？

EC2をパッとクローンする方法を探していたところterraformで複製できるリポジトリを発見！

https://github.com/AKSarav/terraform-ec2-clone

ただ、これだとインスタンスIDを調べたりめんどくさかったのでpecoを使って**魔改造**してみた

# これ

<a href="https://github.com/dip-kato/terraform-ec2-clone"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/dip-kato/terraform-ec2-clone.png" width="460px"></a>

# セットアップ

- chmod 755 clone.shとかで実行権付けてください
- ユーザーのホームディレクトリにterraformの実行バイナリを置いてください。（パス通ったとこにあるならシェル内の~/を消してもらっても良い）
- tmp_providersファイル内のリージョンの定義をクローンしたいEC2があるリージョンに書き換えてください
  - region  = "ap-northeast-1" を "us-east-2"とかに

# こんなかんじでうごく

シェル叩くと

```
./clone.sh 
```

~/.aws/credentialsを見に行ってそこにあるプロファイル一覧を取得
(今更credentials使う？というツッコミはありますよね、、わかってます、、、、)

![1](https://github.com/dip-kato/terraform-ec2-clone/assets/95202883/6d16e54b-4513-4530-9a92-d99cbdb87707)

出てくるプロファイルを選択すると自動的にEC2インスタンスの一覧を取得してpecoから選べます

![2](https://github.com/dip-kato/terraform-ec2-clone/assets/95202883/bc2c8d25-57b5-408c-b449-4ced2a63ee16)

pecoなので入力保管の検索もできる！

![3](https://github.com/dip-kato/terraform-ec2-clone/assets/95202883/d17208b2-7221-4c12-adf7-f184507c2075)

インスタンス名を選ぶとクローンが走ります

```
(略)
aws_ami_from_instance.sourceami: Creating...
aws_ami_from_instance.sourceami: Still creating... [10s elapsed]
aws_ami_from_instance.sourceami: Still creating... [20s elapsed]
aws_ami_from_instance.sourceami: Still creating... [6m0s elapsed]
aws_ami_from_instance.sourceami: Still creating... [6m10s elapsed]
aws_ami_from_instance.sourceami: Still creating... [6m20s elapsed]
aws_ami_from_instance.sourceami: Still creating... [6m30s elapsed]
aws_ami_from_instance.sourceami: Still creating... [6m40s elapsed]
aws_ami_from_instance.sourceami: Still creating... [6m50s elapsed]
aws_ami_from_instance.sourceami: Creation complete after 6m58s [id=ami-07cf3719a40f167ea]
aws_instance.newinstance: Creating...
aws_instance.newinstance: Still creating... [10s elapsed]
aws_instance.newinstance: Creation complete after 15s [id=i-0e4114627d45e0620]
```

AMIとNAMEタグに　**-clone**　が付いたEC2ができる。さらにAMIは複製後に自動的に消される

![4](https://github.com/dip-kato/terraform-ec2-clone/assets/95202883/f19177e5-f5ff-47ed-9669-09a880a7cb35)

**超絶便利！セキュリティグループや、サブネットまで複製されます！！**
terraform管理しているのでdestroyも効くので作り直しも簡単!!

```
DIP22-M10011:terraform-ec2-clone yasutaka-kato$ ~/terraform destroy
(略)
Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

aws_instance.newinstance: Destroying... [id=i-0e4114627d45e0620]
aws_instance.newinstance: Still destroying... [id=i-0e4114627d45e0620, 10s elapsed]
aws_instance.newinstance: Still destroying... [id=i-0e4114627d45e0620, 20s elapsed]
aws_instance.newinstance: Destruction complete after 30s

Destroy complete! Resources: 1 destroyed.
```

# 弱点

①publicなのはグローバルIPがつかない
②タグが複製されない
③sshの鍵が空になる

ま、ちゃちゃっとクローン目的だからいっか！
Qiita CLIをDockerコンテナ化してみた！

## 目的
どこでもQiitaの記事を編集するべくDockerを用いてQiita CLIの環境を構築する事を目的とする

## TL;DL
```Dockerfile
FROM ubuntu:20.04
RUN apt-get -y update && apt-get -y install git nano vim curl
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && apt-get install -y nodejs
RUN mkdir -p /etc/qiita
WORKDIR /etc/qiita
RUN npm install @qiita/qiita-cli --save-dev
RUN npx qiita version
RUN npm install @qiita/qiita-cli@latest
RUN npx qiita init
RUN sed -e "s/localhost/qiita/g" -i /etc/qiita/node_modules/@qiita/qiita-cli/dist/server/app.js
RUN echo "____YOUR___Qiita___TOKEN___" | npx qiita login
ENTRYPOINT ["npx","qiita","preview"]
```

```docker-compose.yml
version: '3'
services:

  qiita:
    container_name: qiita
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 8888:8888
    restart: always
    volumes:
    - ./qiita/:/etc/qiita/public/
    environment:
      TZ: Asia/Tokyo
```

起動
```
root@shoma:/home/shoma/qiita# docker-compose up
qiita is up-to-date
Attaching to qiita
qiita    | Preview: http://qiita:8888
```
ホストの8888ポートにアクセス
すごい！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738475/7736d457-4507-2100-94d2-2ec7af967ff4.png)


## 準備

qiitaのTokenは以下URLから取得する事が出来る

https://qiita.com/settings/applications 

`設定 > アプリーケーション > 個人用アクセストークン`からトークンを発行。
トークンの権限には「read_qiita」と「write_qiita」を設定。

## 解説

ベースイメージにはubuntuを使用。後は必要そうなものをインストール
```Dockerfile
FROM ubuntu:20.04
RUN apt-get -y update && apt-get -y install git nano vim curl
```

nodejs環境の構築
```Dockerfile
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && apt-get install -y nodejs
```

workディレクトリ作成・指定
```Dockerfile
RUN mkdir -p /etc/qiita
WORKDIR /etc/qiita
```

qiita-cliのインストール
```Dockerfile
RUN npm install @qiita/qiita-cli --save-dev
RUN npx qiita version
RUN npm install @qiita/qiita-cli@latest
RUN npx qiita init
```

qiita-cliはデフォルトでlocalhostのみの公開となっているため、コンテナ名で名前解決することによって外部に公開。この設定を入れる事で、docker-composeのポートフォワーディングを用いる事でアクセス出来る様になる。
```Dockerfile
RUN sed -e "s/localhost/qiita/g" -i /etc/qiita/node_modules/@qiita/qiita-cli/dist/server/app.js
```

Tokenの設定
```Dockerfile
RUN echo "____YOUR___Qiita___TOKEN___" | npx qiita login
```

コンテナ起動時にpreview機能の実行
```Dockerfile
ENTRYPOINT ["npx","qiita","preview"]
```


## 参考文献

https://github.com/increments/qiita-cli#readme