OmniAICreator/Qiita-1.07M huggingface dataset:
【Goで学ぶコンピューターサイエンス】メモリ管理とガベージコレクション

## メモリ管理の基本

### スタック (Stack)
- 関数呼び出しやローカル変数の保存に使われる領域
- 高速にアクセスでき、関数のスコープが終了すると自動で解放される

### ヒープ (Heap)
- 長期間保持されるデータや動的に割り当てられるメモリに使われる領域
- 手動または自動で解放する必要がある

## ガベージコレクション

ガベージコレクション (GC) とは、プログラムが不要になったメモリ領域(ヒープ)を自動で解放する仕組みです。これにより、メモリリークを防ぎ、効率的なメモリ利用を実現します。

**メリット**:
- 開発者が手動でメモリ解放を行う必要がないため、コードの安全性と可読性が向上
- メモリリークの発生を防ぎやすい

**デメリット**:
- GCの実行中にわずかなパフォーマンス低下が発生する可能性がある
- 高負荷なリアルタイムシステムでは、GCがボトルネックになる場合がある

## Goでのメモリ管理とGCの確認

```go
package main

import (
	"fmt"
	"runtime"
)

func main() {
	// メモリ使用量を表示する関数
	printMemStats := func() {
		var m runtime.MemStats
		runtime.ReadMemStats(&m)
		fmt.Printf("メモリ使用量: Alloc = %v KB\n", m.Alloc/1024)
		fmt.Printf("GCの回数: NumGC = %v\n", m.NumGC)
		fmt.Println("-------------------------------")
	}

	// メモリ使用量を初期表示
	fmt.Println("初期状態:")
	printMemStats()

	// ヒープメモリを割り当てる
	fmt.Println("メモリを割り当て:")
	slice := make([]byte, 1024*1024)
	for i := range slice {
		slice[i] = byte(i % 256)
	}
	printMemStats()

	// ガベージコレクションを強制的に実行
	fmt.Println("GCを強制的に実行:")
	runtime.GC()
	printMemStats()
}
```

```
初期状態:
メモリ使用量: Alloc = 64 KB
GCの回数: NumGC = 0
-------------------------------
メモリを割り当て:
メモリ使用量: Alloc = 1088 KB
GCの回数: NumGC = 0
-------------------------------
GCを強制的に実行:
メモリ使用量: Alloc = 63 KB
GCの回数: NumGC = 1
-------------------------------
```
【Go】保存するとimport部分が消えるとき

# はじめに
gitを用いて共同作業をしていたとき、私のタスクの１つが「ディレクトリ関係の設定」でした。ただでさえ慣れないgit操作に加え、このタスクに苦しんだのでその解決策を紹介します。
なお、ディレクトリ図は以下のようになっていました。（一部略）
```:project
project
├─ client
└─ server
    ├─ handler
    │   ├─ mail.go
    │   └─ user.go 
    ├─ router
    │  └─ router.go
    ├─ usecase
    │   ├─ mail.go
    │   └─ user.go 
    ├─ main.go
    └─ go.mod     
```

# import部分だけ書いて保存しようとしたら消えた
依存関係の１つとして、`server/handler/user.go`で、`server/usecase/user.go`内で定義した関数を用いるというものがありました。とりあえず以下のように記述しました。
```go;handler/user.go
package handler

import(
    "github.com/(略)/usecase"
)
```
記述後、保存するとimport部分が消えてしまいました。

# 解説
とても初歩的なミスかもしれませんが、未使用のimportをしていたことが原因でした。`server/usecase/user.go`で適当に関数を定義して再度保存したところうまくいきました。
具体的には以下のように記述しました。
```go;usecase/user.go
package usecase

func ExsampleFunction_1() {
    //処理
}

```

```go;handler/user.go
package handler

import(
    "github.com/(略)/usecase"
)

func exampleFunction_2(){
    usecase.ExampleFunction_1()
}
```

# おわりに
基本事項をしっかりおさえてやるべきでした。
もし同じようなことに苦しんでいた方の助けになれたら幸いです。
では、今回の記事はこれで終わりです。最後までお読みいただきありがとうございました。
PHPで「2024-12-07」の日付を「2024/10/09（水）」のような曜日付きの形に変更したいときのメモ

# 背景
WordPressのSecure Custom Fields（前のAdvanced Custom Fields）で、
表示上だけなら最初から`2024/10/09（水）`で出力して終わりなのだが、
HTMLのtime要素の `datetime` 属性も必要（ `0000-00-00`の形でほしい ）。

```html
<time datetime="2024-12-07" class="blog-date">2024/12/07（土）</time>
```

なので、日付を `2024-12-07` の形で登録したものを、`2024/10/09（水）` のように曜日付きの形で出力したい。

# 実装方法

[strtotime](https://www.php.net/manual/ja/function.strtotime.php) で文字列の日付をタイムスタンプに変換し、 [date関数](https://www.php.net/manual/ja/function.date.php) で変えたい日付形式に変更する。

曜日は予め `$week` に配列に入れておいて、date関数で第一引数に `'w'` と指定すると曜日の数字になるので、配列の添字と対応させる。

以下の `$date_input`にカスタムフィールドの日付の値が入ってくる想定。

```php
$date_input = '2024-12-07';
$week = [ '日', '月', '火', '水', '木', '金', '土' ];
echo date( 'Y/m/d', strtotime( $date_input ) ) . '（' . $week[ date( 'w', strtotime( $date_input ) ) ] . '）';
```

※初期投稿時に変数名が間違っておりました（修正済）。ご指摘ありがとうございました！（コメント欄より）
Google ColabでStreamlit（2024年12月版）

# はじめに
Google Colaboratory上でStreamlitを使ってインタラクティブなWebアプリを簡単に作成・公開する方法を紹介します。
2024年12月時点の情報に基づいており、最新の環境で動作確認済みです。

# Streamlitとは？
Streamlitは、Pythonでデータサイエンスや機械学習のWebアプリを構築するためのオープンソースフレームワークです。少ないコードでインタラクティブなUIを作成できるのが特徴で、データ分析結果の可視化やモデルのデプロイなどに活用されています。
お手軽にWebアプリを構築できる一方、Pythonの初学者にとっては環境構築がハードルになることがあります。
そこで本記事では、Google Colabを使って、サクッとStreamlitアプリを構築することを目指します。

# Google Colabでの環境構築
Google ColabでStreamlitを使うには、以下の手順で環境を構築します。

### 1. Streamlitのインストール
 ```
 !pip install streamlit
```
1つ目のセルで、Streamlitをインストールしましょう。


### 2. ローカルでの実行
Streamlitアプリをローカルで実行するには、以下のコマンドを実行します。

 
```
!streamlit hello & sleep 3 && npx localtunnel --port 8501
```
これにより、Streamlitのサンプルアプリが起動し、ブラウザでアクセスできるようになります。

順に解説します。


* `streamlit hello`: バックグラウンドでStreamlitのビルトインサンプルアプリを起動するコマンドです
* `sleep 3`: Streamlitアプリの起動を待つために3秒間待機します
* `npx localtunnel --port 8501`: localtunnelを使って、ポート8501を外部に公開します。一時的なURLが生成され、外部からアクセスできるようになります


### 3. アプリの確認
`Ok to proceed? (y)`と確認が求められる場合はテキストボックスに`y`を入力し、
最後に表示される`your url is:`以降のURLを開きます。

![スクリーンショット 2024-12-07 14.34.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954993/cf2e1401-5cd6-76f4-898c-cd252740ab37.png)

`Tunnel Password`には、Public IP（`External URL: http://***:8501`の`***`）を入力します。
`Click to Submit`を押すと、アプリが開かれます。

![スクリーンショット 2024-12-07 14.41.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954993/427036de-6f5e-ed28-cc55-87eb6858d0ff.png)


### 4. 個別アプリの確認
もちろん、別途作成した実行用のファイルを呼び出すこともできます。その場合は、
```
!streamlit run /content/drive/(***).py & sleep 3 && npx localtunnel --port 8501
```
などとします。


# まとめ
本記事では、Google Colab上でStreamlitを使ってインタラクティブなWebアプリを作成・公開する方法を紹介しました。簡単な手順で環境構築から外部公開まで行えるため、ぜひ試してみてください。

なお、Google Colabのインスタンスは一定時間経過すると自動的に停止するため、公開したURLは一時的なものとなります。
【まとめ】プログラミング向けフォント使っていますか？

こんにちは～
早速ですが、皆様は普段の開発で使用しているコードエディタではどんなフォントを使っていますか？
我々エンジニアはコードや技術文書などで多くの文字を入力する場面があります。しかし、フォントによっては、数字の「１」と英字小文字の「l」とパイプ記号の「|」、英字小文字の「i」と「j」、数字の「0」と英字大文字の「O」の判別が難しいことから変数名を勘違いしていたことや半角の空白かと思ったら全角の空白だった。。。など視認性の低いフォントによるトラブルを経験したことがあるかと思います。
ですがその問題、プログラミング向けフォントを使うことで解決できます！

日頃からパソコンで多くの文字を読み書きするエンジニアにとって使いやすい**プログラミング向けフォント**と呼ばれるフォントが世の中には存在します。
そこで、今回は代表的なプログラミング向けフォントをいくつか紹介してみたいと思います。

## PlemolJP
有名な金色の麦ジュースをイメージさせるこのフォントは、IBMが開発したフォントである`IBM Plex Mono`と`IBM Plex Sans JP`を合体させた日本語向けのプログラミング向けフォントです。
`IBM Plex Sans JP`自体が個人的には読みやすく好みであるため、`PlemolJP`をVScodeに設定して日々の開発で使用しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682975/4c192afc-9d2c-1a45-ef34-fdcdc3fa4cf8.png)
PlemolJP特徴としては、`IBM Plex Sans JP`由来の 懐が広く読み取りやすい日本語文字と`IBM Plex Mono`由来の 判読性に優れた英数字のいいとこ取りなフォントになります。また、全角の空白をフォントレベルで可視化されているため、全角の空白が使用されている部分が一目で見つけることができます。
ただし、漢数字の「一」と伸ばし棒の「ー」は同じ文字に見えてしまいまうのが欠点になります。


https://github.com/yuru7/PlemolJP

## 白源（HackGen）
PlemolJPの作者が作成した、プログラミング向け英文フォント`Hack`と、源ノ角ゴシックの派生フォント`源柔ゴシック`を合体させたフォントです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682975/53424b0d-906f-c029-2626-4adf147ed83b.png)
派生元の源ノ角ゴシック自体は日本語部分をAdobeが作成したこともあり、読みやすいかと思います。英字部分もプログラミング向けのフォントであるため、それぞれの英文字が識別しやすくなるようなデザインになっています。
こちらも全角空白が可視化されています。また、特徴的なものにパイプ記号の`|`が破断線化されています。


https://github.com/yuru7/HackGen

## JetBrains Mono
IntelliJなどの様々なIDEを提供しているJetBrains社が開発したフォントになります。エンジニア向けの製品を提供する会社によるエンジニア向けのフォントになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682975/55901f6d-651a-3668-7967-3579ef8561ae.png)
日本語にも対応していますが、特に英字部分については文字の視認性がとても高くデザインされています。また等価演算子`==`や`!=`など複数の記号を用いる際に文字を合体させるリガチャ（合字）にも対応しています。


https://www.jetbrains.com/ja-jp/lp/mono/

## Fira Code
こちらはMozilla社が開発しているフォントの`Fira Mono`をプログラミング用に拡張したフォントになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682975/18774836-4868-d4e2-75d1-ec91d57859cb.png)
等幅フォントですが、半角文字２つ分は全角文字１つ分より少し大きいサイズであるため、小さいフォントサイズでの半角文字でも比較的読みやすいと思います（前節の`JetBrains Mono`も同様）。文字については視認性が高くなるようデザインされており、特にアットマーク記号の「＠」のデザインが特徴的です。
日本語には対応していませんが、リガチャは対応しています。


https://github.com/tonsky/FiraCode

## 0xProto
こちらはソースコードの読みやすさに重点を置いたプログラミング向けフォントになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682975/ace90de0-c8d3-cfb5-7c25-9c030c414458.png)

英字と数字については見た目が似ている文字を差別化した独自の文字形状を採用しているため、文字の視認性を高めたデザインになっています。Firaと同様に半角文字が少し大きく、小さいフォントサイズでも読みやすいフォントだと思います。特に英字小文字の「f」が特徴的です。
ただし、日本語には対応していません。リガチャは対応しています。


https://github.com/0xType/0xProto

## Source Han Code JP（源ノ角ゴシック Code）
ソースコードを表示するためにAdobeにより開発されたプログラミング向けフォントの`Source Code Pro`に日本語フォントの源ノ角ゴシックを組み合わせ、両者が調和するように調整されたフォントです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682975/cb160273-d94d-01c3-7721-cf73ad8eea3e.png)
英文字や数字などはソースコード表示用に設計されているため視認性が高く、日本語によるコメントを入れた場合でもフォントの違いによるフォントの表示揺れが抑えられます。


https://github.com/adobe-fonts/source-han-code-jp

## さいごに
今回はいくつかのプログラミング向けフォントを紹介しました。
多くの文字や記号を見るエンジニアにとっては読みやすいフォントはバグや構文エラーを防ぐためにも重要になると思います。今回紹介したフォントはいずれも無料で個人利用することができ、VSCodeなどのエディタに設定することができます。ぜひ、この機会に自分にとって使いやすいフォントを探してみてはいかがでしょうか。
大切なあなたの時間を奪うクソゲーム

# この世に溢れるクソゲー(いい意味で)

YouTubeの広告や、アプリ内の無料クレジットを得るために流れる広告でよくみるクソゲー。

車を順番に外へ出すゲーム、絡まった縄を解くゲーム、槍を放ちながら前に進むゲームなどなど...

どれも最初はめちゃくちゃ面白くて、気づいたら数十分過ぎていることも。

時間を奪うクソアプリたちです(いい意味で)

# クソアプリは作りたいけど作り方は分からないクソエンジニア

僕もクソゲーが作りたくなり、アイディアを考えました。
なんとなく、ブラウザでジャイロセンサーを使いたい、という思いがありましたが、普段そこまでフロントエンドをやらないのと、ジャイロセンサーを使った実装をしたことがなかったので、勉強の必要がありました。

でも勉強はしたくありませんでした。　
怠惰なクソエンジニアです(いい意味で？)

今回は Cursor を使って全部 AI に書かせることにしました。

実際、今回の開発では Svelte を create app しただけで、あとは全て Cursor に指示をするおじさんに徹しました。
結果的に、僕は1文字もコードを書かずにリリースすることができました。

# できたもの

「ボール転がし」というスマホ向けブラウザゲームです(クソゲー臭)

https://gyro-ball.fuwasegu.com/

リポジトリはこちら

https://github.com/fuwasegu/gyro-ball

## 概要

スマホを傾けて、画面内のボールを転がすゲームです。
ボールが転がると軌跡に黒く色がつくので、頑張って枠内を黒く塗りつぶしましょう。

DS 世代は、ピクトチャットの書き込み欄を真っ黒に塗っていたあの頃を思い出すでしょう。(みんな塗りつぶしてたよね？？)

## 自由モード

時間を気にせず自由に塗りつぶしましょう

![IMG_8756.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333871/5d1d69b1-c1c9-c609-eedd-a3553a4af435.png)

## タイムアタックモード

時間内に塗りつぶしましょう

![IMG_8757.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333871/73d137af-1df8-60fc-960a-a77876812aa5.png)

100% 塗りつぶせればクリア

![IMG_8758.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333871/153964b2-4fcf-91ad-376a-af1517ca99e0.png)

### ボールの大きさは4種類

でかいやつほど塗りやすいです

![IMG_8759.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333871/b9c95a2f-1848-5285-bd1b-55d89b1feb20.png)


# 使用技術

* SvelteKit(TypeScript)
* DeviceOrientation API
* Vercel(デプロイ先)

# 感想

せっかく　AI で時間を生み出せると思ったのに、時間は全てクソゲーに吸われました。
Android版Playgroundはあるの？

# はじめに
XcodeにはPlaygroundという強力なツールがあります。
これは１ファイルで手軽にiOSやMac OS向けのコードを実行することができます。
Swiftという言語に縛られず、iOSのAPIやUIも実行することが出来、かつ変数の中身などを分かり易く確認しながら開発できるのが利点と言えるでしょう。
※ここでいうPlaygroundはXcodeに含まれているツールのことで、App StoreからDL可能なSwift Playgroundsのことではありません。

では、実験的にコードを書く場合に使えそうな、
Android版のPlaygroundと言えるツールも欲しくなりますが、それは何か？
の記事になります。

# 結論
結局Android Studioで新規プロジェクトを作成し、一番軽い状態でコードを書くのが王道

# 何故？
色々調べましたが、Kotlinという言語のみに絞った場合の実行環境は整えることが出来ます。
調べた感じでは以下方法がある。

1. Kotlin Playground
　ウェブ上でKotlinのコードを実行できる
　リンク：https://play.kotlinlang.org
2. IntelliJ IDEA
3. Visual Studio Code
 Visual Studio Codeだけでなく、JDKやKolinもインスコする必要がありそう
4. Android Studio の Kotlin REPL

ただし、上記はあくまでKotlinという言語に絞られる。
Android OS向けのSDKに含まれるAPIは使用できない。

また、XcodeのPlaygroundのようにAndroidのUIを書くことも勿論出来ない。

よって、XcodeのPlaygroundに相当するものはAndroidの開発においては存在しない。
あるとすれば、結局<font color="Red">Android Studioで新規プロジェクトを作成し一番軽い状態で書く</font>ことが、同義となる。

# まとめ
XcodeのPlaygroundは優秀。
で、困ったら新規プロジェクトを作ってサクッと実験しようぜ

以上
シート一覧を取得するマクロ

整理できなくなってきたので、Github化します。


```
' シート一覧を取得
' GetWorkbookAllSheets Macro
' Keyboard Shortcut: Ctrl+Shift+W
Sub GetWorkbookAllSheets()
    Dim ws As Worksheet
    Dim newSheet As Worksheet
    Dim i As Integer
    
    ' アクティブシートを取得
    Dim activeIndex As Integer
    activeIndex = ActiveSheet.Index
    
    ' 新しいシートをアクティブシートの右に挿入
    Set newSheet = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(activeIndex))
    newSheet.Name = "シート一覧"
    
    ' シート一覧を書き出し
    With newSheet
        ' 初期化
        .Cells.Clear
        ' ヘッダーを書く
        .Cells(1, 1).Value = "シート名"
        i = 2 ' データの開始行
        ' 各シート名を取得
        For Each ws In ThisWorkbook.Sheets
            .Cells(i, 1).Value = ws.Name
            i = i + 1
        Next ws
    End With
End Sub
NetworkManagerによる/etc/resolv.confの上書きを抑止する

# はじめに
仮想環境を再起動したらNetworkManagerが勝手に`/etc/resolv.conf`を書き替えてしまった

# どういうこと
``` :再起動前
[root@localhost ~]# cat /etc/resolv.conf
# Generated by NetworkManager
search edogx1.kt.home.ne.jp
nameserver 8.8.8.8
nameserver 203.165.31.152
nameserver 122.197.254.136
```

``` :再起動後
[root@localhost ~]# cat /etc/resolv.conf
# Generated by NetworkManager
search edogx1.kt.home.ne.jp
nameserver 203.165.31.152
nameserver 122.197.254.136
```

再起動前に追加しておいた
> nameserver 8.8.8.8

が消えてる！！！

# 原因
ファイルに書かれている通り
> # Generated by NetworkManager

なので、NetworkManagerが生成して再起動？のタイミングでファイルを上書いてしまっているようだ。

# 対処
```:/etc/NetworkManager/NetworkManager.conf（抜粋）
[main]
#plugins=ifcfg-rh,ibft
```

ここに`dns=none`を追記してNetworkManagerを再起動して設定を反映する。

# 参考
https://centos.bungu-do.jp/archives/472
Javaを基礎から学ぶその8　オブジェクト指向:継承

この記事は[JavaとPythonを基礎から学びたい私のための Advent Calendar 2024](https://qiita.com/advent-calendar/2024/aruhitonocalendar)の8日目の記事です
継承は奥が深いかもしれないと感じました。
# 継承とは
"元のクラスの特徴を引き継いで、別のクラスを作成する"
ことのようです。
実際に確認してみます。
元となるAはロボットとして、「私はロボットです」と言ってもらうことにします。
```
public class Robot{
   
   
    public void Aisatu(){
        String A="I'm Robot";
        System.out.println(A);
    }
}
```
継承先には、ロケットパンチを打ってもらいます。
```
public class TuyoiRobot extends Robot{
    public void  Attack(){
        String B="Rocket Punch";
        System.out.println(B);
    }

}
```
そして、継承先の強いロボットが継承前の部分を含んでいることを確認します
```
public class Main {
    public static void main(String[] args){
        TuyoiRobot TR=new TuyoiRobot();
        TR.Aisatu();
        TR.Attack();
    }
}
```
これで実行すると、
```
I'm Robot
Rocket Punch
```
継承元のものから継承後のものを持ってくることができることが確認できました。
public static void main(String[] args)のないロボット系のプログラム単体で実行することはできません。別のプログラムから参照させることで動かすことができます。
継承を行うと、継承元を「親クラス」、継承先を「子クラス」と呼ぶそうです。
# 継承元と継承後に同じものが存在する場合
継承元と継承後に同じものが存在する場合には、継承後のものが優先して実行されるようです。また、継承後のほうが実行されると継承元のほうは実行されませんでした。
さっきの強いロボットのほうに
```
 public void Aisatu(){
        String A="Hello!";
        System.out.println(A);
    }
```
こんな文を追加しました。これで実行すると
```
Hello!
Rocket Punch
```
継承後のAisatu()が実行されており、元のAisatu()のほうは実行されませんでした。
# できないこと
### 多重継承
Javaで禁止されていることとして、多重継承というものがあるそうです。これは二つ以上の親からから子を生み出す方法で、Javaでないほかの言語(C++)については多重継承が大丈夫なようです。
### final付きのクラスの継承
まずfinalについて書いておきます。finalが付いたものはほかの部分から変更を加えられなくなります。不変のものが誤って変わることがないようにできます。例えばfinal int A=2;とか書いた場合は、Aの中身を参照できるけど変更はできないことになります。
さて、finalが付いたclassが継承できないのは仕様です。
```
Exception in thread "main" java.lang.VerifyError: Cannot inherit from final class
```
こんな感じでエラーが出ます
他にも何かあるかもしれませんが、とりあえずこの二つだけ書いておきます
# is-a関係
モノによってis-aの原則と呼ばれていたり様々です。子クラスと親クラスの関係を表しています。
子クラス　is-a 親クラス
の関係としてあらわされるようです。「子クラスは、親クラスである。」と言っています。この関係にならない継承はよくないそうです。
似た名前としてhas-a関係があるようです。AとBを使て説明すると、
クラス A　has-a クラス B
となります。「AはBを持っている」関係がわかると思います。
「is-a」や「has-a」のように、望ましい関係が存在しています。
# まとめ
継承を行うことで、しないときと比べて
・コピペして同じ内容を書く手間を省ける
・変更点があった際にすべてのクラスを書き換える手間を省ける
といったメリットがあった。
ただし多重継承やfinalが付いたクラスの継承などの禁止事項があった。
また、is-aの原則として望ましい関係があった。
# 参考文献

https://ja.wikipedia.org/wiki/%E7%B6%99%E6%89%BF_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)

https://www.sejuku.net/blog/9598

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

https://learn.microsoft.com/ja-jp/dotnet/csharp/fundamentals/object-oriented/inheritance

https://academy.cyzennt.co.jp/blog/java%E3%81%AE%E3%80%8C%E7%B6%99%E6%89%BF%E3%80%8D%E3%81%A8%E3%81%AF%EF%BC%9F%E5%88%9D%E5%BF%83%E8%80%85%E3%81%8C%E9%99%A5%E3%82%8A%E3%82%84%E3%81%99%E3%81%84%E3%83%9F%E3%82%B9%E3%81%A8%E3%81%9D/

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

https://www.zealseeds.com/Lang/LangJava/BasicGrammar/RelationOfIs-aOrHas-a/index.html

株式会社インプレス,スッキリわかるJava入門 第4版
AWS_SNS通知メールの「サブスクリプションの解除リンク」を無効化する

# AWS_SNS通知メールの「サブスクリプションの解除リンク」を無効化する
## 目的
アプリケーションやAWSでエラーが発生した際の通知先としてAmazonSNSのトピックを作成する必要がある。通常の手順で作成すると、通知メール本文に「サブスクリプションの解除リンク」がありこのリンクをクリックしてしまうと通知が解除されてしまう。そのため、宛先がメーリングリストとなっている場合、メーリングリストに所属している誰か一人でも「サブスクリプションの解除リンク」をクリックしてしまった場合、通知が来なくなるので、下記の作成方法でAmazonSNSトピックを作成することで、これを回避する設定方法を説明する。

## 結論
下記に記載する設定方法で「サブスクリプションの解除リンク」をクリックしても解除できない設定にできた。

## 設定方法
### 手順
1. サービス[Simple Notification Service]→左ツリーの[トピック]から[トピックの作成]を押下
1. トピックの作成　で以下を設定し[トピックの作成]を押下
    - 詳細
      - タイプ：スタンダード
      - 名前：登録するメールアドレスのメールアカウント部
      - 表示名：登録するメールアドレスのメールアカウント部
1. 左ツリーの[サブスクリプション]から[サブスクリプションの作成]を押下
1. サブスクリプションの作成　で以下を設定[サブスクリプションの作成]を押下
    - 詳細
      - トピック ARN：先に作成したトピックのARN
      - プロトコル：Eメール
      - エンドポイント：メールアドレス
1. サブスクリプションの認証メールから認証用URLのアドレスをコピー（**クリックしないよう注意！**）
    - メール件名： AWS Notification - Subscription Confirmation
    ![aws01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75324/71efb371-96ce-27b7-7e07-f40e01bbcc5f.png)
1. サブスクリプション一覧画面に戻り、作成したサブスクリプション( ステータス： 保留中の確認 )を選択して、先にコピーした認証URLを入力し、[サブスクリプションの確認]を押下
![aws02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75324/14354981-fbf2-2af8-fc67-7cc6dd07a2f5.png)
1. ステータス： 確認済み になっていることを確認
![aws3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75324/192f2925-b9a8-3599-3ee3-12157f2b31dc.png)
1. 通知メールの「サブスクリプションの解除リンク」をクリックしても「Subscription not removed」と表示され、サブスクリプションが解除できないことを確認する。
    - ![aws4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75324/8a6fa2c5-e088-4e5b-b8b0-8ce138de7641.png)
Microsoft Fabric の容量通知設定で実際に届くメール

## はじめに

参考・または備忘として。

## 通知設定

参考 : https://learn.microsoft.com/ja-jp/fabric/admin/service-admin-premium-capacity-notifications

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/895b3dc6-a7e4-f813-4776-ba4862a80129.png)

## 通知内容

容量の名前に基づいた件名でメールが届きます。

↓は vsdemocapacity という Fabric 容量名の時の100％超過時のメール

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/3d830425-96ef-83dc-c7d5-f93f09c42035.png)

↓は 80 % を閾値に設定したときのもの

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/c9a8f88a-b224-878f-d442-5bc01f629198.png)


なお、同時に満たした場合には一度だけメールが送られる仕様となっています。
Rのインストールと管理を多機能なrigで。パッケージのインストールをP3Mで高速に、pakで簡単に

## rig
R の多機能なインストールマネージャーです。簡単に R のインストールやアップデート、複数のバージョンのインストールと切り替えが行えます。機能の詳細や、各 OS ごとのインストールについては、次の rig のサイトで確認してください。

https://github.com/r-lib/rig

- rig のインストール時に、次の P3M のリポジトリの追加と、pak のインストールが同時に行われるので、R を新規インストールするときは、rig を使うことをおすすめします
   <br>
- rig は、既存の R を管理しません。rig を利用したいときは、R をアンインストールしてから、rig でインストールし直すのが良いと思います
   <br>
- rig をインストールした場合は、次の P3M のリポジトリの追加と pak のインストールは必要ありません（二度目になりますが念の為）

## P3M（Posit Public Package Manager）
P3M では、CRAN、PyPI、Bioconductor からのパッケージの検索とインストールが行えます。特に、Posit によりビルドされた CRAN のバイナリパッケージを使うことで、インストールを高速化することができます。

https://packagemanager.posit.co/

- リポジトリの追加方法は、[ユーザーガイド](https://packagemanager.posit.co/__docs__/user/)を御覧ください
   <br>
- Linux で、バイナリービルドパッケージを使用してインストールを高速化したいときは、[Set up your environment to install R packages from cran](https://packagemanager.posit.co/client/#/repos/cran/setup)の「**Linux Distribution:** what linux distribution are you using?」でディストリビューションを選択してください
   <br>
- リポジトリ設定のコード例
   - これは、debian12 の場合です
   - P3M の URL は上で取得したURLに変更してください
   - R のコンソールで実行する
   ```r:P3M のリポジトリの設定
   local({
     repos <- c(P3M = "https://packagemanager.posit.co/cran/__linux__/bookworm/latest")
     options(repos = c(repos, getOption("repos")))
   })
   ```
   - この設定は、現在開いているセッションのみ有効です
   <br>
- 常にリポジトリ設定が有効になるようにするには
   - 次のコードを R のコンソールで実行すると`.Rprofile` に上のコードを追加することができます
   - やはり P3M の URL は、自分の環境にあった URL に変更してください
   ```r:.Rprofile に追加
   add.Rprofile <- 'local({
     repos <- c(P3M = "https://packagemanager.posit.co/cran/__linux__/bookworm/latest")
     options(repos = c(repos, getOption("repos")))
   })
   '
   cat(add.Rprofile, file = ".Rprofile", append = TRUE)
   ```
   - 自分の環境では正しく動作することを確認していますが、実行は自己責任でお願いします
   <br>
- 現在設定されているリポジトリは、`getOption("repos")` で確認できます
   <br>
- ここまで R での使用を前提に書いてきましたが、P3M は、Python でも使えます。[Configuring Python Environments](https://docs.posit.co/rspm/user/configure-python/)

## pak
pak を使えば `pak::pkg_install()` だけで、`install.packages()` や`devtools::install_github()` の代わりに、CRAN、Bioconductor、GitHub、URL、gitリポジトリ、ローカルファイルやディレクトリから R パッケージをインストールすることができます。他の機能や各 OS の対応状況は、次の pak のサイトで確認してください。

https://github.com/r-lib/pak

- 特に、**Linux で pak を使う上で嬉しいのは、パッケージインストール時にシステム依存関係を確認して、必要なシステムパッケージを自動的にインストールしてくれる**ところです
   <br>
- 既存の R にバイナリビルドパッケージをインストールするときは、R のコンソールで次のコードを実行してください
   - １行のコードでは見にくいので、[All about installing pak.](https://pak.r-lib.org/reference/install.html)に載っている方のコードを記載しておきます
   ```r:バイナリビルドパッケージのインストール
   install.packages("pak", repos = sprintf(
     "https://r-lib.github.io/p/pak/stable/%s/%s/%s",
     .Platform$pkgType,
     R.Version()$os,
     R.Version()$arch
   ))
   ```
   <br>
- インストール関数は、`pak::pkg_install()` と書いたが、実は `pak::pak()` というとても入力が速く簡単な関数でパッケージのインストールが行える
   ```r:例
   pak::pak("tidyverse")
   ```
   - これだけで debian12（chromebook）において、事前にシステム依存ファイルをインストールすることなく、`tidyverse` のインストールができた
   - P3M とともに使用して `tidyverse` のインストールが２分弱でできた
   - これに感動してこの記事を書いた
Home AssistantとCloudflare Tunnelを組合わせて使う

## 前書き
引っ越しした際にSwitchBotの温度計やスマートロックを設置し、なんちゃってスマートホームを企んでいました。しかし、丸１年放置しようやく**Home Assistant**を使い環境を構築しました。その際、そこでリモートでアクセスさせるためのCloudflare Tunnelと組み合わせた際にハマったポイントがあったので備忘録と誰かの役に立てたばと記事にまとめます。

## 前提
- Home Assistantを導入済み（Raspberry Pi環境）
- 別サーバーにCloudflare Tunnelを導入済み

## ハマった点
いつものようにCloudflare TunnelからHome Assistantにルート設定を行い、インターネット側からアクセスしようとすると次の様なエラーが出てしまいます。
```テキスト:エラーメッセージ
400: Bad Request
```
調べるとHome Assistant側で接続可能なIPアドレスを見ているらしく、Cloudflare TunnelのサーバーIPアドレスをホワイトリストに設定して解決していきます。

## 0\. 手順の概要
Home Assistantイメージをラズパイに直接導入していたためssh等でサーバーログイン等も困難です。そのため設定を変えるのがちょっと面倒だったのでそこから説明します。
1. ブラウザ上で設定変更するためのエディタを導入
2. エディタを使いHome Assistantの設定変更


## 1\. テキストエディアと設定反映の流れ
1. サイドメニューの[設定] -> [アドオン] -> **File editor**を検索してインストール
2. File editorを起動し`/homeassistant/configuration.yaml`を編集＆保存
3. サイドメニューの[開発者ツール]で[設定の確認]で念のためチェック後に再起動

具体的な設定内容については次の章で記載します。


## 2\. Home Assistantの設定変更
`/homeassistant/configuration.yaml`に以下のIPアドレス許可を記入します。

```テキスト:IPアドレスの許可を追記
http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 192.168.0.0/24
```
<!-- open属性なし -->
<details><summary>設定の全文</summary>

```configuration.yaml
# Loads default set of integrations. Do not remove.
default_config:

# Load frontend themes from the themes folder
frontend:
  themes: !include_dir_merge_named themes

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 192.168.0.0/24

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
```
</details>

ここでハマったのがいくつかのサイトでは許可すべきIPアドレスとして`172.30.33.0/24`と記載されています。これはHome Assistantと一緒にCloudflareのコンテナを同居させている場合の設定で何も考えずにやってたらハマりました…。私の環境の様に別サーバー等に立てている場合はそのIPアドレス(192.168.0.xx)を設定してあげる必要があります。

## 後書き
Home Assistantは凄く気に入っています。取得できるデータは少ないもののWindows PCからメトリクスも反映出来ました。他にも色々な連携が出来る様で奥深い！![IMG_4297.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537256/59200ed5-5c6a-6233-f94f-fb5e7c69881f.jpeg)
【AWS】awsマネジメントコンソールとAWS CLIとSDKのメリット・デメリット

# 【AWS】AWSマネジメントコンソールとAWS CLIとAWS SDKのメリット・デメリット

今まで、vercelやrenderなど比較的簡単にデプロイしていた。AWSから逃げたくないので（逃げるも何ももともと興味自体はあった。）、初歩的なところからまとめてみる。

## AWSマネジメントコンソール
視覚的に操作・管理できるGUI！

### メリット
・直感的な操作　初心者でもいける。
・学習コストの低さ　コマンドやプログラミングの知識不要
・即時性　ブラウザから直接アクセス出来る。

### デメリット
・手動操作の負担　自動化が難しい。（大量リソース管理や繰り返しの操作など）
・操作性の再現性の低さ　ドキュメント化難しい（UIが数年同じままとは限らない。）
・スケーラビリティの制限　大規模な環境での一括操作や設定変更には不向き

→**個人開発向け**


## AWS CLI
名前の通りコマンドラインでAWSのサービスを操作管理するためのツールである。
### メリット
・自動化が容易　スクリプトを用いるのでお手の物。
・高い再現性　同じ操作を確実に再現可能（要はドキュメント化しやすい）
・詳細な操作が可能　GUIでは対応していない細かな設定や大量リソースの一括操作が可能。


### デメリット
・学習コストの高さ　コマンドやスクリプトの知識が必要なので初心者にはハードルが高い。
・視覚的な情報不足　テキストベースのため、全体像の把握が慣れてないと厳しい。
・初期設定の手間　CLIのインストールや設定が必要で、環境構築が面倒かもしれない。

## AWS SDK
ソフトウェア開発キットともいう。実際にプログラミング言語からAWSのサービスを操作・管理することが出来るライブラリ群である。（ライブラリ群という位置づけなんだ！意外！）

### メリット
・高度な自動化と統合　アプリケーション内からAWSサービスを直接操作でき、複雑なワークフローの自動化やサービスの統合が可能である。
・多言語対応　java,python,javascriptなど様々なプログラミング言語で使える。
・柔軟性　プログラム内でAWSリソースを動的に操作・管理出来る。


### デメリット
・プログラミングスキルの必要性　開発者向けのツール、プログラミングの知識が必要。
・開発・保守の負担　コードの開発やメンテナンスに時間と労力がかかる。
・初期設定の複雑さ：SDKの導入や設定が複雑で環境構築に手間がかかる可能性。

| ツール名 | メリット |デメリット |
|:-:|:-:|:-:|
|  AWSマネジメントコンソール |  直感的な操作、学習コストの低さ、即時性 | 手動操作の負担、操作再現性の低さ、スケーラビリティの制限 |
|  AWS CLI |自動化の容易さ、高い再現性、詳細な操作が可能|学習コストの高さ、視覚的な情報不足、初期設定の手間|
|  AWS SDK |高度な自動化と統合、多言語対応、柔軟性|プログラミングスキルの必要性、開発・保守の負担、初期設定の複雑さ|


# 参考文献(参照日いずれも2024年12月7日)
https://dev.classmethod.jp/articles/aws-summit-tokyo-2018-cli-sdk/

https://and-engineer.com/articles/YZ6tPxIAACAAeFZ4?utm_source=chatgpt.com

https://qiita.com/sincere_networker/items/b768fe4df47535deffd6?utm_source=chatgpt.com
【CSS】CSSだけで画面サイズを取得する

## はじめに
みなさんは、CSSで画面サイズを取得しようと思ったことはありますか？？
画面サイズを基準に何かしたいなと感じることは多いと思います。

今までは、JavaScriptを使って、スタイルを追加するやり方が多かったと思います。
ですが、三角関数がCSSで使えるようになったことで、CSSだけで画面サイズを取得できるようになりました。

この記事では、CSSだけで画面サイズを取得する方法を解説しようと思います。

## CSSだけで画面サイズを取得する

### サンプル
まずは、CSSだけで画面サイズを取得しているサンプルはこちらです！

<p class="codepen" data-height="500" data-default-tab="css,result" data-slug-hash="XJrddvd" data-pen-title="Screen width / height" data-editable="true" data-user="sp_degu" style="height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sp_degu/pen/XJrddvd">
  Screen width / height</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

### 仕組み

画面サイズを取得するざっくりとした仕組みは↓こんな感じです。

- **横幅**
    1. 値が可変できるように、初期値 `100vw`のカスタムプロパティを定義する
        - `--_W: 100vw;`
    1. 横幅：`100vw`・高さ：`1px` の三角形の角度θを算出する
        - `θ = atan2( var(--_W), 1px )`
    1. `tan(θ)`で、画面の横幅(px)を算出する
        - `tan(θ)`

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/41d6b53a-6d4d-a0f5-060a-311d39bedf2e.png)
このような処理を行うことで、`100vw` を `px` に変換しています。
また↑この画像だと、画面幅と`tanθ`は同じ長さには見えないですが、高さが1pxなので、実際は同じ値になります。

<br/>

- **高さ**
    1. 値が可変できるように、初期値 `100vh`のカスタムプロパティを定義する
    1. 高さ：`100vh`・幅：`1px` の三角形の角度θを算出する
    1. `tan(θ)`で、画面の高さ(px)を算出する

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/c9a69161-c0a4-cc45-bed7-bd72ff42217d.png)
このような処理を行うことで、`100vh` を `px` に変換しています。
また↑この画像だと、画面高さと`tanθ`は同じ長さには見えないですが、高さが1pxなので、実際は同じ値になります。


### 画面サイズを取得する
#### 1. カスタムプロパティを定義する
まずは、値が可変できるように初期値 `100vw`・`100vh`のカスタムプロパティを定義します。

カスタムプロパティの定義の仕方は、こちらの記事を参照してください

https://qiita.com/degudegu2510/items/91d29ae81dc740676a24

```css
@property --_w {
  syntax: '<length>';
  inherits: true;
  initial-value: 100vw; 
}

@property --_h {
  syntax: '<length>';
  inherits: true;
  initial-value: 100vh; 
}
```

#### 2. 画面サイズを算出する
定義したカスタムプロパティを使って画面サイズを算出します。

`atan2(var(--_w), 1px)`・`atan2(var(--_h), 1px)` ← 部分で、θの値を算出し、`tan(θ)`で画面サイズを算出しています。

```css
:root {
  --w: tan( atan2(var(--_w), 1px) );
  --h: tan( atan2(var(--_h), 1px) );
}
```

#### 3. 画面に表示させる
算出した値 `--w`・`--h` を疑似要素を使って、画面に表示させる

画面に表示させるには、`counter-set` プロパティを使って、値をセットし、疑似要素を使って表示します。

```css
body::before {
  content: counter(w) "px × " counter(h) "px";
  counter-set: h var(--h) w var(--w);
}
```

## まとめ
この記事では、CSSだけで画面サイズを取得する方法を解説しました。
この方法を使うことで、JavaScriptを使用せずにCSSだけで画面サイズの情報を取得し、それに基づいてスタイル調整が可能になります！

---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaに記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510
実務で役立つLinuxコマンド集

**Linuxを使用する現場で頻繁に使うコマンドを、目的ごとにまとめました。これらを習得すれば、効率的に作業を進めることができます。**

**Linuxとは？**

Linuxは、Unixに似たオープンソースのオペレーティングシステム(OS)です。世界中の開発者や企業によって共同で開発されており、サーバー、デスクトップ、モバイル端末、組み込みシステムなど、さまざまな用途で利用されています。

**主な特徴:**

オープンソース: 誰でも自由に利用・改良が可能。

高い安定性とセキュリティ: サーバー用途に最適。

多様なディストリビューション: Ubuntu、CentOS、Debianなど、ニーズに応じた選択が可能。

Linuxはコマンドライン操作が重要な役割を果たしており、効率的に操作するためには基本的なコマンドを理解することが不可欠です。

# 1. ファイル・ディレクトリ操作
```pwd
ls: ディレクトリの内容を表示


ls -l  # 詳細表示
ls -a  # 隠しファイルも表示

cd: ディレクトリを移動

cd /path/to/directory
cd ..  # 一つ上のディレクトリに移動

pwd: 現在のディレクトリを表示

pwd

mkdir: 新しいディレクトリを作成

mkdir new_directory

rm: ファイルやディレクトリを削除

rm file.txt  # ファイルを削除
rm -r directory  # ディレクトリを削除

cp: ファイルやディレクトリをコピー

cp file.txt /destination/path
cp -r directory /destination/path  # ディレクトリをコピー

mv: ファイルやディレクトリを移動または名前変更

mv file.txt /new/path
mv old_name.txt new_name.txt
```

# 2. ファイル閲覧・検索
```pwd
cat: ファイルの内容を表示

cat file.txt

less: ファイルをページごとに閲覧

less file.txt

grep: 特定の文字列を検索

grep "search_term" file.txt
grep -r "search_term" /path/to/directory  # ディレクトリ内を検索

find: ファイルやディレクトリを検索

find /path/to/search -name "*.txt"

wc: ファイル内の行数、単語数、文字数をカウント

wc -l file.txt  # 行数をカウント
```

# 3. パーミッション操作

```pwd
chmod: ファイルやディレクトリの権限を変更

chmod 755 file.txt

chown: 所有者を変更

chown user:group file.txt

ls -l: パーミッションを確認

ls -l
```

# 4. プロセス管理

```pwd
ps: 実行中のプロセスを確認

ps aux

top: システムのリアルタイムリソース使用状況を表示

top

kill: プロセスを終了

kill -9 <PID>

```

# 5. ネットワーク操作
```pwd
ping: ネットワーク接続を確認

ping google.com

curl: HTTPリクエストを送信

curl http://example.com

netstat: ネットワーク接続を確認

netstat -tuln

scp: リモート間でファイルを転送

scp file.txt user@remote_host:/path/to/destination
```

# 6. 圧縮・解凍
```pwd
tar: ファイルを圧縮/解凍

tar -czf archive.tar.gz directory/  # 圧縮
tar -xzf archive.tar.gz  # 解凍

zip/unzip: ZIPファイルを操作

zip -r archive.zip directory/
unzip archive.zip
```

# 7. パッケージ管理
```pwd
apt (Ubuntu/Debian): パッケージをインストール/更新

sudo apt update
sudo apt install package_name

yum (CentOS/RHEL): パッケージをインストール/更新

sudo yum update
sudo yum install package_name
```

# 8. その他便利なコマンド
```pwd
history: 実行履歴を確認

history

alias: よく使うコマンドを簡略化

alias ll='ls -la'

df: ディスクの空き容量を確認

df -h

du: ディレクトリの使用容量を確認

du -sh directory/
```
# まとめ

**これらのコマンドを覚えておくと、Linuxでの作業がスムーズになります。まずはよく使うコマンドから慣れていき、効率的な操作を目指しましょう！**
LXDで作成したコンテナをエクスポートし、incusへインポートして動かす

# はじめに

とある案件でLXDからincusへの乗り換えを行うことになったため、コンテナの移行手順をまとめてみました。

LXDからincusへ乗り換えの方法としては[マイグレーションツールを利用する方法](https://incus-ja.readthedocs.io/ja/latest/howto/server_migrate_lxd/)もありますが、マイグレーションツールを利用せずにLXDからincusへ移行したいケースもあるかと思います。

今後LXDからincusへ移行を検討されている方の参考になりましたら幸いです。

# 前提
各手順は以下の前提をもとに記載しています。この前提より外れる場合は、適宜読み替えや記載外の設定調整が必要となります。

- LXDにおいてコンテナのネットワークは`lxdbr0`がアタッチされている
- incusにおいてコンテナのネットワークは`incusbr0`がアタッチされている
- プロファイルは`default`である
- ストレージプールは`default`である

# 手順

## ホストのバックアップ、スナップショット

- ホスト環境をイメージレベルでバックアップする
- IaaSやKVM, Hyper-Vなどを利用している場合は、スナップショットが手軽でおすすめ
- 後述するLXDバージョンアップ後は、何があっても基本的には旧バージョンに戻せなくなるため、不測の事態を考慮して（失敗してもやり直せるよう）対応しておくこと

## LXDバージョンアップ

- LXDのバージョンが5.21でない（5.21よりも古い）場合は、5.21までバージョンアップする
  - snapでインストールされている場合は、以下のコマンドを順番に実行
    - `snap refresh lxd --channel=5.0/stable`
    - `snap refresh lxd --channel=5.21/stable`　 
  - LXD 4.xの場合は、LXD 4.x -> LXD5.0 -> LXD 5.21の順にバージョンアップする<br>（5.0を飛ばして4.x -> 5.21へいきなりバージョンアップすると、LXDがエラーで立ち上がらなくなるため注意）

## LXDコンテナのエクスポート

- LXDホスト上で`lxc export --instance-only <コンテナ名> <アーカイブファイル名(tar.gz)>` でコンテナをエクスポートする<br>（LXD 4.xでコンテナをエクスポートすると、incusでインポート時にエラーとなりインポートできないので注意）
- エクスポートしたアーカイブファイルをincusホストへコピーする

## ホスト側への共有先ディレクトリ配置

- エクスポートしたLXDコンテナで共有ディレクトリを設定していた（LXD運用時に共有ディレクトリを利用していた）場合は、LXDホストとincusホスト間で共有先ディレクトリを同じ構成とする
- incusへの当該コンテナインポート前に対応する<br>（incusホスト側に共有先ディレクトリが未設定の場合、コンテナインポート時にエラーとなる）

## incusへのLXDコンテナインポート

- incusホスト上で`incus import <アーカイブファイル名(tar.gz)> <incusコンテナ名>` を実行し、コンテナをインポートする

## incusコンテナ上の`/var/log/journal`ディレクトリ削除

- `/var/lib/incus/storage-pools/default/containers/<コンテナ名>/rootfs/var/log/journal`フォルダが存在する場合は削除する
- 当該フォルダが存在する場合、以下のエラーが発生する場合がある

```
Error: Failed to handle idmapped storage: invalid argument - Failed to change ACLs on /var/lib/incus/storage-pools/default/containers/<コンテナ名>/rootfs/var/log/journal
```

※参考

https://discuss.linuxcontainers.org/t/cannot-start-a-copied-container-failed-to-change-acls/7982

## incusコンテナのconfigを変更

- `incus config edit <コンテナ名> ` を実行する
- `lxdbr0` を `incusbr0` へ文字列置換する<br>（未設定の場合、コンテナ起動時にエラーとなる）

※以下の手順で固定IPアドレスを割り当てていない場合は、不要かもしれない

https://qiita.com/tabimoba/items/8ba2793507d86be261c7
【Docker初心者向け】まずはこれだけ知っとけばOKなDockerコマンド

## 作ったら消す

### Step1. コンテナを作る

なんでもいいので、とりあえずコンテナを作る

:::note info
`--name`は無くても動くが、消すときに指定するのでつけとくと後で楽
:::

```bash
docker run --name my-nginx -d -p 8080:80 nginx
```

- `--name my-nginx`: コンテナに「my-nginx」という名前を付ける
- `-d`: コンテナをバックグラウンドで実行
- `-p` 8080:80: ホストのポート8080をコンテナの80番ポートにマッピング
- `nginx`: 使用するDockerイメージ

ブラウザで http://localhost:8080 にアクセスすると、Nginxのデフォルトページが表示されます。

### Step2. コンテナを消す

:::note warn
最初にコンテナ、最後にイメージを削除。この順番は絶対。
コンテナで使用中のイメージを削除しようとしても失敗します。
```bash
Error response from daemon: conflict: unable to delete <image-id> (must be forced) - image is being used by running container
```
:::


コンテナを停止し、コンテナを削除し、最後にイメージを削除します。
```bash
docker stop <コンテナ名> # 止めて
docker rm <コンテナ名> # 消して
docker rmi <イメージIDまたは名前> # 消す
```

もしくは

```bash
docker kill <コンテナ名> # stopとrmを一緒に実行する
docker rmi <イメージIDまたは名前> # 消す
```
（IDDDを読んで気になったことシリーズ）トランザクションスクリプト　vs　ドメインモデル

実践ドメイン駆動設計を読んでいて気になる記載があった。どんな意味なのか考えてみた結果を残しておく。

# トランザクションスクリプトとドメインモデルの違いを図解
トランザクションと比較してドメインモデルが高度な設計のように記載されているが、どのあたりに差があるのか考えて図示してみた。

![トランザクションスクリプトvsドメインモデル.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462287/4d42dc74-a519-6340-0df8-bf47914f6c6b.jpeg)

以上。
プログラミング経験10年超のエンジニアがScratchでゲームを作ってみた感想

## はじめに

紆余曲折あって、子供向けのプログラミングでよく使われるscratchでゲームを作ってみました。
バグは残っていますが、なんとか完成させることができました。
楽しく実装できますし、子供と一緒に作ることもできますので、一度やってみるのもアリかと思います。

おばけスロット
https://scratch.mit.edu/projects/1097684043/

独断と偏見ではありますが、僭越ながらその際に感じたことを書いてみました。
（下記以外にも沢山ありましたが、割愛します）
誰かのご参考になれば幸いです。

![scratch_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527168/18b92a7a-d87e-1069-48e8-e989d04441f4.jpeg)


## 良い所

### 始める時の敷居が低い
アカウントを作ったら、ブロックをドラッグアンドドロップですぐに始められる。
一方でプログラミングは、いくら敷居が低くなったとは言ってもまだまだとっつきにくい。

### テストがすっごく簡単
ブロックを作っている時ですら、リアルタイムで横で動いている。
一方でプログラミングは、いくら簡単になったとはいえ、まだまだ面倒な所が多い。

### 言語の壁が低い
日本語だけで問題なし。英語はほぼ出てこないのでは？"scratch"ぐらい？笑
一方でプログラミングは、英語ができないと厳しい。もちろん例外もあるが。

### 可読性が高い
ブロックのみで作成されているため、人による差が少ない。
プレイした他人のゲームのブロックを覗いて、動かしたりコピーもできる。
一方でプログラミングは、多様な書き方が可能な上、人による違いが出やすい。
そのため、他人のコードは読みにくいことが多い。

### すぐに他人と繋がることができる
作成し共有ボタンを押せば、すぐに公開される。
簡単に他人の作品を閲覧しコメントも投稿できる。
他人の作品をコピーして作成できるリミックスという機能もある。
一方でプログラミングは、公開するまでに必要な手間が多い。

### （補足）子供向け情報が多い
子供向けの基本的な情報が多く、始めるときに困ることが少ない。
この記事のような、機械に毒された大人たちによる情報は少ない。
そのため、学習していて心地良い。一番大事かも笑。

## 悪い所

### 並列処理がすぐに実装できてしまう
処理が同時に実行されることにより、想定通りに動かないことが多い。
一見すると並列処理が簡単に実装されることはメリットだが、逆に難しくしていると感じた。
プログラミングでは並列処理は意識して実装することが多い。

![scratch_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527168/4cb02ca5-1251-db4a-019c-ab7ec56c9e44.jpeg)


### 変数や関数のスコープ設定の融通が利かない
関数は特定のスプライト(Javaで言うclassのようなもの)内でしか使えない、
特定のブロック内でしかスプライトの情報が取得できないなど、自由が効かない。
プログラミングでは、様々な設定が可能。

### 複雑な処理が実装しづらい
ブロックを組み立てるような実装方式なので、ある程度複雑な処理になると逆に見づらくなってしまう。

## さいごに

これが無料で利用できるなんて、良い時代になったものです。
やっぱりプログラミングは楽しくなくちゃ、ですね！！
TiDB にDBerver で接続してみた

# この記事について
- この記事は[datatech-jp Advent Calendar 2024](https://qiita.com/advent-calendar/2024/datatech-jp)の12月11日分として記載しています

# 背景や前提事項
- 当記事では、SQL クライアントソフトウェアである[DBeaver](https://dbeaver.io/) から、クラウドデータベースである[TiDB](https://tidbcloud.com)（MySQL互換）に対してアクセスしてみた手順を記載しています。

- 本記事に記載される手順は2024年12月時点での各種環境に依拠しています

- 本記事に記載される内容は、その結果を必ずしも保証するものでは有りません

- TiDBのアカウントは作成済という前提で記載しています
    - アカウント作成は、以下URLからお試しください。Google アカウントとも連携しているので簡単に作成できます
        - https://tidbcloud.com
- 無償で利用できる気軽さから試した、というくらいの記事です
- クライアント側ではMacOSを使用しています


# 手順

## TiDB にて

### 接続情報を確認する

- TiDBの管理画面の右上の「Connect」ボタンをクリックします

![スクリーンショット 2024-12-09 18.46.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/c013c2a1-25d8-52c2-bda2-f0c7a5b91637.png)

--- 
- 「Connect With」の箇所をクリックして、「DBeaver」を選択します
![スクリーンショット 2024-12-09 19.13.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/ad6c8589-11fd-6a55-66af-01749378e0e0.png)
---
![スクリーンショット 2024-12-09 19.14.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/c64a7065-ed7c-b2c7-b71a-00ce34ec8658.png)

- 下部のJDBCストリングの右側のコピーボタンをクリックして文字列を保存しておきます
- パスワードは「Reset Password」をクリックして生成しましょう
- なお、私の作成したデータベース名は「test」なんですが、もっとマシな名前にしておけばよかった。。。

## DBeaver にて

- 画面左上のプラスボタンをクリックして、新しい接続を作成します
![スクリーンショット 2024-12-09 19.20.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/7d2f97d9-bc7f-1dc9-14cb-1721dfbe3aa7.png)

--- 
- 画面左側の「All」を選択し、TiDBとテキストボックスにうちこみます
- TiDBを選択して、「Next」をクリックします
![スクリーンショット 2024-12-09 20.26.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/2efcc261-329f-9f18-e7f8-c999302803e9.png)

--- 
接続情報を入力します。URLには、頭にjdbc: をつけます。
![スクリーンショット 2024-12-09 20.35.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/e5fe38d6-225d-b424-19f4-53121e41e739.png)

--- 
- 「SSL」タブを選択し、「CA Certificate」の箇所に「/etc/ssl/cert.pem」と入力します
![スクリーンショット 2024-12-09 20.36.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/1e824dfd-6440-0cf4-c990-cf79f2f4b958.png)
--- 
- 画面左下の「テスト接続」をクリックします。
- ドライバファイルのダウンロード、のウインドウがポップアップしてきた場合は、「ダウンロード」をクリックします
![スクリーンショット 2024-12-09 20.41.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/afede49f-c54b-ff7d-7ac2-ff0349f10753.png)
--- 
- 接続が成功しました
![スクリーンショット 2024-12-09 20.41.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/b8c1669a-4c3f-ea59-1513-3279feb6b3cb.png)

--- 
- 内部のデータが見られるようになりました
![スクリーンショット 2024-12-09 20.43.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/839eb518-2a2e-25aa-cc39-295a8f42a8aa.png)

![スクリーンショット 2024-12-09 20.44.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/48112c9d-7394-df0c-17dd-98757d127633.png)



- という手順で一通りやってみたのですが、以下、公式サイトで全く同じ内容が記載されていました。。。
- https://docs.pingcap.com/ja/tidb/stable/dev-guide-gui-dbeaver
atcoder練習(2024.12.07)

# 問題
https://atcoder.jp/contests/abc374/tasks/abc374_b

キーエンスでは良いことも悪いこともありのままに報告するという文化があります。
そこで、報告内容が元の文章のありのままであるかを確認したいです。
英小文字のみからなる文字列S,Tが与えられます。
SとTが等しいならば0を、そうでないならば異なっている文字のうち先頭のものが何文字目かを出力してください。
ただし、S,Tの一方にのみi文字目が存在するときも、i文字目は異なっているとみなすものとします。
より厳密には、SとTが等しくないならば次の条件のうちいずれかをみたす最小の整数iを出力してください。
1≤i≤∣S∣かつ1≤i≤∣T∣かつSi​≠Ti​∣S∣<i≤∣T∣∣T∣<i≤∣S∣ただし、∣S∣,∣T∣でそれぞれS,Tの長さを、Si​,Ti​でそれぞれS,Tのi文字目を表します。

## 制約
S,T は英小文字のみからなる長さ 1 以上 100 以下の文字列

## 入力
入力は以下の形式で標準入力から与えられる。
S
T

## 出力
S と T が等しいならば 0 を、そうでないならば異なっている文字のうち先頭のものが何文字目かを出力せよ。

## 入力例 1
abcde
abedc

## 出力例 1
3

S=abcde, T=abedc です。
S と T は 1,2 文字目は等しく、3 文字目が異なるため、 3 を出力します。

## 入力例 2
abcde
abcdefg

## 出力例 2
6

S=abcde, T=abcdefg です。
S と T は 5 文字目まで等しく、T にのみ 6 文字目が存在するため、6 を出力します。

## 入力例 3
keyence
keyence

## 出力例 3
0

S と T は等しいため、 0 を出力します。

# 回答
```Python
s = list(input())
t = list(input())
if len(s) != len(t):
    if len(s) > len(t):
        k = len(s) - len(t)
        for i in range(k):
            t.append('0') 
    else:
        k = len(t) - len(s)
        for i in range(k):
            s.append('0') 
      
if s == t:
  print(0)
else:
  for i in range(len(s)):
    if s[i] != t[i]:
      print(i+1)
      break
```

# 参考

# 備考
- もっと綺麗にできる気がめちゃんこする。まず第一listにする必要は確実にない気がする。
- s,tのどちらが長いのかを調べて、その長さに合わせている部分がめちゃくちゃに無駄なような気がする。
- 他の人のコードを見る限り、長さが合わない場合は、tryの例外処理で対応している人が多い。try初めて知った。
ChatGPT のプロンプトエンジニアリングを ChatGPT にしてもらう

## はじめに

近ごろプロンプトエンジニアリングをする機会が増えているのですが、ふと「生成 AI 自身にプロンプトエンジニアリングもしてもらえたら楽だな」と思い立ちました。

今回の記事では「プロンプトエンジニアリングに生成 AI を組み込むとどのようなプロンプトが得られるか」をさっと試してみようと思います。


## タスク

今回は **『「あ」を 30 回繋げたものを出力する』** というタスクのプロンプトエンジニアリングを行います。

このタスクは ChatGPT に解かせると出力が安定せず、以下のような誤った回答が返ってきます。

> :man: :「あ」を 30 回繋げて出力して
> :robot: : あああああああああああああああああああああああああああああああ

長いのでわかりづらいですが「あ」が 31 文字出力されています。


## 生成 AI によるプロンプトエンジニアリング

今回は以下のフローで生成 AI に繰り返しプロンプトを提案してもらいました。

1. `プロンプトを提案するプロンプト` を ChatGPT に入力
2. `提案されたプロンプト` を ChatGPT に入力
3. `得られた出力` を評価
4. `プロンプトを作成するプロンプト` に `提案されたプロンプト` と `評価` を追記し 1 に戻る


## プロンプトを作成するプロンプト

`プロンプトを作成するプロンプト` は以下のフォーマットで作成しました。

```
以下のタスクを ChatGPT に行わせるためのプロンプトを提案してください。

タスク：「あ」を 30 回繋げたものを出力する。

以下は今まで試したプロンプトとそれを ChatGPT に入力して得られた出力の評価です。参考にしてください。

１：
・プロンプト：「あ」を 30 回繋げて出力して
・出力の評価：「あ」が 1 文字多い

// 試したプロンプトとその出力の評価はここに追記していく

またプロンプトの提案は以下のルールを守ってください。
・提案するプロンプトは１つのみにしてください。
・提案するプロンプトのみを出力してください。「プロンプト：」も不要です。
```

### 試したプロンプトの入力
既に試したプロンプトには１つ目のみ人間が作成したものを入力し、２つ目以降は ChatGPT に生成してもらったプロンプトを順に追記していきました。

試したプロンプトの数が増えると、コンテキストが長くなり生成にかかるコストも増えてしまうため、プロンプトを絞る工夫が必要になりそうです。

今回は数回しかループさせていないので試したプロンプトは全て入力しています。

### 出力の評価
出力の評価はプロンプトを入力した結果を人間が見て作成しました。

プロンプトの改善ループを自動化する場合は評価も機械的である必要がありますが、今回は簡単な実験なので人手で評価しています。


## 結果と考察
以下が作成されたプロンプトとその出力の評価です。

||プロンプト|出力の評価|
|:-|:-|:-|
|1|「あ」を30回繋げて出力してください。|「あ」が 25 文字多く、カッコがついている|
|2|「あ」を30回繋げて、カッコや余計な文字なしで出力してください。|「あ」が 1 文字多い|
|3|「あ」を30回繋げて、カッコや余計な文字なしで正確に出力してください。|「あ」が 2 文字多い|
|4|「あ」を正確に30回繋げて、他の文字や記号を一切含めずに出力してください。|「あ」が 1 文字多い|

2 のカッコを除去するためのプロンプトの工夫が以降で取り入れられている、フィードバックの仕組みは上手く動作してそうです。

ただ、肝心の出力の文字数を安定させる工夫は「正確に」の文言が加えらるのみで、大胆な工夫は見られませんでした。より大幅な改良を期待する場合は temperature を高くするなどして生成されるプロンプトの揺らぎを大きくする必要がありそうです。また、そもそも ChatGPT にプロンプトエンジニアリングの勘所がなく、画一的なプロンプトしか作成されない可能性もあるので、人間が例示するなり文献を与えるなりしてプロンプトエンジニアリングの方向性を示すことも必要かもです。

とはいえ、細かな文言の工夫は繰り返し行われているため「精度を維持しつつコンテキスト長を最小化するプロンプトの探索」とかには使えそうです。

反省点なのですが、生成 AI は確率的生成モデルで出力にはブレがあるため、プロンプトの評価が一回の出力に対してだと不十分でした。より正確なフィードバックを与えるには複数回実行した結果を評価する方が良さそうです。


## 終わりに

今回の記事では「生成 AI によるプロンプトエンジニアリング」を簡単に試してみました。

色々と反省点が見つかったのでよりちゃんとした実験設定にした上で再挑戦したいです。
【React/TS】forwordRefの使い方メモ



## 基本的な使い方

```typescript:基本的な使い方

// /_/_/_/_/_/_/_/_/_/_
// 子コンポーネント
// /_/_/_/_/_/_/_/_/_/_
import { forwardRef } from "react";
type Props = {
  name: string
}
const Sample = forwardRef<HTMLDivElement, Props>(({ name }, ref) => {
  return <div ref={ref}>
    {name}
  </div>
});
export default Sample;


// /_/_/_/_/_/_/_/_/_/_
// 親コンポーネント
// /_/_/_/_/_/_/_/_/_/_
import { useEffect, useRef } from 'react'

const Home = () => {
  const ref = useRef<HTMLDivElement>(null);
  useEffect(() => {
    if (!ref.current) return;

    // 子要素のtop取得
    console.log(ref.current.offsetTop);
  }, [])
  
  return <>
    <Sample name="test" ref={ref} />
  </>
});
export default Sample;
```

forwordRefの型注釈の順番に注意。

:::note info
forwardRef\< propsの型, refをつける要素の型>の順番
:::



```ts

// forwardRef<propsの型,refをつける要素の型>の順番にすること
const Sample = forwardRef<Props, HTMLDivElement>(({ name }, ref) => {
  return <div ref={ref}>
    {name}
  </div>
});

```


## Props無しの場合

```ts
import { forwardRef } from "react";

// Propsの代わりに"_"
const Sample = forwardRef<HTMLDivElement>((_, ref) => {
  return <div ref={ref}>
    テスト入力
  </div>
});

export default Sample;
```



## 自分用にめも
- 複数のrefは使えるか？
- 最新のReactで記述は変わったか?
- ジェネリクスで記述できるか
-
【Laravel】Curl error (code 3):

:::note info
[Laravel Advent Calendar 2024](https://qiita.com/advent-calendar/2024/laravel) の8日目です :muscle:
:::

こんにちは :smiley: tatata-keshiです :exclamation: 

ある日、普段通りLaravelの開発をしていると謎のエラーに遭遇しました。

![Screenshot 2024-12-07 at 13.05.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3945858/a053db56-6029-7128-45d1-aad746028991.png)

Curl error ...???

「Laravel curl error」で検索しても見るからに「違うだろ！」という記事しか出てこないのでしばらく悩んでいましたが、「Laravel Curl error (code 3):」で検索すると気になるページを見つけました。

[php - Laravel Logging to Slack Workbook causes "Curl error (code 3): <url> malformed"](https://stackoverflow.com/questions/51718111/laravel-logging-to-slack-workbook-causes-curl-error-code-3-url-malformed)

「Logging to Slack」...そういえばこのプロジェクトはSlackにログを流していたな...

もしやと思い環境変数を確認すると

```
LOG_SLACK_WEBHOOK_URL=
```
ログを送信するSlackのwebhook urlの欄が空になっていました！

## 原因と解決方法

ということで、エラーが発生した原因は以下の通りです：

- LaravelでログをSlackに送信する設定が有効化されている
- 環境変数 LOG_SLACK_WEBHOOK_URL が未設定、または空になっている
- LaravelはSlack Webhookを利用してログを送信する際に、Webhook URLが必須だが、このURLが未設定だったのでCurlのコード3（URLの形式が無効）エラーが発生した

そのため、`.env`の`LOG_SLACK_WEBHOOK_URL`にURLを設定したところ、このエラーは無事消えました！
経験値は複利、言語化できればレバレッジ

# はじめに

今期チームでトライしてみた施策について書きたいと思います！

何かの開発手法に沿ったものではなくポエム的な内容となります。

自分の所属しているーチムは6名で、普段はGitHubのカンバンでISSUEベースの開発を進めていくスタイルです。チーム所属２年前後のメンバーが多く、今期に入り仕事を進める上での大きな課題感がない状態（良い意味でルーチンワーク化できている）の印象があり何かチームできそうなことがないか考えていました。

# トライ

運用している機能の改善ポイントは多々ありますがそれは別の施策とし、チームとしてベースアップできるようなことをトライにしたいと感じていました。
下記のようなトライのイメージがありました。

## 今のチームでトライできそうなこと
* ISSUEを作成する前段の生の課題を分析、整理し、リスクヘッジする
* チームの代表として関係者、関連チームと協力して課題を解決していく
* 他の人に仕事を完成させられる精度で説明する

部分的には対応しているメンバーもいますが、一つの課題に関して最初から最後までまるっと取り組むという機会があまりなく、課題を分析して言語化する経験を積むことはチームのびしろとしては良さそうに感じました。

今まで要件フェーズは特定の人で対応することが多く、他チーム調整済みで実現性などリスクヘッジされたものをチームでインプットしISSUEにしていくという流れが多かったので、トライの要素としてはマッチしてそうでした。

## ポック

不明確な課題を実現していく作業がPoCのイメージが近かったのでポックという呼び名にしました。（チーム内の呼称で他意はないです）
各課題に対しメイン担当としてアサインし、その人を中心に分析、整理し、各種リスクオフして案件を進めていくような流れとなります。
今回は半年で4つの課題を進める計画としました。

### メイン担当が担うこと
* メイン担当として案件を進める
* ドラフト設計やミニマム実装のようなものを作りチームに課題の説明を行う
* 情報共有としてslackのチームチャンネルに案件の状況を共有していく
* 実際の設計や開発は（なるべく）別メンバーが担当し、メイン担当は根拠を整理、説明する

※ 最初から明確なルールなどを定義したわけではなく、実施していく中で調整していきました。

目的としてはチーム向けの説明が最低でも２回とメンバーへの個別説明など、説明を繰り返すことで言語化していくことを期待したものとなります。
設計や開発前に、ドラフトの成果物をもとに議論できるため空中戦ではなく具体的な指摘が事前にできることも良さそうに感じました。

メイン担当は課題の完了状態を俯瞰的に把握し、メンバーを通して実現していくことでなんやかんやスキルアップするというイメージです！

# 実施してよかったこと

開発生産性は一時的に下がったかもしれないですが、主体的に幅広いフェーズの経験することができたと思います。
また、特に問題もなく進めている姿をみているとタスクベースのアサインが成長を阻害していたのかもとも思えました。

メンバーの経験値として設計、開発の勘所はわかっていて、ドラフトのアウトプットを作成する際も議論になりそうなポイントを押さえ進行できるレベルの習熟度もあり、良いタイミングで実施できたと思っています。

改善、もしくはもっと意識してやっても良かったと思った点ですが、 `自分で開発したくなってしまう欲はなかなか止められない` という感じでした。

# 最後に

何のフレームワークでもないあそびのようなトライをポジティブに受け取ってくれたメンバーが揃っているというチームコンディションが良い状態だから実現できたと考えています。

今後の開発で何か一つでも活かせるものがあったらチームのあたりまえレベルをすこしは上げることにつながったのかなと思います。
スマホゲーをMacで自動操作

ソシャゲの自動化をしたく、debug buildでのテストはいくつもあるのですが、
AppStoreからダウンロードしたものを自動化できないか調べてみました！

[appium](https://github.com/appium/appium)に[mac driver](https://github.com/appium/appium-mac2-driver)があるので、それで操作できました！
今回はRuby(irbでdebugしやすいので)ですが、TS, Pythonなどなんでも動きそう

## アプリのダウンロード
macで起動させるため、Mac AppStoreからダウンロードします。
Mac AppStoreで配信されてないアプリの場合、[Play Cover](https://playcover.io/)で起動できるかも...?

## appiumのダウンロード
```zsh
brew install node
npx appium driver install mac2

gem install --no-document appium_lib

npx appium
```

システム設定→セキュリティとプライバシー→プライバシー→アクセシビリティ→Xcode Helperを追加

```
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/
```

## サンプルコード

```ruby
require "appium_lib"
opts = {
  caps: {
    platformName: "mac",
    'appium:automationName': "Mac2",
    'appium:bundleId': "com.apple.calculator",
  },
  appium_lib: {
    server_url: "http://127.0.0.1:4723",
    wait: 0.1,
  },
}

driver = Appium::Driver.new(opts).start_driver
driver.page_source # => xmlがstringで返ってくるのでここからDOMを探す
application_element = @driver.find_element(:class_name, 'XCUIElementTypeApplication')
puts application_element.attribute(:title) # => 計算機
element = driver.find_element(xpath: "//XCUIElementTypeButton[@label='2']") # => 2のボタンを取得
element.click # => 2のボタンをクリック
```

ゲームなどは、DOMがないので、スクリーンショットを撮ってクリックしたい座標を求めクリックします

```ruby
element = @driver.find_element(name: "計算機")
elememnt.save_element_screenshot(element, "screenshot.png") # => スクリーンショットが撮れる

# スクロールの操作例
f1 = ::Selenium::WebDriver::Interactions.pointer(:touch, name: 'finger1')
f1.create_pointer_move(duration: 1, x: 200, y: 500, origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
f1.create_pointer_down(:left)
f1.create_pointer_move(duration: 1, x: 200, y: 200, origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
f1.create_pointer_up(:left)

@driver.perform_actions([f1])
```

操作例など詳しくは↓(seleniumを継承して上手くやっているみたい)

https://github.com/appium/ruby_lib_core/blob/master/lib/appium_lib_core/common/base/driver.rb